├── README.md └── services ├── docker-compose.yaml ├── emails ├── Dockerfile ├── README.md ├── api │ ├── __pycache__ │ │ ├── models.cpython-36.pyc │ │ ├── settings.cpython-36.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── views.cpython-36.pyc │ │ └── wsgi.cpython-36.pyc │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-36.pyc │ │ │ └── __init__.cpython-36.pyc │ ├── models.py │ ├── serializers.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── manage.py └── requirements.txt ├── orders ├── Dockerfile ├── README.md ├── api │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── celery_conf.cpython-36.pyc │ │ ├── models.cpython-36.pyc │ │ ├── settings.cpython-36.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── views.cpython-36.pyc │ │ └── wsgi.cpython-36.pyc │ ├── celery_conf.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_order_items.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-36.pyc │ │ │ ├── 0002_order_items.cpython-36.pyc │ │ │ └── __init__.cpython-36.pyc │ ├── models.py │ ├── serializers.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── manage.py └── requirements.txt ├── products ├── Dockerfile ├── README.md ├── api │ ├── __pycache__ │ │ ├── models.cpython-36.pyc │ │ ├── serializers.cpython-36.pyc │ │ ├── settings.cpython-36.pyc │ │ ├── urls.cpython-36.pyc │ │ ├── views.cpython-36.pyc │ │ └── wsgi.cpython-36.pyc │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-36.pyc │ │ │ └── __init__.cpython-36.pyc │ ├── models.py │ ├── serializers.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ ├── rest_framework │ ├── css │ │ ├── bootstrap-tweaks.css │ │ ├── bootstrap.min.css │ │ ├── default.css │ │ └── prettify.css │ ├── docs │ │ ├── css │ │ │ ├── base.css │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap.min.css │ │ │ ├── font-awesome-4.0.3.css │ │ │ ├── highlight.css │ │ │ └── jquery.json-view.min.css │ │ ├── fonts │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── img │ │ │ ├── favicon.ico │ │ │ └── grid.png │ │ └── js │ │ │ ├── api.js │ │ │ ├── bootstrap.min.js │ │ │ ├── highlight.pack.js │ │ │ ├── jquery-1.10.2.min.js │ │ │ └── jquery.json-view.min.js │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── img │ │ ├── glyphicons-halflings-white.png │ │ ├── glyphicons-halflings.png │ │ └── grid.png │ └── js │ │ ├── ajax-form.js │ │ ├── bootstrap.min.js │ │ ├── coreapi-0.1.1.js │ │ ├── csrf.js │ │ ├── default.js │ │ ├── jquery-1.12.4.min.js │ │ └── prettify-min.js │ └── rest_framework_swagger │ ├── css │ ├── print.css │ ├── reset.css │ ├── screen.css │ └── typography.css │ ├── fonts │ ├── DroidSans-Bold.ttf │ └── DroidSans.ttf │ ├── images │ ├── collapse.gif │ ├── expand.gif │ ├── explorer_icons.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── logo_small.png │ ├── pet_store_api.png │ ├── throbber.gif │ └── wordnik_api.png │ ├── init.js │ ├── lang │ ├── en.js │ ├── es.js │ ├── fr.js │ ├── geo.js │ ├── it.js │ ├── ja.js │ ├── ko-kr.js │ ├── pl.js │ ├── pt.js │ ├── ru.js │ ├── tr.js │ ├── translator.js │ └── zh-cn.js │ ├── lib │ ├── backbone-min.js │ ├── handlebars-2.0.0.js │ ├── highlight.9.1.0.pack.js │ ├── highlight.9.1.0.pack_extended.js │ ├── jquery-1.8.0.min.js │ ├── jquery.ba-bbq.min.js │ ├── jquery.slideto.min.js │ ├── jquery.wiggle.min.js │ ├── js-yaml.min.js │ ├── jsoneditor.min.js │ ├── lodash.min.js │ ├── marked.js │ ├── object-assign-pollyfill.js │ └── swagger-oauth.js │ ├── o2c.html │ ├── swagger-ui.js │ └── swagger-ui.min.js └── web ├── Dockerfile └── services.conf /README.md: -------------------------------------------------------------------------------- 1 | # UNMAINTAINED 2 | 3 | # Microservices architecture based web application 4 | 5 | This is example web application based on microservices architecture. It has 3 decoupled and scalable services: 6 | 7 | 01. Products Management 8 | 02. Order Management 9 | 03. Email Sending 10 | 11 | Technology Stack: 12 | 01. Python 13 | 02. Django/Django REST Framework 14 | 03. Mongodb 15 | 16 | 04. Nginx 17 | 05. Docker 18 | 06. Swagger UI 19 | 20 | Python used as the backend development language. Django used as the backend framework. Django REST Framework or DRF used as the REST API development framework, Mongodb used as the database backend, Nginx used as the API gateway and finally docker used as the deployment method. Swagger used for documenting API 21 | 22 | Each services have their seperate database completely decoupled. Nginx sits in front of each of the services to abstract all the microservices API endpoints into single one. 23 | 24 | For testing: 25 | 01. Clone the repo 26 | 02. Run "docker-compose build" while inside the services folder 27 | 03. After docker completes all the building staffs, run "docker-compose up -d" to run each microservices. 28 | 04. Now go to your localhost, docker machine ip or server ip to access the API endpoints. 29 | 30 | API endpoints: please see /api/v1/{services}/docs/ 31 | 32 | Deployed and tested in a real production server. 33 | -------------------------------------------------------------------------------- /services/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | products_web: 5 | build: ./products 6 | command: bash -c "python3 ./products/manage.py makemigrations && python3 ./products/manage.py migrate && python3 ./products/manage.py runserver 0.0.0.0:8001" 7 | volumes: 8 | - .:/code 9 | ports: 10 | - 8001:8001 11 | restart: always 12 | depends_on: 13 | - mongod 14 | links: 15 | - mongod 16 | 17 | emails_web: 18 | build: ./emails 19 | command: bash -c "python3 ./emails/manage.py makemigrations && python3 ./emails/manage.py migrate && python3 ./emails/manage.py runserver 0.0.0.0:8002" 20 | volumes: 21 | - .:/code 22 | ports: 23 | - 8002:8002 24 | restart: always 25 | depends_on: 26 | - mongod 27 | links: 28 | - mongod 29 | 30 | orders_web: 31 | build: ./orders 32 | command: bash -c "python3 ./orders/manage.py makemigrations && python3 ./orders/manage.py migrate && python3 ./orders/manage.py runserver 0.0.0.0:8003" 33 | volumes: 34 | - .:/code 35 | ports: 36 | - 8003:8003 37 | restart: always 38 | depends_on: 39 | - mongod 40 | links: 41 | - mongod 42 | 43 | mongod: 44 | restart: always 45 | image: mongo:3.4.7 46 | ports: 47 | - 27017:27017 48 | command: mongod 49 | 50 | nginx: 51 | build: ./web 52 | ports: 53 | - 80:80 54 | links: 55 | - products_web 56 | - orders_web 57 | - emails_web 58 | depends_on: 59 | - products_web 60 | - orders_web 61 | - emails_web 62 | -------------------------------------------------------------------------------- /services/emails/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6.4-slim 2 | 3 | ENV PYTHONUNBUFFERED 1 4 | 5 | RUN mkdir /code 6 | 7 | WORKDIR /code 8 | 9 | COPY . . 10 | 11 | RUN pip install -r requirements.txt -------------------------------------------------------------------------------- /services/emails/README.md: -------------------------------------------------------------------------------- 1 | # djmicro 2 | -------------------------------------------------------------------------------- /services/emails/api/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.2 on 2018-03-24 18:06 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Email', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('sender', models.EmailField(max_length=254)), 19 | ('receiver', models.EmailField(max_length=254)), 20 | ('subject', models.CharField(max_length=300)), 21 | ('body', models.TextField()), 22 | ], 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /services/emails/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/migrations/__init__.py -------------------------------------------------------------------------------- /services/emails/api/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/emails/api/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /services/emails/api/models.py: -------------------------------------------------------------------------------- 1 | #from django.db import models #for sql 2 | from djongo import models #for mongodb nosql 3 | 4 | # TODO: write here your models 5 | 6 | class Email(models.Model): 7 | sender = models.EmailField() 8 | receiver = models.EmailField() 9 | subject = models.CharField(max_length=300) 10 | body = models.TextField() 11 | -------------------------------------------------------------------------------- /services/emails/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | # TODO: write here your model serializers 4 | -------------------------------------------------------------------------------- /services/emails/api/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 | 5 | SECRET_KEY = '********* SET HERE YOUR SECRET *********' 6 | 7 | DEBUG = True 8 | 9 | ALLOWED_HOSTS = ['*'] 10 | 11 | INSTALLED_APPS = [ 12 | 'rest_framework', 13 | 14 | 'api' 15 | ] 16 | 17 | MIDDLEWARE = [ 18 | 'django.middleware.security.SecurityMiddleware', 19 | 'django.middleware.common.CommonMiddleware', 20 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 21 | ] 22 | 23 | ROOT_URLCONF = 'api.urls' 24 | 25 | WSGI_APPLICATION = 'api.wsgi.application' 26 | 27 | DATABASES = { 28 | 'default': { 29 | 'ENGINE': 'djongo', 30 | 'NAME': 'emails', 31 | 'HOST': 'mongod', 32 | 'PORT': 27017 33 | } 34 | } 35 | 36 | LANGUAGE_CODE = 'en-us' 37 | 38 | TIME_ZONE = 'UTC' 39 | 40 | USE_I18N = True 41 | 42 | USE_L10N = True 43 | 44 | USE_TZ = True 45 | 46 | REST_FRAMEWORK = { 47 | 'UNAUTHENTICATED_USER': None 48 | } 49 | 50 | EMAIL_HOST = "smtp.gmail.com" 51 | EMAIL_PORT = "587" 52 | EMAIL_HOST_USER = "logformat4@gmail.com" 53 | EMAIL_HOST_PASSWORD = "logformat444" 54 | EMAIL_USE_TLS = True 55 | -------------------------------------------------------------------------------- /services/emails/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | # TODO: add here your API URLs 5 | 6 | urlpatterns = [ 7 | path("emails/send/", views.email_send) 8 | ] 9 | -------------------------------------------------------------------------------- /services/emails/api/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.views import APIView 2 | from django.conf import settings 3 | from django.core.mail import send_mail 4 | from .models import Email 5 | from rest_framework.response import Response 6 | from rest_framework.decorators import api_view 7 | 8 | # TODO: add here your API Views 9 | 10 | @api_view(http_method_names=["POST"]) 11 | def email_send(request): 12 | sender = settings.EMAIL_HOST_USER 13 | try: 14 | receiver = request.data["receiver"] 15 | subject = request.data["subject"] 16 | body = request.data["body"] 17 | 18 | new_mail = Email.objects.create( 19 | sender=sender, 20 | receiver=receiver, 21 | subject=subject, 22 | body=body 23 | ) 24 | 25 | send_mail(subject, body, sender, [receiver], fail_silently=False) 26 | return Response({"message": "Email sent successfully"}, status=200) 27 | 28 | except: 29 | return Response({"message": "Email sending error"}, status=500) 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /services/emails/api/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for microservice 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", "api.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /services/emails/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", "api.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 | -------------------------------------------------------------------------------- /services/emails/requirements.txt: -------------------------------------------------------------------------------- 1 | Django 2 | djangorestframework 3 | djongo 4 | psycopg2 5 | gunicorn 6 | requests 7 | -------------------------------------------------------------------------------- /services/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6.4-slim 2 | 3 | ENV PYTHONUNBUFFERED 1 4 | 5 | RUN mkdir /code 6 | 7 | WORKDIR /code 8 | 9 | COPY . . 10 | 11 | RUN pip install -r requirements.txt -------------------------------------------------------------------------------- /services/orders/README.md: -------------------------------------------------------------------------------- 1 | # djmicro 2 | -------------------------------------------------------------------------------- /services/orders/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__init__.py -------------------------------------------------------------------------------- /services/orders/api/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/celery_conf.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/celery_conf.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/celery_conf.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/celery_conf.py -------------------------------------------------------------------------------- /services/orders/api/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.2 on 2018-03-24 21:02 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Order', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('total', models.FloatField()), 19 | ('customer_name', models.CharField(max_length=100)), 20 | ('customer_email', models.CharField(max_length=100)), 21 | ], 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /services/orders/api/migrations/0002_order_items.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.2 on 2018-03-24 21:03 2 | 3 | from django.db import migrations 4 | import djongo.models.fields 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='order', 16 | name='items', 17 | field=djongo.models.fields.ListField(default=None), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /services/orders/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/migrations/__init__.py -------------------------------------------------------------------------------- /services/orders/api/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/migrations/__pycache__/0002_order_items.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/migrations/__pycache__/0002_order_items.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/orders/api/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /services/orders/api/models.py: -------------------------------------------------------------------------------- 1 | #from django.db import models #for sql 2 | from djongo import models #for mongodb nosql 3 | 4 | # TODO: write here your models 5 | 6 | 7 | class Order(models.Model): 8 | total = models.FloatField() 9 | customer_name = models.CharField(max_length=100) 10 | customer_email = models.CharField(max_length=100) 11 | items = models.ListField(default=None) 12 | -------------------------------------------------------------------------------- /services/orders/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | # TODO: write here your model serializers 4 | -------------------------------------------------------------------------------- /services/orders/api/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 | 5 | SECRET_KEY = '********* SET HERE YOUR SECRET *********' 6 | 7 | DEBUG = True 8 | 9 | ALLOWED_HOSTS = ['*'] 10 | 11 | INSTALLED_APPS = [ 12 | 'rest_framework', 13 | 14 | 'api', 15 | ] 16 | 17 | MIDDLEWARE = [ 18 | 'django.middleware.security.SecurityMiddleware', 19 | 'django.middleware.common.CommonMiddleware', 20 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 21 | ] 22 | 23 | ROOT_URLCONF = 'api.urls' 24 | 25 | WSGI_APPLICATION = 'api.wsgi.application' 26 | 27 | DATABASES = { 28 | 'default': { 29 | 'ENGINE': 'djongo', 30 | 'NAME': 'orders', 31 | 'HOST': 'mongod', 32 | 'PORT': 27017 33 | } 34 | } 35 | 36 | LANGUAGE_CODE = 'en-us' 37 | 38 | TIME_ZONE = 'UTC' 39 | 40 | USE_I18N = True 41 | 42 | USE_L10N = True 43 | 44 | USE_TZ = True 45 | 46 | REST_FRAMEWORK = { 47 | 'UNAUTHENTICATED_USER': None 48 | } 49 | 50 | # CELERY_BROKER_URL = 'redis://localhost:6379' 51 | # CELERY_RESULT_BACKEND = 'redis://localhost:6379' 52 | # CELERY_ACCEPT_CONTENT = ['application/json'] 53 | # CELERY_TASK_SERIALIZER = 'json' 54 | # CELERY_RESULT_SERIALIZER = 'json' 55 | # CELERY_TIMEZONE = TIME_ZONE 56 | -------------------------------------------------------------------------------- /services/orders/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | # TODO: add here your API URLs 5 | 6 | urlpatterns = [ 7 | path("orders/add/", views.add_order) 8 | ] 9 | -------------------------------------------------------------------------------- /services/orders/api/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.response import Response 2 | from rest_framework.decorators import api_view 3 | import requests 4 | from .models import Order 5 | 6 | 7 | # TODO: add here your API Views 8 | 9 | @api_view(http_method_names=["POST"]) 10 | def add_order(request): 11 | total_price = 0 12 | order = Order() 13 | order.customer_name = request.data["customer_name"] 14 | order.customer_email = request.data["customer_email"] 15 | order.items = [] 16 | 17 | print(request.data) 18 | 19 | for product in request.data["products_id"]: 20 | response = requests.get("http://127.0.0.1:8001/products/fetch/?prod_id=%s" % product).json() 21 | print(response) 22 | total_price += float(response[0]["price"]) 23 | 24 | order.items.append({ 25 | "item_name": response[0]["name"], 26 | "item_description": response[0]["description"], 27 | "item_price": response[0]["price"], 28 | }) 29 | order.total = total_price 30 | order.save() 31 | 32 | # send_email.delay(order) 33 | send_email(order) 34 | 35 | return Response({"message": "Order successfully created!"}) 36 | 37 | 38 | def send_email(order): 39 | requests.post("http://127.0.0.1/api/v1/emails/send/", data={ 40 | "receiver": order.customer_email, 41 | "subject": "Order Created", 42 | "body": "Hello %s, your order has been created. Total of: %s. Thanks" % (order.customer_name, order.total) 43 | }) 44 | -------------------------------------------------------------------------------- /services/orders/api/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for microservice 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", "api.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /services/orders/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", "api.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 | 24 | 25 | -------------------------------------------------------------------------------- /services/orders/requirements.txt: -------------------------------------------------------------------------------- 1 | Django 2 | djangorestframework 3 | djongo 4 | psycopg2 5 | gunicorn 6 | requests -------------------------------------------------------------------------------- /services/products/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6.4-slim 2 | 3 | ENV PYTHONUNBUFFERED 1 4 | 5 | RUN mkdir /code 6 | 7 | WORKDIR /code 8 | 9 | COPY . . 10 | 11 | RUN pip install -r requirements.txt -------------------------------------------------------------------------------- /services/products/README.md: -------------------------------------------------------------------------------- 1 | # djmicro 2 | -------------------------------------------------------------------------------- /services/products/api/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/__pycache__/serializers.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/serializers.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.2 on 2018-03-24 15:40 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='Category', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('name', models.CharField(max_length=100)), 20 | ], 21 | ), 22 | migrations.CreateModel( 23 | name='Product', 24 | fields=[ 25 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 26 | ('name', models.CharField(max_length=100)), 27 | ('price', models.FloatField()), 28 | ('description', models.TextField()), 29 | ('category', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='api.Category')), 30 | ], 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /services/products/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/migrations/__init__.py -------------------------------------------------------------------------------- /services/products/api/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/api/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /services/products/api/models.py: -------------------------------------------------------------------------------- 1 | from djongo import models #for mongodb nosql 2 | 3 | # TODO: write here your models 4 | 5 | class Category(models.Model): 6 | name = models.CharField(max_length=100) 7 | 8 | 9 | class Product(models.Model): 10 | category = models.ForeignKey(Category, on_delete=models.DO_NOTHING) 11 | name = models.CharField(max_length=100) 12 | price = models.FloatField() 13 | description = models.TextField() 14 | -------------------------------------------------------------------------------- /services/products/api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from .models import Category, Product 4 | 5 | # TODO: write here your model serializers 6 | 7 | class CategorySerializer(serializers.ModelSerializer): 8 | 9 | class Meta: 10 | model = Category 11 | fields = [ 12 | "id", 13 | "name" 14 | ] 15 | 16 | class ProductSerializer(serializers.ModelSerializer): 17 | class Meta: 18 | model = Product 19 | fields = "__all__" 20 | -------------------------------------------------------------------------------- /services/products/api/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 | 5 | SECRET_KEY = '********* SET HERE YOUR SECRET *********' 6 | 7 | DEBUG = True 8 | 9 | ALLOWED_HOSTS = ['*'] 10 | 11 | INSTALLED_APPS = [ 12 | 'django.contrib.staticfiles', 13 | 'rest_framework', 14 | 'rest_framework_swagger', 15 | 16 | 'api' 17 | ] 18 | 19 | MIDDLEWARE = [ 20 | 'django.middleware.security.SecurityMiddleware', 21 | 'django.middleware.common.CommonMiddleware', 22 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 23 | ] 24 | 25 | ROOT_URLCONF = 'api.urls' 26 | 27 | WSGI_APPLICATION = 'api.wsgi.application' 28 | 29 | DATABASES = { 30 | 'default': { 31 | 'ENGINE': 'djongo', 32 | 'NAME': 'products', 33 | 'HOST': 'mongod', 34 | 'PORT': 27017 35 | } 36 | } 37 | 38 | LANGUAGE_CODE = 'en-us' 39 | 40 | TIME_ZONE = 'UTC' 41 | 42 | USE_I18N = True 43 | 44 | USE_L10N = True 45 | 46 | USE_TZ = True 47 | 48 | REST_FRAMEWORK = { 49 | 'UNAUTHENTICATED_USER': None 50 | } 51 | 52 | TEMPLATES = [ 53 | { 54 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 55 | 'DIRS': [], 56 | 'APP_DIRS': True, 57 | 'OPTIONS': { 58 | 'context_processors': [ 59 | 'django.template.context_processors.debug', 60 | 'django.template.context_processors.request', 61 | 'django.contrib.auth.context_processors.auth', 62 | 'django.contrib.messages.context_processors.messages', 63 | ], 64 | }, 65 | }, 66 | ] 67 | 68 | STATIC_URL = '/static/' 69 | 70 | STATIC_ROOT = os.path.join(BASE_DIR, "static") 71 | -------------------------------------------------------------------------------- /services/products/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | from rest_framework_swagger.views import get_swagger_view 4 | 5 | # TODO: add here your API URLs 6 | 7 | schema_view = get_swagger_view(title='Micromerce API') 8 | 9 | 10 | urlpatterns = [ 11 | path("private/categories/", views.categories), 12 | path("products/fetch/", views.products_fetch), 13 | path("products/create/", views.products_create), 14 | path("products/delete/", views.products_delete), 15 | path("products/docs/", schema_view), 16 | ] 17 | -------------------------------------------------------------------------------- /services/products/api/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.views import APIView 2 | from .models import Category, Product 3 | import json 4 | from rest_framework.response import Response 5 | from .serializers import CategorySerializer, ProductSerializer 6 | from rest_framework.decorators import api_view 7 | 8 | 9 | @api_view(http_method_names=["GET", "POST"]) 10 | def categories(request): 11 | if not request.META["HTTP_AUTH_ID"] or request.META["HTTP_AUTH_ID"] != "MY155": 12 | return Response({"message": "Authorization Failed"}) 13 | 14 | if request.method == "POST": 15 | new_cat = Category.objects.create(name=request.data["category_name"]) 16 | categories_lst = Category.objects.all() 17 | srlz = CategorySerializer(categories_lst, many=True) 18 | return Response(srlz.data) 19 | 20 | 21 | @api_view(http_method_names=["GET"]) 22 | def products_fetch(request): 23 | if request.query_params.get("cat_id"): 24 | products_list = Product.objects.filter(category__id=request.query_params.get("cat_id")) 25 | elif request.query_params.get("prod_id"): 26 | products_list = Product.objects.filter(id=request.query_params.get("prod_id")) 27 | else: 28 | products_list = Product.objects.all() 29 | if products_list: 30 | srlz = ProductSerializer(products_list, many=True) 31 | return Response(srlz.data, status=200) 32 | else: 33 | return Response({"message": "Sorry not found!"}, status=404) 34 | 35 | 36 | @api_view(http_method_names=["POST"]) 37 | def products_create(request): 38 | new_prod = Product.objects.create( 39 | category=request.data["cat_id"], 40 | name=request.data["prod_name"], 41 | price=request.data["prod_price"], 42 | description=request.data["prod_description"], 43 | ) 44 | return Response({"message": "Product added successfully"}, status=300) 45 | 46 | 47 | @api_view(http_method_names=["DELETE"]) 48 | def products_delete(request): 49 | if not request.data["prod_id"]: 50 | return Response({"message": "Sorry not found!"}, status=500) 51 | product = Product.objects.get(id=request.data["prod_id"]) 52 | product.delete() 53 | return Response({"message": "Product deleted successfully"}, status=300) 54 | -------------------------------------------------------------------------------- /services/products/api/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for microservice 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", "api.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /services/products/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", "api.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 | -------------------------------------------------------------------------------- /services/products/requirements.txt: -------------------------------------------------------------------------------- 1 | Django 2 | djangorestframework 3 | djongo 4 | psycopg2 5 | gunicorn 6 | requests 7 | -------------------------------------------------------------------------------- /services/products/static/rest_framework/css/bootstrap-tweaks.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This CSS file contains some tweaks specific to the included Bootstrap theme. 4 | It's separate from `style.css` so that it can be easily overridden by replacing 5 | a single block in the template. 6 | 7 | */ 8 | 9 | .form-actions { 10 | background: transparent; 11 | border-top-color: transparent; 12 | padding-top: 0; 13 | text-align: right; 14 | } 15 | 16 | #generic-content-form textarea { 17 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 18 | font-size: 80%; 19 | } 20 | 21 | .navbar-inverse .brand a { 22 | color: #999999; 23 | } 24 | .navbar-inverse .brand:hover a { 25 | color: white; 26 | text-decoration: none; 27 | } 28 | 29 | /* custom navigation styles */ 30 | .navbar { 31 | width: 100%; 32 | position: fixed; 33 | left: 0; 34 | top: 0; 35 | } 36 | 37 | .navbar { 38 | background: #2C2C2C; 39 | color: white; 40 | border: none; 41 | border-top: 5px solid #A30000; 42 | border-radius: 0px; 43 | } 44 | 45 | .navbar .nav li, .navbar .nav li a, .navbar .brand:hover { 46 | color: white; 47 | } 48 | 49 | .nav-list > .active > a, .nav-list > .active > a:hover { 50 | background: #2C2C2C; 51 | } 52 | 53 | .navbar .dropdown-menu li a, .navbar .dropdown-menu li { 54 | color: #A30000; 55 | } 56 | 57 | .navbar .dropdown-menu li a:hover { 58 | background: #EEEEEE; 59 | color: #C20000; 60 | } 61 | 62 | ul.breadcrumb { 63 | margin: 70px 0 0 0; 64 | } 65 | 66 | .breadcrumb li.active a { 67 | color: #777; 68 | } 69 | 70 | .pagination>.disabled>a, 71 | .pagination>.disabled>a:hover, 72 | .pagination>.disabled>a:focus { 73 | cursor: not-allowed; 74 | pointer-events: none; 75 | } 76 | 77 | .pager>.disabled>a, 78 | .pager>.disabled>a:hover, 79 | .pager>.disabled>a:focus { 80 | pointer-events: none; 81 | } 82 | 83 | .pager .next { 84 | margin-left: 10px; 85 | } 86 | 87 | /*=== dabapps bootstrap styles ====*/ 88 | 89 | html { 90 | width:100%; 91 | background: none; 92 | } 93 | 94 | /*body, .navbar .container-fluid { 95 | max-width: 1150px; 96 | margin: 0 auto; 97 | }*/ 98 | 99 | body { 100 | background: url("../img/grid.png") repeat-x; 101 | background-attachment: fixed; 102 | } 103 | 104 | #content { 105 | margin: 0; 106 | padding-bottom: 60px; 107 | } 108 | 109 | /* sticky footer and footer */ 110 | html, body { 111 | height: 100%; 112 | } 113 | 114 | .wrapper { 115 | position: relative; 116 | top: 0; 117 | left: 0; 118 | padding-top: 60px; 119 | margin: -60px 0; 120 | min-height: 100%; 121 | } 122 | 123 | .form-switcher { 124 | margin-bottom: 0; 125 | } 126 | 127 | .well { 128 | -webkit-box-shadow: none; 129 | -moz-box-shadow: none; 130 | box-shadow: none; 131 | } 132 | 133 | .well .form-actions { 134 | padding-bottom: 0; 135 | margin-bottom: 0; 136 | } 137 | 138 | .well form { 139 | margin-bottom: 0; 140 | } 141 | 142 | .nav-tabs { 143 | border: 0; 144 | } 145 | 146 | .nav-tabs > li { 147 | float: right; 148 | } 149 | 150 | .nav-tabs li a { 151 | margin-right: 0; 152 | } 153 | 154 | .nav-tabs > .active > a { 155 | background: #F5F5F5; 156 | } 157 | 158 | .nav-tabs > .active > a:hover { 159 | background: #F5F5F5; 160 | } 161 | 162 | .tabbable.first-tab-active .tab-content { 163 | border-top-right-radius: 0; 164 | } 165 | 166 | footer { 167 | position: absolute; 168 | bottom: 0; 169 | left: 0; 170 | clear: both; 171 | z-index: 10; 172 | height: 60px; 173 | width: 95%; 174 | margin: 0 2.5%; 175 | } 176 | 177 | footer p { 178 | text-align: center; 179 | color: gray; 180 | border-top: 1px solid #DDDDDD; 181 | padding-top: 10px; 182 | } 183 | 184 | footer a { 185 | color: gray !important; 186 | font-weight: bold; 187 | } 188 | 189 | footer a:hover { 190 | color: gray; 191 | } 192 | 193 | .page-header { 194 | border-bottom: none; 195 | padding-bottom: 0px; 196 | margin: 0; 197 | } 198 | 199 | /* custom general page styles */ 200 | .hero-unit h1, .hero-unit h2 { 201 | color: #A30000; 202 | } 203 | 204 | body a { 205 | color: #A30000; 206 | } 207 | 208 | body a:hover { 209 | color: #c20000; 210 | } 211 | 212 | .request-info { 213 | clear:both; 214 | } 215 | 216 | .horizontal-checkbox label { 217 | padding-top: 0; 218 | } 219 | 220 | .horizontal-checkbox label { 221 | padding-top: 0 !important; 222 | } 223 | 224 | .horizontal-checkbox input { 225 | float: left; 226 | width: 20px; 227 | margin-top: 3px; 228 | } 229 | 230 | .modal-footer form { 231 | margin-left: 5px; 232 | margin-right: 5px; 233 | } 234 | -------------------------------------------------------------------------------- /services/products/static/rest_framework/css/default.css: -------------------------------------------------------------------------------- 1 | 2 | /* The navbar is fixed at >= 980px wide, so add padding to the body to prevent 3 | content running up underneath it. */ 4 | 5 | h1 { 6 | font-weight: 300; 7 | } 8 | 9 | h2, h3 { 10 | font-weight: 300; 11 | } 12 | 13 | .resource-description, .response-info { 14 | margin-bottom: 2em; 15 | } 16 | 17 | .version:before { 18 | content: "v"; 19 | opacity: 0.6; 20 | padding-right: 0.25em; 21 | } 22 | 23 | .version { 24 | font-size: 70%; 25 | } 26 | 27 | .format-option { 28 | font-family: Menlo, Consolas, "Andale Mono", "Lucida Console", monospace; 29 | } 30 | 31 | .button-form { 32 | float: right; 33 | margin-right: 1em; 34 | } 35 | 36 | td.nested { 37 | padding: 0 !important; 38 | } 39 | 40 | td.nested > table { 41 | margin: 0; 42 | } 43 | 44 | form select, form input, form textarea { 45 | width: 90%; 46 | } 47 | 48 | form select[multiple] { 49 | height: 150px; 50 | } 51 | 52 | /* To allow tooltips to work on disabled elements */ 53 | .disabled-tooltip-shield { 54 | position: absolute; 55 | top: 0; 56 | right: 0; 57 | bottom: 0; 58 | left: 0; 59 | } 60 | 61 | .errorlist { 62 | margin-top: 0.5em; 63 | } 64 | 65 | pre { 66 | overflow: auto; 67 | word-wrap: normal; 68 | white-space: pre; 69 | font-size: 12px; 70 | } 71 | 72 | .page-header { 73 | border-bottom: none; 74 | padding-bottom: 0px; 75 | } 76 | 77 | #filtersModal form input[type=submit] { 78 | width: auto; 79 | } 80 | 81 | #filtersModal .modal-body h2 { 82 | margin-top: 0 83 | } 84 | -------------------------------------------------------------------------------- /services/products/static/rest_framework/css/prettify.css: -------------------------------------------------------------------------------- 1 | .com { color: #93a1a1; } 2 | .lit { color: #195f91; } 3 | .pun, .opn, .clo { color: #93a1a1; } 4 | .fun { color: #dc322f; } 5 | .str, .atv { color: #D14; } 6 | .kwd, .prettyprint .tag { color: #1e347b; } 7 | .typ, .atn, .dec, .var { color: teal; } 8 | .pln { color: #48484c; } 9 | 10 | .prettyprint { 11 | padding: 8px; 12 | background-color: #f7f7f9; 13 | border: 1px solid #e1e1e8; 14 | } 15 | .prettyprint.linenums { 16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 19 | } 20 | 21 | /* Specify class=linenums on a pre to get line numbering */ 22 | ol.linenums { 23 | margin: 0 0 0 33px; /* IE indents via margin-left */ 24 | } 25 | ol.linenums li { 26 | padding-left: 12px; 27 | color: #bebec5; 28 | line-height: 20px; 29 | text-shadow: 0 1px 0 #fff; 30 | } -------------------------------------------------------------------------------- /services/products/static/rest_framework/docs/css/base.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 45px; 3 | } 4 | 5 | .intro-code { 6 | margin-top: 20px; 7 | } 8 | 9 | pre.highlight code * { 10 | white-space: nowrap; // this sets all children inside to nowrap 11 | } 12 | 13 | pre.highlight { 14 | overflow-x: auto; // this sets the scrolling in x 15 | } 16 | 17 | pre.highlight code { 18 | white-space: pre; // forces to respect
 formatting
 19 | }
 20 | 
 21 | .main-container {
 22 |   padding-left: 30px;
 23 |   padding-right: 30px;
 24 | }
 25 | 
 26 | .btn:focus,
 27 | .btn:focus:active {
 28 |   outline: none;
 29 | }
 30 | 
 31 | .sidebar {
 32 |   overflow: auto;
 33 |   font-family: verdana;
 34 |   font-size: 12px;
 35 |   font-weight: 200;
 36 |   background-color: #2e353d;
 37 |   position: fixed;
 38 |   top: 0px;
 39 |   width: 225px;
 40 |   height: 100%;
 41 |   color: #FFF;
 42 | }
 43 | 
 44 | .sidebar .brand {
 45 |     background-color: #23282e;
 46 |     display: block;
 47 |     text-align: center;
 48 |     padding: 25px 0;
 49 |     margin-top: 0;
 50 |     margin-bottom: 0;
 51 | }
 52 | 
 53 | .sidebar .brand a {
 54 |     color: #FFF;
 55 | }
 56 | 
 57 | .sidebar .brand a:hover,
 58 | .sidebar .brand a:active,
 59 | .sidebar .brand a:focus {
 60 |   text-decoration: none;
 61 | }
 62 | 
 63 | .sidebar .toggle-btn {
 64 |   display: none;
 65 | }
 66 | 
 67 | .sidebar .menu-list {
 68 |   width: inherit;
 69 | }
 70 | 
 71 | .sidebar .menu-list ul,
 72 | .sidebar .menu-list li {
 73 |   background: #2e353d;
 74 |   list-style: none;
 75 |   padding: 0px;
 76 |   margin: 0px;
 77 |   line-height: 35px;
 78 |   cursor: pointer;
 79 | }
 80 | 
 81 | .sidebar .menu-list ul :not(collapsed) .arrow:before,
 82 | .sidebar .menu-list li :not(collapsed) .arrow:before {
 83 |   font-family: FontAwesome;
 84 |   content: "\f078";
 85 |   display: inline-block;
 86 |   padding-left: 10px;
 87 |   padding-right: 10px;
 88 |   vertical-align: middle;
 89 |   float: right;
 90 | }
 91 | 
 92 | .sidebar .menu-list ul .active,
 93 | .sidebar .menu-list li .active {
 94 |   border-left: 3px solid #d19b3d;
 95 |   background-color: #4f5b69;
 96 | }
 97 | 
 98 | .sidebar .menu-list ul .sub-menu li.active,
 99 | .sidebar .menu-list li .sub-menu li.active {
100 |   color: #d19b3d;
101 | }
102 | 
103 | .sidebar .menu-list ul .sub-menu li.active a,
104 | .sidebar .menu-list li .sub-menu li.active a {
105 |   color: #d19b3d;
106 | }
107 | 
108 | .sidebar .menu-list ul .sub-menu li,
109 | .sidebar .menu-list li .sub-menu li {
110 |   background-color: #181c20;
111 |   border: none;
112 |   border-bottom: 1px solid #23282e;
113 |   margin-left: 0px;
114 |   text-indent: 10px;
115 | }
116 | 
117 | .sidebar .menu-list ul .sub-menu li:hover,
118 | .sidebar .menu-list li .sub-menu li:hover {
119 |   background-color: #020203;
120 | }
121 | 
122 | 
123 | .sidebar .menu-list ul .sub-menu li a,
124 | .sidebar .menu-list li .sub-menu li a {
125 |   display: block;
126 | }
127 | 
128 | .sidebar .menu-list ul .sub-menu li a:before,
129 | .sidebar .menu-list li .sub-menu li a:before {
130 |   font-family: FontAwesome;
131 |   content: "\f105";
132 |   display: inline-block;
133 |   padding-left: 10px;
134 |   padding-right: 10px;
135 |   vertical-align: middle;
136 | }
137 | 
138 | .sidebar .menu-list li {
139 |   padding-left: 0px;
140 |   border-left: 3px solid #2e353d;
141 |   border-bottom: 1px solid #23282e;
142 | }
143 | 
144 | .sidebar .menu-list li a {
145 |   text-decoration: none;
146 |   color: white;
147 | }
148 | 
149 | .sidebar .menu-list li a i {
150 |   padding-left: 10px;
151 |   width: 20px;
152 |   padding-right: 20px;
153 | }
154 | 
155 | .sidebar .menu-list li:hover {
156 |   border-left: 3px solid #d19b3d;
157 |   background-color: #4f5b69;
158 |   -webkit-transition: all 1s ease;
159 |   -moz-transition: all 1s ease;
160 |   -o-transition: all 1s ease;
161 |   -ms-transition: all 1s ease;
162 |   transition: all 1s ease;
163 | }
164 | 
165 | body {
166 |   margin: 0px;
167 |   padding: 0px;
168 | }
169 | 
170 | .coredocs-section-title {
171 |     margin-top: 20px;
172 |     padding-bottom: 10px;
173 |     border-bottom: 1px solid lightgrey;
174 | }
175 | 
176 | .coredocs-link-title a,
177 | .coredocs-section-title a {
178 |   display: none;
179 | }
180 | 
181 | .coredocs-link-title a,
182 | .coredocs-section-title a {
183 |   text-decoration: none;
184 | }
185 | 
186 | .coredocs-link-title:hover a,
187 | .coredocs-section-title:hover a {
188 |   display: inline;
189 |   font-size: 20px;
190 | }
191 | 
192 | .coredocs-section-title:last-child {
193 |     margin-top: 0;
194 | }
195 | 
196 | 
197 | /* @group Language Switcher */
198 | 
199 | .sidebar .menu-list.menu-list-bottom {
200 |     margin-bottom: 0;
201 |     position: fixed;
202 |     width: inherit;
203 |     bottom: 0;
204 |     left: 0;
205 |     right: 0;
206 |     border-top: 1px solid #23282e;
207 | }
208 | 
209 | .sidebar .menu-list-bottom li span {
210 |   float: right;
211 |   margin-right: 20px;
212 |   color: #d19b3d;
213 | }
214 | 
215 | /* @end Language Switcher */
216 | 
217 | 
218 | /* @group Docs Content */
219 | 
220 | .docs-content .meta .label {
221 |     vertical-align: middle;
222 |     font-size: 14px;
223 |     font-weight: normal;
224 | }
225 | 
226 | .docs-content .meta code {
227 |     vertical-align: middle;
228 |     padding: .2em .6em .3em;
229 |     font-size: 14px;
230 | }
231 | 
232 | .docs-content .btn {
233 |   font-size: inherit;
234 | }
235 | 
236 | .code-samples pre {
237 |   margin-top: 20px;
238 | }
239 | 
240 | /* @end Docs Content */
241 | 
242 | 
243 | @media (max-width: 767px) {
244 |   .main-container {
245 |     padding-left: 15px;
246 |     padding-right: 15px;
247 |   }
248 | 
249 |   .sidebar {
250 |     position: relative;
251 |     width: 100%;
252 |     margin-bottom: 10px;
253 |     overflow: visible;
254 |   }
255 | 
256 |   .sidebar .toggle-btn {
257 |     display: block;
258 |     cursor: pointer;
259 |     position: absolute;
260 |     right: 10px;
261 |     top: 10px;
262 |     z-index: 10 !important;
263 |     padding: 3px;
264 |     width: 40px;
265 |     text-align: center;
266 |   }
267 | 
268 |   .sidebar .menu-list.menu-list-bottom {
269 |     position: static;
270 |   }
271 | 
272 |   .sidebar .brand {
273 |     margin-top: 0;
274 |     margin-bottom: 0;
275 | 
276 |     text-align: left !important;
277 |     font-size: 22px;
278 |     padding: 0;
279 |     padding-left: 20px;
280 |     line-height: 50px !important;
281 |   }
282 | }
283 | 
284 | @media (min-width: 767px) {
285 |   .sidebar .menu-list .menu-content {
286 |     display: block;
287 |   }
288 |   #main {
289 |     width:calc(100% - 225px);
290 |     float: right;
291 |   }
292 | }
293 | 
294 | @media (min-width: 992px) {
295 |   .modal-lg {
296 |       width: 980px;
297 |   }
298 | }
299 | 
300 | .api-modal .modal-title .fa {
301 |   color: #93c54b;
302 | }
303 | 
304 | .api-modal .modal-body .request-awaiting {
305 |   padding: 35px 10px;
306 |   color: #7F8177;
307 |   text-align: center;
308 | }
309 | 
310 | .api-modal .modal-body .meta {
311 |   margin-bottom: 20px;
312 | }
313 | 
314 | .api-modal .modal-body .meta .label {
315 |     vertical-align: middle;
316 |     font-size: 14px;
317 |     font-weight: normal;
318 | }
319 | 
320 | .api-modal .modal-body .meta code {
321 |     vertical-align: middle;
322 |     padding: .2em .6em .3em;
323 |     font-size: 14px;
324 | }
325 | 
326 | .api-modal .modal-content .toggle-view {
327 |   text-align: right;
328 |   float: right;
329 | }
330 | 
331 | .api-modal .modal-content .response .well {
332 |   margin: 0;
333 |   max-height: 550px;
334 | }
335 | 
336 | .highlight {
337 |     background-color: #f7f7f9
338 | }
339 | 
340 | .checkbox label.control-label {
341 |     font-weight: bold
342 | }
343 | 
344 | @media (min-width: 768px) {
345 |     .navbar-nav.navbar-right:last-child {
346 |         margin-right: 0 !important;
347 |     }
348 | }
349 | 


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/css/font-awesome-4.0.3.css:
--------------------------------------------------------------------------------
   1 | /*!
   2 |  *  Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
   3 |  *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
   4 |  */
   5 | /* FONT PATH
   6 |  * -------------------------- */
   7 | @font-face {
   8 |   font-family: 'FontAwesome';
   9 |   src: url('../fonts/fontawesome-webfont.eot?v=4.0.3');
  10 |   src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');
  11 |   font-weight: normal;
  12 |   font-style: normal;
  13 | }
  14 | .fa {
  15 |   display: inline-block;
  16 |   font-family: FontAwesome;
  17 |   font-style: normal;
  18 |   font-weight: normal;
  19 |   line-height: 1;
  20 |   -webkit-font-smoothing: antialiased;
  21 |   -moz-osx-font-smoothing: grayscale;
  22 | }
  23 | /* makes the font 33% larger relative to the icon container */
  24 | .fa-lg {
  25 |   font-size: 1.3333333333333333em;
  26 |   line-height: 0.75em;
  27 |   vertical-align: -15%;
  28 | }
  29 | .fa-2x {
  30 |   font-size: 2em;
  31 | }
  32 | .fa-3x {
  33 |   font-size: 3em;
  34 | }
  35 | .fa-4x {
  36 |   font-size: 4em;
  37 | }
  38 | .fa-5x {
  39 |   font-size: 5em;
  40 | }
  41 | .fa-fw {
  42 |   width: 1.2857142857142858em;
  43 |   text-align: center;
  44 | }
  45 | .fa-ul {
  46 |   padding-left: 0;
  47 |   margin-left: 2.142857142857143em;
  48 |   list-style-type: none;
  49 | }
  50 | .fa-ul > li {
  51 |   position: relative;
  52 | }
  53 | .fa-li {
  54 |   position: absolute;
  55 |   left: -2.142857142857143em;
  56 |   width: 2.142857142857143em;
  57 |   top: 0.14285714285714285em;
  58 |   text-align: center;
  59 | }
  60 | .fa-li.fa-lg {
  61 |   left: -1.8571428571428572em;
  62 | }
  63 | .fa-border {
  64 |   padding: .2em .25em .15em;
  65 |   border: solid 0.08em #eeeeee;
  66 |   border-radius: .1em;
  67 | }
  68 | .pull-right {
  69 |   float: right;
  70 | }
  71 | .pull-left {
  72 |   float: left;
  73 | }
  74 | .fa.pull-left {
  75 |   margin-right: .3em;
  76 | }
  77 | .fa.pull-right {
  78 |   margin-left: .3em;
  79 | }
  80 | .fa-spin {
  81 |   -webkit-animation: spin 2s infinite linear;
  82 |   -moz-animation: spin 2s infinite linear;
  83 |   -o-animation: spin 2s infinite linear;
  84 |   animation: spin 2s infinite linear;
  85 | }
  86 | @-moz-keyframes spin {
  87 |   0% {
  88 |     -moz-transform: rotate(0deg);
  89 |   }
  90 |   100% {
  91 |     -moz-transform: rotate(359deg);
  92 |   }
  93 | }
  94 | @-webkit-keyframes spin {
  95 |   0% {
  96 |     -webkit-transform: rotate(0deg);
  97 |   }
  98 |   100% {
  99 |     -webkit-transform: rotate(359deg);
 100 |   }
 101 | }
 102 | @-o-keyframes spin {
 103 |   0% {
 104 |     -o-transform: rotate(0deg);
 105 |   }
 106 |   100% {
 107 |     -o-transform: rotate(359deg);
 108 |   }
 109 | }
 110 | @-ms-keyframes spin {
 111 |   0% {
 112 |     -ms-transform: rotate(0deg);
 113 |   }
 114 |   100% {
 115 |     -ms-transform: rotate(359deg);
 116 |   }
 117 | }
 118 | @keyframes spin {
 119 |   0% {
 120 |     transform: rotate(0deg);
 121 |   }
 122 |   100% {
 123 |     transform: rotate(359deg);
 124 |   }
 125 | }
 126 | .fa-rotate-90 {
 127 |   filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
 128 |   -webkit-transform: rotate(90deg);
 129 |   -moz-transform: rotate(90deg);
 130 |   -ms-transform: rotate(90deg);
 131 |   -o-transform: rotate(90deg);
 132 |   transform: rotate(90deg);
 133 | }
 134 | .fa-rotate-180 {
 135 |   filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
 136 |   -webkit-transform: rotate(180deg);
 137 |   -moz-transform: rotate(180deg);
 138 |   -ms-transform: rotate(180deg);
 139 |   -o-transform: rotate(180deg);
 140 |   transform: rotate(180deg);
 141 | }
 142 | .fa-rotate-270 {
 143 |   filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
 144 |   -webkit-transform: rotate(270deg);
 145 |   -moz-transform: rotate(270deg);
 146 |   -ms-transform: rotate(270deg);
 147 |   -o-transform: rotate(270deg);
 148 |   transform: rotate(270deg);
 149 | }
 150 | .fa-flip-horizontal {
 151 |   filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
 152 |   -webkit-transform: scale(-1, 1);
 153 |   -moz-transform: scale(-1, 1);
 154 |   -ms-transform: scale(-1, 1);
 155 |   -o-transform: scale(-1, 1);
 156 |   transform: scale(-1, 1);
 157 | }
 158 | .fa-flip-vertical {
 159 |   filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
 160 |   -webkit-transform: scale(1, -1);
 161 |   -moz-transform: scale(1, -1);
 162 |   -ms-transform: scale(1, -1);
 163 |   -o-transform: scale(1, -1);
 164 |   transform: scale(1, -1);
 165 | }
 166 | .fa-stack {
 167 |   position: relative;
 168 |   display: inline-block;
 169 |   width: 2em;
 170 |   height: 2em;
 171 |   line-height: 2em;
 172 |   vertical-align: middle;
 173 | }
 174 | .fa-stack-1x,
 175 | .fa-stack-2x {
 176 |   position: absolute;
 177 |   left: 0;
 178 |   width: 100%;
 179 |   text-align: center;
 180 | }
 181 | .fa-stack-1x {
 182 |   line-height: inherit;
 183 | }
 184 | .fa-stack-2x {
 185 |   font-size: 2em;
 186 | }
 187 | .fa-inverse {
 188 |   color: #ffffff;
 189 | }
 190 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
 191 |    readers do not read off random characters that represent icons */
 192 | .fa-glass:before {
 193 |   content: "\f000";
 194 | }
 195 | .fa-music:before {
 196 |   content: "\f001";
 197 | }
 198 | .fa-search:before {
 199 |   content: "\f002";
 200 | }
 201 | .fa-envelope-o:before {
 202 |   content: "\f003";
 203 | }
 204 | .fa-heart:before {
 205 |   content: "\f004";
 206 | }
 207 | .fa-star:before {
 208 |   content: "\f005";
 209 | }
 210 | .fa-star-o:before {
 211 |   content: "\f006";
 212 | }
 213 | .fa-user:before {
 214 |   content: "\f007";
 215 | }
 216 | .fa-film:before {
 217 |   content: "\f008";
 218 | }
 219 | .fa-th-large:before {
 220 |   content: "\f009";
 221 | }
 222 | .fa-th:before {
 223 |   content: "\f00a";
 224 | }
 225 | .fa-th-list:before {
 226 |   content: "\f00b";
 227 | }
 228 | .fa-check:before {
 229 |   content: "\f00c";
 230 | }
 231 | .fa-times:before {
 232 |   content: "\f00d";
 233 | }
 234 | .fa-search-plus:before {
 235 |   content: "\f00e";
 236 | }
 237 | .fa-search-minus:before {
 238 |   content: "\f010";
 239 | }
 240 | .fa-power-off:before {
 241 |   content: "\f011";
 242 | }
 243 | .fa-signal:before {
 244 |   content: "\f012";
 245 | }
 246 | .fa-gear:before,
 247 | .fa-cog:before {
 248 |   content: "\f013";
 249 | }
 250 | .fa-trash-o:before {
 251 |   content: "\f014";
 252 | }
 253 | .fa-home:before {
 254 |   content: "\f015";
 255 | }
 256 | .fa-file-o:before {
 257 |   content: "\f016";
 258 | }
 259 | .fa-clock-o:before {
 260 |   content: "\f017";
 261 | }
 262 | .fa-road:before {
 263 |   content: "\f018";
 264 | }
 265 | .fa-download:before {
 266 |   content: "\f019";
 267 | }
 268 | .fa-arrow-circle-o-down:before {
 269 |   content: "\f01a";
 270 | }
 271 | .fa-arrow-circle-o-up:before {
 272 |   content: "\f01b";
 273 | }
 274 | .fa-inbox:before {
 275 |   content: "\f01c";
 276 | }
 277 | .fa-play-circle-o:before {
 278 |   content: "\f01d";
 279 | }
 280 | .fa-rotate-right:before,
 281 | .fa-repeat:before {
 282 |   content: "\f01e";
 283 | }
 284 | .fa-refresh:before {
 285 |   content: "\f021";
 286 | }
 287 | .fa-list-alt:before {
 288 |   content: "\f022";
 289 | }
 290 | .fa-lock:before {
 291 |   content: "\f023";
 292 | }
 293 | .fa-flag:before {
 294 |   content: "\f024";
 295 | }
 296 | .fa-headphones:before {
 297 |   content: "\f025";
 298 | }
 299 | .fa-volume-off:before {
 300 |   content: "\f026";
 301 | }
 302 | .fa-volume-down:before {
 303 |   content: "\f027";
 304 | }
 305 | .fa-volume-up:before {
 306 |   content: "\f028";
 307 | }
 308 | .fa-qrcode:before {
 309 |   content: "\f029";
 310 | }
 311 | .fa-barcode:before {
 312 |   content: "\f02a";
 313 | }
 314 | .fa-tag:before {
 315 |   content: "\f02b";
 316 | }
 317 | .fa-tags:before {
 318 |   content: "\f02c";
 319 | }
 320 | .fa-book:before {
 321 |   content: "\f02d";
 322 | }
 323 | .fa-bookmark:before {
 324 |   content: "\f02e";
 325 | }
 326 | .fa-print:before {
 327 |   content: "\f02f";
 328 | }
 329 | .fa-camera:before {
 330 |   content: "\f030";
 331 | }
 332 | .fa-font:before {
 333 |   content: "\f031";
 334 | }
 335 | .fa-bold:before {
 336 |   content: "\f032";
 337 | }
 338 | .fa-italic:before {
 339 |   content: "\f033";
 340 | }
 341 | .fa-text-height:before {
 342 |   content: "\f034";
 343 | }
 344 | .fa-text-width:before {
 345 |   content: "\f035";
 346 | }
 347 | .fa-align-left:before {
 348 |   content: "\f036";
 349 | }
 350 | .fa-align-center:before {
 351 |   content: "\f037";
 352 | }
 353 | .fa-align-right:before {
 354 |   content: "\f038";
 355 | }
 356 | .fa-align-justify:before {
 357 |   content: "\f039";
 358 | }
 359 | .fa-list:before {
 360 |   content: "\f03a";
 361 | }
 362 | .fa-dedent:before,
 363 | .fa-outdent:before {
 364 |   content: "\f03b";
 365 | }
 366 | .fa-indent:before {
 367 |   content: "\f03c";
 368 | }
 369 | .fa-video-camera:before {
 370 |   content: "\f03d";
 371 | }
 372 | .fa-picture-o:before {
 373 |   content: "\f03e";
 374 | }
 375 | .fa-pencil:before {
 376 |   content: "\f040";
 377 | }
 378 | .fa-map-marker:before {
 379 |   content: "\f041";
 380 | }
 381 | .fa-adjust:before {
 382 |   content: "\f042";
 383 | }
 384 | .fa-tint:before {
 385 |   content: "\f043";
 386 | }
 387 | .fa-edit:before,
 388 | .fa-pencil-square-o:before {
 389 |   content: "\f044";
 390 | }
 391 | .fa-share-square-o:before {
 392 |   content: "\f045";
 393 | }
 394 | .fa-check-square-o:before {
 395 |   content: "\f046";
 396 | }
 397 | .fa-arrows:before {
 398 |   content: "\f047";
 399 | }
 400 | .fa-step-backward:before {
 401 |   content: "\f048";
 402 | }
 403 | .fa-fast-backward:before {
 404 |   content: "\f049";
 405 | }
 406 | .fa-backward:before {
 407 |   content: "\f04a";
 408 | }
 409 | .fa-play:before {
 410 |   content: "\f04b";
 411 | }
 412 | .fa-pause:before {
 413 |   content: "\f04c";
 414 | }
 415 | .fa-stop:before {
 416 |   content: "\f04d";
 417 | }
 418 | .fa-forward:before {
 419 |   content: "\f04e";
 420 | }
 421 | .fa-fast-forward:before {
 422 |   content: "\f050";
 423 | }
 424 | .fa-step-forward:before {
 425 |   content: "\f051";
 426 | }
 427 | .fa-eject:before {
 428 |   content: "\f052";
 429 | }
 430 | .fa-chevron-left:before {
 431 |   content: "\f053";
 432 | }
 433 | .fa-chevron-right:before {
 434 |   content: "\f054";
 435 | }
 436 | .fa-plus-circle:before {
 437 |   content: "\f055";
 438 | }
 439 | .fa-minus-circle:before {
 440 |   content: "\f056";
 441 | }
 442 | .fa-times-circle:before {
 443 |   content: "\f057";
 444 | }
 445 | .fa-check-circle:before {
 446 |   content: "\f058";
 447 | }
 448 | .fa-question-circle:before {
 449 |   content: "\f059";
 450 | }
 451 | .fa-info-circle:before {
 452 |   content: "\f05a";
 453 | }
 454 | .fa-crosshairs:before {
 455 |   content: "\f05b";
 456 | }
 457 | .fa-times-circle-o:before {
 458 |   content: "\f05c";
 459 | }
 460 | .fa-check-circle-o:before {
 461 |   content: "\f05d";
 462 | }
 463 | .fa-ban:before {
 464 |   content: "\f05e";
 465 | }
 466 | .fa-arrow-left:before {
 467 |   content: "\f060";
 468 | }
 469 | .fa-arrow-right:before {
 470 |   content: "\f061";
 471 | }
 472 | .fa-arrow-up:before {
 473 |   content: "\f062";
 474 | }
 475 | .fa-arrow-down:before {
 476 |   content: "\f063";
 477 | }
 478 | .fa-mail-forward:before,
 479 | .fa-share:before {
 480 |   content: "\f064";
 481 | }
 482 | .fa-expand:before {
 483 |   content: "\f065";
 484 | }
 485 | .fa-compress:before {
 486 |   content: "\f066";
 487 | }
 488 | .fa-plus:before {
 489 |   content: "\f067";
 490 | }
 491 | .fa-minus:before {
 492 |   content: "\f068";
 493 | }
 494 | .fa-asterisk:before {
 495 |   content: "\f069";
 496 | }
 497 | .fa-exclamation-circle:before {
 498 |   content: "\f06a";
 499 | }
 500 | .fa-gift:before {
 501 |   content: "\f06b";
 502 | }
 503 | .fa-leaf:before {
 504 |   content: "\f06c";
 505 | }
 506 | .fa-fire:before {
 507 |   content: "\f06d";
 508 | }
 509 | .fa-eye:before {
 510 |   content: "\f06e";
 511 | }
 512 | .fa-eye-slash:before {
 513 |   content: "\f070";
 514 | }
 515 | .fa-warning:before,
 516 | .fa-exclamation-triangle:before {
 517 |   content: "\f071";
 518 | }
 519 | .fa-plane:before {
 520 |   content: "\f072";
 521 | }
 522 | .fa-calendar:before {
 523 |   content: "\f073";
 524 | }
 525 | .fa-random:before {
 526 |   content: "\f074";
 527 | }
 528 | .fa-comment:before {
 529 |   content: "\f075";
 530 | }
 531 | .fa-magnet:before {
 532 |   content: "\f076";
 533 | }
 534 | .fa-chevron-up:before {
 535 |   content: "\f077";
 536 | }
 537 | .fa-chevron-down:before {
 538 |   content: "\f078";
 539 | }
 540 | .fa-retweet:before {
 541 |   content: "\f079";
 542 | }
 543 | .fa-shopping-cart:before {
 544 |   content: "\f07a";
 545 | }
 546 | .fa-folder:before {
 547 |   content: "\f07b";
 548 | }
 549 | .fa-folder-open:before {
 550 |   content: "\f07c";
 551 | }
 552 | .fa-arrows-v:before {
 553 |   content: "\f07d";
 554 | }
 555 | .fa-arrows-h:before {
 556 |   content: "\f07e";
 557 | }
 558 | .fa-bar-chart-o:before {
 559 |   content: "\f080";
 560 | }
 561 | .fa-twitter-square:before {
 562 |   content: "\f081";
 563 | }
 564 | .fa-facebook-square:before {
 565 |   content: "\f082";
 566 | }
 567 | .fa-camera-retro:before {
 568 |   content: "\f083";
 569 | }
 570 | .fa-key:before {
 571 |   content: "\f084";
 572 | }
 573 | .fa-gears:before,
 574 | .fa-cogs:before {
 575 |   content: "\f085";
 576 | }
 577 | .fa-comments:before {
 578 |   content: "\f086";
 579 | }
 580 | .fa-thumbs-o-up:before {
 581 |   content: "\f087";
 582 | }
 583 | .fa-thumbs-o-down:before {
 584 |   content: "\f088";
 585 | }
 586 | .fa-star-half:before {
 587 |   content: "\f089";
 588 | }
 589 | .fa-heart-o:before {
 590 |   content: "\f08a";
 591 | }
 592 | .fa-sign-out:before {
 593 |   content: "\f08b";
 594 | }
 595 | .fa-linkedin-square:before {
 596 |   content: "\f08c";
 597 | }
 598 | .fa-thumb-tack:before {
 599 |   content: "\f08d";
 600 | }
 601 | .fa-external-link:before {
 602 |   content: "\f08e";
 603 | }
 604 | .fa-sign-in:before {
 605 |   content: "\f090";
 606 | }
 607 | .fa-trophy:before {
 608 |   content: "\f091";
 609 | }
 610 | .fa-github-square:before {
 611 |   content: "\f092";
 612 | }
 613 | .fa-upload:before {
 614 |   content: "\f093";
 615 | }
 616 | .fa-lemon-o:before {
 617 |   content: "\f094";
 618 | }
 619 | .fa-phone:before {
 620 |   content: "\f095";
 621 | }
 622 | .fa-square-o:before {
 623 |   content: "\f096";
 624 | }
 625 | .fa-bookmark-o:before {
 626 |   content: "\f097";
 627 | }
 628 | .fa-phone-square:before {
 629 |   content: "\f098";
 630 | }
 631 | .fa-twitter:before {
 632 |   content: "\f099";
 633 | }
 634 | .fa-facebook:before {
 635 |   content: "\f09a";
 636 | }
 637 | .fa-github:before {
 638 |   content: "\f09b";
 639 | }
 640 | .fa-unlock:before {
 641 |   content: "\f09c";
 642 | }
 643 | .fa-credit-card:before {
 644 |   content: "\f09d";
 645 | }
 646 | .fa-rss:before {
 647 |   content: "\f09e";
 648 | }
 649 | .fa-hdd-o:before {
 650 |   content: "\f0a0";
 651 | }
 652 | .fa-bullhorn:before {
 653 |   content: "\f0a1";
 654 | }
 655 | .fa-bell:before {
 656 |   content: "\f0f3";
 657 | }
 658 | .fa-certificate:before {
 659 |   content: "\f0a3";
 660 | }
 661 | .fa-hand-o-right:before {
 662 |   content: "\f0a4";
 663 | }
 664 | .fa-hand-o-left:before {
 665 |   content: "\f0a5";
 666 | }
 667 | .fa-hand-o-up:before {
 668 |   content: "\f0a6";
 669 | }
 670 | .fa-hand-o-down:before {
 671 |   content: "\f0a7";
 672 | }
 673 | .fa-arrow-circle-left:before {
 674 |   content: "\f0a8";
 675 | }
 676 | .fa-arrow-circle-right:before {
 677 |   content: "\f0a9";
 678 | }
 679 | .fa-arrow-circle-up:before {
 680 |   content: "\f0aa";
 681 | }
 682 | .fa-arrow-circle-down:before {
 683 |   content: "\f0ab";
 684 | }
 685 | .fa-globe:before {
 686 |   content: "\f0ac";
 687 | }
 688 | .fa-wrench:before {
 689 |   content: "\f0ad";
 690 | }
 691 | .fa-tasks:before {
 692 |   content: "\f0ae";
 693 | }
 694 | .fa-filter:before {
 695 |   content: "\f0b0";
 696 | }
 697 | .fa-briefcase:before {
 698 |   content: "\f0b1";
 699 | }
 700 | .fa-arrows-alt:before {
 701 |   content: "\f0b2";
 702 | }
 703 | .fa-group:before,
 704 | .fa-users:before {
 705 |   content: "\f0c0";
 706 | }
 707 | .fa-chain:before,
 708 | .fa-link:before {
 709 |   content: "\f0c1";
 710 | }
 711 | .fa-cloud:before {
 712 |   content: "\f0c2";
 713 | }
 714 | .fa-flask:before {
 715 |   content: "\f0c3";
 716 | }
 717 | .fa-cut:before,
 718 | .fa-scissors:before {
 719 |   content: "\f0c4";
 720 | }
 721 | .fa-copy:before,
 722 | .fa-files-o:before {
 723 |   content: "\f0c5";
 724 | }
 725 | .fa-paperclip:before {
 726 |   content: "\f0c6";
 727 | }
 728 | .fa-save:before,
 729 | .fa-floppy-o:before {
 730 |   content: "\f0c7";
 731 | }
 732 | .fa-square:before {
 733 |   content: "\f0c8";
 734 | }
 735 | .fa-bars:before {
 736 |   content: "\f0c9";
 737 | }
 738 | .fa-list-ul:before {
 739 |   content: "\f0ca";
 740 | }
 741 | .fa-list-ol:before {
 742 |   content: "\f0cb";
 743 | }
 744 | .fa-strikethrough:before {
 745 |   content: "\f0cc";
 746 | }
 747 | .fa-underline:before {
 748 |   content: "\f0cd";
 749 | }
 750 | .fa-table:before {
 751 |   content: "\f0ce";
 752 | }
 753 | .fa-magic:before {
 754 |   content: "\f0d0";
 755 | }
 756 | .fa-truck:before {
 757 |   content: "\f0d1";
 758 | }
 759 | .fa-pinterest:before {
 760 |   content: "\f0d2";
 761 | }
 762 | .fa-pinterest-square:before {
 763 |   content: "\f0d3";
 764 | }
 765 | .fa-google-plus-square:before {
 766 |   content: "\f0d4";
 767 | }
 768 | .fa-google-plus:before {
 769 |   content: "\f0d5";
 770 | }
 771 | .fa-money:before {
 772 |   content: "\f0d6";
 773 | }
 774 | .fa-caret-down:before {
 775 |   content: "\f0d7";
 776 | }
 777 | .fa-caret-up:before {
 778 |   content: "\f0d8";
 779 | }
 780 | .fa-caret-left:before {
 781 |   content: "\f0d9";
 782 | }
 783 | .fa-caret-right:before {
 784 |   content: "\f0da";
 785 | }
 786 | .fa-columns:before {
 787 |   content: "\f0db";
 788 | }
 789 | .fa-unsorted:before,
 790 | .fa-sort:before {
 791 |   content: "\f0dc";
 792 | }
 793 | .fa-sort-down:before,
 794 | .fa-sort-asc:before {
 795 |   content: "\f0dd";
 796 | }
 797 | .fa-sort-up:before,
 798 | .fa-sort-desc:before {
 799 |   content: "\f0de";
 800 | }
 801 | .fa-envelope:before {
 802 |   content: "\f0e0";
 803 | }
 804 | .fa-linkedin:before {
 805 |   content: "\f0e1";
 806 | }
 807 | .fa-rotate-left:before,
 808 | .fa-undo:before {
 809 |   content: "\f0e2";
 810 | }
 811 | .fa-legal:before,
 812 | .fa-gavel:before {
 813 |   content: "\f0e3";
 814 | }
 815 | .fa-dashboard:before,
 816 | .fa-tachometer:before {
 817 |   content: "\f0e4";
 818 | }
 819 | .fa-comment-o:before {
 820 |   content: "\f0e5";
 821 | }
 822 | .fa-comments-o:before {
 823 |   content: "\f0e6";
 824 | }
 825 | .fa-flash:before,
 826 | .fa-bolt:before {
 827 |   content: "\f0e7";
 828 | }
 829 | .fa-sitemap:before {
 830 |   content: "\f0e8";
 831 | }
 832 | .fa-umbrella:before {
 833 |   content: "\f0e9";
 834 | }
 835 | .fa-paste:before,
 836 | .fa-clipboard:before {
 837 |   content: "\f0ea";
 838 | }
 839 | .fa-lightbulb-o:before {
 840 |   content: "\f0eb";
 841 | }
 842 | .fa-exchange:before {
 843 |   content: "\f0ec";
 844 | }
 845 | .fa-cloud-download:before {
 846 |   content: "\f0ed";
 847 | }
 848 | .fa-cloud-upload:before {
 849 |   content: "\f0ee";
 850 | }
 851 | .fa-user-md:before {
 852 |   content: "\f0f0";
 853 | }
 854 | .fa-stethoscope:before {
 855 |   content: "\f0f1";
 856 | }
 857 | .fa-suitcase:before {
 858 |   content: "\f0f2";
 859 | }
 860 | .fa-bell-o:before {
 861 |   content: "\f0a2";
 862 | }
 863 | .fa-coffee:before {
 864 |   content: "\f0f4";
 865 | }
 866 | .fa-cutlery:before {
 867 |   content: "\f0f5";
 868 | }
 869 | .fa-file-text-o:before {
 870 |   content: "\f0f6";
 871 | }
 872 | .fa-building-o:before {
 873 |   content: "\f0f7";
 874 | }
 875 | .fa-hospital-o:before {
 876 |   content: "\f0f8";
 877 | }
 878 | .fa-ambulance:before {
 879 |   content: "\f0f9";
 880 | }
 881 | .fa-medkit:before {
 882 |   content: "\f0fa";
 883 | }
 884 | .fa-fighter-jet:before {
 885 |   content: "\f0fb";
 886 | }
 887 | .fa-beer:before {
 888 |   content: "\f0fc";
 889 | }
 890 | .fa-h-square:before {
 891 |   content: "\f0fd";
 892 | }
 893 | .fa-plus-square:before {
 894 |   content: "\f0fe";
 895 | }
 896 | .fa-angle-double-left:before {
 897 |   content: "\f100";
 898 | }
 899 | .fa-angle-double-right:before {
 900 |   content: "\f101";
 901 | }
 902 | .fa-angle-double-up:before {
 903 |   content: "\f102";
 904 | }
 905 | .fa-angle-double-down:before {
 906 |   content: "\f103";
 907 | }
 908 | .fa-angle-left:before {
 909 |   content: "\f104";
 910 | }
 911 | .fa-angle-right:before {
 912 |   content: "\f105";
 913 | }
 914 | .fa-angle-up:before {
 915 |   content: "\f106";
 916 | }
 917 | .fa-angle-down:before {
 918 |   content: "\f107";
 919 | }
 920 | .fa-desktop:before {
 921 |   content: "\f108";
 922 | }
 923 | .fa-laptop:before {
 924 |   content: "\f109";
 925 | }
 926 | .fa-tablet:before {
 927 |   content: "\f10a";
 928 | }
 929 | .fa-mobile-phone:before,
 930 | .fa-mobile:before {
 931 |   content: "\f10b";
 932 | }
 933 | .fa-circle-o:before {
 934 |   content: "\f10c";
 935 | }
 936 | .fa-quote-left:before {
 937 |   content: "\f10d";
 938 | }
 939 | .fa-quote-right:before {
 940 |   content: "\f10e";
 941 | }
 942 | .fa-spinner:before {
 943 |   content: "\f110";
 944 | }
 945 | .fa-circle:before {
 946 |   content: "\f111";
 947 | }
 948 | .fa-mail-reply:before,
 949 | .fa-reply:before {
 950 |   content: "\f112";
 951 | }
 952 | .fa-github-alt:before {
 953 |   content: "\f113";
 954 | }
 955 | .fa-folder-o:before {
 956 |   content: "\f114";
 957 | }
 958 | .fa-folder-open-o:before {
 959 |   content: "\f115";
 960 | }
 961 | .fa-smile-o:before {
 962 |   content: "\f118";
 963 | }
 964 | .fa-frown-o:before {
 965 |   content: "\f119";
 966 | }
 967 | .fa-meh-o:before {
 968 |   content: "\f11a";
 969 | }
 970 | .fa-gamepad:before {
 971 |   content: "\f11b";
 972 | }
 973 | .fa-keyboard-o:before {
 974 |   content: "\f11c";
 975 | }
 976 | .fa-flag-o:before {
 977 |   content: "\f11d";
 978 | }
 979 | .fa-flag-checkered:before {
 980 |   content: "\f11e";
 981 | }
 982 | .fa-terminal:before {
 983 |   content: "\f120";
 984 | }
 985 | .fa-code:before {
 986 |   content: "\f121";
 987 | }
 988 | .fa-reply-all:before {
 989 |   content: "\f122";
 990 | }
 991 | .fa-mail-reply-all:before {
 992 |   content: "\f122";
 993 | }
 994 | .fa-star-half-empty:before,
 995 | .fa-star-half-full:before,
 996 | .fa-star-half-o:before {
 997 |   content: "\f123";
 998 | }
 999 | .fa-location-arrow:before {
1000 |   content: "\f124";
1001 | }
1002 | .fa-crop:before {
1003 |   content: "\f125";
1004 | }
1005 | .fa-code-fork:before {
1006 |   content: "\f126";
1007 | }
1008 | .fa-unlink:before,
1009 | .fa-chain-broken:before {
1010 |   content: "\f127";
1011 | }
1012 | .fa-question:before {
1013 |   content: "\f128";
1014 | }
1015 | .fa-info:before {
1016 |   content: "\f129";
1017 | }
1018 | .fa-exclamation:before {
1019 |   content: "\f12a";
1020 | }
1021 | .fa-superscript:before {
1022 |   content: "\f12b";
1023 | }
1024 | .fa-subscript:before {
1025 |   content: "\f12c";
1026 | }
1027 | .fa-eraser:before {
1028 |   content: "\f12d";
1029 | }
1030 | .fa-puzzle-piece:before {
1031 |   content: "\f12e";
1032 | }
1033 | .fa-microphone:before {
1034 |   content: "\f130";
1035 | }
1036 | .fa-microphone-slash:before {
1037 |   content: "\f131";
1038 | }
1039 | .fa-shield:before {
1040 |   content: "\f132";
1041 | }
1042 | .fa-calendar-o:before {
1043 |   content: "\f133";
1044 | }
1045 | .fa-fire-extinguisher:before {
1046 |   content: "\f134";
1047 | }
1048 | .fa-rocket:before {
1049 |   content: "\f135";
1050 | }
1051 | .fa-maxcdn:before {
1052 |   content: "\f136";
1053 | }
1054 | .fa-chevron-circle-left:before {
1055 |   content: "\f137";
1056 | }
1057 | .fa-chevron-circle-right:before {
1058 |   content: "\f138";
1059 | }
1060 | .fa-chevron-circle-up:before {
1061 |   content: "\f139";
1062 | }
1063 | .fa-chevron-circle-down:before {
1064 |   content: "\f13a";
1065 | }
1066 | .fa-html5:before {
1067 |   content: "\f13b";
1068 | }
1069 | .fa-css3:before {
1070 |   content: "\f13c";
1071 | }
1072 | .fa-anchor:before {
1073 |   content: "\f13d";
1074 | }
1075 | .fa-unlock-alt:before {
1076 |   content: "\f13e";
1077 | }
1078 | .fa-bullseye:before {
1079 |   content: "\f140";
1080 | }
1081 | .fa-ellipsis-h:before {
1082 |   content: "\f141";
1083 | }
1084 | .fa-ellipsis-v:before {
1085 |   content: "\f142";
1086 | }
1087 | .fa-rss-square:before {
1088 |   content: "\f143";
1089 | }
1090 | .fa-play-circle:before {
1091 |   content: "\f144";
1092 | }
1093 | .fa-ticket:before {
1094 |   content: "\f145";
1095 | }
1096 | .fa-minus-square:before {
1097 |   content: "\f146";
1098 | }
1099 | .fa-minus-square-o:before {
1100 |   content: "\f147";
1101 | }
1102 | .fa-level-up:before {
1103 |   content: "\f148";
1104 | }
1105 | .fa-level-down:before {
1106 |   content: "\f149";
1107 | }
1108 | .fa-check-square:before {
1109 |   content: "\f14a";
1110 | }
1111 | .fa-pencil-square:before {
1112 |   content: "\f14b";
1113 | }
1114 | .fa-external-link-square:before {
1115 |   content: "\f14c";
1116 | }
1117 | .fa-share-square:before {
1118 |   content: "\f14d";
1119 | }
1120 | .fa-compass:before {
1121 |   content: "\f14e";
1122 | }
1123 | .fa-toggle-down:before,
1124 | .fa-caret-square-o-down:before {
1125 |   content: "\f150";
1126 | }
1127 | .fa-toggle-up:before,
1128 | .fa-caret-square-o-up:before {
1129 |   content: "\f151";
1130 | }
1131 | .fa-toggle-right:before,
1132 | .fa-caret-square-o-right:before {
1133 |   content: "\f152";
1134 | }
1135 | .fa-euro:before,
1136 | .fa-eur:before {
1137 |   content: "\f153";
1138 | }
1139 | .fa-gbp:before {
1140 |   content: "\f154";
1141 | }
1142 | .fa-dollar:before,
1143 | .fa-usd:before {
1144 |   content: "\f155";
1145 | }
1146 | .fa-rupee:before,
1147 | .fa-inr:before {
1148 |   content: "\f156";
1149 | }
1150 | .fa-cny:before,
1151 | .fa-rmb:before,
1152 | .fa-yen:before,
1153 | .fa-jpy:before {
1154 |   content: "\f157";
1155 | }
1156 | .fa-ruble:before,
1157 | .fa-rouble:before,
1158 | .fa-rub:before {
1159 |   content: "\f158";
1160 | }
1161 | .fa-won:before,
1162 | .fa-krw:before {
1163 |   content: "\f159";
1164 | }
1165 | .fa-bitcoin:before,
1166 | .fa-btc:before {
1167 |   content: "\f15a";
1168 | }
1169 | .fa-file:before {
1170 |   content: "\f15b";
1171 | }
1172 | .fa-file-text:before {
1173 |   content: "\f15c";
1174 | }
1175 | .fa-sort-alpha-asc:before {
1176 |   content: "\f15d";
1177 | }
1178 | .fa-sort-alpha-desc:before {
1179 |   content: "\f15e";
1180 | }
1181 | .fa-sort-amount-asc:before {
1182 |   content: "\f160";
1183 | }
1184 | .fa-sort-amount-desc:before {
1185 |   content: "\f161";
1186 | }
1187 | .fa-sort-numeric-asc:before {
1188 |   content: "\f162";
1189 | }
1190 | .fa-sort-numeric-desc:before {
1191 |   content: "\f163";
1192 | }
1193 | .fa-thumbs-up:before {
1194 |   content: "\f164";
1195 | }
1196 | .fa-thumbs-down:before {
1197 |   content: "\f165";
1198 | }
1199 | .fa-youtube-square:before {
1200 |   content: "\f166";
1201 | }
1202 | .fa-youtube:before {
1203 |   content: "\f167";
1204 | }
1205 | .fa-xing:before {
1206 |   content: "\f168";
1207 | }
1208 | .fa-xing-square:before {
1209 |   content: "\f169";
1210 | }
1211 | .fa-youtube-play:before {
1212 |   content: "\f16a";
1213 | }
1214 | .fa-dropbox:before {
1215 |   content: "\f16b";
1216 | }
1217 | .fa-stack-overflow:before {
1218 |   content: "\f16c";
1219 | }
1220 | .fa-instagram:before {
1221 |   content: "\f16d";
1222 | }
1223 | .fa-flickr:before {
1224 |   content: "\f16e";
1225 | }
1226 | .fa-adn:before {
1227 |   content: "\f170";
1228 | }
1229 | .fa-bitbucket:before {
1230 |   content: "\f171";
1231 | }
1232 | .fa-bitbucket-square:before {
1233 |   content: "\f172";
1234 | }
1235 | .fa-tumblr:before {
1236 |   content: "\f173";
1237 | }
1238 | .fa-tumblr-square:before {
1239 |   content: "\f174";
1240 | }
1241 | .fa-long-arrow-down:before {
1242 |   content: "\f175";
1243 | }
1244 | .fa-long-arrow-up:before {
1245 |   content: "\f176";
1246 | }
1247 | .fa-long-arrow-left:before {
1248 |   content: "\f177";
1249 | }
1250 | .fa-long-arrow-right:before {
1251 |   content: "\f178";
1252 | }
1253 | .fa-apple:before {
1254 |   content: "\f179";
1255 | }
1256 | .fa-windows:before {
1257 |   content: "\f17a";
1258 | }
1259 | .fa-android:before {
1260 |   content: "\f17b";
1261 | }
1262 | .fa-linux:before {
1263 |   content: "\f17c";
1264 | }
1265 | .fa-dribbble:before {
1266 |   content: "\f17d";
1267 | }
1268 | .fa-skype:before {
1269 |   content: "\f17e";
1270 | }
1271 | .fa-foursquare:before {
1272 |   content: "\f180";
1273 | }
1274 | .fa-trello:before {
1275 |   content: "\f181";
1276 | }
1277 | .fa-female:before {
1278 |   content: "\f182";
1279 | }
1280 | .fa-male:before {
1281 |   content: "\f183";
1282 | }
1283 | .fa-gittip:before {
1284 |   content: "\f184";
1285 | }
1286 | .fa-sun-o:before {
1287 |   content: "\f185";
1288 | }
1289 | .fa-moon-o:before {
1290 |   content: "\f186";
1291 | }
1292 | .fa-archive:before {
1293 |   content: "\f187";
1294 | }
1295 | .fa-bug:before {
1296 |   content: "\f188";
1297 | }
1298 | .fa-vk:before {
1299 |   content: "\f189";
1300 | }
1301 | .fa-weibo:before {
1302 |   content: "\f18a";
1303 | }
1304 | .fa-renren:before {
1305 |   content: "\f18b";
1306 | }
1307 | .fa-pagelines:before {
1308 |   content: "\f18c";
1309 | }
1310 | .fa-stack-exchange:before {
1311 |   content: "\f18d";
1312 | }
1313 | .fa-arrow-circle-o-right:before {
1314 |   content: "\f18e";
1315 | }
1316 | .fa-arrow-circle-o-left:before {
1317 |   content: "\f190";
1318 | }
1319 | .fa-toggle-left:before,
1320 | .fa-caret-square-o-left:before {
1321 |   content: "\f191";
1322 | }
1323 | .fa-dot-circle-o:before {
1324 |   content: "\f192";
1325 | }
1326 | .fa-wheelchair:before {
1327 |   content: "\f193";
1328 | }
1329 | .fa-vimeo-square:before {
1330 |   content: "\f194";
1331 | }
1332 | .fa-turkish-lira:before,
1333 | .fa-try:before {
1334 |   content: "\f195";
1335 | }
1336 | .fa-plus-square-o:before {
1337 |   content: "\f196";
1338 | }
1339 | 


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/css/highlight.css:
--------------------------------------------------------------------------------
  1 | /*
  2 | This is the GitHub theme for highlight.js
  3 | 
  4 | github.com style (c) Vasily Polovnyov 
  5 | 
  6 | */
  7 | 
  8 | .hljs {
  9 |   display: block;
 10 |   overflow-x: auto;
 11 |   padding: 0.5em;
 12 |   color: #333;
 13 |   -webkit-text-size-adjust: none;
 14 | }
 15 | 
 16 | .hljs-comment,
 17 | .diff .hljs-header,
 18 | .hljs-javadoc {
 19 |   color: #998;
 20 |   font-style: italic;
 21 | }
 22 | 
 23 | .hljs-keyword,
 24 | .css .rule .hljs-keyword,
 25 | .hljs-winutils,
 26 | .nginx .hljs-title,
 27 | .hljs-subst,
 28 | .hljs-request,
 29 | .hljs-status {
 30 |   color: #333;
 31 |   font-weight: bold;
 32 | }
 33 | 
 34 | .hljs-number,
 35 | .hljs-hexcolor,
 36 | .ruby .hljs-constant {
 37 |   color: #008080;
 38 | }
 39 | 
 40 | .hljs-string,
 41 | .hljs-tag .hljs-value,
 42 | .hljs-phpdoc,
 43 | .hljs-dartdoc,
 44 | .tex .hljs-formula {
 45 |   color: #d14;
 46 | }
 47 | 
 48 | .hljs-title,
 49 | .hljs-id,
 50 | .scss .hljs-preprocessor {
 51 |   color: #900;
 52 |   font-weight: bold;
 53 | }
 54 | 
 55 | .hljs-list .hljs-keyword,
 56 | .hljs-subst {
 57 |   font-weight: normal;
 58 | }
 59 | 
 60 | .hljs-class .hljs-title,
 61 | .hljs-type,
 62 | .vhdl .hljs-literal,
 63 | .tex .hljs-command {
 64 |   color: #458;
 65 |   font-weight: bold;
 66 | }
 67 | 
 68 | .hljs-tag,
 69 | .hljs-tag .hljs-title,
 70 | .hljs-rule .hljs-property,
 71 | .django .hljs-tag .hljs-keyword {
 72 |   color: #000080;
 73 |   font-weight: normal;
 74 | }
 75 | 
 76 | .hljs-attribute,
 77 | .hljs-variable,
 78 | .lisp .hljs-body,
 79 | .hljs-name {
 80 |   color: #008080;
 81 | }
 82 | 
 83 | .hljs-regexp {
 84 |   color: #009926;
 85 | }
 86 | 
 87 | .hljs-symbol,
 88 | .ruby .hljs-symbol .hljs-string,
 89 | .lisp .hljs-keyword,
 90 | .clojure .hljs-keyword,
 91 | .scheme .hljs-keyword,
 92 | .tex .hljs-special,
 93 | .hljs-prompt {
 94 |   color: #990073;
 95 | }
 96 | 
 97 | .hljs-built_in {
 98 |   color: #0086b3;
 99 | }
100 | 
101 | .hljs-preprocessor,
102 | .hljs-pragma,
103 | .hljs-pi,
104 | .hljs-doctype,
105 | .hljs-shebang,
106 | .hljs-cdata {
107 |   color: #999;
108 |   font-weight: bold;
109 | }
110 | 
111 | .hljs-deletion {
112 |   background: #fdd;
113 | }
114 | 
115 | .hljs-addition {
116 |   background: #dfd;
117 | }
118 | 
119 | .diff .hljs-change {
120 |   background: #0086b3;
121 | }
122 | 
123 | .hljs-chunk {
124 |   color: #aaa;
125 | }
126 | 


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/css/jquery.json-view.min.css:
--------------------------------------------------------------------------------
 1 | .json-view{position:relative}
 2 | .json-view .collapser{width:20px;height:18px;display:block;position:absolute;left:-1.7em;top:-.2em;z-index:5;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYGBgOADE%2F3Hgw0DM4IRHgSsDFOzFInmMAQnY49ONzZRjDFiADT7dMLALiE8y4AGW6LoBAgwAuIkf%2F%2FB7O9sAAAAASUVORK5CYII%3D);background-repeat:no-repeat;background-position:center center;opacity:.5;cursor:pointer}
 3 | .json-view .collapsed{-ms-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-khtml-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}
 4 | .json-view .bl{display:block;padding-left:20px;margin-left:-20px;position:relative}
 5 | .json-view{font-family:monospace}
 6 | .json-view ul{list-style-type:none;padding-left:2em;border-left:1px dotted;margin:.3em}
 7 | .json-view ul li{position:relative}
 8 | .json-view .comments,.json-view .dots{display:none;-moz-user-select:none;-ms-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}
 9 | .json-view .comments{padding-left:.8em;font-style:italic;color:#888}
10 | .json-view .bool,.json-view .null,.json-view .num,.json-view .undef{font-weight:700;color:#1A01CC}
11 | .json-view .str{color:#800}


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.eot


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.ttf


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/fontawesome-webfont.woff


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.eot


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.ttf


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff2


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/img/favicon.ico


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/img/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyantarek/django-microservices/205acee4f006b2dd8ed40b7f54021003b2899bc8/services/products/static/rest_framework/docs/img/grid.png


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/js/api.js:
--------------------------------------------------------------------------------
  1 | var responseDisplay = 'data'
  2 | var coreapi = window.coreapi
  3 | var schema = window.schema
  4 | 
  5 | function normalizeKeys (arr) {
  6 |   var _normarr = [];
  7 |   for (var i = 0; i < arr.length; i++) {
  8 |     _normarr = _normarr.concat(arr[i].split(' > '));
  9 |   }
 10 |   return _normarr;
 11 | }
 12 | 
 13 | function normalizeHTTPHeader (str) {
 14 |   // Capitalize HTTP headers for display.
 15 |   return (str.charAt(0).toUpperCase() + str.substring(1))
 16 |     .replace(/-(.)/g, function ($1) {
 17 |       return $1.toUpperCase()
 18 |     })
 19 |     .replace(/(Www)/g, function ($1) {
 20 |       return 'WWW'
 21 |     })
 22 |     .replace(/(Xss)/g, function ($1) {
 23 |       return 'XSS'
 24 |     })
 25 |     .replace(/(Md5)/g, function ($1) {
 26 |       return 'MD5'
 27 |     })
 28 | }
 29 | 
 30 | function formEntries (form) {
 31 |   // Polyfill for new FormData(form).entries()
 32 |   var formData = new FormData(form)
 33 |   if (formData.entries !== undefined) {
 34 |     return Array.from(formData.entries())
 35 |   }
 36 | 
 37 |   var entries = []
 38 | 
 39 |   for (var i = 0; i < form.elements.length; i++) {
 40 |     var element = form.elements[i]
 41 | 
 42 |     if (!element.name) {
 43 |       continue
 44 |     }
 45 | 
 46 |     if (element.type === 'file') {
 47 |       for (var j = 0; j < element.files.length; j++) {
 48 |         entries.push([element.name, element.files[j]])
 49 |       }
 50 |     } else if (element.type === 'select-multiple' || element.type === 'select-one') {
 51 |       for (var j = 0; j < element.selectedOptions.length; j++) {
 52 |         entries.push([element.name, element.selectedOptions[j].value])
 53 |       }
 54 |     } else if (element.type === 'checkbox') {
 55 |       if (element.checked) {
 56 |         entries.push([element.name, element.value])
 57 |       }
 58 |     } else {
 59 |       entries.push([element.name, element.value])
 60 |     }
 61 |   }
 62 | 
 63 |   return entries
 64 | }
 65 | 
 66 | $(function () {
 67 |   var $selectedAuthentication = $('#selected-authentication')
 68 |   var $authControl = $('#auth-control')
 69 |   var $authTokenModal = $('#auth_token_modal')
 70 |   var $authBasicModal = $('#auth_basic_modal')
 71 |   var $authSessionModal = $('#auth_session_modal')
 72 | 
 73 |   // Language Control
 74 |   $('#language-control li').click(function (event) {
 75 |     event.preventDefault()
 76 |     var $languageMenuItem = $(this).find('a')
 77 |     var $languageControls = $(this).closest('ul').find('li')
 78 |     var $languageControlLinks = $languageControls.find('a')
 79 |     var language = $languageMenuItem.data('language')
 80 | 
 81 |     $languageControlLinks.not('[data-language="' + language + '"]').parent().removeClass('active')
 82 |     $languageControlLinks.filter('[data-language="' + language + '"]').parent().addClass('active')
 83 | 
 84 |     $('#selected-language').text(language)
 85 | 
 86 |     var $codeBlocks = $('pre.highlight')
 87 |     $codeBlocks.not('[data-language="' + language + '"]').addClass('hide')
 88 |     $codeBlocks.filter('[data-language="' + language + '"]').removeClass('hide')
 89 |   })
 90 | 
 91 |   // API Explorer
 92 |   $('form.api-interaction').submit(function (event) {
 93 |     event.preventDefault()
 94 | 
 95 |     var $form = $(this).closest('form')
 96 |     var $requestMethod = $form.find('.request-method')
 97 |     var $requestUrl = $form.find('.request-url')
 98 |     var $toggleView = $form.closest('.modal-content').find('.toggle-view')
 99 |     var $responseStatusCode = $form.find('.response-status-code')
100 |     var $meta = $form.find('.meta')
101 |     var $responseRawResponse = $form.find('.response-raw-response')
102 |     var $requestAwaiting = $form.find('.request-awaiting')
103 |     var $responseRaw = $form.find('.response-raw')
104 |     var $responseData = $form.find('.response-data')
105 |     var key = normalizeKeys($form.data('key'))
106 |     var params = {}
107 |     var entries = formEntries($form.get()[0])
108 | 
109 |     for (var i = 0; i < entries.length; i++) {
110 |       var entry = entries[i]
111 |       var paramKey = entry[0]
112 |       var paramValue = entry[1]
113 |       var $elem = $form.find('[name="' + paramKey + '"]')
114 |       var dataType = $elem.data('type') || 'string'
115 | 
116 |       if (dataType === 'integer' && paramValue) {
117 |         var value = parseInt(paramValue)
118 |         if (!isNaN(value)) {
119 |           params[paramKey] = value
120 |         }
121 |       } else if (dataType === 'number' && paramValue) {
122 |         var value = parseFloat(paramValue)
123 |         if (!isNaN(value)) {
124 |           params[paramKey] = value
125 |         }
126 |       } else if (dataType === 'boolean' && paramValue) {
127 |         var value = {
128 |           'true': true,
129 |           'false': false
130 |         }[paramValue.toLowerCase()]
131 |         if (value !== undefined) {
132 |           params[paramKey] = value
133 |         }
134 |       } else if (dataType === 'array' && paramValue) {
135 |         try {
136 |           params[paramKey] = JSON.parse(paramValue)
137 |         } catch (err) {
138 |           // Ignore malformed JSON
139 |         }
140 |       } else if (dataType === 'object' && paramValue) {
141 |         try {
142 |           params[paramKey] = JSON.parse(paramValue)
143 |         } catch (err) {
144 |           // Ignore malformed JSON
145 |         }
146 |       } else if (dataType === 'string' && paramValue) {
147 |         params[paramKey] = paramValue
148 |       }
149 |     }
150 | 
151 |     $form.find(':checkbox').each(function (index) {
152 |       // Handle unselected checkboxes
153 |       var name = $(this).attr('name')
154 |       if (!params.hasOwnProperty(name)) {
155 |         params[name] = false
156 |       }
157 |     })
158 | 
159 |     function requestCallback (request) {
160 |       // Fill in the "GET /foo/" display.
161 |       var parser = document.createElement('a')
162 |       parser.href = request.url
163 |       var method = request.options.method
164 |       var path = parser.pathname + parser.hash + parser.search
165 | 
166 |       $requestMethod.text(method)
167 |       $requestUrl.text(path)
168 |     }
169 | 
170 |     function responseCallback (response, responseText) {
171 |       // Display the 'Data'/'Raw' control.
172 |       $toggleView.removeClass('hide')
173 | 
174 |       // Fill in the "200 OK" display.
175 |       $responseStatusCode.removeClass('label-success').removeClass('label-danger')
176 |       if (response.ok) {
177 |         $responseStatusCode.addClass('label-success')
178 |       } else {
179 |         $responseStatusCode.addClass('label-danger')
180 |       }
181 |       $responseStatusCode.text(response.status)
182 |       $meta.removeClass('hide')
183 | 
184 |       // Fill in the Raw HTTP response display.
185 |       var panelText = 'HTTP/1.1 ' + response.status + ' ' + response.statusText + '\n'
186 |       response.headers.forEach(function (header, key) {
187 |         panelText += normalizeHTTPHeader(key) + ': ' + header + '\n'
188 |       })
189 |       if (responseText) {
190 |         panelText += '\n' + responseText
191 |       }
192 |       $responseRawResponse.text(panelText)
193 |     }
194 | 
195 |     // Instantiate a client to make the outgoing request.
196 |     var options = {
197 |       requestCallback: requestCallback,
198 |       responseCallback: responseCallback
199 |     }
200 | 
201 |     // Setup authentication options.
202 |     if (window.auth && window.auth.type === 'token') {
203 |       // Header authentication
204 |       options.auth = new coreapi.auth.TokenAuthentication({
205 |         scheme: window.auth.scheme,
206 |         token: window.auth.token
207 |       })
208 |     } else if (window.auth && window.auth.type === 'basic') {
209 |       // Basic authentication
210 |       options.auth = new coreapi.auth.BasicAuthentication({
211 |         username: window.auth.username,
212 |         password: window.auth.password
213 |       })
214 |     } else if (window.auth && window.auth.type === 'session') {
215 |       // Session authentication
216 |       options.auth = new coreapi.auth.SessionAuthentication({
217 |         csrfCookieName: 'csrftoken',
218 |         csrfHeaderName: 'X-CSRFToken'
219 |       })
220 |     }
221 | 
222 |     var client = new coreapi.Client(options)
223 |     client.action(schema, key, params).then(function (data) {
224 |       var response = JSON.stringify(data, null, 2)
225 |       $requestAwaiting.addClass('hide')
226 |       $responseRaw.addClass('hide')
227 |       $responseData.addClass('hide').text('').jsonView(response)
228 | 
229 |       if (responseDisplay === 'data') {
230 |         $responseData.removeClass('hide')
231 |       } else {
232 |         $responseRaw.removeClass('hide')
233 |       }
234 |     }).catch(function (error) {
235 |       var response = JSON.stringify(error.content, null, 2)
236 |       $requestAwaiting.addClass('hide')
237 |       $responseRaw.addClass('hide')
238 |       $responseData.addClass('hide').text('').jsonView(response)
239 | 
240 |       if (responseDisplay === 'data') {
241 |         $responseData.removeClass('hide')
242 |       } else {
243 |         $responseRaw.removeClass('hide')
244 |       }
245 |     })
246 |   })
247 | 
248 |   // 'Data'/'Raw' control
249 |   $('.toggle-view button').click(function () {
250 |     var $modalContent = $(this).closest('.modal-content')
251 |     var $modalResponseRaw = $modalContent.find('.response-raw')
252 |     var $modalResponseData = $modalContent.find('.response-data')
253 | 
254 |     responseDisplay = $(this).data('display-toggle')
255 | 
256 |     $(this).removeClass('btn-default').addClass('btn-info').siblings().removeClass('btn-info')
257 | 
258 |     if (responseDisplay === 'raw') {
259 |       $modalResponseRaw.removeClass('hide')
260 |       $modalResponseData.addClass('hide')
261 |     } else {
262 |       $modalResponseData.removeClass('hide')
263 |       $modalResponseRaw.addClass('hide')
264 |     }
265 |   })
266 | 
267 |   // Authentication: none
268 |   $authControl.find("[data-auth='none']").click(function (event) {
269 |     event.preventDefault()
270 |     window.auth = null
271 |     $selectedAuthentication.text('none')
272 |     $authControl.find("[data-auth]").closest('li').removeClass('active')
273 |     $authControl.find("[data-auth='none']").closest('li').addClass('active')
274 |   })
275 | 
276 |   // Authentication: token
277 |   $('form.authentication-token-form').submit(function (event) {
278 |     event.preventDefault()
279 |     var $form = $(this).closest('form')
280 |     var scheme = $form.find('input#scheme').val()
281 |     var token = $form.find('input#token').val()
282 |     window.auth = {
283 |       'type': 'token',
284 |       'scheme': scheme,
285 |       'token': token
286 |     }
287 |     $selectedAuthentication.text('token')
288 |     $authControl.find("[data-auth]").closest('li').removeClass('active')
289 |     $authControl.find("[data-auth='token']").closest('li').addClass('active')
290 |     $authTokenModal.modal('hide')
291 |   })
292 | 
293 |   // Authentication: basic
294 |   $('form.authentication-basic-form').submit(function (event) {
295 |     event.preventDefault()
296 |     var $form = $(this).closest('form')
297 |     var username = $form.find('input#username').val()
298 |     var password = $form.find('input#password').val()
299 |     window.auth = {
300 |       'type': 'basic',
301 |       'username': username,
302 |       'password': password
303 |     }
304 |     $selectedAuthentication.text('basic')
305 |     $authControl.find("[data-auth]").closest('li').removeClass('active')
306 |     $authControl.find("[data-auth='basic']").closest('li').addClass('active')
307 |     $authBasicModal.modal('hide')
308 |   })
309 | 
310 |   // Authentication: session
311 |   $('form.authentication-session-form').submit(function (event) {
312 |     event.preventDefault()
313 |     window.auth = {
314 |       'type': 'session'
315 |     }
316 |     $selectedAuthentication.text('session')
317 |     $authControl.find("[data-auth]").closest('li').removeClass('active')
318 |     $authControl.find("[data-auth='session']").closest('li').addClass('active')
319 |     $authSessionModal.modal('hide')
320 |   })
321 | })
322 | 


--------------------------------------------------------------------------------
/services/products/static/rest_framework/docs/js/jquery.json-view.min.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * jquery.json-view - jQuery collapsible JSON plugin
3 |  * @version v1.0.0
4 |  * @link http://github.com/bazh/jquery.json-view
5 |  * @license MIT
6 |  */
7 | !function(e){"use strict";var n=function(n){var a=e("",{"class":"collapser",on:{click:function(){var n=e(this);n.toggleClass("collapsed");var a=n.parent().children(".block"),p=a.children("ul");n.hasClass("collapsed")?(p.hide(),a.children(".dots, .comments").show()):(p.show(),a.children(".dots, .comments").hide())}}});return n&&a.addClass("collapsed"),a},a=function(a,p){var t=e.extend({},{nl2br:!0},p),r=function(e){return e.toString()?e.toString().replace(/&/g,"&").replace(/"/g,""").replace(//g,">"):""},s=function(n,a){return e("",{"class":a,html:r(n)})},l=function(a,p){switch(e.type(a)){case"object":p||(p=0);var c=e("",{"class":"block"}),d=Object.keys(a).length;if(!d)return c.append(s("{","b")).append(" ").append(s("}","b"));c.append(s("{","b"));var i=e("