├── .gitignore ├── README.md ├── apps ├── __init__.py ├── blog │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── assets.py │ ├── context_processor.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_post_category.py │ │ ├── 0003_auto_20170417_1637.py │ │ ├── 0004_auto_20170419_0231.py │ │ ├── 0005_emailsubscription.py │ │ ├── 0006_auto_20170501_2337.py │ │ ├── 0007_auto_20170501_2339.py │ │ └── __init__.py │ ├── models.py │ ├── templatetags │ │ ├── __init__.py │ │ ├── adsense_tags.py │ │ └── blog_tags.py │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py └── notes │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── 0001_initial.py │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── assets └── robots.txt ├── locale ├── en │ └── LC_MESSAGES │ │ └── django.po └── ru │ └── LC_MESSAGES │ └── django.po ├── logs └── .keep ├── manage.py ├── notion ├── .env-template ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── requirements.txt ├── staticfiles ├── courses │ └── images │ │ ├── adil.jpg │ │ ├── bgimage.jpg │ │ ├── logo_aws.png │ │ ├── logo_bootstrap.png │ │ ├── logo_circle_ci.png │ │ ├── logo_django.png │ │ ├── logo_do.png │ │ ├── logo_docker.png │ │ ├── logo_es6.png │ │ ├── logo_falcon.png │ │ ├── logo_jest.png │ │ ├── logo_jwt.png │ │ ├── logo_postman.png │ │ ├── logo_python.png │ │ ├── logo_vue.png │ │ └── luigi-logo.png ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── monokai-sublime.min.css │ ├── normalize.css │ └── style.css ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── images │ ├── DE_770x193.jpg │ ├── Python900x120.png │ ├── arrow.jpg │ ├── author.jpg │ ├── devbrain.jpg │ ├── devbrain.png │ ├── icon.png │ ├── like.png │ ├── machine-learning-course.jpg │ ├── ml-agenda.jpg │ ├── ml-poster2.jpg │ ├── pydata-analysis.jpg │ ├── ru-flag.png │ ├── social.jpg │ ├── telegram-logo.png │ └── us-flag.png ├── js │ ├── app.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── highlight.min.js │ ├── jquery-3.2.1.min.js │ └── npm.js └── redactor │ └── plugins │ └── source.js └── templates ├── base.html ├── blog ├── _sidebar.html ├── adsense.html ├── archives.html ├── category_detail.html ├── index.html ├── page.html ├── post_detail.html └── search.html ├── courses └── index.html ├── notes ├── note_detail.html └── notes.html └── tags └── jobs.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # IPython Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # dotenv 81 | .env 82 | 83 | # virtualenv 84 | venv/ 85 | ENV/ 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | 90 | # Rope project settings 91 | .ropeproject 92 | ### VirtualEnv template 93 | # Virtualenv 94 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 95 | .Python 96 | [Bb]in 97 | [Ii]nclude 98 | [Ll]ib 99 | [Ll]ib64 100 | [Ll]ocal 101 | [Ss]cripts 102 | pyvenv.cfg 103 | .venv 104 | pip-selfcheck.json 105 | ### JetBrains template 106 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 107 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 108 | 109 | # User-specific stuff: 110 | .idea/workspace.xml 111 | .idea/tasks.xml 112 | .idea/dictionaries 113 | .idea/vcs.xml 114 | .idea/jsLibraryMappings.xml 115 | 116 | # Sensitive or high-churn files: 117 | .idea/dataSources.ids 118 | .idea/dataSources.xml 119 | .idea/dataSources.local.xml 120 | .idea/sqlDataSources.xml 121 | .idea/dynamic.xml 122 | .idea/uiDesigner.xml 123 | 124 | # Gradle: 125 | .idea/gradle.xml 126 | .idea/libraries 127 | 128 | # Mongo Explorer plugin: 129 | .idea/mongoSettings.xml 130 | 131 | ## File-based project format: 132 | *.iws 133 | 134 | ## Plugin-specific files: 135 | 136 | # IntelliJ 137 | /out/ 138 | 139 | # mpeltonen/sbt-idea plugin 140 | .idea_modules/ 141 | 142 | # JIRA plugin 143 | atlassian-ide-plugin.xml 144 | 145 | # Crashlytics plugin (for Android Studio and IntelliJ) 146 | com_crashlytics_export_strings.xml 147 | crashlytics.properties 148 | crashlytics-build.properties 149 | fabric.properties 150 | 151 | .idea/ 152 | static/ 153 | logs/ 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # notion 2 | Simple blog engine which powers https://khashtamov.com/ 3 | 4 | ## Features 5 | * As simple as possible 6 | * Multiple language support 7 | -------------------------------------------------------------------------------- /apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/apps/__init__.py -------------------------------------------------------------------------------- /apps/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/apps/blog/__init__.py -------------------------------------------------------------------------------- /apps/blog/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django import forms 3 | from redactor.widgets import RedactorEditor 4 | 5 | from apps.blog.models import Category, Post, Page, EmailSubscription, AlternateURL 6 | 7 | 8 | class PostAdminForm(forms.ModelForm): 9 | class Meta: 10 | model = Post 11 | fields = ['title', 'slug', 'text', 'lang', 'status', 'category'] 12 | widgets = { 13 | 'text': RedactorEditor(redactor_options={ 14 | 'plugins': ['table'], 15 | 16 | }), 17 | } 18 | 19 | 20 | class PageAdminForm(forms.ModelForm): 21 | class Meta: 22 | model = Page 23 | fields = ['title', 'slug', 'text', 'lang', 'visible'] 24 | widgets = { 25 | 'text': RedactorEditor(redactor_options={'plugins': ['source']}), 26 | } 27 | 28 | 29 | class CategoryAdmin(admin.ModelAdmin): 30 | list_display = ['title', 'slug', 'created'] 31 | search_fields = ['title'] 32 | 33 | 34 | class PostAdmin(admin.ModelAdmin): 35 | list_display = ['title', 'page_views', 'lang', 'slug', 'status', 'created'] 36 | search_fields = ['title'] 37 | ordering = ['-created'] 38 | form = PostAdminForm 39 | 40 | 41 | class PageAdmin(admin.ModelAdmin): 42 | list_display = ['title', 'lang', 'slug', 'visible', 'created'] 43 | form = PageAdminForm 44 | 45 | 46 | class EmailSubscriptionAdmin(admin.ModelAdmin): 47 | list_display = ['email', 'lang', 'created'] 48 | 49 | 50 | class AlternateURLAdmin(admin.ModelAdmin): 51 | list_display = ['post', 'lang', 'alternate_post', 'created'] 52 | 53 | 54 | admin.site.register(Post, PostAdmin) 55 | admin.site.register(Category, CategoryAdmin) 56 | admin.site.register(Page, PageAdmin) 57 | admin.site.register(EmailSubscription, EmailSubscriptionAdmin) 58 | admin.site.register(AlternateURL, AlternateURLAdmin) 59 | -------------------------------------------------------------------------------- /apps/blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | name = 'apps.blog' 6 | -------------------------------------------------------------------------------- /apps/blog/assets.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django_assets import Bundle, register 4 | 5 | css = Bundle( 6 | os.path.join('css', 'normalize.css'), 7 | os.path.join('css', 'bootstrap.min.css'), 8 | os.path.join('css', 'bootstrap-theme.min.css'), 9 | os.path.join('css', 'style.css'), 10 | os.path.join('css', 'monokai-sublime.min.css'), 11 | filters='cssmin', output='css/build.css' 12 | ) 13 | 14 | js = Bundle( 15 | os.path.join('js', 'jquery-3.2.1.min.js'), 16 | os.path.join('js', 'highlight.min.js'), 17 | os.path.join('js', 'bootstrap.min.js'), 18 | filters='jsmin', output='js/build.js' 19 | ) 20 | register('css_all', css) 21 | register('js_all', js) 22 | -------------------------------------------------------------------------------- /apps/blog/context_processor.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import django 3 | from django.conf import settings 4 | 5 | 6 | def generic(request): 7 | return { 8 | 'DEBUG': settings.DEBUG, 9 | 'DJANGO_VERSION': django.__version__, 10 | 'PYTHON_VERSION': sys.version[:6] 11 | } 12 | -------------------------------------------------------------------------------- /apps/blog/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class EmailForm(forms.Form): 5 | email = forms.EmailField() 6 | -------------------------------------------------------------------------------- /apps/blog/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-04-17 09:42 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='Category', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('title', models.CharField(max_length=30, verbose_name='Title')), 21 | ('slug', models.SlugField()), 22 | ('created', models.DateTimeField(auto_now_add=True)), 23 | ], 24 | options={ 25 | 'verbose_name': 'category', 26 | 'verbose_name_plural': 'categories', 27 | }, 28 | ), 29 | migrations.CreateModel( 30 | name='Post', 31 | fields=[ 32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 33 | ('title', models.CharField(max_length=254)), 34 | ('slug', models.SlugField(max_length=100)), 35 | ('text', models.TextField(verbose_name='Text')), 36 | ('lang', models.CharField(choices=[('ru', 'Russian'), ('en', 'English')], max_length=2, verbose_name='Language')), 37 | ('status', models.SmallIntegerField(choices=[(0, 'Draft'), (1, 'Published')], verbose_name='Status')), 38 | ('created', models.DateTimeField(auto_now_add=True)), 39 | ('updated', models.DateTimeField(auto_now=True)), 40 | ], 41 | options={ 42 | 'verbose_name': 'post', 43 | 'verbose_name_plural': 'Posts', 44 | }, 45 | ), 46 | ] 47 | -------------------------------------------------------------------------------- /apps/blog/migrations/0002_post_category.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-04-17 10:36 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('blog', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='post', 18 | name='category', 19 | field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='blog.Category'), 20 | preserve_default=False, 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /apps/blog/migrations/0003_auto_20170417_1637.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-04-17 10:37 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('blog', '0002_post_category'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='post', 18 | name='category', 19 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.Category'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /apps/blog/migrations/0004_auto_20170419_0231.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-04-18 20:31 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('blog', '0003_auto_20170417_1637'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Page', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('title', models.CharField(max_length=30)), 20 | ('slug', models.SlugField(max_length=30)), 21 | ('text', models.TextField(verbose_name='Text')), 22 | ('lang', models.CharField(choices=[('ru', 'Russian'), ('en', 'English')], max_length=2, verbose_name='Language')), 23 | ('visible', models.BooleanField(default=False)), 24 | ('created', models.DateTimeField(auto_now_add=True)), 25 | ], 26 | options={ 27 | 'verbose_name': 'page', 28 | 'verbose_name_plural': 'Pages', 29 | }, 30 | ), 31 | migrations.AddField( 32 | model_name='post', 33 | name='page_views', 34 | field=models.PositiveIntegerField(default=0, verbose_name='Page views'), 35 | ), 36 | ] 37 | -------------------------------------------------------------------------------- /apps/blog/migrations/0005_emailsubscription.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-04-28 17:32 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import uuid 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('blog', '0004_auto_20170419_0231'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='EmailSubscription', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('email', models.EmailField(max_length=254, unique=True, verbose_name='Email')), 21 | ('lang', models.CharField(max_length=2, verbose_name='Language')), 22 | ('activated', models.BooleanField(default=False, verbose_name='Activated')), 23 | ('activation_code', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='Activation code')), 24 | ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), 25 | ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), 26 | ], 27 | options={ 28 | 'verbose_name': 'subscription', 29 | 'verbose_name_plural': 'Subscriptions', 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /apps/blog/migrations/0006_auto_20170501_2337.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-05-01 17:37 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('blog', '0005_emailsubscription'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='AlternateURL', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('lang', models.CharField(choices=[('ru', 'Russian'), ('en', 'English')], max_length=2, verbose_name='Language')), 21 | ('url', models.URLField(max_length=254, verbose_name='URL')), 22 | ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), 23 | ], 24 | options={ 25 | 'verbose_name': 'alternate URL', 26 | 'verbose_name_plural': 'Alternate URLs', 27 | }, 28 | ), 29 | migrations.AlterField( 30 | model_name='post', 31 | name='slug', 32 | field=models.SlugField(max_length=100, verbose_name='Slug'), 33 | ), 34 | migrations.AlterField( 35 | model_name='post', 36 | name='title', 37 | field=models.CharField(max_length=254, verbose_name='Title'), 38 | ), 39 | migrations.AddField( 40 | model_name='alternateurl', 41 | name='post', 42 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.Post'), 43 | ), 44 | ] 45 | -------------------------------------------------------------------------------- /apps/blog/migrations/0007_auto_20170501_2339.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11 on 2017-05-01 17:39 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('blog', '0006_auto_20170501_2337'), 13 | ] 14 | 15 | operations = [ 16 | migrations.RemoveField( 17 | model_name='alternateurl', 18 | name='url', 19 | ), 20 | migrations.AddField( 21 | model_name='alternateurl', 22 | name='alternate_post', 23 | field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='alternate_post', to='blog.Post', verbose_name='Alternate post'), 24 | preserve_default=False, 25 | ), 26 | migrations.AlterField( 27 | model_name='alternateurl', 28 | name='post', 29 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.Post', verbose_name='Original post'), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /apps/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/apps/blog/migrations/__init__.py -------------------------------------------------------------------------------- /apps/blog/models.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | from django.db import models 4 | from django.utils.translation import gettext_lazy as _ 5 | from django.conf import settings 6 | from django.urls import reverse 7 | from django.contrib.contenttypes.models import ContentType 8 | 9 | 10 | class Category(models.Model): 11 | title = models.CharField(_('Title'), max_length=30) 12 | slug = models.SlugField() 13 | created = models.DateTimeField(auto_now_add=True) 14 | 15 | class Meta: 16 | verbose_name = _('category') 17 | verbose_name_plural = _('categories') 18 | 19 | def __str__(self): 20 | return self.title 21 | 22 | 23 | class Post(models.Model): 24 | DRAFT, PUBLISHED = range(2) 25 | 26 | STATUSES = ( 27 | (DRAFT, _('Draft')), 28 | (PUBLISHED, _('Published')) 29 | ) 30 | 31 | title = models.CharField(_('Title'), max_length=254) 32 | slug = models.SlugField(_('Slug'), max_length=100) 33 | text = models.TextField(_('Text')) 34 | lang = models.CharField(_('Language'), max_length=2, choices=settings.LANGUAGES) 35 | category = models.ForeignKey('Category', null=True, on_delete=models.CASCADE) 36 | status = models.SmallIntegerField(_('Status'), choices=STATUSES) 37 | page_views = models.PositiveIntegerField(_('Page views'), default=0) 38 | created = models.DateTimeField(auto_now_add=True) 39 | updated = models.DateTimeField(auto_now=True) 40 | 41 | class Meta: 42 | verbose_name = _('post') 43 | verbose_name_plural = _('Posts') 44 | 45 | def __str__(self): 46 | return self.title 47 | 48 | def get_absolute_url(self): 49 | return '/{}/{}/'.format(self.lang, self.slug) 50 | 51 | def month_year(self) -> str: 52 | return _(self.created.strftime('%B')) + ', ' + self.created.strftime('%Y') 53 | 54 | def get_admin_url(self): 55 | content_type = ContentType.objects.get_for_model(self.__class__) 56 | return reverse('admin:%s_%s_change' % (content_type.app_label, content_type.model), 57 | args=(self.id,)) 58 | 59 | 60 | class Page(models.Model): 61 | title = models.CharField(max_length=30) 62 | slug = models.SlugField(max_length=30) 63 | text = models.TextField(_('Text')) 64 | lang = models.CharField(_('Language'), max_length=2, choices=settings.LANGUAGES) 65 | visible = models.BooleanField(default=False) 66 | created = models.DateTimeField(auto_now_add=True) 67 | 68 | class Meta: 69 | verbose_name = _('page') 70 | verbose_name_plural = _('Pages') 71 | 72 | def __str__(self): 73 | return self.title 74 | 75 | def get_absolute_url(self): 76 | return '/{}/p/{}/'.format(self.lang, self.slug) 77 | 78 | 79 | class EmailSubscription(models.Model): 80 | email = models.EmailField(_('Email'), unique=True) 81 | lang = models.CharField(_('Language'), max_length=2) 82 | activated = models.BooleanField(_('Activated'), default=False) 83 | activation_code = models.UUIDField(_('Activation code'), default=uuid.uuid4, editable=False) 84 | created = models.DateTimeField(_('Created'), auto_now_add=True) 85 | updated = models.DateTimeField(_('Updated'), auto_now=True) 86 | 87 | class Meta: 88 | verbose_name = _('subscription') 89 | verbose_name_plural = _('Subscriptions') 90 | 91 | def __str__(self): 92 | return self.email 93 | 94 | def activate(self): 95 | self.activated = True 96 | self.save() 97 | 98 | def send_activation_code(self): 99 | pass 100 | 101 | 102 | class AlternateURL(models.Model): 103 | post = models.ForeignKey('Post', verbose_name=_('Original post'), on_delete=models.CASCADE) 104 | lang = models.CharField(_('Language'), max_length=2, choices=settings.LANGUAGES) 105 | alternate_post = models.ForeignKey('Post', related_name='alternate_post', 106 | verbose_name=_('Alternate post'), on_delete=models.CASCADE) 107 | created = models.DateTimeField(_('Created'), auto_now_add=True) 108 | 109 | class Meta: 110 | verbose_name = _('alternate URL') 111 | verbose_name_plural = _('Alternate URLs') 112 | 113 | def __str__(self): 114 | return self.post.slug 115 | -------------------------------------------------------------------------------- /apps/blog/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Adylzhan' 2 | -------------------------------------------------------------------------------- /apps/blog/templatetags/adsense_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.template.loader import render_to_string 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.filter 8 | def inject_adsense_after_n_paragraph(value, arg): 9 | ad_code = render_to_string('blog/adsense.html') 10 | paragraphs = value.split('

') 11 | 12 | if arg < len(paragraphs): 13 | paragraphs[arg] = ad_code + paragraphs[arg] 14 | 15 | value = '

'.join(paragraphs) 16 | return value 17 | -------------------------------------------------------------------------------- /apps/blog/templatetags/blog_tags.py: -------------------------------------------------------------------------------- 1 | from django.template.defaulttags import register 2 | from django.template.loader import render_to_string 3 | from django.utils.safestring import mark_safe 4 | 5 | from apps.blog.utils import get_latest_jobs 6 | 7 | 8 | @register.filter 9 | def text_preview(text): 10 | more = text.find('') 11 | if more != -1: 12 | return text[:more] 13 | else: 14 | return text 15 | 16 | 17 | @register.filter 18 | def erase_breaks(text): 19 | return text.replace('\n', '').replace('\r\n', '').replace('\r', '') 20 | 21 | 22 | @register.simple_tag 23 | def display_jobs(limit=5): 24 | jobs = get_latest_jobs(limit, text='python') 25 | return mark_safe(render_to_string('tags/jobs.html', {'jobs': jobs})) 26 | -------------------------------------------------------------------------------- /apps/blog/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/blog/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from apps.blog.views import ( 4 | HomePageView, 5 | PostDetailView, 6 | CategoryDetailView, 7 | PageDetailView, 8 | LastestPostFeed, 9 | SearchView, 10 | ) 11 | 12 | app_name = 'blog' 13 | urlpatterns = [ 14 | path('', HomePageView.as_view(), name='posts'), 15 | path('p//', PageDetailView.as_view(), name='page'), 16 | path('category//', CategoryDetailView.as_view(), name='category'), 17 | path('feed/', LastestPostFeed(), name='feed'), 18 | path('search/', SearchView.as_view(), name='search'), 19 | path('/', PostDetailView.as_view(), name='post'), 20 | ] 21 | -------------------------------------------------------------------------------- /apps/blog/utils.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | 4 | def get_latest_jobs(limit=5, text=''): 5 | try: 6 | response = requests.get( 7 | 'https://remotelist.ru/api/jobs', 8 | params={'limit': limit, 'text': text}, 9 | timeout=5 10 | ) 11 | except Exception: 12 | return [] 13 | else: 14 | return response.json() 15 | -------------------------------------------------------------------------------- /apps/blog/views.py: -------------------------------------------------------------------------------- 1 | from django.views.generic import ListView, DetailView, View 2 | from django.utils import translation 3 | from django.utils.translation import gettext as _ 4 | from django.urls import reverse, reverse_lazy 5 | from django.contrib.syndication.views import Feed 6 | from django.http import JsonResponse, HttpResponseRedirect, HttpResponseForbidden 7 | from django.db.models import F 8 | from django.contrib.postgres.search import SearchQuery, SearchVector 9 | from django.shortcuts import render 10 | 11 | from apps.blog.models import Post, Category, Page, EmailSubscription, AlternateURL 12 | from apps.notes.models import Note 13 | from apps.blog.forms import EmailForm 14 | 15 | 16 | class LastestPostFeed(Feed): 17 | title = _("Adil Khashtamov's personal blog") 18 | description = _('pragmatic programmer') 19 | link = reverse_lazy('blog:posts') 20 | 21 | def items(self): 22 | return Post.objects.filter( 23 | lang=translation.get_language(), status=Post.PUBLISHED 24 | ).order_by('-created')[:5] 25 | 26 | def item_title(self, item): 27 | return item.title 28 | 29 | def item_description(self, item): 30 | return item.text[: item.text.find('')] 31 | 32 | def item_link(self, item): 33 | return reverse('blog:post', kwargs={'slug': item.slug}) 34 | 35 | 36 | class HomePageView(ListView): 37 | template_name = 'blog/index.html' 38 | model = Post 39 | 40 | def get_queryset(self): 41 | if self.request.user.is_superuser: 42 | return self.model.objects.filter(lang=translation.get_language()).order_by( 43 | '-id' 44 | ) 45 | else: 46 | return self.model.objects.filter( 47 | lang=translation.get_language(), status=Post.PUBLISHED 48 | ).order_by('-id') 49 | 50 | def get_context_data(self, *, object_list=None, **kwargs): 51 | context = super().get_context_data(object_list=object_list, **kwargs) 52 | context['popular_posts'] = self.model.objects.filter( 53 | lang=translation.get_language(), status=Post.PUBLISHED 54 | ).order_by('-page_views')[:10] 55 | context['recent_posts'] = self.model.objects.filter( 56 | lang=translation.get_language(), status=Post.PUBLISHED 57 | ).order_by('-id')[:10] 58 | return context 59 | 60 | 61 | class PostDetailView(DetailView): 62 | template_name = 'blog/post_detail.html' 63 | model = Post 64 | 65 | def get_queryset(self): 66 | if self.request.user.is_superuser: 67 | return super().get_queryset().filter(lang=translation.get_language()) 68 | else: 69 | return ( 70 | super() 71 | .get_queryset() 72 | .filter(lang=translation.get_language(), status=Post.PUBLISHED) 73 | ) 74 | 75 | def get_context_data(self, **kwargs): 76 | context = super().get_context_data(**kwargs) 77 | article = context['object'] 78 | article.page_views = F('page_views') + 1 79 | article.save() 80 | context['object'] = self.model.objects.get(id=article.id) 81 | 82 | context['lastest_notes'] = ( 83 | Note.objects.filter(status=Note.PUBLISHED, lang=translation.get_language()) 84 | .select_related('theme') 85 | .order_by('-created')[:5] 86 | ) 87 | context['related_articles'] = Post.objects.filter( 88 | status=Post.PUBLISHED, 89 | lang=translation.get_language(), 90 | category=article.category, 91 | ).exclude(id=article.id) 92 | context['alternate_posts'] = AlternateURL.objects.filter(post=self.object) 93 | context['popular_posts'] = self.model.objects.filter( 94 | lang=translation.get_language(), status=Post.PUBLISHED 95 | ).order_by('-page_views')[:10] 96 | context['recent_posts'] = self.model.objects.filter( 97 | lang=translation.get_language(), status=Post.PUBLISHED 98 | ).order_by('-id')[:10] 99 | return context 100 | 101 | 102 | class CategoryDetailView(DetailView): 103 | template_name = 'blog/category_detail.html' 104 | model = Category 105 | 106 | def get_context_data(self, **kwargs): 107 | context = super().get_context_data(**kwargs) 108 | context['posts'] = Post.objects.filter( 109 | lang=translation.get_language(), 110 | status=Post.PUBLISHED, 111 | category=self.get_object(), 112 | ).order_by('-created') 113 | return context 114 | 115 | 116 | class PageDetailView(DetailView): 117 | template_name = 'blog/page.html' 118 | model = Page 119 | 120 | def get_queryset(self): 121 | return ( 122 | super().get_queryset().filter(lang=translation.get_language(), visible=True) 123 | ) 124 | 125 | 126 | class SubscriptionView(View): 127 | def post(self, request): 128 | form = EmailForm(request.POST) 129 | if form.is_valid(): 130 | try: 131 | EmailSubscription.objects.create( 132 | email=form.cleaned_data['email'], 133 | lang=translation.get_language() 134 | ) 135 | except: # duplicate email 136 | pass 137 | return HttpResponseRedirect(reverse('blog:posts')) 138 | 139 | 140 | class SearchView(View): 141 | def get(self, request): 142 | lang_mapping = {'en': 'english', 'ru': 'russian'} 143 | query = request.GET.get('query') 144 | lang = translation.get_language() 145 | lang_config = lang_mapping.get(lang, 'russian') 146 | search_query = SearchQuery(query, config=lang_config) 147 | vector = SearchVector('text', config=lang_config) 148 | results = ( 149 | Post.objects.annotate(search=vector) 150 | .filter(lang=lang, search=search_query) 151 | .order_by('-created') 152 | ) 153 | 154 | return render(request, 'blog/search.html', {'results': results, 'query': query}) 155 | -------------------------------------------------------------------------------- /apps/notes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/apps/notes/__init__.py -------------------------------------------------------------------------------- /apps/notes/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django import forms 3 | from redactor.widgets import RedactorEditor 4 | 5 | from apps.notes.models import Note, Theme 6 | 7 | 8 | class NoteAdminForm(forms.ModelForm): 9 | class Meta: 10 | model = Note 11 | fields = ['title', 'slug', 'text', 'lang', 'status', 'theme'] 12 | widgets = { 13 | 'text': RedactorEditor(redactor_options={ 14 | 'plugins': ['table'], 15 | 16 | }), 17 | } 18 | 19 | 20 | class NoteAdmin(admin.ModelAdmin): 21 | list_display = ['title', 'lang', 'slug', 'status', 'created'] 22 | search_fields = ['title'] 23 | ordering = ['-created'] 24 | form = NoteAdminForm 25 | 26 | 27 | class ThemeAdmin(admin.ModelAdmin): 28 | list_display = ['title', 'slug'] 29 | search_fields = ['title'] 30 | 31 | 32 | admin.site.register(Note, NoteAdmin) 33 | admin.site.register(Theme, ThemeAdmin) 34 | -------------------------------------------------------------------------------- /apps/notes/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class NotesConfig(AppConfig): 5 | name = 'apps.notes' 6 | -------------------------------------------------------------------------------- /apps/notes/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0 on 2020-04-20 03:30 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Theme', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('title', models.CharField(max_length=30, verbose_name='Title')), 20 | ('slug', models.SlugField(max_length=64, verbose_name='Slug')), 21 | ], 22 | options={ 23 | 'verbose_name': 'theme', 24 | 'verbose_name_plural': 'Themes', 25 | }, 26 | ), 27 | migrations.CreateModel( 28 | name='Note', 29 | fields=[ 30 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 31 | ('slug', models.SlugField(max_length=100, verbose_name='Slug')), 32 | ('title', models.CharField(max_length=254, verbose_name='Title')), 33 | ('text', models.TextField(verbose_name='Text')), 34 | ('created', models.DateTimeField(auto_now_add=True)), 35 | ('lang', models.CharField(choices=[('ru', 'Russian'), ('en', 'English')], max_length=2, verbose_name='Language')), 36 | ('status', models.SmallIntegerField(choices=[(0, 'Draft'), (1, 'Published')], verbose_name='Status')), 37 | ('theme', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='notes.Theme')), 38 | ], 39 | options={ 40 | 'verbose_name': 'note', 41 | 'verbose_name_plural': 'Notes', 42 | }, 43 | ), 44 | ] 45 | -------------------------------------------------------------------------------- /apps/notes/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/apps/notes/migrations/__init__.py -------------------------------------------------------------------------------- /apps/notes/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.utils.translation import gettext_lazy as _ 3 | from django.conf import settings 4 | from django.contrib.contenttypes.models import ContentType 5 | from django.urls import reverse 6 | 7 | 8 | 9 | 10 | class Theme(models.Model): 11 | title = models.CharField(_('Title'), max_length=30) 12 | slug = models.SlugField(_('Slug'), max_length=64) 13 | 14 | class Meta: 15 | verbose_name = _('theme') 16 | verbose_name_plural = _('Themes') 17 | 18 | def __str__(self): 19 | return self.title 20 | 21 | 22 | class Note(models.Model): 23 | DRAFT, PUBLISHED = range(2) 24 | 25 | STATUSES = ((DRAFT, _('Draft')), (PUBLISHED, _('Published'))) 26 | 27 | slug = models.SlugField(_('Slug'), max_length=100) 28 | title = models.CharField(_('Title'), max_length=254) 29 | text = models.TextField(_('Text')) 30 | created = models.DateTimeField(auto_now_add=True) 31 | lang = models.CharField(_('Language'), max_length=2, choices=settings.LANGUAGES) 32 | status = models.SmallIntegerField(_('Status'), choices=STATUSES) 33 | theme = models.ForeignKey('Theme', on_delete=models.CASCADE) 34 | 35 | class Meta: 36 | verbose_name = _('note') 37 | verbose_name_plural = _('Notes') 38 | 39 | def get_absolute_url(self): 40 | return '/{}/{}/'.format(self.lang, self.slug) 41 | 42 | def get_admin_url(self): 43 | content_type = ContentType.objects.get_for_model(self.__class__) 44 | return reverse( 45 | 'admin:%s_%s_change' % (content_type.app_label, content_type.model), 46 | args=(self.id,), 47 | ) 48 | 49 | def __str__(self): 50 | return self.title 51 | -------------------------------------------------------------------------------- /apps/notes/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/notes/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from apps.notes.views import ( 4 | NoteDetailView, 5 | NotesListView, 6 | ) 7 | 8 | app_name = 'notes' 9 | urlpatterns = [ 10 | path('', NotesListView.as_view(), name='notes-list'), 11 | path('//', NoteDetailView.as_view(), name='note-detail'), 12 | ] 13 | -------------------------------------------------------------------------------- /apps/notes/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404 2 | from django.views.generic import ListView, View 3 | from django.utils import translation 4 | 5 | from apps.notes.models import Note, Theme 6 | 7 | 8 | class NotesListView(ListView): 9 | model = Note 10 | template_name = 'notes/notes.html' 11 | 12 | def get_queryset(self): 13 | return ( 14 | super() 15 | .get_queryset() 16 | .filter(lang=translation.get_language(), status=Note.PUBLISHED) 17 | .order_by('theme', '-created') 18 | .select_related('theme') 19 | ) 20 | 21 | 22 | class NoteDetailView(View): 23 | def get(self, request, theme_name: str, slug: str): 24 | theme = get_object_or_404(Theme, slug=theme_name) 25 | note = get_object_or_404(Note, slug=slug, status=Note.PUBLISHED) 26 | return render(request, 'notes/note_detail.html', { 27 | 'theme': theme, 28 | 'object': note 29 | }) 30 | -------------------------------------------------------------------------------- /assets/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /ru/search/* 3 | Disallow: /en/search/* 4 | Host: https://khashtamov.com 5 | Sitemap: https://khashtamov.com/sitemap.xml 6 | -------------------------------------------------------------------------------- /locale/en/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2021-01-11 18:34+0600\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: .\apps\blog\models.py:11 .\apps\blog\models.py:31 .\apps\notes\models.py:9 21 | #: .\apps\notes\models.py:26 22 | msgid "Title" 23 | msgstr "" 24 | 25 | #: .\apps\blog\models.py:16 .\templates\blog\category_detail.html:3 26 | #: .\templates\blog\category_detail.html:9 27 | msgid "category" 28 | msgstr "" 29 | 30 | #: .\apps\blog\models.py:17 31 | msgid "categories" 32 | msgstr "" 33 | 34 | #: .\apps\blog\models.py:27 .\apps\notes\models.py:23 35 | #: .\templates\blog\index.html:26 .\templates\blog\post_detail.html:36 36 | #: .\templates\notes\note_detail.html:22 37 | msgid "Draft" 38 | msgstr "" 39 | 40 | #: .\apps\blog\models.py:28 .\apps\notes\models.py:23 41 | msgid "Published" 42 | msgstr "" 43 | 44 | #: .\apps\blog\models.py:32 .\apps\notes\models.py:10 .\apps\notes\models.py:25 45 | msgid "Slug" 46 | msgstr "" 47 | 48 | #: .\apps\blog\models.py:33 .\apps\blog\models.py:60 .\apps\notes\models.py:27 49 | msgid "Text" 50 | msgstr "" 51 | 52 | #: .\apps\blog\models.py:34 .\apps\blog\models.py:61 .\apps\blog\models.py:78 53 | #: .\apps\blog\models.py:101 .\apps\notes\models.py:29 54 | msgid "Language" 55 | msgstr "" 56 | 57 | #: .\apps\blog\models.py:36 .\apps\notes\models.py:30 58 | msgid "Status" 59 | msgstr "" 60 | 61 | #: .\apps\blog\models.py:37 62 | msgid "Page views" 63 | msgstr "" 64 | 65 | #: .\apps\blog\models.py:42 66 | msgid "post" 67 | msgstr "" 68 | 69 | #: .\apps\blog\models.py:43 70 | msgid "Posts" 71 | msgstr "" 72 | 73 | #: .\apps\blog\models.py:66 74 | msgid "page" 75 | msgstr "" 76 | 77 | #: .\apps\blog\models.py:67 78 | msgid "Pages" 79 | msgstr "" 80 | 81 | #: .\apps\blog\models.py:77 82 | msgid "Email" 83 | msgstr "" 84 | 85 | #: .\apps\blog\models.py:79 86 | msgid "Activated" 87 | msgstr "" 88 | 89 | #: .\apps\blog\models.py:80 90 | msgid "Activation code" 91 | msgstr "" 92 | 93 | #: .\apps\blog\models.py:81 .\apps\blog\models.py:104 94 | msgid "Created" 95 | msgstr "" 96 | 97 | #: .\apps\blog\models.py:82 98 | msgid "Updated" 99 | msgstr "" 100 | 101 | #: .\apps\blog\models.py:85 102 | msgid "subscription" 103 | msgstr "" 104 | 105 | #: .\apps\blog\models.py:86 106 | msgid "Subscriptions" 107 | msgstr "" 108 | 109 | #: .\apps\blog\models.py:100 110 | msgid "Original post" 111 | msgstr "" 112 | 113 | #: .\apps\blog\models.py:103 114 | msgid "Alternate post" 115 | msgstr "" 116 | 117 | #: .\apps\blog\models.py:107 118 | msgid "alternate URL" 119 | msgstr "" 120 | 121 | #: .\apps\blog\models.py:108 122 | msgid "Alternate URLs" 123 | msgstr "" 124 | 125 | #: .\apps\blog\views.py:20 126 | msgid "Adil Khashtamov's personal blog" 127 | msgstr "" 128 | 129 | #: .\apps\blog\views.py:21 130 | msgid "pragmatic programmer" 131 | msgstr "" 132 | 133 | #: .\apps\notes\models.py:13 134 | msgid "theme" 135 | msgstr "" 136 | 137 | #: .\apps\notes\models.py:14 138 | msgid "Themes" 139 | msgstr "" 140 | 141 | #: .\apps\notes\models.py:34 142 | msgid "note" 143 | msgstr "" 144 | 145 | #: .\apps\notes\models.py:35 .\templates\base.html:40 146 | msgid "Notes" 147 | msgstr "" 148 | 149 | #: .\notion\settings.py:118 150 | msgid "Russian" 151 | msgstr "" 152 | 153 | #: .\notion\settings.py:119 154 | msgid "English" 155 | msgstr "" 156 | 157 | #: .\templates\base.html:11 158 | msgid "" 159 | "Software engineer personal blog. Usually write about building web apps, " 160 | "machine learning and data analysis" 161 | msgstr "" 162 | 163 | #: .\templates\base.html:13 164 | msgid "Adil Khashtamov's personal blog — pragmatic programmer" 165 | msgstr "" 166 | 167 | #: .\templates\base.html:39 168 | msgid "Blog" 169 | msgstr "" 170 | 171 | #: .\templates\base.html:41 172 | msgid "Archives" 173 | msgstr "" 174 | 175 | #: .\templates\base.html:42 176 | msgid "Contacts" 177 | msgstr "" 178 | 179 | #: .\templates\base.html:51 180 | msgid "Admin" 181 | msgstr "" 182 | 183 | #: .\templates\base.html:67 184 | msgid "Powered by" 185 | msgstr "" 186 | 187 | #: .\templates\blog\_sidebar.html:9 188 | msgid "Subscription" 189 | msgstr "" 190 | 191 | #: .\templates\blog\_sidebar.html:14 .\templates\blog\post_detail.html:53 192 | msgid "e-mail" 193 | msgstr "" 194 | 195 | #: .\templates\blog\_sidebar.html:16 .\templates\blog\post_detail.html:55 196 | msgid "Subscribe" 197 | msgstr "" 198 | 199 | #: .\templates\blog\_sidebar.html:21 200 | msgid "Search" 201 | msgstr "" 202 | 203 | #: .\templates\blog\_sidebar.html:25 204 | msgid "search term" 205 | msgstr "" 206 | 207 | #: .\templates\blog\_sidebar.html:28 208 | msgid "Find" 209 | msgstr "" 210 | 211 | #: .\templates\blog\_sidebar.html:34 212 | msgid "Recent notes" 213 | msgstr "" 214 | 215 | #: .\templates\blog\_sidebar.html:43 216 | msgid "Recent posts" 217 | msgstr "" 218 | 219 | #: .\templates\blog\_sidebar.html:55 220 | msgid "Ad" 221 | msgstr "" 222 | 223 | #: .\templates\blog\archives.html:3 .\templates\blog\archives.html:9 224 | msgid "Archive of posts" 225 | msgstr "" 226 | 227 | #: .\templates\blog\archives.html:11 228 | msgid "By category" 229 | msgstr "" 230 | 231 | #: .\templates\blog\archives.html:23 232 | msgid "By year" 233 | msgstr "" 234 | 235 | #: .\templates\blog\index.html:24 .\templates\blog\post_detail.html:34 236 | #: .\templates\notes\note_detail.html:20 237 | msgid "Edit" 238 | msgstr "" 239 | 240 | #: .\templates\blog\index.html:30 241 | msgid "read more" 242 | msgstr "" 243 | 244 | #: .\templates\blog\post_detail.html:31 .\templates\blog\search.html:26 245 | msgid "views" 246 | msgstr "" 247 | 248 | #: .\templates\blog\post_detail.html:45 249 | msgid "Join the mailing list" 250 | msgstr "" 251 | 252 | #: .\templates\blog\post_detail.html:46 253 | msgid "" 254 | "If you like the content I produce, please join my mailing list to stay tuned." 255 | msgstr "" 256 | 257 | #: .\templates\blog\post_detail.html:65 258 | msgid "Related posts" 259 | msgstr "" 260 | 261 | #: .\templates\blog\search.html:8 262 | #, python-format 263 | msgid "Results for «%(query)s»" 264 | msgstr "" 265 | 266 | #: .\templates\blog\search.html:16 267 | msgid "No articles found" 268 | msgstr "" 269 | 270 | #: .\templates\blog\search.html:18 271 | msgid "Articles found" 272 | msgstr "" 273 | 274 | #: .\templates\notes\notes.html:5 .\templates\notes\notes.html:11 275 | msgid "Useful notes" 276 | msgstr "" 277 | 278 | #: .\templates\tags\jobs.html:7 279 | msgid "Remote jobs" 280 | msgstr "" 281 | -------------------------------------------------------------------------------- /locale/ru/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: \n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2021-03-04 22:11+0600\n" 11 | "PO-Revision-Date: 2021-03-04 22:12+0600\n" 12 | "Last-Translator: \n" 13 | "Language-Team: \n" 14 | "Language: ru\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" 19 | "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" 20 | "%100>=11 && n%100<=14)? 2 : 3);\n" 21 | "X-Generator: Poedit 2.3\n" 22 | 23 | #: .\apps\blog\models.py:11 .\apps\blog\models.py:31 .\apps\notes\models.py:9 24 | #: .\apps\notes\models.py:26 25 | msgid "Title" 26 | msgstr "Заголовок" 27 | 28 | #: .\apps\blog\models.py:16 .\templates\blog\category_detail.html:3 29 | #: .\templates\blog\category_detail.html:9 30 | msgid "category" 31 | msgstr "категория" 32 | 33 | #: .\apps\blog\models.py:17 34 | msgid "categories" 35 | msgstr "категории" 36 | 37 | #: .\apps\blog\models.py:27 .\apps\notes\models.py:23 38 | #: .\templates\blog\index.html:26 .\templates\blog\post_detail.html:37 39 | #: .\templates\notes\note_detail.html:22 40 | msgid "Draft" 41 | msgstr "Черновик" 42 | 43 | #: .\apps\blog\models.py:28 .\apps\notes\models.py:23 44 | msgid "Published" 45 | msgstr "Опубликован" 46 | 47 | #: .\apps\blog\models.py:32 .\apps\notes\models.py:10 .\apps\notes\models.py:25 48 | msgid "Slug" 49 | msgstr "Ссылка" 50 | 51 | #: .\apps\blog\models.py:33 .\apps\blog\models.py:60 .\apps\notes\models.py:27 52 | msgid "Text" 53 | msgstr "Текст" 54 | 55 | #: .\apps\blog\models.py:34 .\apps\blog\models.py:61 .\apps\blog\models.py:78 56 | #: .\apps\blog\models.py:101 .\apps\notes\models.py:29 57 | msgid "Language" 58 | msgstr "Язык" 59 | 60 | #: .\apps\blog\models.py:36 .\apps\notes\models.py:30 61 | msgid "Status" 62 | msgstr "Статус" 63 | 64 | #: .\apps\blog\models.py:37 65 | msgid "Page views" 66 | msgstr "Просмотры" 67 | 68 | #: .\apps\blog\models.py:42 69 | msgid "post" 70 | msgstr "запись" 71 | 72 | #: .\apps\blog\models.py:43 73 | msgid "Posts" 74 | msgstr "Записи" 75 | 76 | #: .\apps\blog\models.py:66 77 | msgid "page" 78 | msgstr "траница" 79 | 80 | #: .\apps\blog\models.py:67 81 | msgid "Pages" 82 | msgstr "Страницы" 83 | 84 | #: .\apps\blog\models.py:77 85 | msgid "Email" 86 | msgstr "Эл.адрес" 87 | 88 | #: .\apps\blog\models.py:79 89 | msgid "Activated" 90 | msgstr "Активирован" 91 | 92 | #: .\apps\blog\models.py:80 93 | msgid "Activation code" 94 | msgstr "Код активации" 95 | 96 | #: .\apps\blog\models.py:81 .\apps\blog\models.py:104 97 | msgid "Created" 98 | msgstr "Создан" 99 | 100 | #: .\apps\blog\models.py:82 101 | msgid "Updated" 102 | msgstr "Обновлён" 103 | 104 | #: .\apps\blog\models.py:85 105 | msgid "subscription" 106 | msgstr "подписка" 107 | 108 | #: .\apps\blog\models.py:86 109 | msgid "Subscriptions" 110 | msgstr "Подписки" 111 | 112 | #: .\apps\blog\models.py:100 113 | msgid "Original post" 114 | msgstr "Оригинальный пост" 115 | 116 | #: .\apps\blog\models.py:103 117 | msgid "Alternate post" 118 | msgstr "Альтернативные посты" 119 | 120 | #: .\apps\blog\models.py:107 121 | msgid "alternate URL" 122 | msgstr "альтернативный URL" 123 | 124 | #: .\apps\blog\models.py:108 125 | msgid "Alternate URLs" 126 | msgstr "Альтернативные URL" 127 | 128 | #: .\apps\blog\views.py:21 129 | msgid "Adil Khashtamov's personal blog" 130 | msgstr "Персональный блог Адиля Хаштамова" 131 | 132 | #: .\apps\blog\views.py:22 133 | msgid "pragmatic programmer" 134 | msgstr "программист-прагматик" 135 | 136 | #: .\apps\notes\models.py:13 137 | msgid "theme" 138 | msgstr "тема" 139 | 140 | #: .\apps\notes\models.py:14 141 | msgid "Themes" 142 | msgstr "Темы" 143 | 144 | #: .\apps\notes\models.py:34 145 | msgid "note" 146 | msgstr "заметка" 147 | 148 | #: .\apps\notes\models.py:35 .\templates\base.html:40 149 | msgid "Notes" 150 | msgstr "Заметки" 151 | 152 | #: .\notion\settings.py:121 153 | msgid "Russian" 154 | msgstr "Русский" 155 | 156 | #: .\notion\settings.py:122 157 | msgid "English" 158 | msgstr "Английский" 159 | 160 | #: .\templates\base.html:11 161 | msgid "" 162 | "Software engineer personal blog. Usually write about building web apps, " 163 | "machine learning and data analysis" 164 | msgstr "" 165 | "Персональный блог программиста-прагматика. Пишу о разработке веб-приложений, " 166 | "машинном обучении и анализе данных" 167 | 168 | #: .\templates\base.html:13 169 | msgid "Adil Khashtamov's personal blog — pragmatic programmer" 170 | msgstr "Персональный блог Адиля Хаштамова — программист-прагматик" 171 | 172 | #: .\templates\base.html:39 173 | msgid "Blog" 174 | msgstr "Блог" 175 | 176 | #: .\templates\base.html:41 177 | msgid "Archives" 178 | msgstr "Архивы" 179 | 180 | #: .\templates\base.html:42 181 | msgid "Contacts" 182 | msgstr "Контакты" 183 | 184 | #: .\templates\base.html:51 185 | msgid "Admin" 186 | msgstr "Админка" 187 | 188 | #: .\templates\base.html:67 189 | msgid "Powered by" 190 | msgstr "Работает на" 191 | 192 | #: .\templates\blog\_sidebar.html:9 193 | msgid "Subscription" 194 | msgstr "Подписка" 195 | 196 | #: .\templates\blog\_sidebar.html:14 .\templates\blog\post_detail.html:63 197 | msgid "e-mail" 198 | msgstr "эл.адрес" 199 | 200 | #: .\templates\blog\_sidebar.html:16 .\templates\blog\post_detail.html:65 201 | msgid "Subscribe" 202 | msgstr "Подписаться" 203 | 204 | #: .\templates\blog\_sidebar.html:21 205 | msgid "Search" 206 | msgstr "Поиск" 207 | 208 | #: .\templates\blog\_sidebar.html:25 209 | msgid "search term" 210 | msgstr "поиск" 211 | 212 | #: .\templates\blog\_sidebar.html:28 213 | msgid "Find" 214 | msgstr "Найти" 215 | 216 | #: .\templates\blog\_sidebar.html:34 217 | msgid "Recent notes" 218 | msgstr "Последние заметки" 219 | 220 | #: .\templates\blog\_sidebar.html:43 221 | msgid "Recent posts" 222 | msgstr "Свежие записи" 223 | 224 | #: .\templates\blog\_sidebar.html:55 225 | msgid "Ad" 226 | msgstr "Реклама" 227 | 228 | #: .\templates\blog\archives.html:3 .\templates\blog\archives.html:9 229 | msgid "Archive of posts" 230 | msgstr "Архив записей" 231 | 232 | #: .\templates\blog\archives.html:11 233 | msgid "By category" 234 | msgstr "По категории" 235 | 236 | #: .\templates\blog\archives.html:23 237 | msgid "By year" 238 | msgstr "По годам" 239 | 240 | #: .\templates\blog\index.html:24 .\templates\blog\post_detail.html:34 241 | #: .\templates\notes\note_detail.html:20 242 | msgid "Edit" 243 | msgstr "Редактировать" 244 | 245 | #: .\templates\blog\index.html:30 246 | msgid "read more" 247 | msgstr "читать дальше" 248 | 249 | #: .\templates\blog\post_detail.html:31 .\templates\blog\search.html:26 250 | msgid "views" 251 | msgstr "просмотров" 252 | 253 | #: .\templates\blog\post_detail.html:45 254 | msgid "Translation in " 255 | msgstr "Перевод на" 256 | 257 | #: .\templates\blog\post_detail.html:55 258 | msgid "Join the mailing list" 259 | msgstr "Присоединяйтесь к рассылке" 260 | 261 | #: .\templates\blog\post_detail.html:56 262 | msgid "" 263 | "If you like the content I produce, please join my mailing list to stay tuned." 264 | msgstr "Понравился контент? Пожалуйста, подпишись на рассылку." 265 | 266 | #: .\templates\blog\post_detail.html:73 267 | msgid "Related posts" 268 | msgstr "Интересные записи" 269 | 270 | #: .\templates\blog\search.html:8 271 | #, python-format 272 | msgid "Results for «%(query)s»" 273 | msgstr "Результаты поиска по запросу «%(query)s»" 274 | 275 | #: .\templates\blog\search.html:16 276 | msgid "No articles found" 277 | msgstr "Ничего не найдено" 278 | 279 | #: .\templates\blog\search.html:18 280 | msgid "Articles found" 281 | msgstr "Найдено статей" 282 | 283 | #: .\templates\notes\notes.html:5 .\templates\notes\notes.html:11 284 | msgid "Useful notes" 285 | msgstr "Полезные заметки" 286 | 287 | #: .\templates\tags\jobs.html:7 288 | msgid "Remote jobs" 289 | msgstr "Удаленная работа" 290 | 291 | #~ msgid "Invalid email" 292 | #~ msgstr "Неверный эл.адрес" 293 | 294 | #~ msgid "Email required" 295 | #~ msgstr "Необходимо указать эл.адрес" 296 | 297 | #~ msgid "Adil Khashtamov" 298 | #~ msgstr "Адиль Хаштамов" 299 | 300 | #~ msgid "" 301 | #~ "\n" 302 | #~ "Hi. My name is Adil. I am passionate about building software. This blog " 303 | #~ "is a notebook of my thoughts and ideas regarding software engineering and " 304 | #~ "life around it. Currently I am interested in engineering of modern web " 305 | #~ "apps, machine learning and data analysis.\n" 306 | #~ msgstr "" 307 | #~ "\n" 308 | #~ "Привет! Меня зовут Адиль. Всю свою сознательную жизнь я занимаюсь " 309 | #~ "разработкой программного обеспечения. Этот блог моя записная книжка, где " 310 | #~ "я стараюсь почаще делать заметки на тему программирования, разработки и " 311 | #~ "проектирования ПО. Сейчас особенно заинтересован в современных веб " 312 | #~ "приложениях, машинном обучении и анализе данных.\n" 313 | 314 | #~ msgid "Telegram" 315 | #~ msgstr "Telegram" 316 | 317 | #~ msgid "Most popular" 318 | #~ msgstr "Самые популярные" 319 | 320 | #~ msgid "Telegram channel" 321 | #~ msgstr "Telegram канал" 322 | 323 | #~ msgid "" 324 | #~ "Recently I opened my own Telegram channel related to software\n" 325 | #~ " development called " 326 | #~ "DevBrain where I share my thoughts and\n" 327 | #~ " external resources (articles, " 328 | #~ "videos, presentations, book recommendations)\n" 329 | #~ " regarding software " 330 | #~ "craftsmanship." 331 | #~ msgstr "" 332 | #~ "Не так давно я открыл канал в Telegram на тему разработки программного " 333 | #~ "обеспечения, называется он DevBrain. На канале я делюсь " 334 | #~ "своими мыслями , а также ресурсами (статьями, видео, презентациями, " 335 | #~ "книжными рекомендациями и т.д.) о кодинге, методологиях разработки и " 336 | #~ "многом другом с чем нам, разработчикам, приходится сталкиваться каждый " 337 | #~ "день в работе." 338 | 339 | #~ msgid "" 340 | #~ "There are more than 2000 members already, so please join us —\n" 341 | #~ " DevBrain" 343 | #~ msgstr "" 344 | #~ "На канале уже более 3000 участников, поэтому присоединяйтесь и Вы — DevBrain" 347 | 348 | #~ msgid "" 349 | #~ "If you like my articles, please subscribe to stay up to date with new " 350 | #~ "material" 351 | #~ msgstr "" 352 | #~ "Если вам нравится материал на сайте — подпишитесь, чтобы не пропустить " 353 | #~ "обновления" 354 | 355 | #~ msgid "Put your email here" 356 | #~ msgstr "Введите электронный адрес" 357 | 358 | #~ msgid "Thank you! You have been successfuly subscribed." 359 | #~ msgstr "Спасибо! Вы успешно подписались." 360 | 361 | #~ msgid "Powered by Django 1.11 & Python 3.5" 362 | #~ msgstr "Работает на Django 1.11 & Python 3.5" 363 | 364 | #~ msgid "In English" 365 | #~ msgstr "На английской" 366 | 367 | #~ msgid "In Russian" 368 | #~ msgstr "На русском" 369 | -------------------------------------------------------------------------------- /logs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/logs/.keep -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notion.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /notion/.env-template: -------------------------------------------------------------------------------- 1 | DEBUG=True 2 | SECRET_KEY='very-secret-key' 3 | ALLOWED_HOSTS=127.0.0.1 4 | DATABASE_URL=psql://notion:password@127.0.0.1:5432/notion 5 | -------------------------------------------------------------------------------- /notion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/notion/__init__.py -------------------------------------------------------------------------------- /notion/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django.utils.translation import gettext_lazy as _ 4 | import environ 5 | 6 | env = environ.Env(DEBUG=(bool, False)) 7 | environ.Env.read_env() 8 | root = environ.Path(__file__) - 2 9 | 10 | BASE_DIR = str(root) 11 | 12 | SECRET_KEY = env.str('SECRET_KEY', 'my-santa-claus') 13 | 14 | DEBUG = env.bool('DEBUG', True) 15 | 16 | ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['*']) 17 | 18 | 19 | INSTALLED_APPS = [ 20 | 'django.contrib.admin', 21 | 'django.contrib.auth', 22 | 'django.contrib.contenttypes', 23 | 'django.contrib.sessions', 24 | 'django.contrib.messages', 25 | 'django.contrib.staticfiles', 26 | 'django.contrib.sites', 27 | 'django.contrib.redirects', 28 | 'django.contrib.sitemaps', 29 | 30 | # project apps 31 | 'apps.blog.apps.BlogConfig', 32 | 'apps.notes.apps.NotesConfig', 33 | 34 | # 3rd party apps 35 | 'redactor', 36 | 'bootstrap_pagination', 37 | 'django_assets', 38 | ] 39 | MIDDLEWARE = [ 40 | 'django.middleware.security.SecurityMiddleware', 41 | 'django.contrib.sessions.middleware.SessionMiddleware', 42 | 'django.middleware.locale.LocaleMiddleware', 43 | 'django.middleware.common.CommonMiddleware', 44 | 'django.middleware.csrf.CsrfViewMiddleware', 45 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 46 | 'django.contrib.messages.middleware.MessageMiddleware', 47 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 48 | 'django.contrib.redirects.middleware.RedirectFallbackMiddleware', 49 | 50 | 'htmlmin.middleware.HtmlMinifyMiddleware', 51 | 'htmlmin.middleware.MarkRequestMiddleware', 52 | ] 53 | 54 | HTML_MINIFY = True 55 | 56 | ROOT_URLCONF = 'notion.urls' 57 | 58 | TEMPLATES = [ 59 | { 60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 61 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 62 | 'APP_DIRS': True, 63 | 'OPTIONS': { 64 | 'context_processors': [ 65 | 'django.template.context_processors.debug', 66 | 'django.template.context_processors.request', 67 | 'django.contrib.auth.context_processors.auth', 68 | 'django.contrib.messages.context_processors.messages', 69 | 'apps.blog.context_processor.generic', 70 | ], 71 | }, 72 | }, 73 | ] 74 | 75 | WSGI_APPLICATION = 'notion.wsgi.application' 76 | 77 | DATABASES = { 78 | 'default': env.db(), 79 | } 80 | 81 | AUTH_PASSWORD_VALIDATORS = [ 82 | { 83 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 84 | }, 85 | { 86 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 87 | }, 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 93 | }, 94 | ] 95 | 96 | LANGUAGE_CODE = 'ru' 97 | 98 | TIME_ZONE = 'UTC' 99 | 100 | USE_I18N = True 101 | 102 | USE_L10N = True 103 | 104 | USE_TZ = True 105 | 106 | STATIC_URL = '/static/' 107 | 108 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') 109 | 110 | STATICFILES_DIRS = [ 111 | os.path.join(BASE_DIR, 'staticfiles') 112 | ] 113 | 114 | STATICFILES_FINDERS = ( 115 | "django.contrib.staticfiles.finders.FileSystemFinder", 116 | "django.contrib.staticfiles.finders.AppDirectoriesFinder", 117 | "django_assets.finders.AssetsFinder" 118 | ) 119 | 120 | LANGUAGES = ( 121 | ('ru', _('Russian')), 122 | ('en', _('English')), 123 | ) 124 | 125 | LOCALE_PATHS = ( 126 | os.path.join(BASE_DIR, 'locale'), 127 | ) 128 | 129 | MAX_LOG_FILE_SIZE = 1024 * 1024 * 50 # 50 megabytes 130 | 131 | LOGGING = { 132 | 'version': 1, 133 | 'disable_existing_loggers': True, 134 | 'filters': { 135 | 'require_debug_false': { 136 | '()': 'django.utils.log.RequireDebugFalse' 137 | } 138 | }, 139 | 'formatters': { 140 | 'verbose': { 141 | 'format': '[%(asctime)s]: %(levelname)s: %(message)s' 142 | }, 143 | }, 144 | 'handlers': { 145 | 'mail_admins': { 146 | 'level': 'ERROR', 147 | 'filters': ['require_debug_false'], 148 | 'class': 'django.utils.log.AdminEmailHandler' 149 | }, 150 | 'console': { 151 | 'level': 'DEBUG', 152 | 'formatter': 'verbose', 153 | 'class': 'logging.StreamHandler' 154 | }, 155 | 'file_handler': { 156 | 'filename': os.path.join(BASE_DIR, 'logs', 'notion.log'), 157 | 'class': 'logging.handlers.RotatingFileHandler', 158 | 'encoding': 'utf-8', 159 | 'formatter': 'verbose', 160 | 'maxBytes': MAX_LOG_FILE_SIZE, 161 | 'backupCount': 20, 162 | }, 163 | 'null': { 164 | 'class': 'logging.NullHandler', 165 | } 166 | }, 167 | 'loggers': { 168 | 'django': { 169 | 'handlers': ['file_handler'], 170 | 'level': 'ERROR', 171 | 'propagate': True, 172 | }, 173 | } 174 | } 175 | 176 | MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') 177 | 178 | REDACTOR_UPLOAD = 'redactor/' 179 | REDACTOR_OPTIONS = {'lang': 'ru', 'removeComments': False} 180 | 181 | MEDIA_URL = '/uploads/' 182 | 183 | SECURE_REFERRER_POLICY = 'no-referrer-when-downgrade' 184 | -------------------------------------------------------------------------------- /notion/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include 2 | from django.contrib import admin 3 | from django.urls import path 4 | from django.conf.urls.i18n import i18n_patterns 5 | from django.contrib.sitemaps.views import sitemap 6 | from django.contrib.sitemaps import GenericSitemap 7 | from django.conf.urls.static import static 8 | from django.conf import settings 9 | 10 | from apps.blog.models import Post, Page 11 | from apps.blog.views import SubscriptionView 12 | 13 | blog_dict = { 14 | 'queryset': Post.objects.filter(status=Post.PUBLISHED), 15 | 'date_field': 'created', 16 | } 17 | 18 | page_dict = { 19 | 'queryset': Page.objects.filter(visible=True), 20 | 'date_field': 'created' 21 | } 22 | 23 | urlpatterns = [ 24 | path( 25 | 'sitemap.xml', 26 | sitemap, { 27 | 'sitemaps': { 28 | 'blog': GenericSitemap(blog_dict, priority=1, protocol='https'), 29 | 'page': GenericSitemap(page_dict, priority=0.5, protocol='https') 30 | } 31 | }, name='django.contrib.sitemaps.views.sitemap' 32 | ), 33 | path('redactor/', include('redactor.urls')), 34 | path('cpadmin/', admin.site.urls), 35 | path('subscribe/', SubscriptionView.as_view(), name='subscription'), 36 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 37 | 38 | urlpatterns += i18n_patterns( 39 | path('notes/', include('apps.notes.urls', namespace='notes')), 40 | path('', include('apps.blog.urls', namespace='blog')), 41 | ) 42 | -------------------------------------------------------------------------------- /notion/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for notion project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notion.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.18 2 | psycopg2==2.9.5 3 | django-environ==0.11.2 4 | https://github.com/adilkhash/django-redactor3/archive/master.zip 5 | redis==4.4.2 6 | https://github.com/adilkhash/django-bootstrap-pagination/archive/master.zip 7 | requests==2.28.2 8 | Pillow==9.4.0 9 | django-assets==2.0 10 | cssmin==0.2.0 11 | django-htmlmin==0.11.0 12 | -------------------------------------------------------------------------------- /staticfiles/courses/images/adil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/adil.jpg -------------------------------------------------------------------------------- /staticfiles/courses/images/bgimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/bgimage.jpg -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_aws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_aws.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_bootstrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_bootstrap.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_circle_ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_circle_ci.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_django.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_django.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_do.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_do.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_docker.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_es6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_es6.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_falcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_falcon.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_jest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_jest.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_jwt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_jwt.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_postman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_postman.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_python.png -------------------------------------------------------------------------------- /staticfiles/courses/images/logo_vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/logo_vue.png -------------------------------------------------------------------------------- /staticfiles/courses/images/luigi-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/courses/images/luigi-logo.png -------------------------------------------------------------------------------- /staticfiles/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | .btn-default, 7 | .btn-primary, 8 | .btn-success, 9 | .btn-info, 10 | .btn-warning, 11 | .btn-danger { 12 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 13 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 14 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | } 16 | .btn-default:active, 17 | .btn-primary:active, 18 | .btn-success:active, 19 | .btn-info:active, 20 | .btn-warning:active, 21 | .btn-danger:active, 22 | .btn-default.active, 23 | .btn-primary.active, 24 | .btn-success.active, 25 | .btn-info.active, 26 | .btn-warning.active, 27 | .btn-danger.active { 28 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 29 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | } 31 | .btn-default.disabled, 32 | .btn-primary.disabled, 33 | .btn-success.disabled, 34 | .btn-info.disabled, 35 | .btn-warning.disabled, 36 | .btn-danger.disabled, 37 | .btn-default[disabled], 38 | .btn-primary[disabled], 39 | .btn-success[disabled], 40 | .btn-info[disabled], 41 | .btn-warning[disabled], 42 | .btn-danger[disabled], 43 | fieldset[disabled] .btn-default, 44 | fieldset[disabled] .btn-primary, 45 | fieldset[disabled] .btn-success, 46 | fieldset[disabled] .btn-info, 47 | fieldset[disabled] .btn-warning, 48 | fieldset[disabled] .btn-danger { 49 | -webkit-box-shadow: none; 50 | box-shadow: none; 51 | } 52 | .btn-default .badge, 53 | .btn-primary .badge, 54 | .btn-success .badge, 55 | .btn-info .badge, 56 | .btn-warning .badge, 57 | .btn-danger .badge { 58 | text-shadow: none; 59 | } 60 | .btn:active, 61 | .btn.active { 62 | background-image: none; 63 | } 64 | .btn-default { 65 | text-shadow: 0 1px 0 #fff; 66 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 67 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 68 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 69 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 70 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 71 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 72 | background-repeat: repeat-x; 73 | border-color: #dbdbdb; 74 | border-color: #ccc; 75 | } 76 | .btn-default:hover, 77 | .btn-default:focus { 78 | background-color: #e0e0e0; 79 | background-position: 0 -15px; 80 | } 81 | .btn-default:active, 82 | .btn-default.active { 83 | background-color: #e0e0e0; 84 | border-color: #dbdbdb; 85 | } 86 | .btn-default.disabled, 87 | .btn-default[disabled], 88 | fieldset[disabled] .btn-default, 89 | .btn-default.disabled:hover, 90 | .btn-default[disabled]:hover, 91 | fieldset[disabled] .btn-default:hover, 92 | .btn-default.disabled:focus, 93 | .btn-default[disabled]:focus, 94 | fieldset[disabled] .btn-default:focus, 95 | .btn-default.disabled.focus, 96 | .btn-default[disabled].focus, 97 | fieldset[disabled] .btn-default.focus, 98 | .btn-default.disabled:active, 99 | .btn-default[disabled]:active, 100 | fieldset[disabled] .btn-default:active, 101 | .btn-default.disabled.active, 102 | .btn-default[disabled].active, 103 | fieldset[disabled] .btn-default.active { 104 | background-color: #e0e0e0; 105 | background-image: none; 106 | } 107 | .btn-primary { 108 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); 109 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); 110 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); 111 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); 112 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); 113 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 114 | background-repeat: repeat-x; 115 | border-color: #245580; 116 | } 117 | .btn-primary:hover, 118 | .btn-primary:focus { 119 | background-color: #265a88; 120 | background-position: 0 -15px; 121 | } 122 | .btn-primary:active, 123 | .btn-primary.active { 124 | background-color: #265a88; 125 | border-color: #245580; 126 | } 127 | .btn-primary.disabled, 128 | .btn-primary[disabled], 129 | fieldset[disabled] .btn-primary, 130 | .btn-primary.disabled:hover, 131 | .btn-primary[disabled]:hover, 132 | fieldset[disabled] .btn-primary:hover, 133 | .btn-primary.disabled:focus, 134 | .btn-primary[disabled]:focus, 135 | fieldset[disabled] .btn-primary:focus, 136 | .btn-primary.disabled.focus, 137 | .btn-primary[disabled].focus, 138 | fieldset[disabled] .btn-primary.focus, 139 | .btn-primary.disabled:active, 140 | .btn-primary[disabled]:active, 141 | fieldset[disabled] .btn-primary:active, 142 | .btn-primary.disabled.active, 143 | .btn-primary[disabled].active, 144 | fieldset[disabled] .btn-primary.active { 145 | background-color: #265a88; 146 | background-image: none; 147 | } 148 | .btn-success { 149 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 150 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 151 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 152 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 153 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 154 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 155 | background-repeat: repeat-x; 156 | border-color: #3e8f3e; 157 | } 158 | .btn-success:hover, 159 | .btn-success:focus { 160 | background-color: #419641; 161 | background-position: 0 -15px; 162 | } 163 | .btn-success:active, 164 | .btn-success.active { 165 | background-color: #419641; 166 | border-color: #3e8f3e; 167 | } 168 | .btn-success.disabled, 169 | .btn-success[disabled], 170 | fieldset[disabled] .btn-success, 171 | .btn-success.disabled:hover, 172 | .btn-success[disabled]:hover, 173 | fieldset[disabled] .btn-success:hover, 174 | .btn-success.disabled:focus, 175 | .btn-success[disabled]:focus, 176 | fieldset[disabled] .btn-success:focus, 177 | .btn-success.disabled.focus, 178 | .btn-success[disabled].focus, 179 | fieldset[disabled] .btn-success.focus, 180 | .btn-success.disabled:active, 181 | .btn-success[disabled]:active, 182 | fieldset[disabled] .btn-success:active, 183 | .btn-success.disabled.active, 184 | .btn-success[disabled].active, 185 | fieldset[disabled] .btn-success.active { 186 | background-color: #419641; 187 | background-image: none; 188 | } 189 | .btn-info { 190 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 191 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 192 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 193 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 194 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 195 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 196 | background-repeat: repeat-x; 197 | border-color: #28a4c9; 198 | } 199 | .btn-info:hover, 200 | .btn-info:focus { 201 | background-color: #2aabd2; 202 | background-position: 0 -15px; 203 | } 204 | .btn-info:active, 205 | .btn-info.active { 206 | background-color: #2aabd2; 207 | border-color: #28a4c9; 208 | } 209 | .btn-info.disabled, 210 | .btn-info[disabled], 211 | fieldset[disabled] .btn-info, 212 | .btn-info.disabled:hover, 213 | .btn-info[disabled]:hover, 214 | fieldset[disabled] .btn-info:hover, 215 | .btn-info.disabled:focus, 216 | .btn-info[disabled]:focus, 217 | fieldset[disabled] .btn-info:focus, 218 | .btn-info.disabled.focus, 219 | .btn-info[disabled].focus, 220 | fieldset[disabled] .btn-info.focus, 221 | .btn-info.disabled:active, 222 | .btn-info[disabled]:active, 223 | fieldset[disabled] .btn-info:active, 224 | .btn-info.disabled.active, 225 | .btn-info[disabled].active, 226 | fieldset[disabled] .btn-info.active { 227 | background-color: #2aabd2; 228 | background-image: none; 229 | } 230 | .btn-warning { 231 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 232 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 233 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 234 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 235 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 236 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 237 | background-repeat: repeat-x; 238 | border-color: #e38d13; 239 | } 240 | .btn-warning:hover, 241 | .btn-warning:focus { 242 | background-color: #eb9316; 243 | background-position: 0 -15px; 244 | } 245 | .btn-warning:active, 246 | .btn-warning.active { 247 | background-color: #eb9316; 248 | border-color: #e38d13; 249 | } 250 | .btn-warning.disabled, 251 | .btn-warning[disabled], 252 | fieldset[disabled] .btn-warning, 253 | .btn-warning.disabled:hover, 254 | .btn-warning[disabled]:hover, 255 | fieldset[disabled] .btn-warning:hover, 256 | .btn-warning.disabled:focus, 257 | .btn-warning[disabled]:focus, 258 | fieldset[disabled] .btn-warning:focus, 259 | .btn-warning.disabled.focus, 260 | .btn-warning[disabled].focus, 261 | fieldset[disabled] .btn-warning.focus, 262 | .btn-warning.disabled:active, 263 | .btn-warning[disabled]:active, 264 | fieldset[disabled] .btn-warning:active, 265 | .btn-warning.disabled.active, 266 | .btn-warning[disabled].active, 267 | fieldset[disabled] .btn-warning.active { 268 | background-color: #eb9316; 269 | background-image: none; 270 | } 271 | .btn-danger { 272 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 273 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 274 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 275 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 276 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 277 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 278 | background-repeat: repeat-x; 279 | border-color: #b92c28; 280 | } 281 | .btn-danger:hover, 282 | .btn-danger:focus { 283 | background-color: #c12e2a; 284 | background-position: 0 -15px; 285 | } 286 | .btn-danger:active, 287 | .btn-danger.active { 288 | background-color: #c12e2a; 289 | border-color: #b92c28; 290 | } 291 | .btn-danger.disabled, 292 | .btn-danger[disabled], 293 | fieldset[disabled] .btn-danger, 294 | .btn-danger.disabled:hover, 295 | .btn-danger[disabled]:hover, 296 | fieldset[disabled] .btn-danger:hover, 297 | .btn-danger.disabled:focus, 298 | .btn-danger[disabled]:focus, 299 | fieldset[disabled] .btn-danger:focus, 300 | .btn-danger.disabled.focus, 301 | .btn-danger[disabled].focus, 302 | fieldset[disabled] .btn-danger.focus, 303 | .btn-danger.disabled:active, 304 | .btn-danger[disabled]:active, 305 | fieldset[disabled] .btn-danger:active, 306 | .btn-danger.disabled.active, 307 | .btn-danger[disabled].active, 308 | fieldset[disabled] .btn-danger.active { 309 | background-color: #c12e2a; 310 | background-image: none; 311 | } 312 | .thumbnail, 313 | .img-thumbnail { 314 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 315 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 316 | } 317 | .dropdown-menu > li > a:hover, 318 | .dropdown-menu > li > a:focus { 319 | background-color: #e8e8e8; 320 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 321 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 322 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 323 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 324 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 325 | background-repeat: repeat-x; 326 | } 327 | .dropdown-menu > .active > a, 328 | .dropdown-menu > .active > a:hover, 329 | .dropdown-menu > .active > a:focus { 330 | background-color: #2e6da4; 331 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 332 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 333 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 334 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 336 | background-repeat: repeat-x; 337 | } 338 | .navbar-default { 339 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 340 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 342 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 344 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 345 | background-repeat: repeat-x; 346 | border-radius: 4px; 347 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 348 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 349 | } 350 | .navbar-default .navbar-nav > .open > a, 351 | .navbar-default .navbar-nav > .active > a { 352 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 353 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 355 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 357 | background-repeat: repeat-x; 358 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 359 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 360 | } 361 | .navbar-brand, 362 | .navbar-nav > li > a { 363 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 364 | } 365 | .navbar-inverse { 366 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 367 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 368 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 369 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 370 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 371 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 372 | background-repeat: repeat-x; 373 | border-radius: 4px; 374 | } 375 | .navbar-inverse .navbar-nav > .open > a, 376 | .navbar-inverse .navbar-nav > .active > a { 377 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 378 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 379 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 380 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 382 | background-repeat: repeat-x; 383 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 384 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 385 | } 386 | .navbar-inverse .navbar-brand, 387 | .navbar-inverse .navbar-nav > li > a { 388 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 389 | } 390 | .navbar-static-top, 391 | .navbar-fixed-top, 392 | .navbar-fixed-bottom { 393 | border-radius: 0; 394 | } 395 | @media (max-width: 767px) { 396 | .navbar .navbar-nav .open .dropdown-menu > .active > a, 397 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, 398 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { 399 | color: #fff; 400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | } 408 | .alert { 409 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 410 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 411 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 412 | } 413 | .alert-success { 414 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 415 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 416 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 417 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 418 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 419 | background-repeat: repeat-x; 420 | border-color: #b2dba1; 421 | } 422 | .alert-info { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 428 | background-repeat: repeat-x; 429 | border-color: #9acfea; 430 | } 431 | .alert-warning { 432 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 433 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 435 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #f5e79e; 439 | } 440 | .alert-danger { 441 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 442 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 443 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 444 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 445 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 446 | background-repeat: repeat-x; 447 | border-color: #dca7a7; 448 | } 449 | .progress { 450 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 451 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 453 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 455 | background-repeat: repeat-x; 456 | } 457 | .progress-bar { 458 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); 459 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); 460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); 461 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); 462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); 463 | background-repeat: repeat-x; 464 | } 465 | .progress-bar-success { 466 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 467 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 469 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 471 | background-repeat: repeat-x; 472 | } 473 | .progress-bar-info { 474 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 475 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 476 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 477 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 478 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 479 | background-repeat: repeat-x; 480 | } 481 | .progress-bar-warning { 482 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 483 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 484 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 485 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 486 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 487 | background-repeat: repeat-x; 488 | } 489 | .progress-bar-danger { 490 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 491 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 492 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 493 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 494 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 495 | background-repeat: repeat-x; 496 | } 497 | .progress-bar-striped { 498 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 499 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 500 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 501 | } 502 | .list-group { 503 | border-radius: 4px; 504 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 505 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 506 | } 507 | .list-group-item.active, 508 | .list-group-item.active:hover, 509 | .list-group-item.active:focus { 510 | text-shadow: 0 -1px 0 #286090; 511 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); 512 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); 513 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); 514 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); 515 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); 516 | background-repeat: repeat-x; 517 | border-color: #2b669a; 518 | } 519 | .list-group-item.active .badge, 520 | .list-group-item.active:hover .badge, 521 | .list-group-item.active:focus .badge { 522 | text-shadow: none; 523 | } 524 | .panel { 525 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 526 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 527 | } 528 | .panel-default > .panel-heading { 529 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 530 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 531 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 532 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 533 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 534 | background-repeat: repeat-x; 535 | } 536 | .panel-primary > .panel-heading { 537 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 538 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 539 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 540 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 541 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 542 | background-repeat: repeat-x; 543 | } 544 | .panel-success > .panel-heading { 545 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 546 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 547 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 548 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 549 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 550 | background-repeat: repeat-x; 551 | } 552 | .panel-info > .panel-heading { 553 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 554 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 555 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 556 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 557 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 558 | background-repeat: repeat-x; 559 | } 560 | .panel-warning > .panel-heading { 561 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 562 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 563 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 564 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 565 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 566 | background-repeat: repeat-x; 567 | } 568 | .panel-danger > .panel-heading { 569 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 570 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 571 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 572 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 573 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 574 | background-repeat: repeat-x; 575 | } 576 | .well { 577 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 578 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 579 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 580 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 581 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 582 | background-repeat: repeat-x; 583 | border-color: #dcdcdc; 584 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 585 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 586 | } 587 | /*# sourceMappingURL=bootstrap-theme.css.map */ 588 | -------------------------------------------------------------------------------- /staticfiles/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /staticfiles/css/bootstrap-theme.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} -------------------------------------------------------------------------------- /staticfiles/css/monokai-sublime.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:0.5em;background:#23241f}.hljs,.hljs-tag,.hljs-subst{color:#f8f8f2}.hljs-strong,.hljs-emphasis{color:#a8a8a2}.hljs-bullet,.hljs-quote,.hljs-number,.hljs-regexp,.hljs-literal,.hljs-link{color:#ae81ff}.hljs-code,.hljs-title,.hljs-section,.hljs-selector-class{color:#a6e22e}.hljs-strong{font-weight:bold}.hljs-emphasis{font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-name,.hljs-attr{color:#f92672}.hljs-symbol,.hljs-attribute{color:#66d9ef}.hljs-params,.hljs-class .hljs-title{color:#f8f8f2}.hljs-string,.hljs-type,.hljs-built_in,.hljs-builtin-name,.hljs-selector-id,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-addition,.hljs-variable,.hljs-template-variable{color:#e6db74}.hljs-comment,.hljs-deletion,.hljs-meta{color:#75715e} -------------------------------------------------------------------------------- /staticfiles/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Change the default font family in all browsers (opinionated). 5 | * 2. Correct the line height in all browsers. 6 | * 3. Prevent adjustments of font size after orientation changes in 7 | * IE on Windows Phone and in iOS. 8 | */ 9 | 10 | /* Document 11 | ========================================================================== */ 12 | 13 | html { 14 | font-family: sans-serif; /* 1 */ 15 | line-height: 1.15; /* 2 */ 16 | -ms-text-size-adjust: 100%; /* 3 */ 17 | -webkit-text-size-adjust: 100%; /* 3 */ 18 | } 19 | 20 | /* Sections 21 | ========================================================================== */ 22 | 23 | /** 24 | * Remove the margin in all browsers (opinionated). 25 | */ 26 | 27 | body { 28 | margin: 0; 29 | } 30 | 31 | /** 32 | * Add the correct display in IE 9-. 33 | */ 34 | 35 | article, 36 | aside, 37 | footer, 38 | header, 39 | nav, 40 | section { 41 | display: block; 42 | } 43 | 44 | /** 45 | * Correct the font size and margin on `h1` elements within `section` and 46 | * `article` contexts in Chrome, Firefox, and Safari. 47 | */ 48 | 49 | h1 { 50 | font-size: 2em; 51 | margin: 0.67em 0; 52 | } 53 | 54 | /* Grouping content 55 | ========================================================================== */ 56 | 57 | /** 58 | * Add the correct display in IE 9-. 59 | * 1. Add the correct display in IE. 60 | */ 61 | 62 | figcaption, 63 | figure, 64 | main { /* 1 */ 65 | display: block; 66 | } 67 | 68 | /** 69 | * Add the correct margin in IE 8. 70 | */ 71 | 72 | figure { 73 | margin: 1em 40px; 74 | } 75 | 76 | /** 77 | * 1. Add the correct box sizing in Firefox. 78 | * 2. Show the overflow in Edge and IE. 79 | */ 80 | 81 | hr { 82 | box-sizing: content-box; /* 1 */ 83 | height: 0; /* 1 */ 84 | overflow: visible; /* 2 */ 85 | } 86 | 87 | /** 88 | * 1. Correct the inheritance and scaling of font size in all browsers. 89 | * 2. Correct the odd `em` font sizing in all browsers. 90 | */ 91 | 92 | pre { 93 | font-family: monospace, monospace; /* 1 */ 94 | font-size: 1em; /* 2 */ 95 | } 96 | 97 | /* Text-level semantics 98 | ========================================================================== */ 99 | 100 | /** 101 | * 1. Remove the gray background on active links in IE 10. 102 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 103 | */ 104 | 105 | a { 106 | background-color: transparent; /* 1 */ 107 | -webkit-text-decoration-skip: objects; /* 2 */ 108 | } 109 | 110 | /** 111 | * Remove the outline on focused links when they are also active or hovered 112 | * in all browsers (opinionated). 113 | */ 114 | 115 | a:active, 116 | a:hover { 117 | outline-width: 0; 118 | } 119 | 120 | /** 121 | * 1. Remove the bottom border in Firefox 39-. 122 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 123 | */ 124 | 125 | abbr[title] { 126 | border-bottom: none; /* 1 */ 127 | text-decoration: underline; /* 2 */ 128 | text-decoration: underline dotted; /* 2 */ 129 | } 130 | 131 | /** 132 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 133 | */ 134 | 135 | b, 136 | strong { 137 | font-weight: inherit; 138 | } 139 | 140 | /** 141 | * Add the correct font weight in Chrome, Edge, and Safari. 142 | */ 143 | 144 | b, 145 | strong { 146 | font-weight: bolder; 147 | } 148 | 149 | /** 150 | * 1. Correct the inheritance and scaling of font size in all browsers. 151 | * 2. Correct the odd `em` font sizing in all browsers. 152 | */ 153 | 154 | code, 155 | kbd, 156 | samp { 157 | font-family: monospace, monospace; /* 1 */ 158 | font-size: 1em; /* 2 */ 159 | } 160 | 161 | /** 162 | * Add the correct font style in Android 4.3-. 163 | */ 164 | 165 | dfn { 166 | font-style: italic; 167 | } 168 | 169 | /** 170 | * Add the correct background and color in IE 9-. 171 | */ 172 | 173 | mark { 174 | background-color: #ff0; 175 | color: #000; 176 | } 177 | 178 | /** 179 | * Add the correct font size in all browsers. 180 | */ 181 | 182 | small { 183 | font-size: 80%; 184 | } 185 | 186 | /** 187 | * Prevent `sub` and `sup` elements from affecting the line height in 188 | * all browsers. 189 | */ 190 | 191 | sub, 192 | sup { 193 | font-size: 75%; 194 | line-height: 0; 195 | position: relative; 196 | vertical-align: baseline; 197 | } 198 | 199 | sub { 200 | bottom: -0.25em; 201 | } 202 | 203 | sup { 204 | top: -0.5em; 205 | } 206 | 207 | /* Embedded content 208 | ========================================================================== */ 209 | 210 | /** 211 | * Add the correct display in IE 9-. 212 | */ 213 | 214 | audio, 215 | video { 216 | display: inline-block; 217 | } 218 | 219 | /** 220 | * Add the correct display in iOS 4-7. 221 | */ 222 | 223 | audio:not([controls]) { 224 | display: none; 225 | height: 0; 226 | } 227 | 228 | /** 229 | * Remove the border on images inside links in IE 10-. 230 | */ 231 | 232 | img { 233 | border-style: none; 234 | } 235 | 236 | /** 237 | * Hide the overflow in IE. 238 | */ 239 | 240 | svg:not(:root) { 241 | overflow: hidden; 242 | } 243 | 244 | /* Forms 245 | ========================================================================== */ 246 | 247 | /** 248 | * 1. Change the font styles in all browsers (opinionated). 249 | * 2. Remove the margin in Firefox and Safari. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | font-family: sans-serif; /* 1 */ 258 | font-size: 100%; /* 1 */ 259 | line-height: 1.15; /* 1 */ 260 | margin: 0; /* 2 */ 261 | } 262 | 263 | /** 264 | * Show the overflow in IE. 265 | * 1. Show the overflow in Edge. 266 | */ 267 | 268 | button, 269 | input { /* 1 */ 270 | overflow: visible; 271 | } 272 | 273 | /** 274 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 275 | * 1. Remove the inheritance of text transform in Firefox. 276 | */ 277 | 278 | button, 279 | select { /* 1 */ 280 | text-transform: none; 281 | } 282 | 283 | /** 284 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 285 | * controls in Android 4. 286 | * 2. Correct the inability to style clickable types in iOS and Safari. 287 | */ 288 | 289 | button, 290 | html [type="button"], /* 1 */ 291 | [type="reset"], 292 | [type="submit"] { 293 | -webkit-appearance: button; /* 2 */ 294 | } 295 | 296 | /** 297 | * Remove the inner border and padding in Firefox. 298 | */ 299 | 300 | button::-moz-focus-inner, 301 | [type="button"]::-moz-focus-inner, 302 | [type="reset"]::-moz-focus-inner, 303 | [type="submit"]::-moz-focus-inner { 304 | border-style: none; 305 | padding: 0; 306 | } 307 | 308 | /** 309 | * Restore the focus styles unset by the previous rule. 310 | */ 311 | 312 | button:-moz-focusring, 313 | [type="button"]:-moz-focusring, 314 | [type="reset"]:-moz-focusring, 315 | [type="submit"]:-moz-focusring { 316 | outline: 1px dotted ButtonText; 317 | } 318 | 319 | /** 320 | * Change the border, margin, and padding in all browsers (opinionated). 321 | */ 322 | 323 | fieldset { 324 | border: 1px solid #c0c0c0; 325 | margin: 0 2px; 326 | padding: 0.35em 0.625em 0.75em; 327 | } 328 | 329 | /** 330 | * 1. Correct the text wrapping in Edge and IE. 331 | * 2. Correct the color inheritance from `fieldset` elements in IE. 332 | * 3. Remove the padding so developers are not caught out when they zero out 333 | * `fieldset` elements in all browsers. 334 | */ 335 | 336 | legend { 337 | box-sizing: border-box; /* 1 */ 338 | color: inherit; /* 2 */ 339 | display: table; /* 1 */ 340 | max-width: 100%; /* 1 */ 341 | padding: 0; /* 3 */ 342 | white-space: normal; /* 1 */ 343 | } 344 | 345 | /** 346 | * 1. Add the correct display in IE 9-. 347 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 348 | */ 349 | 350 | progress { 351 | display: inline-block; /* 1 */ 352 | vertical-align: baseline; /* 2 */ 353 | } 354 | 355 | /** 356 | * Remove the default vertical scrollbar in IE. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; 361 | } 362 | 363 | /** 364 | * 1. Add the correct box sizing in IE 10-. 365 | * 2. Remove the padding in IE 10-. 366 | */ 367 | 368 | [type="checkbox"], 369 | [type="radio"] { 370 | box-sizing: border-box; /* 1 */ 371 | padding: 0; /* 2 */ 372 | } 373 | 374 | /** 375 | * Correct the cursor style of increment and decrement buttons in Chrome. 376 | */ 377 | 378 | [type="number"]::-webkit-inner-spin-button, 379 | [type="number"]::-webkit-outer-spin-button { 380 | height: auto; 381 | } 382 | 383 | /** 384 | * 1. Correct the odd appearance in Chrome and Safari. 385 | * 2. Correct the outline style in Safari. 386 | */ 387 | 388 | [type="search"] { 389 | -webkit-appearance: textfield; /* 1 */ 390 | outline-offset: -2px; /* 2 */ 391 | } 392 | 393 | /** 394 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 395 | */ 396 | 397 | [type="search"]::-webkit-search-cancel-button, 398 | [type="search"]::-webkit-search-decoration { 399 | -webkit-appearance: none; 400 | } 401 | 402 | /** 403 | * 1. Correct the inability to style clickable types in iOS and Safari. 404 | * 2. Change font properties to `inherit` in Safari. 405 | */ 406 | 407 | ::-webkit-file-upload-button { 408 | -webkit-appearance: button; /* 1 */ 409 | font: inherit; /* 2 */ 410 | } 411 | 412 | /* Interactive 413 | ========================================================================== */ 414 | 415 | /* 416 | * Add the correct display in IE 9-. 417 | * 1. Add the correct display in Edge, IE, and Firefox. 418 | */ 419 | 420 | details, /* 1 */ 421 | menu { 422 | display: block; 423 | } 424 | 425 | /* 426 | * Add the correct display in all browsers. 427 | */ 428 | 429 | summary { 430 | display: list-item; 431 | } 432 | 433 | /* Scripting 434 | ========================================================================== */ 435 | 436 | /** 437 | * Add the correct display in IE 9-. 438 | */ 439 | 440 | canvas { 441 | display: inline-block; 442 | } 443 | 444 | /** 445 | * Add the correct display in IE. 446 | */ 447 | 448 | template { 449 | display: none; 450 | } 451 | 452 | /* Hidden 453 | ========================================================================== */ 454 | 455 | /** 456 | * Add the correct display in IE 10-. 457 | */ 458 | 459 | [hidden] { 460 | display: none; 461 | } 462 | -------------------------------------------------------------------------------- /staticfiles/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "PT Serif", serif; 3 | background-color: #fff; 4 | color: #000; 5 | line-height: 2em; 6 | } 7 | 8 | p { 9 | font-size: 1.25em; 10 | } 11 | 12 | .blog-masthead { 13 | background-color: #000; 14 | -webkit-box-shadow: inset 0 -2px 5px rgba(0,0,0,.1); 15 | box-shadow: inset 0 -2px 5px rgba(0,0,0,.1); 16 | } 17 | 18 | /* Nav links */ 19 | .blog-nav-item { 20 | position: relative; 21 | display: inline-block; 22 | padding-top: 15px; 23 | padding-right: 30px; 24 | padding-bottom: 15px; 25 | font-weight: 500; 26 | color: #cdddeb; 27 | font-size: 1.3em; 28 | } 29 | .blog-nav-item:hover, 30 | .blog-nav-item:focus { 31 | color: #fff; 32 | text-decoration: none; 33 | } 34 | 35 | /* Active state gets a caret at the bottom */ 36 | .blog-nav .active { 37 | color: #fff; 38 | } 39 | .blog-nav .active:after { 40 | position: absolute; 41 | bottom: 0; 42 | left: 50%; 43 | width: 0; 44 | height: 0; 45 | margin-left: -5px; 46 | vertical-align: middle; 47 | content: " "; 48 | border-right: 5px solid transparent; 49 | border-bottom: 5px solid; 50 | border-left: 5px solid transparent; 51 | } 52 | 53 | div.article-meta { 54 | margin-bottom: 10px; 55 | } 56 | 57 | .star-ratings-rating-stars-container { 58 | vertical-align: bottom; 59 | } 60 | 61 | .article-meta span { 62 | color: #9b9b9b; 63 | } 64 | 65 | div.hello-msg { 66 | background-color: #f6f6f6; 67 | padding: 15px; 68 | margin-top: -29px; 69 | } 70 | 71 | img.arrow-msg { 72 | position: relative; 73 | top: 100px; 74 | left: -14px; 75 | } 76 | 77 | 78 | div.social-btns a{ 79 | display: inline-block; 80 | margin-right: 5px; 81 | text-decoration: none; 82 | color:#000; 83 | } 84 | 85 | article.post-list { 86 | margin-bottom: 90px; 87 | } 88 | div.articles { 89 | margin-top: 40px; 90 | } 91 | 92 | @media (min-width: 1200px) { 93 | .container { 94 | width: 970px; 95 | } 96 | } 97 | 98 | div.subscription { 99 | background-color: #f5f5f1; 100 | border: 1px #b9baba solid; 101 | border-radius: 2px; 102 | padding: 10px; 103 | } 104 | 105 | div.tchannel-info { 106 | background-color: #f6f6f6; 107 | padding: 15px; 108 | padding-left: 25px; 109 | padding-right: 25px; 110 | } 111 | 112 | 113 | button.search-btn { 114 | border: none; 115 | background: transparent; 116 | position: absolute; 117 | margin-left: 150px; 118 | padding-top: 4px; 119 | /*top: 23%;*/ 120 | /*right: 30px;*/ 121 | /*padding: 0;*/ 122 | height: 16px; 123 | width: 16px; 124 | font-size: 16px; 125 | outline: none; 126 | } 127 | 128 | ul.menu__navigation { 129 | padding: 0; 130 | } 131 | 132 | ul.menu__navigation li { 133 | list-style: none; 134 | font-size: 1.05em; 135 | } 136 | 137 | ul.menu__navigation li a { 138 | color: #f5f5f1; 139 | } 140 | @media (min-width: 768px) { 141 | ul.menu__navigation li { 142 | display: inline-block; 143 | padding-right: 10px; 144 | } 145 | } 146 | 147 | .navbar-toggle .icon-bar { 148 | background-color: #fff; 149 | } 150 | 151 | .sidebar-widget { 152 | border: 1px solid #ebebeb; 153 | padding: 25px; 154 | margin-bottom: 20px; 155 | } 156 | 157 | h4.sidebar-title { 158 | font-weight: bold; 159 | font-size: 1.5em; 160 | border-bottom: 1px solid #ebebeb; 161 | margin-bottom: 21px; 162 | padding-bottom: 7px; 163 | } 164 | 165 | @media (min-width: 1200px) { 166 | .container-wrap { 167 | width: 1200px; 168 | } 169 | } 170 | 171 | .tlgr-info { 172 | padding: 10px; 173 | border: 1px #b9baba solid; 174 | background-color: #f9ffc6; 175 | } 176 | 177 | a.job { 178 | color: #499402; 179 | } 180 | 181 | span.job-company { 182 | font-size: 1.1em; 183 | font-weight: bold; 184 | } 185 | 186 | hr { 187 | display: block; 188 | unicode-bidi: isolate; 189 | margin-block-start: 0.5em; 190 | margin-block-end: 0.5em; 191 | margin-inline-start: auto; 192 | margin-inline-end: auto; 193 | overflow: hidden; 194 | } 195 | 196 | figure img { 197 | /*width:100%;*/ 198 | } 199 | -------------------------------------------------------------------------------- /staticfiles/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /staticfiles/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /staticfiles/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /staticfiles/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /staticfiles/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /staticfiles/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /staticfiles/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /staticfiles/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /staticfiles/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /staticfiles/images/DE_770x193.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/DE_770x193.jpg -------------------------------------------------------------------------------- /staticfiles/images/Python900x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/Python900x120.png -------------------------------------------------------------------------------- /staticfiles/images/arrow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/arrow.jpg -------------------------------------------------------------------------------- /staticfiles/images/author.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/author.jpg -------------------------------------------------------------------------------- /staticfiles/images/devbrain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/devbrain.jpg -------------------------------------------------------------------------------- /staticfiles/images/devbrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/devbrain.png -------------------------------------------------------------------------------- /staticfiles/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/icon.png -------------------------------------------------------------------------------- /staticfiles/images/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/like.png -------------------------------------------------------------------------------- /staticfiles/images/machine-learning-course.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/machine-learning-course.jpg -------------------------------------------------------------------------------- /staticfiles/images/ml-agenda.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/ml-agenda.jpg -------------------------------------------------------------------------------- /staticfiles/images/ml-poster2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/ml-poster2.jpg -------------------------------------------------------------------------------- /staticfiles/images/pydata-analysis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/pydata-analysis.jpg -------------------------------------------------------------------------------- /staticfiles/images/ru-flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/ru-flag.png -------------------------------------------------------------------------------- /staticfiles/images/social.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/social.jpg -------------------------------------------------------------------------------- /staticfiles/images/telegram-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/telegram-logo.png -------------------------------------------------------------------------------- /staticfiles/images/us-flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adilkhash/notion/5bb5af9464ce580b72b4151527876017ecca2e38/staticfiles/images/us-flag.png -------------------------------------------------------------------------------- /staticfiles/js/app.js: -------------------------------------------------------------------------------- 1 | var app = new Vue({ 2 | el: '#app', 3 | data: { 4 | email: '', 5 | subscribed: false, 6 | invalidSubscription: false, 7 | validationError: '' 8 | }, 9 | methods: { 10 | subscribeBtn: function (e) { 11 | this.invalidSubscription = false; 12 | this.subscribed = false; 13 | this.validationError = ''; 14 | 15 | axios.post('/subscribe/', Qs.stringify({'email': this.email})) 16 | .then(function (response) { 17 | if (response.data.status == 'ok') { 18 | app.subscribed = true; 19 | app.email = ''; 20 | } else { 21 | app.invalidSubscription = true; 22 | app.validationError = response.data.msg; 23 | } 24 | }) 25 | .catch(function (error) { 26 | app.invalidSubscription = true; 27 | }) 28 | } 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /staticfiles/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /staticfiles/redactor/plugins/source.js: -------------------------------------------------------------------------------- 1 | (function($) 2 | { 3 | $.Redactor.prototype.source = function() 4 | { 5 | return { 6 | init: function() 7 | { 8 | var button = this.button.addFirst('html', 'HTML'); 9 | this.button.setIcon(button, ''); 10 | this.button.addCallback(button, this.source.toggle); 11 | 12 | var style = { 13 | 'width': '100%', 14 | 'margin': '0', 15 | 'background': '#1d1d1d', 16 | 'box-sizing': 'border-box', 17 | 'color': '#ccc', 18 | 'font-size': '15px', 19 | 'outline': 'none', 20 | 'padding': '20px', 21 | 'line-height': '24px', 22 | 'font-family': 'Consolas, Menlo, Monaco, "Courier New", monospace' 23 | }; 24 | 25 | this.source.$textarea = $('