├── .dockerignore
├── .gitignore
├── Dockerfile
├── README.md
├── django_classifier_profile
├── __init__.py
├── apps
│ ├── __init__.py
│ └── account
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── forms.py
│ │ ├── formsets.py
│ │ ├── managers.py
│ │ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ └── views.py
├── settings.py
├── static
│ ├── js
│ │ └── profile-formset.js
│ ├── node_modules
│ │ ├── bootstrap
│ │ │ ├── CHANGELOG.md
│ │ │ ├── Gruntfile.js
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── fonts
│ │ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ │ └── glyphicons-halflings-regular.woff2
│ │ │ ├── grunt
│ │ │ │ ├── .jshintrc
│ │ │ │ ├── bs-commonjs-generator.js
│ │ │ │ ├── bs-glyphicons-data-generator.js
│ │ │ │ ├── bs-lessdoc-parser.js
│ │ │ │ ├── bs-raw-files-generator.js
│ │ │ │ ├── change-version.js
│ │ │ │ ├── configBridge.json
│ │ │ │ ├── npm-shrinkwrap.json
│ │ │ │ └── sauce_browsers.yml
│ │ │ ├── js
│ │ │ │ ├── affix.js
│ │ │ │ ├── alert.js
│ │ │ │ ├── button.js
│ │ │ │ ├── carousel.js
│ │ │ │ ├── collapse.js
│ │ │ │ ├── dropdown.js
│ │ │ │ ├── modal.js
│ │ │ │ ├── popover.js
│ │ │ │ ├── scrollspy.js
│ │ │ │ ├── tab.js
│ │ │ │ ├── tooltip.js
│ │ │ │ └── transition.js
│ │ │ ├── less
│ │ │ │ ├── alerts.less
│ │ │ │ ├── badges.less
│ │ │ │ ├── bootstrap.less
│ │ │ │ ├── breadcrumbs.less
│ │ │ │ ├── button-groups.less
│ │ │ │ ├── buttons.less
│ │ │ │ ├── carousel.less
│ │ │ │ ├── close.less
│ │ │ │ ├── code.less
│ │ │ │ ├── component-animations.less
│ │ │ │ ├── dropdowns.less
│ │ │ │ ├── forms.less
│ │ │ │ ├── glyphicons.less
│ │ │ │ ├── grid.less
│ │ │ │ ├── input-groups.less
│ │ │ │ ├── jumbotron.less
│ │ │ │ ├── labels.less
│ │ │ │ ├── list-group.less
│ │ │ │ ├── media.less
│ │ │ │ ├── mixins.less
│ │ │ │ ├── mixins
│ │ │ │ │ ├── alerts.less
│ │ │ │ │ ├── background-variant.less
│ │ │ │ │ ├── border-radius.less
│ │ │ │ │ ├── buttons.less
│ │ │ │ │ ├── center-block.less
│ │ │ │ │ ├── clearfix.less
│ │ │ │ │ ├── forms.less
│ │ │ │ │ ├── gradients.less
│ │ │ │ │ ├── grid-framework.less
│ │ │ │ │ ├── grid.less
│ │ │ │ │ ├── hide-text.less
│ │ │ │ │ ├── image.less
│ │ │ │ │ ├── labels.less
│ │ │ │ │ ├── list-group.less
│ │ │ │ │ ├── nav-divider.less
│ │ │ │ │ ├── nav-vertical-align.less
│ │ │ │ │ ├── opacity.less
│ │ │ │ │ ├── pagination.less
│ │ │ │ │ ├── panels.less
│ │ │ │ │ ├── progress-bar.less
│ │ │ │ │ ├── reset-filter.less
│ │ │ │ │ ├── reset-text.less
│ │ │ │ │ ├── resize.less
│ │ │ │ │ ├── responsive-visibility.less
│ │ │ │ │ ├── size.less
│ │ │ │ │ ├── tab-focus.less
│ │ │ │ │ ├── table-row.less
│ │ │ │ │ ├── text-emphasis.less
│ │ │ │ │ ├── text-overflow.less
│ │ │ │ │ └── vendor-prefixes.less
│ │ │ │ ├── modals.less
│ │ │ │ ├── navbar.less
│ │ │ │ ├── navs.less
│ │ │ │ ├── normalize.less
│ │ │ │ ├── pager.less
│ │ │ │ ├── pagination.less
│ │ │ │ ├── panels.less
│ │ │ │ ├── popovers.less
│ │ │ │ ├── print.less
│ │ │ │ ├── progress-bars.less
│ │ │ │ ├── responsive-embed.less
│ │ │ │ ├── responsive-utilities.less
│ │ │ │ ├── scaffolding.less
│ │ │ │ ├── tables.less
│ │ │ │ ├── theme.less
│ │ │ │ ├── thumbnails.less
│ │ │ │ ├── tooltip.less
│ │ │ │ ├── type.less
│ │ │ │ ├── utilities.less
│ │ │ │ ├── variables.less
│ │ │ │ └── wells.less
│ │ │ └── package.json
│ │ └── jquery
│ │ │ ├── AUTHORS.txt
│ │ │ ├── LICENSE.txt
│ │ │ ├── README.md
│ │ │ ├── bower.json
│ │ │ ├── external
│ │ │ └── sizzle
│ │ │ │ └── LICENSE.txt
│ │ │ ├── package.json
│ │ │ └── src
│ │ │ ├── .eslintrc.json
│ │ │ ├── ajax.js
│ │ │ ├── ajax
│ │ │ ├── jsonp.js
│ │ │ ├── load.js
│ │ │ ├── parseXML.js
│ │ │ ├── script.js
│ │ │ └── xhr.js
│ │ │ ├── attributes.js
│ │ │ ├── attributes
│ │ │ ├── attr.js
│ │ │ ├── classes.js
│ │ │ ├── prop.js
│ │ │ ├── support.js
│ │ │ └── val.js
│ │ │ ├── callbacks.js
│ │ │ ├── core.js
│ │ │ ├── core
│ │ │ ├── DOMEval.js
│ │ │ ├── access.js
│ │ │ ├── init.js
│ │ │ ├── parseHTML.js
│ │ │ ├── ready-no-deferred.js
│ │ │ ├── ready.js
│ │ │ ├── readyException.js
│ │ │ ├── stripAndCollapse.js
│ │ │ └── support.js
│ │ │ ├── css.js
│ │ │ ├── css
│ │ │ ├── addGetHookIf.js
│ │ │ ├── adjustCSS.js
│ │ │ ├── curCSS.js
│ │ │ ├── hiddenVisibleSelectors.js
│ │ │ ├── showHide.js
│ │ │ └── support.js
│ │ │ ├── data.js
│ │ │ ├── data
│ │ │ └── Data.js
│ │ │ ├── deferred.js
│ │ │ ├── deferred
│ │ │ └── exceptionHook.js
│ │ │ ├── deprecated.js
│ │ │ ├── dimensions.js
│ │ │ ├── effects.js
│ │ │ ├── effects
│ │ │ ├── Tween.js
│ │ │ └── animatedSelector.js
│ │ │ ├── event.js
│ │ │ ├── event
│ │ │ ├── ajax.js
│ │ │ ├── alias.js
│ │ │ ├── focusin.js
│ │ │ ├── support.js
│ │ │ └── trigger.js
│ │ │ ├── exports
│ │ │ ├── amd.js
│ │ │ └── global.js
│ │ │ ├── jquery.js
│ │ │ ├── manipulation.js
│ │ │ ├── manipulation
│ │ │ ├── _evalUrl.js
│ │ │ ├── buildFragment.js
│ │ │ ├── getAll.js
│ │ │ ├── setGlobalEval.js
│ │ │ ├── support.js
│ │ │ └── wrapMap.js
│ │ │ ├── offset.js
│ │ │ ├── queue.js
│ │ │ ├── queue
│ │ │ └── delay.js
│ │ │ ├── selector-native.js
│ │ │ ├── selector-sizzle.js
│ │ │ ├── selector.js
│ │ │ ├── serialize.js
│ │ │ ├── traversing.js
│ │ │ ├── traversing
│ │ │ └── findFilter.js
│ │ │ └── wrap.js
│ └── package.json
├── templates
│ ├── account
│ │ ├── includes
│ │ │ └── formset_form.html
│ │ └── profile_edit.html
│ └── base.html
├── urls.py
├── utils
│ ├── __init__.py
│ └── forms.py
└── wsgi.py
├── docker-compose.yml
├── fixtures
└── initial.json
├── manage.py
└── requirements.txt
/.dockerignore:
--------------------------------------------------------------------------------
1 | *.sqlite3
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite*
2 | # Created by https://www.gitignore.io/api/python,emacs,macos
3 |
4 | ### Emacs ###
5 | # -*- mode: gitignore; -*-
6 | *~
7 | \#*\#
8 | /.emacs.desktop
9 | /.emacs.desktop.lock
10 | *.elc
11 | auto-save-list
12 | tramp
13 | .\#*
14 |
15 | # Org-mode
16 | .org-id-locations
17 | *_archive
18 |
19 | # flymake-mode
20 | *_flymake.*
21 |
22 | # eshell files
23 | /eshell/history
24 | /eshell/lastdir
25 |
26 | # elpa packages
27 | /elpa/
28 |
29 | # reftex files
30 | *.rel
31 |
32 | # AUCTeX auto folder
33 | /auto/
34 |
35 | # cask packages
36 | .cask/
37 | dist/
38 |
39 | # Flycheck
40 | flycheck_*.el
41 |
42 | # server auth directory
43 | /server/
44 |
45 | # projectiles files
46 | .projectile
47 |
48 | # directory configuration
49 | .dir-locals.el
50 |
51 | ### macOS ###
52 | *.DS_Store
53 | .AppleDouble
54 | .LSOverride
55 |
56 | # Icon must end with two \r
57 | Icon
58 |
59 |
60 | # Thumbnails
61 | ._*
62 |
63 | # Files that might appear in the root of a volume
64 | .DocumentRevisions-V100
65 | .fseventsd
66 | .Spotlight-V100
67 | .TemporaryItems
68 | .Trashes
69 | .VolumeIcon.icns
70 | .com.apple.timemachine.donotpresent
71 |
72 | # Directories potentially created on remote AFP share
73 | .AppleDB
74 | .AppleDesktop
75 | Network Trash Folder
76 | Temporary Items
77 | .apdisk
78 |
79 | ### Python ###
80 | # Byte-compiled / optimized / DLL files
81 | __pycache__/
82 | *.py[cod]
83 | *$py.class
84 |
85 | # C extensions
86 | *.so
87 |
88 | # Distribution / packaging
89 | .Python
90 | env/
91 | build/
92 | develop-eggs/
93 | downloads/
94 | eggs/
95 | .eggs/
96 | lib/
97 | lib64/
98 | parts/
99 | sdist/
100 | var/
101 | wheels/
102 | *.egg-info/
103 | .installed.cfg
104 | *.egg
105 |
106 | # PyInstaller
107 | # Usually these files are written by a python script from a template
108 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
109 | *.manifest
110 | *.spec
111 |
112 | # Installer logs
113 | pip-log.txt
114 | pip-delete-this-directory.txt
115 |
116 | # Unit test / coverage reports
117 | htmlcov/
118 | .tox/
119 | .coverage
120 | .coverage.*
121 | .cache
122 | nosetests.xml
123 | coverage.xml
124 | *,cover
125 | .hypothesis/
126 |
127 | # Translations
128 | *.mo
129 | *.pot
130 |
131 | # Django stuff:
132 | *.log
133 | local_settings.py
134 |
135 | # Flask stuff:
136 | instance/
137 | .webassets-cache
138 |
139 | # Scrapy stuff:
140 | .scrapy
141 |
142 | # Sphinx documentation
143 | docs/_build/
144 |
145 | # PyBuilder
146 | target/
147 |
148 | # Jupyter Notebook
149 | .ipynb_checkpoints
150 |
151 | # pyenv
152 | .python-version
153 |
154 | # celery beat schedule file
155 | celerybeat-schedule
156 |
157 | # dotenv
158 | .env
159 |
160 | # virtualenv
161 | .venv
162 | venv/
163 | ENV/
164 |
165 | # Spyder project settings
166 | .spyderproject
167 |
168 | # Rope project settings
169 | .ropeproject
170 |
171 | # End of https://www.gitignore.io/api/python,emacs,macos
172 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.5.3-alpine
2 | COPY requirements.txt /requirements.txt
3 | RUN pip install -r /requirements.txt
4 | ADD . /project
5 | WORKDIR /project
6 | RUN ["python", "manage.py", "migrate"]
7 | RUN ["python", "manage.py", "loaddata", "fixtures/initial.json"]
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # django-classifier-profile
2 |
3 | It's very simple project to show how to use [django-classifier](https://django-classifier.readthedocs.io)
4 | Here we build properties for user profile with help of django-classifier and it gives an opportunity to add new properties just from admin.
5 |
6 | ## How to run
7 | just run `docker-compose up` and you will have django on [localhost:8000](http://localhost:8000/)
8 |
9 | login/password for admin: admin@localhost/admin
10 |
--------------------------------------------------------------------------------
/django_classifier_profile/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/__init__.py
--------------------------------------------------------------------------------
/django_classifier_profile/apps/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/apps/__init__.py
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/apps/account/__init__.py
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.db.utils import OperationalError
3 |
4 | from .models import (
5 | User, UserAttributeClassifier, UserAttributeClassifierLabel, UserAttribute
6 | )
7 |
8 |
9 | class BaseUserAttributeAdmin(admin.TabularInline):
10 | model = UserAttribute
11 | extra = 0
12 |
13 | def get_queryset(self, request):
14 | qs = super(BaseUserAttributeAdmin, self).get_queryset(request)
15 | label_model = self.model._meta.get_field('label').related_model
16 | classifier_field_name = label_model.get_classifier_related_field().name
17 | kwargs = {
18 | 'label__{}'.format(classifier_field_name): self.CLASSIFIER,
19 | }
20 | qs = qs.filter(**kwargs)
21 |
22 | return qs
23 |
24 |
25 | def user_attribute_admin_factory(classifier):
26 | class UserAttributeAdmin(BaseUserAttributeAdmin):
27 | CLASSIFIER = classifier
28 | verbose_name = classifier.category
29 | verbose_name_plural = classifier.category
30 |
31 | return UserAttributeAdmin
32 |
33 |
34 | @admin.register(User)
35 | class UserAdmin(admin.ModelAdmin):
36 | list_display = ('email', 'first_name', 'last_name', )
37 |
38 | @property
39 | def inlines(self):
40 | inlines = []
41 | try:
42 | for classifier in UserAttributeClassifier.objects.all():
43 | inline_cls = user_attribute_admin_factory(classifier)
44 | inlines.append(inline_cls)
45 | except OperationalError: # raised when migrations weren't applied
46 | pass
47 |
48 | return inlines
49 |
50 |
51 | class UserAttributeClassifierLabelAdmin(admin.TabularInline):
52 | model = UserAttributeClassifierLabel
53 |
54 |
55 | @admin.register(UserAttributeClassifier)
56 | class UserAttributeClassifierAdmin(admin.ModelAdmin):
57 | list_display = (
58 | 'kind', 'category', 'labels', 'value_type', 'value_validator'
59 | )
60 | inlines = [
61 | UserAttributeClassifierLabelAdmin,
62 | ]
63 |
64 | def labels(self, obj):
65 | return ', '.join(obj.labels.values_list('label', flat=True))
66 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AccountConfig(AppConfig):
5 | name = 'django_classifier_profile.apps.account'
6 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from classifier.forms import ClassifierFormMixin
3 |
4 | from django_classifier_profile.utils.forms import BootstrapFormMixin
5 | from .models import User, UserAttribute
6 |
7 |
8 | class UserForm(BootstrapFormMixin, forms.ModelForm):
9 |
10 | class Meta:
11 | model = User
12 | fields = (
13 | 'id',
14 | 'first_name', 'last_name',
15 | )
16 |
17 |
18 | class UserAttributeForm(
19 | BootstrapFormMixin, ClassifierFormMixin, forms.ModelForm
20 | ):
21 | CLASSIFIER_VALUE_FIELD = 'value'
22 |
23 | class Meta:
24 | model = UserAttribute
25 | fields = (
26 | 'id', 'user', 'label', 'value',
27 | )
28 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/formsets.py:
--------------------------------------------------------------------------------
1 | from django.utils.functional import cached_property
2 | from classifier.formsets import ClassifierFormSet
3 |
4 | from .models import UserAttributeClassifier
5 |
6 |
7 | class UserClassifierFormSet(ClassifierFormSet):
8 | """
9 | extended with one additional method to get forms grouped by category
10 | """
11 |
12 | @cached_property
13 | def grouped_forms(self):
14 | """
15 | grouped forms by category and filter options of kind field
16 | """
17 | self.empty_forms = {}
18 | forms = {}
19 | for kind in UserAttributeClassifier.objects.all():
20 | self.create_empty_form(kind)
21 | labels = list(kind.labels.values_list('pk', flat=True))
22 | forms[kind.category] = []
23 | for form in self.forms:
24 | label_id = None
25 | try:
26 | label_id = form.cleaned_data['label'].pk
27 | except (AttributeError, KeyError):
28 | label_id = form.data.get('label', form.initial.get('label'))
29 |
30 | if label_id in labels:
31 | form.fields['label'].choices = kind.labels.values_list(
32 | 'pk', 'label'
33 | )
34 | forms[kind.category].append(form)
35 |
36 | return sorted(forms.items(), key=lambda i: i[0])
37 |
38 | def create_empty_form(self, kind):
39 | """
40 | returns empty form for specific attribute
41 | """
42 | form = self.form(
43 | auto_id=self.auto_id,
44 | prefix=self.add_prefix('__prefix__'),
45 | empty_permitted=True,
46 | use_required_attribute=False,
47 | **self.get_form_kwargs(None)
48 | )
49 | self.add_fields(form, None)
50 | form.fields['label'].choices = kind.labels.values_list('pk', 'label')
51 | form.fields['user'].initial = self.initial_extra[0]['user']
52 |
53 | self.empty_forms[kind.category] = form
54 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/managers.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import BaseUserManager
2 |
3 |
4 | class UserManager(BaseUserManager):
5 |
6 | def create_user(self, email, password=None):
7 | if not email:
8 | raise ValueError('Users must gave an email address')
9 |
10 | user = self.model(email=email)
11 | user.set_password(password)
12 | user.save(using=self._db)
13 |
14 | return user
15 |
16 | def create_superuser(self, email, password):
17 | user = self.create_user(email, password)
18 | user.is_staff = True
19 | user.is_superuser = True
20 | user.save(using=self._db)
21 |
22 | return user
23 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/apps/account/migrations/__init__.py
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.utils.translation import gettext_lazy as _
3 | from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
4 | from classifier.models import ClassifierAbstract, ClassifierLabelAbstract
5 |
6 | from .managers import UserManager
7 |
8 |
9 | class User(PermissionsMixin, AbstractBaseUser):
10 | email = models.EmailField(unique=True)
11 | first_name = models.CharField(max_length=30, blank=True, null=True)
12 | last_name = models.CharField(max_length=30, blank=True, null=True)
13 |
14 | is_staff = models.BooleanField(
15 | default=False,
16 | help_text=_(
17 | 'Designates whether the user can log into this admin site.'
18 | ),
19 | )
20 | is_active = models.BooleanField(
21 | default=True,
22 | help_text=_(
23 | 'Designates whether this user should be treated as active. '
24 | 'Unselect this instead of deleting accounts.'
25 | ),
26 | )
27 |
28 | objects = UserManager()
29 |
30 | USERNAME_FIELD = 'email'
31 | REQUIRED_FIELDS = []
32 |
33 | class Meta:
34 | ordering = ('first_name', 'last_name', )
35 |
36 | def __str__(self):
37 | return self.get_full_name()
38 |
39 | def get_short_name(self):
40 | if self.first_name:
41 | return self.first_name
42 | return self.email.split('@')[0]
43 |
44 | def get_full_name(self):
45 | return ' '.join(filter(None, [self.first_name, self.last_name]))
46 |
47 | def get_mobile(self):
48 | attr = (
49 | self.attributes
50 | .filter(label__slug=UserAttributeClassifierLabel.PHONE_MOBILE)
51 | .first()
52 | )
53 | if attr:
54 | return attr.value
55 |
56 | def get_skype(self):
57 | attr = (
58 | self.attributes
59 | .filter(label__slug=UserAttributeClassifierLabel.IM_SKYPE)
60 | .first()
61 | )
62 | if attr:
63 | return attr.value
64 |
65 | def get_birhday(self):
66 | attr = (
67 | self.attributes
68 | .filter(label__slug=UserAttributeClassifierLabel.GENERAL_BIRTHDAY)
69 | .first()
70 | )
71 | if attr:
72 | return attr.label.classifier.to_python(attr.value)
73 |
74 |
75 | class UserAttributeClassifier(ClassifierAbstract):
76 | category = models.CharField(max_length=100)
77 |
78 | class Meta:
79 | ordering = ('category', )
80 |
81 |
82 | class UserAttributeClassifierLabel(ClassifierLabelAbstract):
83 | # have to be the same as in database to be able to fetch specific value
84 | GENERAL_BIRTHDAY = 'birthday'
85 | PHONE_MOBILE = 'mobile'
86 | IM_SKYPE = 'skype'
87 |
88 | classifier = models.ForeignKey(
89 | UserAttributeClassifier,
90 | related_name='labels'
91 | )
92 | slug = models.CharField(max_length=100, null=True, blank=True)
93 |
94 | class Meta:
95 | ordering = ('label', )
96 |
97 |
98 | class UserAttribute(models.Model):
99 | user = models.ForeignKey(User, related_name='attributes')
100 | label = models.ForeignKey(UserAttributeClassifierLabel, related_name='+')
101 | value = models.CharField(max_length=200)
102 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/django_classifier_profile/apps/account/views.py:
--------------------------------------------------------------------------------
1 | from django.core.urlresolvers import reverse
2 | from django.forms import modelformset_factory
3 | from django.http import HttpResponseForbidden
4 | from django.views.generic import UpdateView
5 | from django.contrib.auth.mixins import LoginRequiredMixin
6 | from django.shortcuts import redirect
7 |
8 | from .models import User, UserAttribute
9 | from .formsets import UserClassifierFormSet
10 | from .forms import UserForm, UserAttributeForm
11 |
12 |
13 | class ProfileEditView(LoginRequiredMixin, UpdateView):
14 | model = User
15 | form_class = UserForm
16 | template_name = 'account/profile_edit.html'
17 |
18 | def get_object(self, queryset=None):
19 | if (
20 | not self.kwargs.get(self.pk_url_kwarg)
21 | and not self.kwargs.get(self.slug_url_kwarg)
22 | ):
23 | self.kwargs[self.pk_url_kwarg] = self.request.user.pk
24 |
25 | user = super(ProfileEditView, self).get_object(queryset=queryset)
26 |
27 | if user != self.request.user and not self.request.user.is_superuser:
28 | raise HttpResponseForbidden
29 |
30 | return user
31 |
32 | def get_context_data(self, **kwargs):
33 | context = super(ProfileEditView, self).get_context_data(**kwargs)
34 |
35 | if not context.get('attribute_formset'):
36 | context['attribute_formset'] = self.get_formset()
37 |
38 | return context
39 |
40 | def form_valid(self, form):
41 | formset = self.get_formset()
42 | if formset.is_valid():
43 | form.save()
44 | formset.save()
45 | else:
46 | return self.form_invalid(form, attribute_formset=formset)
47 |
48 | return redirect(reverse('profile-edit'))
49 |
50 | def form_invalid(self, form, attribute_formset=None):
51 | return self.render_to_response(
52 | self.get_context_data(
53 | form=form,
54 | attribute_formset=attribute_formset
55 | )
56 | )
57 |
58 | def get_formset(self):
59 | """
60 | create formset of attributes with help of custome formset class
61 | """
62 | FormSetClass = modelformset_factory(
63 | UserAttribute,
64 | formset=UserClassifierFormSet,
65 | form=UserAttributeForm,
66 | can_delete=True,
67 | extra=0
68 | )
69 |
70 | formset = FormSetClass(
71 | data=self.request.POST if self.request.method == 'POST' else None,
72 | queryset=self.get_object().attributes.all(),
73 | initial={
74 | 'user': self.get_object().pk,
75 | }
76 | )
77 |
78 | return formset
79 |
--------------------------------------------------------------------------------
/django_classifier_profile/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for django_classifier_profile project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.10.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.10/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.10/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 | rel = lambda *p: os.path.join(os.path.dirname(os.path.abspath(__file__)), *p)
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'oyk@z2y0m7o1v*u_q5z78iwnya+q)&bb-g(fz7$)og-d&2me6v'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 |
41 | 'classifier',
42 |
43 | 'django_classifier_profile.apps.account.apps.AccountConfig',
44 | ]
45 |
46 | MIDDLEWARE = [
47 | 'django.middleware.security.SecurityMiddleware',
48 | 'django.contrib.sessions.middleware.SessionMiddleware',
49 | 'django.middleware.common.CommonMiddleware',
50 | 'django.middleware.csrf.CsrfViewMiddleware',
51 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
52 | 'django.contrib.messages.middleware.MessageMiddleware',
53 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
54 | ]
55 |
56 | ROOT_URLCONF = 'django_classifier_profile.urls'
57 |
58 | TEMPLATES = [
59 | {
60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
61 | 'DIRS': [
62 | rel('templates/'),
63 | ],
64 | 'APP_DIRS': True,
65 | 'OPTIONS': {
66 | 'context_processors': [
67 | 'django.template.context_processors.debug',
68 | 'django.template.context_processors.request',
69 | 'django.contrib.auth.context_processors.auth',
70 | 'django.contrib.messages.context_processors.messages',
71 | ],
72 | },
73 | },
74 | ]
75 |
76 | WSGI_APPLICATION = 'django_classifier_profile.wsgi.application'
77 |
78 |
79 | # Database
80 | # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
81 |
82 | DATABASES = {
83 | 'default': {
84 | 'ENGINE': 'django.db.backends.sqlite3',
85 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
86 | }
87 | }
88 |
89 |
90 | # Password validation
91 | # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
92 |
93 | AUTH_USER_MODEL = 'account.User'
94 |
95 | AUTH_PASSWORD_VALIDATORS = []
96 |
97 | LOGIN_URL = '/admin/'
98 |
99 |
100 | # Internationalization
101 | # https://docs.djangoproject.com/en/1.10/topics/i18n/
102 |
103 | LANGUAGE_CODE = 'en-us'
104 |
105 | TIME_ZONE = 'UTC'
106 |
107 | USE_I18N = True
108 |
109 | USE_L10N = True
110 |
111 | USE_TZ = True
112 |
113 |
114 | # Static files (CSS, JavaScript, Images)
115 | # https://docs.djangoproject.com/en/1.10/howto/static-files/
116 |
117 | STATIC_URL = '/static/'
118 | STATIC_ROOT = rel('static_collected/')
119 | STATICFILES_DIRS = [
120 | rel('static/'),
121 | ]
122 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/js/profile-formset.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 | var totalForms = $('#id_form-TOTAL_FORMS');
3 |
4 | $('.formset-btn-add-form').click(function() {
5 | var $btn = $(this);
6 | var emptyForm = $('#empty-form-' + $btn.data('group'));
7 | var index = parseInt(totalForms.val(), 10);
8 |
9 | $btn.parent().find('.formset-forms').append(
10 | emptyForm.html().replace(/__prefix__/g, index)
11 | );
12 |
13 | totalForms.val(index + 1);
14 | });
15 |
16 | $(document).on('click', '.formset-btn-delete', function() {
17 | var $btn = $(this);
18 | $btn.parent().find('input[name$=DELETE]').prop('checked', true);
19 | $btn.parents('.form-user-attribute').hide();
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Bootstrap uses [GitHub's Releases feature](https://github.com/blog/1547-release-your-software) for its changelogs.
2 |
3 | See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap.
4 |
5 | Release announcement posts on [the official Bootstrap blog](http://blog.getbootstrap.com) contain summaries of the most noteworthy changes made in each release.
6 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2016 Twitter, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-stars/django-classifier-profile/2584e9c8bd2ff998ee1ac4813f7b6852e0ce8aff/django_classifier_profile/static/node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends" : "../js/.jshintrc",
3 | "asi" : false,
4 | "browser" : false,
5 | "es3" : false,
6 | "node" : true
7 | }
8 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/bs-commonjs-generator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Grunt task for the CommonJS module generation
3 | * http://getbootstrap.com
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | 'use strict';
9 |
10 | var fs = require('fs');
11 | var path = require('path');
12 |
13 | var COMMONJS_BANNER = '// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.\n';
14 |
15 | module.exports = function generateCommonJSModule(grunt, srcFiles, destFilepath) {
16 | var destDir = path.dirname(destFilepath);
17 |
18 | function srcPathToDestRequire(srcFilepath) {
19 | var requirePath = path.relative(destDir, srcFilepath).replace(/\\/g, '/');
20 | return 'require(\'' + requirePath + '\')';
21 | }
22 |
23 | var moduleOutputJs = COMMONJS_BANNER + srcFiles.map(srcPathToDestRequire).join('\n');
24 | try {
25 | fs.writeFileSync(destFilepath, moduleOutputJs);
26 | } catch (err) {
27 | grunt.fail.warn(err);
28 | }
29 | grunt.log.writeln('File ' + destFilepath.cyan + ' created.');
30 | };
31 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/bs-glyphicons-data-generator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Grunt task for Glyphicons data generation
3 | * http://getbootstrap.com
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | 'use strict';
9 |
10 | var fs = require('fs');
11 |
12 | module.exports = function generateGlyphiconsData(grunt) {
13 | // Pass encoding, utf8, so `readFileSync` will return a string instead of a
14 | // buffer
15 | var glyphiconsFile = fs.readFileSync('less/glyphicons.less', 'utf8');
16 | var glyphiconsLines = glyphiconsFile.split('\n');
17 |
18 | // Use any line that starts with ".glyphicon-" and capture the class name
19 | var iconClassName = /^\.(glyphicon-[a-zA-Z0-9-]+)/;
20 | var glyphiconsData = '# This file is generated via Grunt task. **Do not edit directly.**\n' +
21 | '# See the \'build-glyphicons-data\' task in Gruntfile.js.\n\n';
22 | var glyphiconsYml = 'docs/_data/glyphicons.yml';
23 | for (var i = 0, len = glyphiconsLines.length; i < len; i++) {
24 | var match = glyphiconsLines[i].match(iconClassName);
25 |
26 | if (match !== null) {
27 | glyphiconsData += '- ' + match[1] + '\n';
28 | }
29 | }
30 |
31 | // Create the `_data` directory if it doesn't already exist
32 | if (!fs.existsSync('docs/_data')) {
33 | fs.mkdirSync('docs/_data');
34 | }
35 |
36 | try {
37 | fs.writeFileSync(glyphiconsYml, glyphiconsData);
38 | } catch (err) {
39 | grunt.fail.warn(err);
40 | }
41 | grunt.log.writeln('File ' + glyphiconsYml.cyan + ' created.');
42 | };
43 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/bs-raw-files-generator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Grunt task for generating raw-files.min.js for the Customizer
3 | * http://getbootstrap.com
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | 'use strict';
9 |
10 | var fs = require('fs');
11 | var btoa = require('btoa');
12 | var glob = require('glob');
13 |
14 | function getFiles(type) {
15 | var files = {};
16 | var recursive = type === 'less';
17 | var globExpr = recursive ? '/**/*' : '/*';
18 | glob.sync(type + globExpr)
19 | .filter(function (path) {
20 | return type === 'fonts' ? true : new RegExp('\\.' + type + '$').test(path);
21 | })
22 | .forEach(function (fullPath) {
23 | var relativePath = fullPath.replace(/^[^/]+\//, '');
24 | files[relativePath] = type === 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8');
25 | });
26 | return 'var __' + type + ' = ' + JSON.stringify(files) + '\n';
27 | }
28 |
29 | module.exports = function generateRawFilesJs(grunt, banner) {
30 | if (!banner) {
31 | banner = '';
32 | }
33 | var dirs = ['js', 'less', 'fonts'];
34 | var files = banner + dirs.map(getFiles).reduce(function (combined, file) {
35 | return combined + file;
36 | }, '');
37 | var rawFilesJs = 'docs/assets/js/raw-files.min.js';
38 | try {
39 | fs.writeFileSync(rawFilesJs, files);
40 | } catch (err) {
41 | grunt.fail.warn(err);
42 | }
43 | grunt.log.writeln('File ' + rawFilesJs.cyan + ' created.');
44 | };
45 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/change-version.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | /* globals Set */
5 | /*!
6 | * Script to update version number references in the project.
7 | * Copyright 2015 Twitter, Inc.
8 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
9 | */
10 | var fs = require('fs');
11 | var path = require('path');
12 | var sh = require('shelljs');
13 | sh.config.fatal = true;
14 | var sed = sh.sed;
15 |
16 | // Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37
17 | RegExp.quote = function (string) {
18 | return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
19 | };
20 | RegExp.quoteReplacement = function (string) {
21 | return string.replace(/[$]/g, '$$');
22 | };
23 |
24 | var DRY_RUN = false;
25 |
26 | function walkAsync(directory, excludedDirectories, fileCallback, errback) {
27 | if (excludedDirectories.has(path.parse(directory).base)) {
28 | return;
29 | }
30 | fs.readdir(directory, function (err, names) {
31 | if (err) {
32 | errback(err);
33 | return;
34 | }
35 | names.forEach(function (name) {
36 | var filepath = path.join(directory, name);
37 | fs.lstat(filepath, function (err, stats) {
38 | if (err) {
39 | process.nextTick(errback, err);
40 | return;
41 | }
42 | if (stats.isSymbolicLink()) {
43 | return;
44 | }
45 | else if (stats.isDirectory()) {
46 | process.nextTick(walkAsync, filepath, excludedDirectories, fileCallback, errback);
47 | }
48 | else if (stats.isFile()) {
49 | process.nextTick(fileCallback, filepath);
50 | }
51 | });
52 | });
53 | });
54 | }
55 |
56 | function replaceRecursively(directory, excludedDirectories, allowedExtensions, original, replacement) {
57 | original = new RegExp(RegExp.quote(original), 'g');
58 | replacement = RegExp.quoteReplacement(replacement);
59 | var updateFile = !DRY_RUN ? function (filepath) {
60 | if (allowedExtensions.has(path.parse(filepath).ext)) {
61 | sed('-i', original, replacement, filepath);
62 | }
63 | } : function (filepath) {
64 | if (allowedExtensions.has(path.parse(filepath).ext)) {
65 | console.log('FILE: ' + filepath);
66 | }
67 | else {
68 | console.log('EXCLUDED:' + filepath);
69 | }
70 | };
71 | walkAsync(directory, excludedDirectories, updateFile, function (err) {
72 | console.error('ERROR while traversing directory!:');
73 | console.error(err);
74 | process.exit(1);
75 | });
76 | }
77 |
78 | function main(args) {
79 | if (args.length !== 2) {
80 | console.error('USAGE: change-version old_version new_version');
81 | console.error('Got arguments:', args);
82 | process.exit(1);
83 | }
84 | var oldVersion = args[0];
85 | var newVersion = args[1];
86 | var EXCLUDED_DIRS = new Set([
87 | '.git',
88 | 'node_modules',
89 | 'vendor'
90 | ]);
91 | var INCLUDED_EXTENSIONS = new Set([
92 | // This extension whitelist is how we avoid modifying binary files
93 | '',
94 | '.css',
95 | '.html',
96 | '.js',
97 | '.json',
98 | '.less',
99 | '.md',
100 | '.nuspec',
101 | '.ps1',
102 | '.scss',
103 | '.txt',
104 | '.yml'
105 | ]);
106 | replaceRecursively('.', EXCLUDED_DIRS, INCLUDED_EXTENSIONS, oldVersion, newVersion);
107 | }
108 |
109 | main(process.argv.slice(2));
110 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/configBridge.json:
--------------------------------------------------------------------------------
1 | {
2 | "paths": {
3 | "customizerJs": [
4 | "../assets/js/vendor/autoprefixer.js",
5 | "../assets/js/vendor/less.min.js",
6 | "../assets/js/vendor/jszip.min.js",
7 | "../assets/js/vendor/uglify.min.js",
8 | "../assets/js/vendor/Blob.js",
9 | "../assets/js/vendor/FileSaver.js",
10 | "../assets/js/raw-files.min.js",
11 | "../assets/js/src/customizer.js"
12 | ],
13 | "docsJs": [
14 | "../assets/js/vendor/holder.min.js",
15 | "../assets/js/vendor/ZeroClipboard.min.js",
16 | "../assets/js/vendor/anchor.min.js",
17 | "../assets/js/src/application.js"
18 | ]
19 | },
20 | "config": {
21 | "autoprefixerBrowsers": [
22 | "Android 2.3",
23 | "Android >= 4",
24 | "Chrome >= 20",
25 | "Firefox >= 24",
26 | "Explorer >= 8",
27 | "iOS >= 6",
28 | "Opera >= 12",
29 | "Safari >= 6"
30 | ],
31 | "jqueryCheck": [
32 | "if (typeof jQuery === 'undefined') {",
33 | " throw new Error('Bootstrap\\'s JavaScript requires jQuery')",
34 | "}\n"
35 | ],
36 | "jqueryVersionCheck": [
37 | "+function ($) {",
38 | " 'use strict';",
39 | " var version = $.fn.jquery.split(' ')[0].split('.')",
40 | " if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {",
41 | " throw new Error('Bootstrap\\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')",
42 | " }",
43 | "}(jQuery);\n\n"
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/grunt/sauce_browsers.yml:
--------------------------------------------------------------------------------
1 | [
2 | # Docs: https://saucelabs.com/docs/platforms/webdriver
3 |
4 | {
5 | browserName: "safari",
6 | platform: "OS X 10.10"
7 | },
8 | {
9 | browserName: "chrome",
10 | platform: "OS X 10.10"
11 | },
12 | {
13 | browserName: "firefox",
14 | platform: "OS X 10.10"
15 | },
16 |
17 | # Mac Opera not currently supported by Sauce Labs
18 |
19 | {
20 | browserName: "internet explorer",
21 | version: "11",
22 | platform: "Windows 8.1"
23 | },
24 | {
25 | browserName: "internet explorer",
26 | version: "10",
27 | platform: "Windows 8"
28 | },
29 | {
30 | browserName: "internet explorer",
31 | version: "9",
32 | platform: "Windows 7"
33 | },
34 | {
35 | browserName: "internet explorer",
36 | version: "8",
37 | platform: "Windows 7"
38 | },
39 |
40 | # { # Unofficial
41 | # browserName: "internet explorer",
42 | # version: "7",
43 | # platform: "Windows XP"
44 | # },
45 |
46 | {
47 | browserName: "chrome",
48 | platform: "Windows 8.1"
49 | },
50 | {
51 | browserName: "firefox",
52 | platform: "Windows 8.1"
53 | },
54 |
55 | # Win Opera 15+ not currently supported by Sauce Labs
56 |
57 | {
58 | browserName: "iphone",
59 | platform: "OS X 10.10",
60 | version: "9.2"
61 | },
62 |
63 | # iOS Chrome not currently supported by Sauce Labs
64 |
65 | # Linux (unofficial)
66 | {
67 | browserName: "chrome",
68 | platform: "Linux"
69 | },
70 | {
71 | browserName: "firefox",
72 | platform: "Linux"
73 | }
74 |
75 | # Android Chrome not currently supported by Sauce Labs
76 |
77 | # { # Android Browser (super-unofficial)
78 | # browserName: "android",
79 | # version: "4.0",
80 | # platform: "Linux"
81 | # }
82 | ]
83 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/js/alert.js:
--------------------------------------------------------------------------------
1 | /* ========================================================================
2 | * Bootstrap: alert.js v3.3.7
3 | * http://getbootstrap.com/javascript/#alerts
4 | * ========================================================================
5 | * Copyright 2011-2016 Twitter, Inc.
6 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 | * ======================================================================== */
8 |
9 |
10 | +function ($) {
11 | 'use strict';
12 |
13 | // ALERT CLASS DEFINITION
14 | // ======================
15 |
16 | var dismiss = '[data-dismiss="alert"]'
17 | var Alert = function (el) {
18 | $(el).on('click', dismiss, this.close)
19 | }
20 |
21 | Alert.VERSION = '3.3.7'
22 |
23 | Alert.TRANSITION_DURATION = 150
24 |
25 | Alert.prototype.close = function (e) {
26 | var $this = $(this)
27 | var selector = $this.attr('data-target')
28 |
29 | if (!selector) {
30 | selector = $this.attr('href')
31 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
32 | }
33 |
34 | var $parent = $(selector === '#' ? [] : selector)
35 |
36 | if (e) e.preventDefault()
37 |
38 | if (!$parent.length) {
39 | $parent = $this.closest('.alert')
40 | }
41 |
42 | $parent.trigger(e = $.Event('close.bs.alert'))
43 |
44 | if (e.isDefaultPrevented()) return
45 |
46 | $parent.removeClass('in')
47 |
48 | function removeElement() {
49 | // detach from parent, fire event then clean up data
50 | $parent.detach().trigger('closed.bs.alert').remove()
51 | }
52 |
53 | $.support.transition && $parent.hasClass('fade') ?
54 | $parent
55 | .one('bsTransitionEnd', removeElement)
56 | .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
57 | removeElement()
58 | }
59 |
60 |
61 | // ALERT PLUGIN DEFINITION
62 | // =======================
63 |
64 | function Plugin(option) {
65 | return this.each(function () {
66 | var $this = $(this)
67 | var data = $this.data('bs.alert')
68 |
69 | if (!data) $this.data('bs.alert', (data = new Alert(this)))
70 | if (typeof option == 'string') data[option].call($this)
71 | })
72 | }
73 |
74 | var old = $.fn.alert
75 |
76 | $.fn.alert = Plugin
77 | $.fn.alert.Constructor = Alert
78 |
79 |
80 | // ALERT NO CONFLICT
81 | // =================
82 |
83 | $.fn.alert.noConflict = function () {
84 | $.fn.alert = old
85 | return this
86 | }
87 |
88 |
89 | // ALERT DATA-API
90 | // ==============
91 |
92 | $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
93 |
94 | }(jQuery);
95 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/js/button.js:
--------------------------------------------------------------------------------
1 | /* ========================================================================
2 | * Bootstrap: button.js v3.3.7
3 | * http://getbootstrap.com/javascript/#buttons
4 | * ========================================================================
5 | * Copyright 2011-2016 Twitter, Inc.
6 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 | * ======================================================================== */
8 |
9 |
10 | +function ($) {
11 | 'use strict';
12 |
13 | // BUTTON PUBLIC CLASS DEFINITION
14 | // ==============================
15 |
16 | var Button = function (element, options) {
17 | this.$element = $(element)
18 | this.options = $.extend({}, Button.DEFAULTS, options)
19 | this.isLoading = false
20 | }
21 |
22 | Button.VERSION = '3.3.7'
23 |
24 | Button.DEFAULTS = {
25 | loadingText: 'loading...'
26 | }
27 |
28 | Button.prototype.setState = function (state) {
29 | var d = 'disabled'
30 | var $el = this.$element
31 | var val = $el.is('input') ? 'val' : 'html'
32 | var data = $el.data()
33 |
34 | state += 'Text'
35 |
36 | if (data.resetText == null) $el.data('resetText', $el[val]())
37 |
38 | // push to event loop to allow forms to submit
39 | setTimeout($.proxy(function () {
40 | $el[val](data[state] == null ? this.options[state] : data[state])
41 |
42 | if (state == 'loadingText') {
43 | this.isLoading = true
44 | $el.addClass(d).attr(d, d).prop(d, true)
45 | } else if (this.isLoading) {
46 | this.isLoading = false
47 | $el.removeClass(d).removeAttr(d).prop(d, false)
48 | }
49 | }, this), 0)
50 | }
51 |
52 | Button.prototype.toggle = function () {
53 | var changed = true
54 | var $parent = this.$element.closest('[data-toggle="buttons"]')
55 |
56 | if ($parent.length) {
57 | var $input = this.$element.find('input')
58 | if ($input.prop('type') == 'radio') {
59 | if ($input.prop('checked')) changed = false
60 | $parent.find('.active').removeClass('active')
61 | this.$element.addClass('active')
62 | } else if ($input.prop('type') == 'checkbox') {
63 | if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
64 | this.$element.toggleClass('active')
65 | }
66 | $input.prop('checked', this.$element.hasClass('active'))
67 | if (changed) $input.trigger('change')
68 | } else {
69 | this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
70 | this.$element.toggleClass('active')
71 | }
72 | }
73 |
74 |
75 | // BUTTON PLUGIN DEFINITION
76 | // ========================
77 |
78 | function Plugin(option) {
79 | return this.each(function () {
80 | var $this = $(this)
81 | var data = $this.data('bs.button')
82 | var options = typeof option == 'object' && option
83 |
84 | if (!data) $this.data('bs.button', (data = new Button(this, options)))
85 |
86 | if (option == 'toggle') data.toggle()
87 | else if (option) data.setState(option)
88 | })
89 | }
90 |
91 | var old = $.fn.button
92 |
93 | $.fn.button = Plugin
94 | $.fn.button.Constructor = Button
95 |
96 |
97 | // BUTTON NO CONFLICT
98 | // ==================
99 |
100 | $.fn.button.noConflict = function () {
101 | $.fn.button = old
102 | return this
103 | }
104 |
105 |
106 | // BUTTON DATA-API
107 | // ===============
108 |
109 | $(document)
110 | .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
111 | var $btn = $(e.target).closest('.btn')
112 | Plugin.call($btn, 'toggle')
113 | if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
114 | // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
115 | e.preventDefault()
116 | // The target component still receive the focus
117 | if ($btn.is('input,button')) $btn.trigger('focus')
118 | else $btn.find('input:visible,button:visible').first().trigger('focus')
119 | }
120 | })
121 | .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
122 | $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
123 | })
124 |
125 | }(jQuery);
126 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/js/popover.js:
--------------------------------------------------------------------------------
1 | /* ========================================================================
2 | * Bootstrap: popover.js v3.3.7
3 | * http://getbootstrap.com/javascript/#popovers
4 | * ========================================================================
5 | * Copyright 2011-2016 Twitter, Inc.
6 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 | * ======================================================================== */
8 |
9 |
10 | +function ($) {
11 | 'use strict';
12 |
13 | // POPOVER PUBLIC CLASS DEFINITION
14 | // ===============================
15 |
16 | var Popover = function (element, options) {
17 | this.init('popover', element, options)
18 | }
19 |
20 | if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
21 |
22 | Popover.VERSION = '3.3.7'
23 |
24 | Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
25 | placement: 'right',
26 | trigger: 'click',
27 | content: '',
28 | template: '
'
29 | })
30 |
31 |
32 | // NOTE: POPOVER EXTENDS tooltip.js
33 | // ================================
34 |
35 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
36 |
37 | Popover.prototype.constructor = Popover
38 |
39 | Popover.prototype.getDefaults = function () {
40 | return Popover.DEFAULTS
41 | }
42 |
43 | Popover.prototype.setContent = function () {
44 | var $tip = this.tip()
45 | var title = this.getTitle()
46 | var content = this.getContent()
47 |
48 | $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
49 | $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
50 | this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
51 | ](content)
52 |
53 | $tip.removeClass('fade top bottom left right in')
54 |
55 | // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
56 | // this manually by checking the contents.
57 | if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
58 | }
59 |
60 | Popover.prototype.hasContent = function () {
61 | return this.getTitle() || this.getContent()
62 | }
63 |
64 | Popover.prototype.getContent = function () {
65 | var $e = this.$element
66 | var o = this.options
67 |
68 | return $e.attr('data-content')
69 | || (typeof o.content == 'function' ?
70 | o.content.call($e[0]) :
71 | o.content)
72 | }
73 |
74 | Popover.prototype.arrow = function () {
75 | return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
76 | }
77 |
78 |
79 | // POPOVER PLUGIN DEFINITION
80 | // =========================
81 |
82 | function Plugin(option) {
83 | return this.each(function () {
84 | var $this = $(this)
85 | var data = $this.data('bs.popover')
86 | var options = typeof option == 'object' && option
87 |
88 | if (!data && /destroy|hide/.test(option)) return
89 | if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
90 | if (typeof option == 'string') data[option]()
91 | })
92 | }
93 |
94 | var old = $.fn.popover
95 |
96 | $.fn.popover = Plugin
97 | $.fn.popover.Constructor = Popover
98 |
99 |
100 | // POPOVER NO CONFLICT
101 | // ===================
102 |
103 | $.fn.popover.noConflict = function () {
104 | $.fn.popover = old
105 | return this
106 | }
107 |
108 | }(jQuery);
109 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/js/transition.js:
--------------------------------------------------------------------------------
1 | /* ========================================================================
2 | * Bootstrap: transition.js v3.3.7
3 | * http://getbootstrap.com/javascript/#transitions
4 | * ========================================================================
5 | * Copyright 2011-2016 Twitter, Inc.
6 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 | * ======================================================================== */
8 |
9 |
10 | +function ($) {
11 | 'use strict';
12 |
13 | // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
14 | // ============================================================
15 |
16 | function transitionEnd() {
17 | var el = document.createElement('bootstrap')
18 |
19 | var transEndEventNames = {
20 | WebkitTransition : 'webkitTransitionEnd',
21 | MozTransition : 'transitionend',
22 | OTransition : 'oTransitionEnd otransitionend',
23 | transition : 'transitionend'
24 | }
25 |
26 | for (var name in transEndEventNames) {
27 | if (el.style[name] !== undefined) {
28 | return { end: transEndEventNames[name] }
29 | }
30 | }
31 |
32 | return false // explicit for ie8 ( ._.)
33 | }
34 |
35 | // http://blog.alexmaccaw.com/css-transitions
36 | $.fn.emulateTransitionEnd = function (duration) {
37 | var called = false
38 | var $el = this
39 | $(this).one('bsTransitionEnd', function () { called = true })
40 | var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
41 | setTimeout(callback, duration)
42 | return this
43 | }
44 |
45 | $(function () {
46 | $.support.transition = transitionEnd()
47 |
48 | if (!$.support.transition) return
49 |
50 | $.event.special.bsTransitionEnd = {
51 | bindType: $.support.transition.end,
52 | delegateType: $.support.transition.end,
53 | handle: function (e) {
54 | if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
55 | }
56 | }
57 | })
58 |
59 | }(jQuery);
60 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/alerts.less:
--------------------------------------------------------------------------------
1 | //
2 | // Alerts
3 | // --------------------------------------------------
4 |
5 |
6 | // Base styles
7 | // -------------------------
8 |
9 | .alert {
10 | padding: @alert-padding;
11 | margin-bottom: @line-height-computed;
12 | border: 1px solid transparent;
13 | border-radius: @alert-border-radius;
14 |
15 | // Headings for larger alerts
16 | h4 {
17 | margin-top: 0;
18 | // Specified for the h4 to prevent conflicts of changing @headings-color
19 | color: inherit;
20 | }
21 |
22 | // Provide class for links that match alerts
23 | .alert-link {
24 | font-weight: @alert-link-font-weight;
25 | }
26 |
27 | // Improve alignment and spacing of inner content
28 | > p,
29 | > ul {
30 | margin-bottom: 0;
31 | }
32 |
33 | > p + p {
34 | margin-top: 5px;
35 | }
36 | }
37 |
38 | // Dismissible alerts
39 | //
40 | // Expand the right padding and account for the close button's positioning.
41 |
42 | .alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.
43 | .alert-dismissible {
44 | padding-right: (@alert-padding + 20);
45 |
46 | // Adjust close link position
47 | .close {
48 | position: relative;
49 | top: -2px;
50 | right: -21px;
51 | color: inherit;
52 | }
53 | }
54 |
55 | // Alternate styles
56 | //
57 | // Generate contextual modifier classes for colorizing the alert.
58 |
59 | .alert-success {
60 | .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
61 | }
62 |
63 | .alert-info {
64 | .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
65 | }
66 |
67 | .alert-warning {
68 | .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
69 | }
70 |
71 | .alert-danger {
72 | .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
73 | }
74 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/badges.less:
--------------------------------------------------------------------------------
1 | //
2 | // Badges
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .badge {
8 | display: inline-block;
9 | min-width: 10px;
10 | padding: 3px 7px;
11 | font-size: @font-size-small;
12 | font-weight: @badge-font-weight;
13 | color: @badge-color;
14 | line-height: @badge-line-height;
15 | vertical-align: middle;
16 | white-space: nowrap;
17 | text-align: center;
18 | background-color: @badge-bg;
19 | border-radius: @badge-border-radius;
20 |
21 | // Empty badges collapse automatically (not available in IE8)
22 | &:empty {
23 | display: none;
24 | }
25 |
26 | // Quick fix for badges in buttons
27 | .btn & {
28 | position: relative;
29 | top: -1px;
30 | }
31 |
32 | .btn-xs &,
33 | .btn-group-xs > .btn & {
34 | top: 0;
35 | padding: 1px 5px;
36 | }
37 |
38 | // Hover state, but only for links
39 | a& {
40 | &:hover,
41 | &:focus {
42 | color: @badge-link-hover-color;
43 | text-decoration: none;
44 | cursor: pointer;
45 | }
46 | }
47 |
48 | // Account for badges in navs
49 | .list-group-item.active > &,
50 | .nav-pills > .active > a > & {
51 | color: @badge-active-color;
52 | background-color: @badge-active-bg;
53 | }
54 |
55 | .list-group-item > & {
56 | float: right;
57 | }
58 |
59 | .list-group-item > & + & {
60 | margin-right: 5px;
61 | }
62 |
63 | .nav-pills > li > a > & {
64 | margin-left: 3px;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/bootstrap.less:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.7 (http://getbootstrap.com)
3 | * Copyright 2011-2016 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | // Core variables and mixins
8 | @import "variables.less";
9 | @import "mixins.less";
10 |
11 | // Reset and dependencies
12 | @import "normalize.less";
13 | @import "print.less";
14 | @import "glyphicons.less";
15 |
16 | // Core CSS
17 | @import "scaffolding.less";
18 | @import "type.less";
19 | @import "code.less";
20 | @import "grid.less";
21 | @import "tables.less";
22 | @import "forms.less";
23 | @import "buttons.less";
24 |
25 | // Components
26 | @import "component-animations.less";
27 | @import "dropdowns.less";
28 | @import "button-groups.less";
29 | @import "input-groups.less";
30 | @import "navs.less";
31 | @import "navbar.less";
32 | @import "breadcrumbs.less";
33 | @import "pagination.less";
34 | @import "pager.less";
35 | @import "labels.less";
36 | @import "badges.less";
37 | @import "jumbotron.less";
38 | @import "thumbnails.less";
39 | @import "alerts.less";
40 | @import "progress-bars.less";
41 | @import "media.less";
42 | @import "list-group.less";
43 | @import "panels.less";
44 | @import "responsive-embed.less";
45 | @import "wells.less";
46 | @import "close.less";
47 |
48 | // Components w/ JavaScript
49 | @import "modals.less";
50 | @import "tooltip.less";
51 | @import "popovers.less";
52 | @import "carousel.less";
53 |
54 | // Utility classes
55 | @import "utilities.less";
56 | @import "responsive-utilities.less";
57 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/breadcrumbs.less:
--------------------------------------------------------------------------------
1 | //
2 | // Breadcrumbs
3 | // --------------------------------------------------
4 |
5 |
6 | .breadcrumb {
7 | padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;
8 | margin-bottom: @line-height-computed;
9 | list-style: none;
10 | background-color: @breadcrumb-bg;
11 | border-radius: @border-radius-base;
12 |
13 | > li {
14 | display: inline-block;
15 |
16 | + li:before {
17 | content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
18 | padding: 0 5px;
19 | color: @breadcrumb-color;
20 | }
21 | }
22 |
23 | > .active {
24 | color: @breadcrumb-active-color;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/close.less:
--------------------------------------------------------------------------------
1 | //
2 | // Close icons
3 | // --------------------------------------------------
4 |
5 |
6 | .close {
7 | float: right;
8 | font-size: (@font-size-base * 1.5);
9 | font-weight: @close-font-weight;
10 | line-height: 1;
11 | color: @close-color;
12 | text-shadow: @close-text-shadow;
13 | .opacity(.2);
14 |
15 | &:hover,
16 | &:focus {
17 | color: @close-color;
18 | text-decoration: none;
19 | cursor: pointer;
20 | .opacity(.5);
21 | }
22 |
23 | // Additional properties for button version
24 | // iOS requires the button element instead of an anchor tag.
25 | // If you want the anchor version, it requires `href="#"`.
26 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
27 | button& {
28 | padding: 0;
29 | cursor: pointer;
30 | background: transparent;
31 | border: 0;
32 | -webkit-appearance: none;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/code.less:
--------------------------------------------------------------------------------
1 | //
2 | // Code (inline and block)
3 | // --------------------------------------------------
4 |
5 |
6 | // Inline and block code styles
7 | code,
8 | kbd,
9 | pre,
10 | samp {
11 | font-family: @font-family-monospace;
12 | }
13 |
14 | // Inline code
15 | code {
16 | padding: 2px 4px;
17 | font-size: 90%;
18 | color: @code-color;
19 | background-color: @code-bg;
20 | border-radius: @border-radius-base;
21 | }
22 |
23 | // User input typically entered via keyboard
24 | kbd {
25 | padding: 2px 4px;
26 | font-size: 90%;
27 | color: @kbd-color;
28 | background-color: @kbd-bg;
29 | border-radius: @border-radius-small;
30 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
31 |
32 | kbd {
33 | padding: 0;
34 | font-size: 100%;
35 | font-weight: bold;
36 | box-shadow: none;
37 | }
38 | }
39 |
40 | // Blocks of code
41 | pre {
42 | display: block;
43 | padding: ((@line-height-computed - 1) / 2);
44 | margin: 0 0 (@line-height-computed / 2);
45 | font-size: (@font-size-base - 1); // 14px to 13px
46 | line-height: @line-height-base;
47 | word-break: break-all;
48 | word-wrap: break-word;
49 | color: @pre-color;
50 | background-color: @pre-bg;
51 | border: 1px solid @pre-border-color;
52 | border-radius: @border-radius-base;
53 |
54 | // Account for some code outputs that place code tags in pre tags
55 | code {
56 | padding: 0;
57 | font-size: inherit;
58 | color: inherit;
59 | white-space: pre-wrap;
60 | background-color: transparent;
61 | border-radius: 0;
62 | }
63 | }
64 |
65 | // Enable scrollable blocks of code
66 | .pre-scrollable {
67 | max-height: @pre-scrollable-max-height;
68 | overflow-y: scroll;
69 | }
70 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/component-animations.less:
--------------------------------------------------------------------------------
1 | //
2 | // Component animations
3 | // --------------------------------------------------
4 |
5 | // Heads up!
6 | //
7 | // We don't use the `.opacity()` mixin here since it causes a bug with text
8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.
9 |
10 | .fade {
11 | opacity: 0;
12 | .transition(opacity .15s linear);
13 | &.in {
14 | opacity: 1;
15 | }
16 | }
17 |
18 | .collapse {
19 | display: none;
20 |
21 | &.in { display: block; }
22 | tr&.in { display: table-row; }
23 | tbody&.in { display: table-row-group; }
24 | }
25 |
26 | .collapsing {
27 | position: relative;
28 | height: 0;
29 | overflow: hidden;
30 | .transition-property(~"height, visibility");
31 | .transition-duration(.35s);
32 | .transition-timing-function(ease);
33 | }
34 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/grid.less:
--------------------------------------------------------------------------------
1 | //
2 | // Grid system
3 | // --------------------------------------------------
4 |
5 |
6 | // Container widths
7 | //
8 | // Set the container width, and override it for fixed navbars in media queries.
9 |
10 | .container {
11 | .container-fixed();
12 |
13 | @media (min-width: @screen-sm-min) {
14 | width: @container-sm;
15 | }
16 | @media (min-width: @screen-md-min) {
17 | width: @container-md;
18 | }
19 | @media (min-width: @screen-lg-min) {
20 | width: @container-lg;
21 | }
22 | }
23 |
24 |
25 | // Fluid container
26 | //
27 | // Utilizes the mixin meant for fixed width containers, but without any defined
28 | // width for fluid, full width layouts.
29 |
30 | .container-fluid {
31 | .container-fixed();
32 | }
33 |
34 |
35 | // Row
36 | //
37 | // Rows contain and clear the floats of your columns.
38 |
39 | .row {
40 | .make-row();
41 | }
42 |
43 |
44 | // Columns
45 | //
46 | // Common styles for small and large grid columns
47 |
48 | .make-grid-columns();
49 |
50 |
51 | // Extra small grid
52 | //
53 | // Columns, offsets, pushes, and pulls for extra small devices like
54 | // smartphones.
55 |
56 | .make-grid(xs);
57 |
58 |
59 | // Small grid
60 | //
61 | // Columns, offsets, pushes, and pulls for the small device range, from phones
62 | // to tablets.
63 |
64 | @media (min-width: @screen-sm-min) {
65 | .make-grid(sm);
66 | }
67 |
68 |
69 | // Medium grid
70 | //
71 | // Columns, offsets, pushes, and pulls for the desktop device range.
72 |
73 | @media (min-width: @screen-md-min) {
74 | .make-grid(md);
75 | }
76 |
77 |
78 | // Large grid
79 | //
80 | // Columns, offsets, pushes, and pulls for the large desktop device range.
81 |
82 | @media (min-width: @screen-lg-min) {
83 | .make-grid(lg);
84 | }
85 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/jumbotron.less:
--------------------------------------------------------------------------------
1 | //
2 | // Jumbotron
3 | // --------------------------------------------------
4 |
5 |
6 | .jumbotron {
7 | padding-top: @jumbotron-padding;
8 | padding-bottom: @jumbotron-padding;
9 | margin-bottom: @jumbotron-padding;
10 | color: @jumbotron-color;
11 | background-color: @jumbotron-bg;
12 |
13 | h1,
14 | .h1 {
15 | color: @jumbotron-heading-color;
16 | }
17 |
18 | p {
19 | margin-bottom: (@jumbotron-padding / 2);
20 | font-size: @jumbotron-font-size;
21 | font-weight: 200;
22 | }
23 |
24 | > hr {
25 | border-top-color: darken(@jumbotron-bg, 10%);
26 | }
27 |
28 | .container &,
29 | .container-fluid & {
30 | border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container
31 | padding-left: (@grid-gutter-width / 2);
32 | padding-right: (@grid-gutter-width / 2);
33 | }
34 |
35 | .container {
36 | max-width: 100%;
37 | }
38 |
39 | @media screen and (min-width: @screen-sm-min) {
40 | padding-top: (@jumbotron-padding * 1.6);
41 | padding-bottom: (@jumbotron-padding * 1.6);
42 |
43 | .container &,
44 | .container-fluid & {
45 | padding-left: (@jumbotron-padding * 2);
46 | padding-right: (@jumbotron-padding * 2);
47 | }
48 |
49 | h1,
50 | .h1 {
51 | font-size: @jumbotron-heading-font-size;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/labels.less:
--------------------------------------------------------------------------------
1 | //
2 | // Labels
3 | // --------------------------------------------------
4 |
5 | .label {
6 | display: inline;
7 | padding: .2em .6em .3em;
8 | font-size: 75%;
9 | font-weight: bold;
10 | line-height: 1;
11 | color: @label-color;
12 | text-align: center;
13 | white-space: nowrap;
14 | vertical-align: baseline;
15 | border-radius: .25em;
16 |
17 | // Add hover effects, but only for links
18 | a& {
19 | &:hover,
20 | &:focus {
21 | color: @label-link-hover-color;
22 | text-decoration: none;
23 | cursor: pointer;
24 | }
25 | }
26 |
27 | // Empty labels collapse automatically (not available in IE8)
28 | &:empty {
29 | display: none;
30 | }
31 |
32 | // Quick fix for labels in buttons
33 | .btn & {
34 | position: relative;
35 | top: -1px;
36 | }
37 | }
38 |
39 | // Colors
40 | // Contextual variations (linked labels get darker on :hover)
41 |
42 | .label-default {
43 | .label-variant(@label-default-bg);
44 | }
45 |
46 | .label-primary {
47 | .label-variant(@label-primary-bg);
48 | }
49 |
50 | .label-success {
51 | .label-variant(@label-success-bg);
52 | }
53 |
54 | .label-info {
55 | .label-variant(@label-info-bg);
56 | }
57 |
58 | .label-warning {
59 | .label-variant(@label-warning-bg);
60 | }
61 |
62 | .label-danger {
63 | .label-variant(@label-danger-bg);
64 | }
65 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/list-group.less:
--------------------------------------------------------------------------------
1 | //
2 | // List groups
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | //
8 | // Easily usable on , , or .
9 |
10 | .list-group {
11 | // No need to set list-style: none; since .list-group-item is block level
12 | margin-bottom: 20px;
13 | padding-left: 0; // reset padding because ul and ol
14 | }
15 |
16 |
17 | // Individual list items
18 | //
19 | // Use on `li`s or `div`s within the `.list-group` parent.
20 |
21 | .list-group-item {
22 | position: relative;
23 | display: block;
24 | padding: 10px 15px;
25 | // Place the border on the list items and negative margin up for better styling
26 | margin-bottom: -1px;
27 | background-color: @list-group-bg;
28 | border: 1px solid @list-group-border;
29 |
30 | // Round the first and last items
31 | &:first-child {
32 | .border-top-radius(@list-group-border-radius);
33 | }
34 | &:last-child {
35 | margin-bottom: 0;
36 | .border-bottom-radius(@list-group-border-radius);
37 | }
38 | }
39 |
40 |
41 | // Interactive list items
42 | //
43 | // Use anchor or button elements instead of `li`s or `div`s to create interactive items.
44 | // Includes an extra `.active` modifier class for showing selected items.
45 |
46 | a.list-group-item,
47 | button.list-group-item {
48 | color: @list-group-link-color;
49 |
50 | .list-group-item-heading {
51 | color: @list-group-link-heading-color;
52 | }
53 |
54 | // Hover state
55 | &:hover,
56 | &:focus {
57 | text-decoration: none;
58 | color: @list-group-link-hover-color;
59 | background-color: @list-group-hover-bg;
60 | }
61 | }
62 |
63 | button.list-group-item {
64 | width: 100%;
65 | text-align: left;
66 | }
67 |
68 | .list-group-item {
69 | // Disabled state
70 | &.disabled,
71 | &.disabled:hover,
72 | &.disabled:focus {
73 | background-color: @list-group-disabled-bg;
74 | color: @list-group-disabled-color;
75 | cursor: @cursor-disabled;
76 |
77 | // Force color to inherit for custom content
78 | .list-group-item-heading {
79 | color: inherit;
80 | }
81 | .list-group-item-text {
82 | color: @list-group-disabled-text-color;
83 | }
84 | }
85 |
86 | // Active class on item itself, not parent
87 | &.active,
88 | &.active:hover,
89 | &.active:focus {
90 | z-index: 2; // Place active items above their siblings for proper border styling
91 | color: @list-group-active-color;
92 | background-color: @list-group-active-bg;
93 | border-color: @list-group-active-border;
94 |
95 | // Force color to inherit for custom content
96 | .list-group-item-heading,
97 | .list-group-item-heading > small,
98 | .list-group-item-heading > .small {
99 | color: inherit;
100 | }
101 | .list-group-item-text {
102 | color: @list-group-active-text-color;
103 | }
104 | }
105 | }
106 |
107 |
108 | // Contextual variants
109 | //
110 | // Add modifier classes to change text and background color on individual items.
111 | // Organizationally, this must come after the `:hover` states.
112 |
113 | .list-group-item-variant(success; @state-success-bg; @state-success-text);
114 | .list-group-item-variant(info; @state-info-bg; @state-info-text);
115 | .list-group-item-variant(warning; @state-warning-bg; @state-warning-text);
116 | .list-group-item-variant(danger; @state-danger-bg; @state-danger-text);
117 |
118 |
119 | // Custom content options
120 | //
121 | // Extra classes for creating well-formatted content within `.list-group-item`s.
122 |
123 | .list-group-item-heading {
124 | margin-top: 0;
125 | margin-bottom: 5px;
126 | }
127 | .list-group-item-text {
128 | margin-bottom: 0;
129 | line-height: 1.3;
130 | }
131 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/media.less:
--------------------------------------------------------------------------------
1 | .media {
2 | // Proper spacing between instances of .media
3 | margin-top: 15px;
4 |
5 | &:first-child {
6 | margin-top: 0;
7 | }
8 | }
9 |
10 | .media,
11 | .media-body {
12 | zoom: 1;
13 | overflow: hidden;
14 | }
15 |
16 | .media-body {
17 | width: 10000px;
18 | }
19 |
20 | .media-object {
21 | display: block;
22 |
23 | // Fix collapse in webkit from max-width: 100% and display: table-cell.
24 | &.img-thumbnail {
25 | max-width: none;
26 | }
27 | }
28 |
29 | .media-right,
30 | .media > .pull-right {
31 | padding-left: 10px;
32 | }
33 |
34 | .media-left,
35 | .media > .pull-left {
36 | padding-right: 10px;
37 | }
38 |
39 | .media-left,
40 | .media-right,
41 | .media-body {
42 | display: table-cell;
43 | vertical-align: top;
44 | }
45 |
46 | .media-middle {
47 | vertical-align: middle;
48 | }
49 |
50 | .media-bottom {
51 | vertical-align: bottom;
52 | }
53 |
54 | // Reset margins on headings for tighter default spacing
55 | .media-heading {
56 | margin-top: 0;
57 | margin-bottom: 5px;
58 | }
59 |
60 | // Media list variation
61 | //
62 | // Undo default ul/ol styles
63 | .media-list {
64 | padding-left: 0;
65 | list-style: none;
66 | }
67 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins.less:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------------------------------
3 |
4 | // Utilities
5 | @import "mixins/hide-text.less";
6 | @import "mixins/opacity.less";
7 | @import "mixins/image.less";
8 | @import "mixins/labels.less";
9 | @import "mixins/reset-filter.less";
10 | @import "mixins/resize.less";
11 | @import "mixins/responsive-visibility.less";
12 | @import "mixins/size.less";
13 | @import "mixins/tab-focus.less";
14 | @import "mixins/reset-text.less";
15 | @import "mixins/text-emphasis.less";
16 | @import "mixins/text-overflow.less";
17 | @import "mixins/vendor-prefixes.less";
18 |
19 | // Components
20 | @import "mixins/alerts.less";
21 | @import "mixins/buttons.less";
22 | @import "mixins/panels.less";
23 | @import "mixins/pagination.less";
24 | @import "mixins/list-group.less";
25 | @import "mixins/nav-divider.less";
26 | @import "mixins/forms.less";
27 | @import "mixins/progress-bar.less";
28 | @import "mixins/table-row.less";
29 |
30 | // Skins
31 | @import "mixins/background-variant.less";
32 | @import "mixins/border-radius.less";
33 | @import "mixins/gradients.less";
34 |
35 | // Layout
36 | @import "mixins/clearfix.less";
37 | @import "mixins/center-block.less";
38 | @import "mixins/nav-vertical-align.less";
39 | @import "mixins/grid-framework.less";
40 | @import "mixins/grid.less";
41 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/alerts.less:
--------------------------------------------------------------------------------
1 | // Alerts
2 |
3 | .alert-variant(@background; @border; @text-color) {
4 | background-color: @background;
5 | border-color: @border;
6 | color: @text-color;
7 |
8 | hr {
9 | border-top-color: darken(@border, 5%);
10 | }
11 | .alert-link {
12 | color: darken(@text-color, 10%);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/background-variant.less:
--------------------------------------------------------------------------------
1 | // Contextual backgrounds
2 |
3 | .bg-variant(@color) {
4 | background-color: @color;
5 | a&:hover,
6 | a&:focus {
7 | background-color: darken(@color, 10%);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/border-radius.less:
--------------------------------------------------------------------------------
1 | // Single side border-radius
2 |
3 | .border-top-radius(@radius) {
4 | border-top-right-radius: @radius;
5 | border-top-left-radius: @radius;
6 | }
7 | .border-right-radius(@radius) {
8 | border-bottom-right-radius: @radius;
9 | border-top-right-radius: @radius;
10 | }
11 | .border-bottom-radius(@radius) {
12 | border-bottom-right-radius: @radius;
13 | border-bottom-left-radius: @radius;
14 | }
15 | .border-left-radius(@radius) {
16 | border-bottom-left-radius: @radius;
17 | border-top-left-radius: @radius;
18 | }
19 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/buttons.less:
--------------------------------------------------------------------------------
1 | // Button variants
2 | //
3 | // Easily pump out default styles, as well as :hover, :focus, :active,
4 | // and disabled options for all buttons
5 |
6 | .button-variant(@color; @background; @border) {
7 | color: @color;
8 | background-color: @background;
9 | border-color: @border;
10 |
11 | &:focus,
12 | &.focus {
13 | color: @color;
14 | background-color: darken(@background, 10%);
15 | border-color: darken(@border, 25%);
16 | }
17 | &:hover {
18 | color: @color;
19 | background-color: darken(@background, 10%);
20 | border-color: darken(@border, 12%);
21 | }
22 | &:active,
23 | &.active,
24 | .open > .dropdown-toggle& {
25 | color: @color;
26 | background-color: darken(@background, 10%);
27 | border-color: darken(@border, 12%);
28 |
29 | &:hover,
30 | &:focus,
31 | &.focus {
32 | color: @color;
33 | background-color: darken(@background, 17%);
34 | border-color: darken(@border, 25%);
35 | }
36 | }
37 | &:active,
38 | &.active,
39 | .open > .dropdown-toggle& {
40 | background-image: none;
41 | }
42 | &.disabled,
43 | &[disabled],
44 | fieldset[disabled] & {
45 | &:hover,
46 | &:focus,
47 | &.focus {
48 | background-color: @background;
49 | border-color: @border;
50 | }
51 | }
52 |
53 | .badge {
54 | color: @background;
55 | background-color: @color;
56 | }
57 | }
58 |
59 | // Button sizes
60 | .button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
61 | padding: @padding-vertical @padding-horizontal;
62 | font-size: @font-size;
63 | line-height: @line-height;
64 | border-radius: @border-radius;
65 | }
66 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/center-block.less:
--------------------------------------------------------------------------------
1 | // Center-align a block level element
2 |
3 | .center-block() {
4 | display: block;
5 | margin-left: auto;
6 | margin-right: auto;
7 | }
8 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/clearfix.less:
--------------------------------------------------------------------------------
1 | // Clearfix
2 | //
3 | // For modern browsers
4 | // 1. The space content is one way to avoid an Opera bug when the
5 | // contenteditable attribute is included anywhere else in the document.
6 | // Otherwise it causes space to appear at the top and bottom of elements
7 | // that are clearfixed.
8 | // 2. The use of `table` rather than `block` is only necessary if using
9 | // `:before` to contain the top-margins of child elements.
10 | //
11 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
12 |
13 | .clearfix() {
14 | &:before,
15 | &:after {
16 | content: " "; // 1
17 | display: table; // 2
18 | }
19 | &:after {
20 | clear: both;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/django_classifier_profile/static/node_modules/bootstrap/less/mixins/forms.less:
--------------------------------------------------------------------------------
1 | // Form validation states
2 | //
3 | // Used in forms.less to generate the form validation CSS for warnings, errors,
4 | // and successes.
5 |
6 | .form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {
7 | // Color the label and help text
8 | .help-block,
9 | .control-label,
10 | .radio,
11 | .checkbox,
12 | .radio-inline,
13 | .checkbox-inline,
14 | &.radio label,
15 | &.checkbox label,
16 | &.radio-inline label,
17 | &.checkbox-inline label {
18 | color: @text-color;
19 | }
20 | // Set the border and box shadow on specific inputs to match
21 | .form-control {
22 | border-color: @border-color;
23 | .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
24 | &:focus {
25 | border-color: darken(@border-color, 10%);
26 | @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);
27 | .box-shadow(@shadow);
28 | }
29 | }
30 | // Set validation states also for addons
31 | .input-group-addon {
32 | color: @text-color;
33 | border-color: @border-color;
34 | background-color: @background-color;
35 | }
36 | // Optional feedback icon
37 | .form-control-feedback {
38 | color: @text-color;
39 | }
40 | }
41 |
42 |
43 | // Form control focus state
44 | //
45 | // Generate a customized focus state and for any input with the specified color,
46 | // which defaults to the `@input-border-focus` variable.
47 | //
48 | // We highly encourage you to not customize the default value, but instead use
49 | // this to tweak colors on an as-needed basis. This aesthetic change is based on
50 | // WebKit's default styles, but applicable to a wider range of browsers. Its
51 | // usability and accessibility should be taken into account with any change.
52 | //
53 | // Example usage: change the default blue border and shadow to white for better
54 | // contrast against a dark gray background.
55 | .form-control-focus(@color: @input-border-focus) {
56 | @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);
57 | &:focus {
58 | border-color: @color;
59 | outline: 0;
60 | .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}");
61 | }
62 | }
63 |
64 | // Form control sizing
65 | //
66 | // Relative text size, padding, and border-radii changes for form controls. For
67 | // horizontal sizing, wrap controls in the predefined grid classes. `