diff --git a/.gitignore b/.gitignore index 1e9fa8329..c462b737e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# 编辑器缓存文件夹 +.idea +.idea/ + *.py[cod] # C extensions diff --git a/xadmin/__init__.py b/xadmin/__init__.py index 3e1a0522c..24f3e498b 100644 --- a/xadmin/__init__.py +++ b/xadmin/__init__.py @@ -1,8 +1,15 @@ VERSION = (0,6,0) +import six +import django +setattr(django.utils, 'six', six) + + from xadmin.sites import AdminSite, site + + class Settings(object): pass diff --git a/xadmin/filters.py b/xadmin/filters.py index 9eba01e99..9ab977a6c 100644 --- a/xadmin/filters.py +++ b/xadmin/filters.py @@ -8,19 +8,19 @@ from django.template.context import Context from django.utils import six from django.utils.safestring import mark_safe -from django.utils.html import escape,format_html +from django.utils.html import escape, format_html from django.utils.text import Truncator from django.core.cache import cache, caches from xadmin.views.list import EMPTY_CHANGELIST_VALUE -from xadmin.util import is_related_field,is_related_field2 +from xadmin.util import is_related_field, is_related_field2 import datetime FILTER_PREFIX = '_p_' SEARCH_VAR = '_q_' from .util import (get_model_from_relation, - reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value) + reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value) class BaseFilter(object): @@ -125,9 +125,9 @@ def __init__(self, field, request, params, model, admin_view, field_path): self.context_params["%s_val" % name] = '' arr = map( - lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]), - self.context_params.items() - ) + lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]), + self.context_params.items() + ) if six.PY3: list(arr) @@ -169,27 +169,27 @@ def choices(self): ('', _('All')), ('1', _('Yes')), ('0', _('No')), - ): + ): yield { - 'selected': ( - self.lookup_exact_val == lookup - and not self.lookup_isnull_val - ), - 'query_string': self.query_string( - {self.lookup_exact_name: lookup}, - [self.lookup_isnull_name], - ), - 'display': title, - } + 'selected': ( + self.lookup_exact_val == lookup + and not self.lookup_isnull_val + ), + 'query_string': self.query_string( + {self.lookup_exact_name: lookup}, + [self.lookup_isnull_name], + ), + 'display': title, + } if isinstance(self.field, models.NullBooleanField): yield { - 'selected': self.lookup_isnull_val == 'True', - 'query_string': self.query_string( - {self.lookup_isnull_name: 'True'}, - [self.lookup_exact_name], - ), - 'display': _('Unknown'), - } + 'selected': self.lookup_isnull_val == 'True', + 'query_string': self.query_string( + {self.lookup_isnull_name: 'True'}, + [self.lookup_exact_name], + ), + 'display': _('Unknown'), + } @manager.register @@ -222,10 +222,10 @@ class TextFieldListFilter(FieldFilter): @classmethod def test(cls, field, request, params, model, admin_view, field_path): return ( - isinstance(field, models.CharField) - and field.max_length > 20 - or isinstance(field, models.TextField) - ) + isinstance(field, models.CharField) + and field.max_length > 20 + or isinstance(field, models.TextField) + ) @manager.register @@ -320,7 +320,7 @@ def choices(self): yield { 'selected': self.date_params == param_dict, 'query_string': self.query_string( - param_dict, [FILTER_PREFIX + self.field_generic]), + param_dict, [FILTER_PREFIX + self.field_generic]), 'display': title, } @@ -339,12 +339,12 @@ def test(cls, field, request, params, model, admin_view, field_path): def __init__(self, field, request, params, model, model_admin, field_path): other_model = get_model_from_relation(field) - if hasattr(field, 'rel'): - rel_name = field.rel.get_related_field().name + if hasattr(field, 'remote_field'): + rel_name = field.remote_field.get_related_field().name else: rel_name = other_model._meta.pk.name - self.lookup_formats = {'in': '%%s__%s__in' % rel_name,'exact': '%%s__%s__exact' % rel_name} + self.lookup_formats = {'in': '%%s__%s__in' % rel_name, 'exact': '%%s__%s__exact' % rel_name} super(RelatedFieldSearchFilter, self).__init__( field, request, params, model, model_admin, field_path) @@ -360,9 +360,9 @@ def __init__(self, field, request, params, model, model_admin, field_path): other_model._meta.app_label, other_model._meta.model_name)) self.label = self.label_for_value(other_model, rel_name, self.lookup_exact_val) if self.lookup_exact_val else "" self.choices = '?' - if field.rel.limit_choices_to: - for i in list(field.rel.limit_choices_to): - self.choices += "&_p_%s=%s" % (i, field.rel.limit_choices_to[i]) + if field.remote_field.limit_choices_to: + for i in list(field.remote_field.limit_choices_to): + self.choices += "&_p_%s=%s" % (i, field.remote_field.limit_choices_to[i]) self.choices = format_html(self.choices) def label_for_value(self, other_model, rel_name, value): @@ -390,12 +390,12 @@ def test(cls, field, request, params, model, admin_view, field_path): def __init__(self, field, request, params, model, model_admin, field_path): other_model = get_model_from_relation(field) - if hasattr(field, 'rel'): - rel_name = field.rel.get_related_field().name + if hasattr(field, 'remote_field'): + rel_name = field.remote_field.get_related_field().name else: rel_name = other_model._meta.pk.name - self.lookup_formats = {'in': '%%s__%s__in' % rel_name,'exact': '%%s__%s__exact' % + self.lookup_formats = {'in': '%%s__%s__in' % rel_name, 'exact': '%%s__%s__exact' % rel_name, 'isnull': '%s__isnull'} self.lookup_choices = field.get_choices(include_blank=False) super(RelatedFieldListFilter, self).__init__( @@ -409,7 +409,7 @@ def __init__(self, field, request, params, model, model_admin, field_path): def has_output(self): if (is_related_field(self.field) - and self.field.field.null or hasattr(self.field, 'rel') + and self.field.field.null or hasattr(self.field, 'remote_field') and self.field.null): extra = 1 else: @@ -435,7 +435,7 @@ def choices(self): 'display': val, } if (is_related_field(self.field) - and self.field.field.null or hasattr(self.field, 'rel') + and self.field.field.null or hasattr(self.field, 'remote_field') and self.field.null): yield { 'selected': bool(self.lookup_isnull_val), @@ -445,81 +445,83 @@ def choices(self): 'display': EMPTY_CHANGELIST_VALUE, } + @manager.register class MultiSelectFieldListFilter(ListFieldFilter): """ Delegates the filter to the default filter and ors the results of each - + Lists the distinct values of each field as a checkbox Uses the default spec for each - + """ template = 'xadmin/filters/checklist.html' lookup_formats = {'in': '%s__in'} - cache_config = {'enabled':False,'key':'quickfilter_%s','timeout':3600,'cache':'default'} - + cache_config = {'enabled': False, 'key': 'quickfilter_%s', 'timeout': 3600, 'cache': 'default'} + @classmethod def test(cls, field, request, params, model, admin_view, field_path): return True - + def get_cached_choices(self): if not self.cache_config['enabled']: return None c = caches(self.cache_config['cache']) - return c.get(self.cache_config['key']%self.field_path) - - def set_cached_choices(self,choices): + return c.get(self.cache_config['key'] % self.field_path) + + def set_cached_choices(self, choices): if not self.cache_config['enabled']: return c = caches(self.cache_config['cache']) - return c.set(self.cache_config['key']%self.field_path,choices) - - def __init__(self, field, request, params, model, model_admin, field_path,field_order_by=None,field_limit=None,sort_key=None,cache_config=None): - super(MultiSelectFieldListFilter,self).__init__(field, request, params, model, model_admin, field_path) - + return c.set(self.cache_config['key'] % self.field_path, choices) + + def __init__(self, field, request, params, model, model_admin, field_path, field_order_by=None, field_limit=None, sort_key=None, cache_config=None): + super(MultiSelectFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path) + # Check for it in the cachce - if cache_config is not None and type(cache_config)==dict: + if cache_config is not None and type(cache_config) == dict: self.cache_config.update(cache_config) - + if self.cache_config['enabled']: self.field_path = field_path choices = self.get_cached_choices() if choices: self.lookup_choices = choices return - + # Else rebuild it - queryset = self.admin_view.queryset().exclude(**{"%s__isnull"%field_path:True}).values_list(field_path, flat=True).distinct() + queryset = self.admin_view.queryset().exclude(**{"%s__isnull" % field_path: True}).values_list(field_path, flat=True).distinct() #queryset = self.admin_view.queryset().distinct(field_path).exclude(**{"%s__isnull"%field_path:True}) - + if field_order_by is not None: # Do a subquery to order the distinct set queryset = self.admin_view.queryset().filter(id__in=queryset).order_by(field_order_by) - - if field_limit is not None and type(field_limit)==int and queryset.count()>field_limit: + + if field_limit is not None and type(field_limit) == int and queryset.count() > field_limit: queryset = queryset[:field_limit] - - self.lookup_choices = [str(it) for it in queryset.values_list(field_path,flat=True) if str(it).strip()!=""] + + self.lookup_choices = [str(it) for it in queryset.values_list(field_path, flat=True) if str(it).strip() != ""] if sort_key is not None: - self.lookup_choices = sorted(self.lookup_choices,key=sort_key) - + self.lookup_choices = sorted(self.lookup_choices, key=sort_key) + if self.cache_config['enabled']: - self.set_cached_choices(self.lookup_choices) + self.set_cached_choices(self.lookup_choices) def choices(self): - self.lookup_in_val = (type(self.lookup_in_val) in (tuple,list)) and self.lookup_in_val or list(self.lookup_in_val) + self.lookup_in_val = (type(self.lookup_in_val) in (tuple, list)) and self.lookup_in_val or list(self.lookup_in_val) yield { 'selected': len(self.lookup_in_val) == 0, - 'query_string': self.query_string({},[self.lookup_in_name]), + 'query_string': self.query_string({}, [self.lookup_in_name]), 'display': _('All'), } for val in self.lookup_choices: yield { 'selected': smart_text(val) in self.lookup_in_val, - 'query_string': self.query_string({self.lookup_in_name: ",".join([val]+self.lookup_in_val),}), - 'remove_query_string': self.query_string({self.lookup_in_name: ",".join([v for v in self.lookup_in_val if v != val]),}), + 'query_string': self.query_string({self.lookup_in_name: ",".join([val] + self.lookup_in_val), }), + 'remove_query_string': self.query_string({self.lookup_in_name: ",".join([v for v in self.lookup_in_val if v != val]), }), 'display': val, } + @manager.register class AllValuesFieldListFilter(ListFieldFilter): lookup_formats = {'exact': '%s__exact', 'isnull': '%s__isnull'} diff --git a/xadmin/migrations/0004_auto_20210425_2223.py b/xadmin/migrations/0004_auto_20210425_2223.py new file mode 100644 index 000000000..8f4bbe649 --- /dev/null +++ b/xadmin/migrations/0004_auto_20210425_2223.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2 on 2021-04-25 14:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('xadmin', '0003_auto_20160715_0100'), + ] + + operations = [ + migrations.AlterField( + model_name='bookmark', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='log', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='usersettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='userwidget', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/xadmin/models.py b/xadmin/models.py index da5145641..09c169b25 100644 --- a/xadmin/models.py +++ b/xadmin/models.py @@ -5,10 +5,12 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy as _, ugettext -from django.core.urlresolvers import NoReverseMatch, reverse +from django.urls.base import reverse from django.core.serializers.json import DjangoJSONEncoder from django.db.models.base import ModelBase -from django.utils.encoding import python_2_unicode_compatible, smart_text +# from django.utils.encoding import python_2_unicode_compatible, smart_text +from django.utils.encoding import smart_text +from six import python_2_unicode_compatible from django.db.models.signals import post_migrate from django.contrib.auth.models import Permission @@ -19,6 +21,7 @@ AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') + def add_view_permissions(sender, **kwargs): """ This syncdb hooks takes care of adding a view permission too all our @@ -35,7 +38,7 @@ def add_view_permissions(sender, **kwargs): Permission.objects.create(content_type=content_type, codename=codename, name="Can view %s" % content_type.name) - #print "Added view permission for %s" % content_type.name + # print "Added view permission for %s" % content_type.name # check for all our view permissions after a syncdb post_migrate.connect(add_view_permissions) @@ -44,9 +47,9 @@ def add_view_permissions(sender, **kwargs): @python_2_unicode_compatible class Bookmark(models.Model): title = models.CharField(_(u'Title'), max_length=128) - user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user"), blank=True, null=True) + user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user"), blank=True, null=True) url_name = models.CharField(_(u'Url Name'), max_length=64) - content_type = models.ForeignKey(ContentType) + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) query = models.CharField(_(u'Query String'), max_length=1000, blank=True) is_share = models.BooleanField(_(u'Is Shared'), default=False) @@ -66,6 +69,7 @@ class Meta: class JSONEncoder(DjangoJSONEncoder): + def default(self, o): if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %H:%M:%S') @@ -84,7 +88,7 @@ def default(self, o): @python_2_unicode_compatible class UserSettings(models.Model): - user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user")) + user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user")) key = models.CharField(_('Settings Key'), max_length=256) value = models.TextField(_('Settings Content')) @@ -104,7 +108,7 @@ class Meta: @python_2_unicode_compatible class UserWidget(models.Model): - user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user")) + user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user")) page_id = models.CharField(_(u"Page"), max_length=256) widget_type = models.CharField(_(u"Widget Type"), max_length=50) value = models.TextField(_(u"Widget Params")) @@ -186,4 +190,3 @@ def __str__(self): def get_edited_object(self): "Returns the edited object represented by this log entry" return self.content_type.get_object_for_this_type(pk=self.object_id) - diff --git a/xadmin/plugins/__init__.py b/xadmin/plugins/__init__.py index e570dfe67..ce3955f94 100644 --- a/xadmin/plugins/__init__.py +++ b/xadmin/plugins/__init__.py @@ -1,34 +1,35 @@ PLUGINS = ( - 'actions', - 'filters', - 'bookmark', - 'export', - 'layout', + 'actions', + 'filters', + 'bookmark', + 'export', + 'layout', 'refresh', 'details', - 'editable', - 'relate', - 'chart', - 'ajax', - 'relfield', - 'inline', - 'topnav', - 'portal', + 'editable', + 'relate', + 'chart', + 'ajax', + 'relfield', + 'inline', + 'topnav', + 'portal', 'quickform', - 'wizard', - 'images', - 'auth', - 'multiselect', - 'themes', - 'aggregation', - 'mobile', + 'wizard', + 'images', + 'auth', + 'multiselect', + 'themes', + 'aggregation', + # 'mobile', 'passwords', - 'sitemenu', - 'language', + 'sitemenu', + 'language', 'quickfilter', 'sortablelist', - 'importexport' + 'importexport', + # 'ueditor', ) diff --git a/xadmin/plugins/actions.py b/xadmin/plugins/actions.py index 02085bf33..d3c244001 100644 --- a/xadmin/plugins/actions.py +++ b/xadmin/plugins/actions.py @@ -1,5 +1,5 @@ from collections import OrderedDict -from django import forms +from django import forms, VERSION as django_version from django.core.exceptions import PermissionDenied from django.db import router from django.http import HttpResponse, HttpResponseRedirect @@ -19,6 +19,7 @@ from xadmin.views import BaseAdminPlugin, ListAdminView from xadmin.views.base import filter_hook, ModelAdminView +from xadmin import views ACTION_CHECKBOX_NAME = '_selected_action' checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False) @@ -26,12 +27,15 @@ def action_checkbox(obj): return checkbox.render(ACTION_CHECKBOX_NAME, force_text(obj.pk)) + + action_checkbox.short_description = mark_safe( '') action_checkbox.allow_tags = True action_checkbox.allow_export = False action_checkbox.is_column = False + class BaseActionView(ModelAdminView): action_name = None description = None @@ -51,6 +55,13 @@ def init_action(self, list_view): def do_action(self, queryset): pass + def __init__(self, request, *args, **kwargs): + super().__init__(request, *args, **kwargs) + if django_version > (2, 0): + for model in self.admin_site._registry: + if not hasattr(self.admin_site._registry[model], 'has_delete_permission'): + setattr(self.admin_site._registry[model], 'has_delete_permission', self.has_delete_permission) + class DeleteSelectedAction(BaseActionView): @@ -70,7 +81,7 @@ def delete_models(self, queryset): n = queryset.count() if n: if self.delete_models_batch: - self.log('delete', _('Batch delete %(count)d %(items)s.') % { "count": n, "items": model_ngettext(self.opts, n) }) + self.log('delete', _('Batch delete %(count)d %(items)s.') % {"count": n, "items": model_ngettext(self.opts, n)}) queryset.delete() else: for obj in queryset: @@ -86,12 +97,17 @@ def do_action(self, queryset): if not self.has_delete_permission(): raise PermissionDenied - using = router.db_for_write(self.model) - # Populate deletable_objects, a data structure of all related objects that # will also be deleted. - deletable_objects, model_count, perms_needed, protected = get_deleted_objects( - queryset, self.opts, self.user, self.admin_site, using) + + if django_version > (2, 1): + deletable_objects, model_count, perms_needed, protected = get_deleted_objects( + queryset, self.opts, self.admin_site) + else: + using = router.db_for_write(self.model) + deletable_objects, model_count, perms_needed, protected = get_deleted_objects( + queryset, self.opts, self.user, self.admin_site, using) + # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. diff --git a/xadmin/plugins/aggregation.py b/xadmin/plugins/aggregation.py index 16114da8d..98cca09b7 100644 --- a/xadmin/plugins/aggregation.py +++ b/xadmin/plugins/aggregation.py @@ -1,5 +1,8 @@ -from django.db.models import FieldDoesNotExist, Avg, Max, Min, Count, Sum + +from django.core.exceptions import FieldDoesNotExist +from django.db.models import Avg, Max, Min, Count, Sum from django.utils.translation import ugettext as _ +from django.forms import Media from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView @@ -61,9 +64,7 @@ def results(self, rows): # Media def get_media(self, media): - media.add_css({'screen': [self.static( - 'xadmin/css/xadmin.plugin.aggregation.css'), ]}) - return media + return media + Media(css={'screen': [self.static('xadmin/css/xadmin.plugin.aggregation.css'), ]}) site.register_plugin(AggregationPlugin, ListAdminView) diff --git a/xadmin/plugins/batch.py b/xadmin/plugins/batch.py index b322af98e..9dbf70b2c 100644 --- a/xadmin/plugins/batch.py +++ b/xadmin/plugins/batch.py @@ -36,7 +36,7 @@ def media(self): media = self.widget.media + vendor('xadmin.plugin.batch.js') return media - def render(self, name, value, attrs=None): + def render(self, name, value, attrs=None, renderer=None): output = [] is_required = self.widget.is_required output.append(u'' @@ -44,7 +44,7 @@ def render(self, name, value, attrs=None): (BATCH_CHECKBOX_NAME, name, (is_required and ' checked="checked"' or ''), _('Change this field'))) output.extend([('' % ((not is_required and 'display: none;' or ''), name)), - self.widget.render(name, value, attrs), '']) + self.widget.render(name, value, attrs, renderer), '']) return mark_safe(u''.join(output)) def build_attrs(self, extra_attrs=None, **kwargs): diff --git a/xadmin/plugins/bookmark.py b/xadmin/plugins/bookmark.py index 3d612cec8..f6e0708e8 100644 --- a/xadmin/plugins/bookmark.py +++ b/xadmin/plugins/bookmark.py @@ -1,6 +1,6 @@ from django.contrib.contenttypes.models import ContentType -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.db import transaction from django.db.models import Q from django.forms import ModelChoiceField @@ -43,16 +43,16 @@ def get_context(self, context): bookmarks = [] current_qs = '&'.join([ - '%s=%s' % (k, v) - for k, v in sorted(filter( - lambda i: bool(i[1] and ( - i[0] in (COL_LIST_VAR, ORDER_VAR, SEARCH_VAR) - or i[0].startswith(FILTER_PREFIX) - or i[0].startswith(RELATE_PREFIX) - )), - self.request.GET.items() - )) - ]) + '%s=%s' % (k, v) + for k, v in sorted(filter( + lambda i: bool(i[1] and ( + i[0] in (COL_LIST_VAR, ORDER_VAR, SEARCH_VAR) + or i[0].startswith(FILTER_PREFIX) + or i[0].startswith(RELATE_PREFIX) + )), + self.request.GET.items() + )) + ]) model_info = (self.opts.app_label, self.opts.model_name) has_selected = False @@ -64,21 +64,22 @@ def get_context(self, context): for bk in self.list_bookmarks: title = bk['title'] params = dict([ - (FILTER_PREFIX + k, v) - for (k, v) in bk['query'].items() - ]) + (FILTER_PREFIX + k, v) + for (k, v) in bk['query'].items() + ]) if 'order' in bk: params[ORDER_VAR] = '.'.join(bk['order']) if 'cols' in bk: params[COL_LIST_VAR] = '.'.join(bk['cols']) if 'search' in bk: params[SEARCH_VAR] = bk['search'] + def check_item(i): return bool(i[1]) or i[1] == False bk_qs = '&'.join([ '%s=%s' % (k, v) for k, v in sorted(filter(check_item, params.items())) - ]) + ]) url = list_base_url + '?' + bk_qs selected = (current_qs == bk_qs) @@ -174,7 +175,6 @@ def get_list_display(self): list_display.remove('user') return list_display - def has_change_permission(self, obj=None): if not obj or self.user.is_superuser: return True @@ -222,12 +222,12 @@ def context(self, context): context['result_headers'] = [c for c in list_view.result_headers( ).cells if c.field_name in base_fields] context['results'] = [ - [o for i, o in enumerate(filter( - lambda c: c.field_name in base_fields, - r.cells - ))] - for r in list_view.results() - ] + [o for i, o in enumerate(filter( + lambda c: c.field_name in base_fields, + r.cells + ))] + for r in list_view.results() + ] context['result_count'] = list_view.result_count context['page_url'] = self.bookmark.url diff --git a/xadmin/plugins/details.py b/xadmin/plugins/details.py index 0b5ed919e..ba167fdc3 100644 --- a/xadmin/plugins/details.py +++ b/xadmin/plugins/details.py @@ -1,7 +1,7 @@ from django.utils.translation import ugettext as _ -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls.base import reverse, NoReverseMatch from django.db import models from xadmin.sites import site @@ -16,7 +16,7 @@ class DetailsPlugin(BaseAdminPlugin): def result_item(self, item, obj, field_name, row): if (self.show_all_rel_details or (field_name in self.show_detail_fields)): rel_obj = None - if hasattr(item.field, 'rel') and isinstance(item.field.rel, models.ManyToOneRel): + if hasattr(item.field, 'remote_field') and isinstance(item.field.remote_field, models.ManyToOneRel): rel_obj = getattr(obj, field_name) elif field_name in self.show_detail_fields: rel_obj = obj diff --git a/xadmin/plugins/editable.py b/xadmin/plugins/editable.py index 1b49feb60..68a596004 100644 --- a/xadmin/plugins/editable.py +++ b/xadmin/plugins/editable.py @@ -2,6 +2,7 @@ from django.core.exceptions import PermissionDenied, ObjectDoesNotExist from django.db import models, transaction from django.forms.models import modelform_factory +from django.forms import Media from django.http import Http404, HttpResponse from django.utils.encoding import force_text, smart_text from django.utils.html import escape, conditional_escape @@ -32,7 +33,7 @@ def init_request(self, *args, **kwargs): return active def result_item(self, item, obj, field_name, row): - if self.list_editable and item.field and item.field.editable and (field_name in self.list_editable): + if self.list_editable and item.field and item.field.editable and (field_name in self.list_editable): pk = getattr(obj, obj._meta.pk.attname) field_label = label_for_field(field_name, obj, model_admin=self.admin_view, @@ -52,7 +53,12 @@ def result_item(self, item, obj, field_name, row): # Media def get_media(self, media): if self.editable_need_fields: - media = media + self.model_form.media + \ + + try: + m = self.model_form.media + except: + m = Media() + media = media + m +\ self.vendor( 'xadmin.plugin.editable.js', 'xadmin.widget.editable.css') return media @@ -75,7 +81,7 @@ def init_request(self, object_id, *args, **kwargs): def get_new_field_html(self, f): result = self.result_item(self.org_obj, f, {'is_display_first': - False, 'object': self.org_obj}) + False, 'object': self.org_obj}) return mark_safe(result.text) if result.allow_tags else conditional_escape(result.text) def _get_new_field_html(self, field_name): @@ -156,5 +162,6 @@ def post(self, request, object_id): return self.render_response(result) + site.register_plugin(EditablePlugin, ListAdminView) site.register_modelview(r'^(.+)/patch/$', EditPatchView, name='%s_%s_patch') diff --git a/xadmin/plugins/filters.py b/xadmin/plugins/filters.py index dc7e171d8..23c505ffe 100644 --- a/xadmin/plugins/filters.py +++ b/xadmin/plugins/filters.py @@ -6,8 +6,10 @@ from django.contrib.admin.utils import get_fields_from_path, lookup_needs_distinct from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured, ValidationError from django.db import models -from django.db.models.fields import FieldDoesNotExist -from django.db.models.sql.query import LOOKUP_SEP, QUERY_TERMS +# from django.db.models.fields import FieldDoesNotExist +from django.core.exceptions import FieldDoesNotExist +from django.db.models.constants import LOOKUP_SEP +# from django.db.models.sql.constants import QUERY_TERMS from django.template import loader from django.utils import six from django.utils.encoding import smart_str @@ -44,8 +46,8 @@ def lookup_allowed(self, lookup, value): # Last term in lookup is a query term (__exact, __startswith etc) # This term can be ignored. - if len(parts) > 1 and parts[-1] in QUERY_TERMS: - parts.pop() + # if len(parts) > 1 and parts[-1] in QUERY_TERMS: + # parts.pop() # Special case -- foo__id__exact and foo__id queries are implied # if foo has been specificially included in the lookup list; so @@ -59,9 +61,9 @@ def lookup_allowed(self, lookup, value): # Lookups on non-existants fields are ok, since they're ignored # later. return True - if hasattr(field, 'rel'): - model = field.rel.to - rel_name = field.rel.get_related_field().name + if hasattr(field, 'remote_field'): + model = field.remote_field.to + rel_name = field.remote_field.get_related_field().name elif is_related_field(field): model = field.model rel_name = model._meta.pk.name @@ -158,7 +160,7 @@ def get_list_queryset(self, queryset): # fix a bug by david: In demo, quick filter by IDC Name() cannot be used. if isinstance(queryset, models.query.QuerySet) and lookup_params: new_lookup_parames = dict() - for k, v in lookup_params.iteritems(): + for k, v in lookup_params.items(): list_v = v.split(',') if len(list_v) > 0: new_lookup_parames.update({k: list_v}) diff --git a/xadmin/plugins/images.py b/xadmin/plugins/images.py index 1c92bca55..7fea2b3b1 100644 --- a/xadmin/plugins/images.py +++ b/xadmin/plugins/images.py @@ -42,13 +42,13 @@ class AdminImageWidget(forms.FileInput): def __init__(self, attrs={}): super(AdminImageWidget, self).__init__(attrs) - def render(self, name, value, attrs=None): + def render(self, name, value, attrs=None, renderer=None): output = [] if value and hasattr(value, "url"): label = self.attrs.get('label', name) output.append('%s ' % (value.url, label, value.url, _('Change:'))) - output.append(super(AdminImageWidget, self).render(name, value, attrs)) + output.append(super(AdminImageWidget, self).render(name, value, attrs, renderer)) return mark_safe(u''.join(output)) diff --git a/xadmin/plugins/importexport.py b/xadmin/plugins/importexport.py index 90fe10c47..507ae5e1e 100644 --- a/xadmin/plugins/importexport.py +++ b/xadmin/plugins/importexport.py @@ -63,7 +63,7 @@ class FooAdmin(object): from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION from django.contrib.contenttypes.models import ContentType from django.contrib import messages -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.core.exceptions import PermissionDenied from django.http import HttpResponseRedirect, HttpResponse @@ -153,6 +153,7 @@ def get_import_formats(self): class ImportView(ImportBaseView): + def get_media(self): media = super(ImportView, self).get_media() media = media + self.vendor('xadmin.plugin.importexport.css') @@ -254,6 +255,7 @@ def post(self, request, *args, **kwargs): class ImportProcessView(ImportBaseView): + @filter_hook @csrf_protect_m @transaction.atomic diff --git a/xadmin/plugins/inline.py b/xadmin/plugins/inline.py index 2fbe5b19d..c95928553 100644 --- a/xadmin/plugins/inline.py +++ b/xadmin/plugins/inline.py @@ -210,7 +210,7 @@ def instance_form(self, **kwargs): rendered_fields = [i[1] for i in layout.get_field_names()] layout.extend([f for f in instance[0] - .fields.keys() if f not in rendered_fields]) + .fields.keys() if f not in rendered_fields]) helper.add_layout(layout) style.update_layout(helper) @@ -227,10 +227,11 @@ def instance_form(self, **kwargs): form.readonly_fields = [] inst = form.save(commit=False) if inst: + meta_field_names = [field.name for field in inst._meta.get_fields()] for readonly_field in readonly_fields: value = None label = None - if readonly_field in inst._meta.get_all_field_names(): + if readonly_field in meta_field_names: label = inst._meta.get_field(readonly_field).verbose_name value = smart_text(getattr(inst, readonly_field)) elif inspect.ismethod(getattr(inst, readonly_field, None)): @@ -268,8 +269,8 @@ def has_change_permission(self): opts = self.opts if opts.auto_created: for field in opts.fields: - if field.rel and field.rel.to != self.parent_model: - opts = field.rel.to._meta + if field.remote_field and field.remote_field.model != self.parent_model: + opts = field.remote_field.model._meta break codename = get_permission_codename('change', opts) @@ -352,7 +353,7 @@ class Inline(Fieldset): def __init__(self, rel_model): self.model = rel_model self.fields = [] - super(Inline,self).__init__(legend="") + super(Inline, self).__init__(legend="") def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): return "" @@ -471,6 +472,7 @@ def _get_detail_formset_instance(self, inline): DetailAdminUtil, fake_admin_class, instance) return formset + class DetailAdminUtil(DetailAdminView): def init_request(self, obj): diff --git a/xadmin/plugins/language.py b/xadmin/plugins/language.py index 3814771e4..7c73b9d7d 100644 --- a/xadmin/plugins/language.py +++ b/xadmin/plugins/language.py @@ -14,6 +14,7 @@ def block_top_navmenu(self, context, nodes): context['redirect_to'] = self.request.get_full_path() nodes.append(loader.render_to_string('xadmin/blocks/comm.top.setlang.html', context=context)) + class SetLangView(BaseAdminView): def post(self, request, *args, **kwargs): @@ -21,6 +22,6 @@ def post(self, request, *args, **kwargs): del request.session['nav_menu'] return set_language(request) -if settings.LANGUAGES and 'django.middleware.locale.LocaleMiddleware' in settings.MIDDLEWARE_CLASSES: +if settings.LANGUAGES and 'django.middleware.locale.LocaleMiddleware' in settings.MIDDLEWARE: site.register_plugin(SetLangNavPlugin, CommAdminView) site.register_view(r'^i18n/setlang/$', SetLangView, 'set_language') diff --git a/xadmin/plugins/multiselect.py b/xadmin/plugins/multiselect.py index 38e0c917d..0681af8ab 100644 --- a/xadmin/plugins/multiselect.py +++ b/xadmin/plugins/multiselect.py @@ -9,7 +9,7 @@ from django.utils.encoding import force_text from django.utils.html import escape, conditional_escape from django.utils.safestring import mark_safe -from xadmin.util import vendor, DJANGO_11 +from xadmin.util import vendor from xadmin.views import BaseAdminPlugin, ModelFormAdminView @@ -37,10 +37,7 @@ def render(self, name, value, attrs=None, choices=()): attrs['class'] += 'stacked' if value is None: value = [] - if DJANGO_11: - final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) - else: - final_attrs = self.build_attrs(attrs, name=name) + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) selected_choices = set(force_text(v) for v in value) available_output = [] diff --git a/xadmin/plugins/passwords.py b/xadmin/plugins/passwords.py index ac7852714..a5f3eebe5 100644 --- a/xadmin/plugins/passwords.py +++ b/xadmin/plugins/passwords.py @@ -1,7 +1,7 @@ # coding=utf-8 from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm from django.contrib.auth.tokens import default_token_generator -from django.contrib.auth.views import password_reset_confirm +from django.contrib.auth.views import PasswordResetConfirmView as password_reset_confirm from django.template.response import TemplateResponse from django.utils.translation import ugettext as _ @@ -53,14 +53,17 @@ def post(self, request, *args, **kwargs): else: return self.get(request, form=form) + site.register_view(r'^xadmin/password_reset/$', ResetPasswordSendView, name='xadmin_password_reset') + class ResetLinkPlugin(BaseAdminPlugin): def block_form_bottom(self, context, nodes): reset_link = self.get_admin_url('xadmin_password_reset') return ' %s' % (reset_link, _('Forgotten your password or username?')) + site.register_plugin(ResetLinkPlugin, LoginView) @@ -75,11 +78,11 @@ class ResetPasswordComfirmView(BaseAdminView): def do_view(self, request, uidb36, token, *args, **kwargs): context = super(ResetPasswordComfirmView, self).get_context() return password_reset_confirm(request, uidb36, token, - template_name=self.password_reset_confirm_template, - token_generator=self.password_reset_token_generator, - set_password_form=self.password_reset_set_form, - post_reset_redirect=self.get_admin_url('xadmin_password_reset_complete'), - current_app=self.admin_site.name, extra_context=context) + template_name=self.password_reset_confirm_template, + token_generator=self.password_reset_token_generator, + set_password_form=self.password_reset_set_form, + post_reset_redirect=self.get_admin_url('xadmin_password_reset_complete'), + current_app=self.admin_site.name, extra_context=context) def get(self, request, uidb36, token, *args, **kwargs): return self.do_view(request, uidb36, token) @@ -91,8 +94,9 @@ def get_media(self): return super(ResetPasswordComfirmView, self).get_media() + \ self.vendor('xadmin.page.form.js', 'xadmin.form.css') + site.register_view(r'^xadmin/password_reset/(?P[0-9A-Za-z]{1,13})-(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', - ResetPasswordComfirmView, name='xadmin_password_reset_confirm') + ResetPasswordComfirmView, name='xadmin_password_reset_confirm') class ResetPasswordCompleteView(BaseAdminView): @@ -107,5 +111,5 @@ def get(self, request, *args, **kwargs): return TemplateResponse(request, self.password_reset_complete_template, context) -site.register_view(r'^xadmin/password_reset/complete/$', ResetPasswordCompleteView, name='xadmin_password_reset_complete') +site.register_view(r'^xadmin/password_reset/complete/$', ResetPasswordCompleteView, name='xadmin_password_reset_complete') diff --git a/xadmin/plugins/quickfilter.py b/xadmin/plugins/quickfilter.py index 6222c34b4..59b3eccb8 100644 --- a/xadmin/plugins/quickfilter.py +++ b/xadmin/plugins/quickfilter.py @@ -6,35 +6,37 @@ from future.utils import iteritems from django.utils import six from django.utils.translation import ugettext_lazy as _ -from xadmin.filters import manager,MultiSelectFieldListFilter +from xadmin.filters import manager, MultiSelectFieldListFilter from xadmin.plugins.filters import * from xadmin.util import is_related_field + @manager.register class QuickFilterMultiSelectFieldListFilter(MultiSelectFieldListFilter): """ Delegates the filter to the default filter and ors the results of each - + Lists the distinct values of each field as a checkbox Uses the default spec for each - + """ template = 'xadmin/filters/quickfilter.html' + class QuickFilterPlugin(BaseAdminPlugin): """ Add a filter menu to the left column of the page """ - list_quick_filter = () # these must be a subset of list_filter to work - quickfilter = {} + list_quick_filter = () # these must be a subset of list_filter to work + quickfilter = {} search_fields = () free_query_filter = True - + def init_request(self, *args, **kwargs): - menu_style_accordian = hasattr(self.admin_view,'menu_style') and self.admin_view.menu_style == 'accordion' + menu_style_accordian = hasattr(self.admin_view, 'menu_style') and self.admin_view.menu_style == 'accordion' return bool(self.list_quick_filter) and not menu_style_accordian - + # Media def get_media(self, media): - return media + self.vendor('xadmin.plugin.quickfilter.js','xadmin.plugin.quickfilter.css') - + return media + self.vendor('xadmin.plugin.quickfilter.js', 'xadmin.plugin.quickfilter.css') + def lookup_allowed(self, lookup, value): model = self.model # Check FKey lookups that are allowed, so that popups produced by @@ -44,14 +46,14 @@ def lookup_allowed(self, lookup, value): for k, v in widgets.url_params_from_lookup_dict(l).items(): if k == lookup and v == value: return True - + parts = lookup.split(LOOKUP_SEP) - + # Last term in lookup is a query term (__exact, __startswith etc) # This term can be ignored. if len(parts) > 1 and parts[-1] in QUERY_TERMS: parts.pop() - + # Special case -- foo__id__exact and foo__id queries are implied # if foo has been specificially included in the lookup list; so # drop __id if it is the last part. However, first we need to find @@ -64,9 +66,9 @@ def lookup_allowed(self, lookup, value): # Lookups on non-existants fields are ok, since they're ignored # later. return True - if hasattr(field, 'rel'): - model = field.rel.to - rel_name = field.rel.get_related_field().name + if hasattr(field, 'remote_field'): + model = field.remote_field.model + rel_name = field.remote_field.get_related_field().name elif is_related_field(field): model = field.model rel_name = model._meta.pk.name @@ -74,32 +76,32 @@ def lookup_allowed(self, lookup, value): rel_name = None if rel_name and len(parts) > 1 and parts[-1] == rel_name: parts.pop() - + if len(parts) == 1: return True clean_lookup = LOOKUP_SEP.join(parts) return clean_lookup in self.list_quick_filter - + def get_list_queryset(self, queryset): lookup_params = dict([(smart_str(k)[len(FILTER_PREFIX):], v) for k, v in self.admin_view.params.items() if smart_str(k).startswith(FILTER_PREFIX) and v != '']) for p_key, p_val in iteritems(lookup_params): if p_val == "False": lookup_params[p_key] = False use_distinct = False - - if not hasattr(self.admin_view,'quickfilter'): + + if not hasattr(self.admin_view, 'quickfilter'): self.admin_view.quickfilter = {} - + # for clean filters self.admin_view.quickfilter['has_query_param'] = bool(lookup_params) self.admin_view.quickfilter['clean_query_url'] = self.admin_view.get_query_string(remove=[k for k in self.request.GET.keys() if k.startswith(FILTER_PREFIX)]) - + # Normalize the types of keys if not self.free_query_filter: for key, value in lookup_params.items(): if not self.lookup_allowed(key, value): raise SuspiciousOperation("Filtering by %s not allowed" % key) - + self.filter_specs = [] if self.list_quick_filter: for list_quick_filter in self.list_quick_filter: @@ -107,10 +109,10 @@ def get_list_queryset(self, queryset): field_order_by = None field_limit = None field_parts = [] - sort_key = None + sort_key = None cache_config = None - - if type(list_quick_filter)==dict and 'field' in list_quick_filter: + + if type(list_quick_filter) == dict and 'field' in list_quick_filter: field = list_quick_filter['field'] if 'order_by' in list_quick_filter: field_order_by = list_quick_filter['order_by'] @@ -118,23 +120,24 @@ def get_list_queryset(self, queryset): field_limit = list_quick_filter['limit'] if 'sort' in list_quick_filter and callable(list_quick_filter['sort']): sort_key = list_quick_filter['sort'] - if 'cache' in list_quick_filter and type(list_quick_filter)==dict: + if 'cache' in list_quick_filter and type(list_quick_filter) == dict: cache_config = list_quick_filter['cache'] - - else: - field = list_quick_filter # This plugin only uses MultiselectFieldListFilter - + + else: + field = list_quick_filter # This plugin only uses MultiselectFieldListFilter + if not isinstance(field, models.Field): field_path = field field_parts = get_fields_from_path(self.model, field_path) field = field_parts[-1] - spec = QuickFilterMultiSelectFieldListFilter(field, self.request, lookup_params,self.model, self.admin_view, field_path=field_path,field_order_by=field_order_by,field_limit=field_limit,sort_key=sort_key,cache_config=cache_config) - - if len(field_parts)>1: - spec.title = "%s %s"%(field_parts[-2].name,spec.title) - + spec = QuickFilterMultiSelectFieldListFilter(field, self.request, lookup_params, self.model, self.admin_view, field_path=field_path, + field_order_by=field_order_by, field_limit=field_limit, sort_key=sort_key, cache_config=cache_config) + + if len(field_parts) > 1: + spec.title = "%s %s" % (field_parts[-2].name, spec.title) + # Check if we need to use distinct() - use_distinct = True#(use_distinct orlookup_needs_distinct(self.opts, field_path)) + use_distinct = True # (use_distinct orlookup_needs_distinct(self.opts, field_path)) if spec and spec.has_output(): try: new_qs = spec.do_filte(queryset) @@ -143,23 +146,23 @@ def get_list_queryset(self, queryset): self.admin_view.message_user(_("Filtering error: %s") % e.messages[0], 'error') if new_qs is not None: queryset = new_qs - + self.filter_specs.append(spec) - + self.has_filters = bool(self.filter_specs) self.admin_view.quickfilter['filter_specs'] = self.filter_specs obj = filter(lambda f: f.is_used, self.filter_specs) if six.PY3: obj = list(obj) self.admin_view.quickfilter['used_filter_num'] = len(obj) - + if use_distinct: return queryset.distinct() else: return queryset - + def block_left_navbar(self, context, nodes): nodes.append(loader.render_to_string('xadmin/blocks/modal_list.left_navbar.quickfilter.html', get_context_dict(context))) - + site.register_plugin(QuickFilterPlugin, ListAdminView) diff --git a/xadmin/plugins/quickform.py b/xadmin/plugins/quickform.py index d93e2c647..7516f688f 100644 --- a/xadmin/plugins/quickform.py +++ b/xadmin/plugins/quickform.py @@ -77,7 +77,7 @@ def render(self, name, value, renderer=None, *args, **kwargs): if self.add_url: output.append(u'' % ( - self.add_url, (_('Create New %s') % self.rel.to._meta.verbose_name), name, + self.add_url, (_('Create New %s') % self.rel.model._meta.verbose_name), name, "%s?_field=%s&%s=" % (self.rel_add_url, name, name))) output.extend(['' % name, self.widget.render(name, value, *args, **kwargs), '']) @@ -103,7 +103,7 @@ def formfield_for_dbfield(self, formfield, db_field, **kwargs): if rel_model in self.admin_site._registry and self.has_model_perm(rel_model, 'add'): add_url = self.get_model_url(rel_model, 'add') formfield.widget = RelatedFieldWidgetWrapper( - formfield.widget, db_field.rel, add_url, self.get_model_url(self.model, 'add')) + formfield.widget, db_field.remote_field, add_url, self.get_model_url(self.model, 'add')) return formfield site.register_plugin(QuickFormPlugin, ModelFormAdminView) diff --git a/xadmin/plugins/relate.py b/xadmin/plugins/relate.py index 4d33977a3..31642757c 100644 --- a/xadmin/plugins/relate.py +++ b/xadmin/plugins/relate.py @@ -1,7 +1,7 @@ # coding=UTF-8 from itertools import chain -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.db.models.options import PROXY_PARENTS from django.utils import six from django.utils.encoding import force_text @@ -47,7 +47,6 @@ def _get_all_related_objects(self, local_only=False, include_hidden=False, fields = chain(fields, relations) return list(fields) - def get_related_list(self): if hasattr(self, '_related_acts'): return self._related_acts @@ -85,20 +84,20 @@ def related_link(self, instance): link = ''.join(('', ' %s' % - ( - reverse('%s:%s_%s_changelist' % ( + ( + reverse('%s:%s_%s_changelist' % ( self.admin_site.app_name, label, model_name)), - RELATE_PREFIX + lookup_name, str(instance.pk), verbose_name, verbose_name) if view_perm else + RELATE_PREFIX + lookup_name, str(instance.pk), verbose_name, verbose_name) if view_perm else ' %s' % verbose_name, '' % - ( - reverse('%s:%s_%s_add' % ( + ( + reverse('%s:%s_%s_add' % ( self.admin_site.app_name, label, model_name)), - RELATE_PREFIX + lookup_name, str( - instance.pk)) if add_perm else "", + RELATE_PREFIX + lookup_name, str( + instance.pk)) if add_perm else "", - '')) + '')) links.append(link) ul_html = '%s' % ''.join( links) diff --git a/xadmin/plugins/relfield.py b/xadmin/plugins/relfield.py index 506222e4c..0fb5f602f 100644 --- a/xadmin/plugins/relfield.py +++ b/xadmin/plugins/relfield.py @@ -7,7 +7,7 @@ from django import forms from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ModelFormAdminView -from xadmin.util import vendor, DJANGO_11 +from xadmin.util import vendor class ForeignKeySearchWidget(forms.Widget): @@ -19,7 +19,7 @@ def __init__(self, rel, admin_view, attrs=None, using=None): super(ForeignKeySearchWidget, self).__init__(attrs) def build_attrs(self, attrs={}, extra_attrs=None, **kwargs): - to_opts = self.rel.to._meta + to_opts = self.rel.model._meta if "class" not in attrs: attrs['class'] = 'select-search' else: @@ -32,20 +32,11 @@ def build_attrs(self, attrs={}, extra_attrs=None, **kwargs): for i in list(self.rel.limit_choices_to): attrs['data-choices'] += "&_p_%s=%s" % (i, self.rel.limit_choices_to[i]) attrs['data-choices'] = format_html(attrs['data-choices']) - if DJANGO_11: - attrs.update(kwargs) - return super(ForeignKeySearchWidget, self).build_attrs(attrs, extra_attrs=extra_attrs) - else: - if extra_attrs: - attrs.update(extra_attrs) - return super(ForeignKeySearchWidget, self).build_attrs(attrs, **kwargs) - - def render(self, name, value, attrs=None): - if DJANGO_11: - final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) - else: - final_attrs = self.build_attrs(attrs, name=name) + attrs.update(kwargs) + return super(ForeignKeySearchWidget, self).build_attrs(attrs, extra_attrs=extra_attrs) + def render(self, name, value, attrs=None, renderer=None): + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) output = [format_html('', flatatt(final_attrs))] if value: output.append(format_html('{1}', value, self.label_for_value(value))) @@ -74,7 +65,7 @@ def build_attrs(self, attrs={}, **kwargs): attrs['class'] = 'select-preload' else: attrs['class'] = attrs['class'] + ' select-preload' - attrs['data-placeholder'] = _('Select %s') % self.rel.to._meta.verbose_name + attrs['data-placeholder'] = _('Select %s') % self.rel.model._meta.verbose_name return attrs diff --git a/xadmin/plugins/sortablelist.py b/xadmin/plugins/sortablelist.py index 8b9942f6e..17d34b615 100644 --- a/xadmin/plugins/sortablelist.py +++ b/xadmin/plugins/sortablelist.py @@ -8,7 +8,7 @@ from __future__ import unicode_literals from django.template.loader import render_to_string -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.db import transaction from xadmin.views import ( diff --git a/xadmin/plugins/themes.py b/xadmin/plugins/themes.py index d83dd9cc3..fca1e4556 100644 --- a/xadmin/plugins/themes.py +++ b/xadmin/plugins/themes.py @@ -1,6 +1,6 @@ -#coding:utf-8 +# coding:utf-8 from __future__ import print_function -import requests +import httplib2 from django.template import loader from django.core.cache import cache from django.utils import six @@ -58,7 +58,7 @@ def block_top_navmenu(self, context, nodes): themes = [ {'name': _(u"Default"), 'description': _(u"Default bootstrap theme"), 'css': self.default_theme}, {'name': _(u"Bootstrap2"), 'description': _(u"Bootstrap 2.x theme"), 'css': self.bootstrap2_theme}, - ] + ] select_css = context.get('site_theme', self.default_theme) if self.user_themes: @@ -71,13 +71,16 @@ def block_top_navmenu(self, context, nodes): else: ex_themes = [] try: - headers = {"Accept": "application/json", "User-Agent": self.request.META['HTTP_USER_AGENT']} - content = requests.get("https://bootswatch.com/api/3.json", headers=headers) + h = httplib2.Http() + resp, content = h.request("https://bootswatch.com/api/3.json", 'GET', '', + headers={"Accept": "application/json", "User-Agent": self.request.META['HTTP_USER_AGENT']}) if six.PY3: - content = content.text.decode() - watch_themes = json.loads(content.text)['themes'] - ex_themes.extend([{'name': t['name'], 'description': t['description'], 'css': t['cssMin'], - 'thumbnail': t['thumbnail']} for t in watch_themes]) + content = content.decode() + watch_themes = json.loads(content)['themes'] + ex_themes.extend([ + {'name': t['name'], 'description': t['description'], + 'css': t['cssMin'], 'thumbnail': t['thumbnail']} + for t in watch_themes]) except Exception as e: print(e) diff --git a/xadmin/plugins/topnav.py b/xadmin/plugins/topnav.py index c92fce549..fdf458b42 100644 --- a/xadmin/plugins/topnav.py +++ b/xadmin/plugins/topnav.py @@ -1,7 +1,7 @@ from django.template import loader from django.utils.text import capfirst -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls.base import reverse, NoReverseMatch from django.utils.translation import ugettext as _ from xadmin.sites import site diff --git a/xadmin/plugins/ueditor.py b/xadmin/plugins/ueditor.py new file mode 100644 index 000000000..216350df8 --- /dev/null +++ b/xadmin/plugins/ueditor.py @@ -0,0 +1,43 @@ +# encoding: utf-8 +__author__ = 'mtianyan' +__date__ = '2018/1/15 0015 08:11' + +import xadmin +from xadmin.views import BaseAdminPlugin, CreateAdminView, ModelFormAdminView, UpdateAdminView +from DjangoUeditor.models import UEditorField +from DjangoUeditor.widgets import UEditorWidget +from django.conf import settings + + +class XadminUEditorWidget(UEditorWidget): + def __init__(self, **kwargs): + self.ueditor_options = kwargs + self.Media.js = None + super(XadminUEditorWidget, self).__init__(kwargs) + + +class UeditorPlugin(BaseAdminPlugin): + + def get_field_style(self, attrs, db_field, style, **kwargs): + if style == 'ueditor': + if isinstance(db_field, UEditorField): + widget = db_field.formfield().widget + param = {} + param.update(widget.ueditor_settings) + param.update(widget.attrs) + return {'widget': XadminUEditorWidget(**param)} + return attrs + + # 在我们生成的页面中放入自己的js文件 + def block_extrahead(self, context, nodes): + js = '' % ( + settings.STATIC_URL + "ueditor/ueditor.config.js") # 自己的静态目录 + js += '' % ( + settings.STATIC_URL + "ueditor/ueditor.all.min.js") # 自己的静态目录 + nodes.append(js) + + +# 新增页面 +xadmin.site.register_plugin(UeditorPlugin, UpdateAdminView) +# 修改页面 +xadmin.site.register_plugin(UeditorPlugin, CreateAdminView) diff --git a/xadmin/plugins/wizard.py b/xadmin/plugins/wizard.py index 38d21d406..84c46fde5 100644 --- a/xadmin/plugins/wizard.py +++ b/xadmin/plugins/wizard.py @@ -22,8 +22,6 @@ from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ModelFormAdminView -from xadmin.util import DJANGO_11 - def normalize_name(name): new = re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', name) diff --git a/xadmin/plugins/xversion.py b/xadmin/plugins/xversion.py index 6e337a72b..a0f6107bd 100644 --- a/xadmin/plugins/xversion.py +++ b/xadmin/plugins/xversion.py @@ -62,10 +62,10 @@ def _register_model(admin, model): fk_name = getattr(inline, 'fk_name', None) if not fk_name: for field in inline_model._meta.fields: - if isinstance(field, (models.ForeignKey, models.OneToOneField)) and issubclass(model, field.rel.to): + if isinstance(field, (models.ForeignKey, models.OneToOneField)) and issubclass(model, field.remote_field.model): fk_name = field.name _autoregister(admin, inline_model, follow=[fk_name]) - if not inline_model._meta.get_field(fk_name).rel.is_hidden(): + if not inline_model._meta.get_field(fk_name).remote_field.is_hidden(): accessor = inline_model._meta.get_field(fk_name).remote_field.get_accessor_name() inline_fields.append(accessor) _autoregister(admin, model, inline_fields) @@ -79,12 +79,14 @@ def register_models(admin_site=None): if getattr(admin, 'reversion_enable', False): _register_model(admin, model) + @contextmanager def do_create_revision(request): with create_revision(): set_user(request.user) yield + class ReversionPlugin(BaseAdminPlugin): # The serialization format to use when registering models with reversion. @@ -144,6 +146,8 @@ def block_nav_btns(self, context, nodes): nodes.append(mark_safe(' %s' % (revisionlist_url, _(u'History')))) # action revision + + class ActionRevisionPlugin(BaseAdminPlugin): reversion_enable = False @@ -204,7 +208,7 @@ def get(self, request, *args, **kwargs): return TemplateResponse( request, self.recover_list_template or self.get_template_list( - "views/recover_list.html"), + "views/recover_list.html"), context) @@ -381,7 +385,7 @@ def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwarg html = '' for field in self.fields: html += ('%s%s' % - (_('Current: %s') % self.attrs.pop('orgdata', ''), render_field(field, form, form_style, context, template_pack=template_pack, attrs=self.attrs))) + (_('Current: %s') % self.attrs.pop('orgdata', ''), render_field(field, form, form_style, context, template_pack=template_pack, attrs=self.attrs))) return html @@ -402,7 +406,7 @@ def get_form_helper(self): helper = super(RevisionView, self).get_form_helper() diff_fields = {} version_data = self.version.field_dict - + for f in self.opts.fields: fvalue = f.value_from_object(self.org_obj) vvalue = version_data.get(f.name, None) @@ -585,6 +589,7 @@ class VersionInline(object): extra = 0 style = 'accordion' + class ReversionAdmin(object): model_icon = 'fa fa-exchange' diff --git a/xadmin/sites.py b/xadmin/sites.py index f5bff8de8..fe5f4dae9 100644 --- a/xadmin/sites.py +++ b/xadmin/sites.py @@ -289,7 +289,7 @@ def create_model_admin_view(self, admin_view_class, model, option_class): return self.get_view_class(admin_view_class, option_class).as_view() def get_urls(self): - from django.conf.urls import url, include + from django.urls import include, path, re_path from xadmin.views.base import BaseAdminView if settings.DEBUG: @@ -298,39 +298,40 @@ def get_urls(self): def wrap(view, cacheable=False): def wrapper(*args, **kwargs): return self.admin_view(view, cacheable)(*args, **kwargs) + wrapper.admin_site = self return update_wrapper(wrapper, view) # Admin-site-wide views. urlpatterns = [ - url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n') + path('jsi18n/', wrap(self.i18n_javascript, cacheable=True), name='jsi18n') ] # Registed admin views # inspect[isclass]: Only checks if the object is a class. With it lets you create an custom view that # inherits from multiple views and have more of a metaclass. urlpatterns += [ - url( - path, + re_path( + _path, wrap(self.create_admin_view(clz_or_func)) if inspect.isclass(clz_or_func) and issubclass(clz_or_func, BaseAdminView) else include(clz_or_func(self)), name=name ) - for path, clz_or_func, name in self._registry_views + for _path, clz_or_func, name in self._registry_views ] # Add in each model's views. for model, admin_class in iteritems(self._registry): view_urls = [ - url( - path, + re_path( + _path, wrap(self.create_model_admin_view(clz, model, admin_class)), name=name % (model._meta.app_label, model._meta.model_name) ) - for path, clz, name in self._registry_modelviews + for _path, clz, name in self._registry_modelviews ] urlpatterns += [ - url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(view_urls)) + re_path(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(view_urls)) ] return urlpatterns @@ -339,17 +340,14 @@ def urls(self): return self.get_urls(), self.name, self.app_name def i18n_javascript(self, request): + from django.views.i18n import JavaScriptCatalog """ Displays the i18n JavaScript that the Django admin requires. This takes into account the USE_I18N setting. If it's set to False, the generated JavaScript will be leaner and faster. """ - if settings.USE_I18N: - from django.views.i18n import javascript_catalog - else: - from django.views.i18n import null_javascript_catalog as javascript_catalog - return javascript_catalog(request, packages=['django.conf', 'xadmin']) + return JavaScriptCatalog.as_view(packages=['django.contrib.admin'])(request) # This global object represents the default admin site, for the common case. # You can instantiate AdminSite in your own code to create a custom admin site. diff --git a/xadmin/static/xadmin/css/xadmin.main.css b/xadmin/static/xadmin/css/xadmin.main.css index 2113276e2..66f891607 100644 --- a/xadmin/static/xadmin/css/xadmin.main.css +++ b/xadmin/static/xadmin/css/xadmin.main.css @@ -243,6 +243,9 @@ ul.nav-sitemenu li a { @media (min-width: 768px) { .panel-group.nav-sitemenu { + top: 65px; + bottom: 0; + overflow-y: auto; position: fixed; margin-left: -15px; } diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.css b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.css new file mode 100644 index 000000000..048cff973 --- /dev/null +++ b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.css @@ -0,0 +1,1338 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); + 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'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.3333333333333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.2857142857142858em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.142857142857143em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.142857142857143em; + width: 2.142857142857143em; + top: 0.14285714285714285em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.8571428571428572em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + 100% { + -ms-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-reply-all:before { + content: "\f122"; +} +.fa-mail-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.min.css b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.min.css new file mode 100644 index 000000000..449d6ac55 --- /dev/null +++ b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');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');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/FontAwesome.otf b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/FontAwesome.otf new file mode 100644 index 000000000..8b0f54e47 Binary files /dev/null and b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/FontAwesome.otf differ diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.eot b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.eot new file mode 100644 index 000000000..7c79c6a6b Binary files /dev/null and b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.eot differ diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.svg b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.svg new file mode 100644 index 000000000..45fdf3383 --- /dev/null +++ b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.ttf b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.ttf new file mode 100644 index 000000000..e89738de5 Binary files /dev/null and b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.ttf differ diff --git a/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.woff b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.woff new file mode 100644 index 000000000..8c1748aab Binary files /dev/null and b/xadmin/static/xadmin/vendor/font-awesome.bak4.0.3/fonts/fontawesome-webfont.woff differ diff --git a/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.css b/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.css index 048cff973..ee906a819 100644 --- a/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.css +++ b/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.css @@ -1,28 +1,27 @@ /*! - * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); - 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'); + src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } .fa { display: inline-block; - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - line-height: 1; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* makes the font 33% larger relative to the icon container */ .fa-lg { - font-size: 1.3333333333333333em; + font-size: 1.33333333em; line-height: 0.75em; vertical-align: -15%; } @@ -39,12 +38,12 @@ font-size: 5em; } .fa-fw { - width: 1.2857142857142858em; + width: 1.28571429em; text-align: center; } .fa-ul { padding-left: 0; - margin-left: 2.142857142857143em; + margin-left: 2.14285714em; list-style-type: none; } .fa-ul > li { @@ -52,19 +51,32 @@ } .fa-li { position: absolute; - left: -2.142857142857143em; - width: 2.142857142857143em; - top: 0.14285714285714285em; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; text-align: center; } .fa-li.fa-lg { - left: -1.8571428571428572em; + left: -1.85714286em; } .fa-border { padding: .2em .25em .15em; border: solid 0.08em #eeeeee; border-radius: .1em; } +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ .pull-right { float: right; } @@ -78,91 +90,70 @@ margin-left: .3em; } .fa-spin { - -webkit-animation: spin 2s infinite linear; - -moz-animation: spin 2s infinite linear; - -o-animation: spin 2s infinite linear; - animation: spin 2s infinite linear; + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } -@-moz-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - } - 100% { - -moz-transform: rotate(359deg); - } +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } -@-webkit-keyframes spin { +@-webkit-keyframes fa-spin { 0% { -webkit-transform: rotate(0deg); + transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); + transform: rotate(359deg); } } -@-o-keyframes spin { - 0% { - -o-transform: rotate(0deg); - } - 100% { - -o-transform: rotate(359deg); - } -} -@-ms-keyframes spin { - 0% { - -ms-transform: rotate(0deg); - } - 100% { - -ms-transform: rotate(359deg); - } -} -@keyframes spin { +@keyframes fa-spin { 0% { + -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { + -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .fa-rotate-90 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; -webkit-transform: rotate(90deg); - -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); - -o-transform: rotate(90deg); transform: rotate(90deg); } .fa-rotate-180 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); -ms-transform: rotate(180deg); - -o-transform: rotate(180deg); transform: rotate(180deg); } .fa-rotate-270 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; -webkit-transform: rotate(270deg); - -moz-transform: rotate(270deg); -ms-transform: rotate(270deg); - -o-transform: rotate(270deg); transform: rotate(270deg); } .fa-flip-horizontal { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; -webkit-transform: scale(-1, 1); - -moz-transform: scale(-1, 1); -ms-transform: scale(-1, 1); - -o-transform: scale(-1, 1); transform: scale(-1, 1); } .fa-flip-vertical { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; -webkit-transform: scale(1, -1); - -moz-transform: scale(1, -1); -ms-transform: scale(1, -1); - -o-transform: scale(1, -1); transform: scale(1, -1); } +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} .fa-stack { position: relative; display: inline-block; @@ -228,6 +219,8 @@ .fa-check:before { content: "\f00c"; } +.fa-remove:before, +.fa-close:before, .fa-times:before { content: "\f00d"; } @@ -369,6 +362,8 @@ .fa-video-camera:before { content: "\f03d"; } +.fa-photo:before, +.fa-image:before, .fa-picture-o:before { content: "\f03e"; } @@ -555,7 +550,8 @@ .fa-arrows-h:before { content: "\f07e"; } -.fa-bar-chart-o:before { +.fa-bar-chart-o:before, +.fa-bar-chart:before { content: "\f080"; } .fa-twitter-square:before { @@ -631,6 +627,7 @@ .fa-twitter:before { content: "\f099"; } +.fa-facebook-f:before, .fa-facebook:before { content: "\f09a"; } @@ -643,6 +640,7 @@ .fa-credit-card:before { content: "\f09d"; } +.fa-feed:before, .fa-rss:before { content: "\f09e"; } @@ -732,6 +730,8 @@ .fa-square:before { content: "\f0c8"; } +.fa-navicon:before, +.fa-reorder:before, .fa-bars:before { content: "\f0c9"; } @@ -791,11 +791,11 @@ content: "\f0dc"; } .fa-sort-down:before, -.fa-sort-asc:before { +.fa-sort-desc:before { content: "\f0dd"; } .fa-sort-up:before, -.fa-sort-desc:before { +.fa-sort-asc:before { content: "\f0de"; } .fa-envelope:before { @@ -985,12 +985,10 @@ .fa-code:before { content: "\f121"; } +.fa-mail-reply-all:before, .fa-reply-all:before { content: "\f122"; } -.fa-mail-reply-all:before { - content: "\f122"; -} .fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { @@ -1280,7 +1278,8 @@ .fa-male:before { content: "\f183"; } -.fa-gittip:before { +.fa-gittip:before, +.fa-gratipay:before { content: "\f184"; } .fa-sun-o:before { @@ -1336,3 +1335,1003 @@ .fa-plus-square-o:before { content: "\f196"; } +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper-pp:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-pied-piper:before { + content: "\f2ae"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.min.css b/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.min.css index 449d6ac55..540440ce8 100644 --- a/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.min.css +++ b/xadmin/static/xadmin/vendor/font-awesome/css/font-awesome.min.css @@ -1,4 +1,4 @@ /*! - * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');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');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/FontAwesome.otf b/xadmin/static/xadmin/vendor/font-awesome/fonts/FontAwesome.otf index 8b0f54e47..401ec0f36 100644 Binary files a/xadmin/static/xadmin/vendor/font-awesome/fonts/FontAwesome.otf and b/xadmin/static/xadmin/vendor/font-awesome/fonts/FontAwesome.otf differ diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.eot b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.eot index 7c79c6a6b..e9f60ca95 100755 Binary files a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.eot and b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.eot differ diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.svg b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.svg index 45fdf3383..855c845e5 100755 --- a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.svg +++ b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.svg @@ -1,414 +1,2671 @@ - - + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.ttf b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.ttf index e89738de5..35acda2fa 100755 Binary files a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.ttf and b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.ttf differ diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff index 8c1748aab..400014a4b 100755 Binary files a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff and b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff differ diff --git a/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff2 b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff2 new file mode 100644 index 000000000..4d13fc604 Binary files /dev/null and b/xadmin/static/xadmin/vendor/font-awesome/fonts/fontawesome-webfont.woff2 differ diff --git a/xadmin/templates/xadmin/blocks/comm.top.setlang.html b/xadmin/templates/xadmin/blocks/comm.top.setlang.html index 81a1303b9..0e53770c4 100644 --- a/xadmin/templates/xadmin/blocks/comm.top.setlang.html +++ b/xadmin/templates/xadmin/blocks/comm.top.setlang.html @@ -3,7 +3,7 @@ - {% get_language_info for LANGUAGE_CODE as l %}{{ l.name_local }} + {% get_current_language as l %}{{ l.name_local }} {% csrf_token %} diff --git a/xadmin/templates/xadmin/views/logged_out.html b/xadmin/templates/xadmin/views/logged_out.html index ffe0c7c08..a2efdc6b7 100644 --- a/xadmin/templates/xadmin/views/logged_out.html +++ b/xadmin/templates/xadmin/views/logged_out.html @@ -16,7 +16,7 @@ {% trans "Logout Success" %} {% trans "Thanks for spending some quality time with the Web site today." %} - {% trans 'Close Window' %} + {% trans 'Close Window' %} {% trans 'Log in again' %} diff --git a/xadmin/templatetags/xadmin_tags.py b/xadmin/templatetags/xadmin_tags.py index ee0fc69c5..093a64139 100644 --- a/xadmin/templatetags/xadmin_tags.py +++ b/xadmin/templatetags/xadmin_tags.py @@ -2,11 +2,13 @@ from django.template import Library from django.utils import six from django.utils.safestring import mark_safe +from django.utils.html import escape from xadmin.util import static, vendor as util_vendor register = Library() + @register.simple_tag(takes_context=True) def view_block(context, block_name, *args, **kwargs): if 'admin_view' not in context: @@ -28,10 +30,12 @@ def view_block(context, block_name, *args, **kwargs): else: return "" + @register.filter def admin_urlname(value, arg): return 'xadmin:%s_%s_%s' % (value.app_label, value.model_name, arg) + static = register.simple_tag(static) @@ -42,13 +46,14 @@ def vendor(context, *tags): class BlockcaptureNode(template.Node): """https://chriskief.com/2013/11/06/conditional-output-of-a-django-block/""" + def __init__(self, nodelist, varname): self.nodelist = nodelist self.varname = varname def render(self, context): output = self.nodelist.render(context) - context[self.varname] = str(output) + context[self.varname] = escape(output) return '' diff --git a/xadmin/util.py b/xadmin/util.py index dc60bef76..a18e04b5e 100644 --- a/xadmin/util.py +++ b/xadmin/util.py @@ -4,14 +4,15 @@ from django.db.models.sql.query import LOOKUP_SEP from django.db.models.deletion import Collector from django.db.models.fields.related import ForeignObjectRel -from django.forms.forms import pretty_name +# from django.forms.forms import pretty_name +from django.forms.utils import pretty_name from django.utils import formats, six from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.text import capfirst from django.utils.encoding import force_text, smart_text, smart_str from django.utils.translation import ungettext -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.conf import settings from django.forms import Media from django.utils.translation import get_language @@ -21,7 +22,8 @@ import decimal if 'django.contrib.staticfiles' in settings.INSTALLED_APPS: - from django.contrib.staticfiles.templatetags.staticfiles import static + # from django.contrib.staticfiles.templatetags.staticfiles import static + from django.templatetags.static import static else: from django.templatetags.static import static @@ -35,11 +37,6 @@ except ImportError: from django.utils.timezone import localtime as tz_localtime -if django.VERSION < (1, 11): - DJANGO_11 = False -else: - DJANGO_11 = True - def xstatic(*tags): from .vendors import vendors @@ -84,15 +81,16 @@ def xstatic(*tags): def vendor(*tags): - media = Media() + css = {'screen': []} + js = [] for tag in tags: file_type = tag.split('.')[-1] files = xstatic(tag) if file_type == 'js': - media.add_js(files) + js.extend(files) elif file_type == 'css': - media.add_css({'screen': files}) - return media + css['screen'] += files + return Media(css=css, js=js) def lookup_needs_distinct(opts, lookup_path): @@ -101,8 +99,8 @@ def lookup_needs_distinct(opts, lookup_path): """ field_name = lookup_path.split('__', 1)[0] field = opts.get_field(field_name) - if ((hasattr(field, 'rel') and - isinstance(field.rel, models.ManyToManyRel)) or + if ((hasattr(field, 'remote_field') and + isinstance(field.remote_field, models.ManyToManyRel)) or (is_related_field(field) and not field.field.unique)): return True @@ -343,7 +341,7 @@ def display_for_field(value, field): return formats.number_format(value, field.decimal_places) elif isinstance(field, models.FloatField): return formats.number_format(value) - elif isinstance(field.rel, models.ManyToManyRel): + elif isinstance(field.remote_field, models.ManyToManyRel): return ', '.join([smart_text(obj) for obj in value.all()]) else: return smart_text(value) @@ -375,8 +373,8 @@ def get_model_from_relation(field): return field.related_model elif is_related_field(field): return field.model - elif getattr(field, 'rel'): # or isinstance? - return field.rel.to + elif getattr(field, 'remote_field'): # or isinstance? + return field.remote_field.to else: raise NotRelationField @@ -451,8 +449,8 @@ def get_limit_choices_to_from_path(model, path): fields = get_fields_from_path(model, path) fields = remove_trailing_data_field(fields) limit_choices_to = ( - fields and hasattr(fields[-1], 'rel') and - getattr(fields[-1].rel, 'limit_choices_to', None)) + fields and hasattr(fields[-1], 'remote_field') and + getattr(fields[-1].remote_field, 'limit_choices_to', None)) if not limit_choices_to: return models.Q() # empty Q elif isinstance(limit_choices_to, models.Q): @@ -482,4 +480,4 @@ def is_related_field(field): def is_related_field2(field): - return (hasattr(field, 'rel') and field.rel != None) or is_related_field(field) + return (hasattr(field, 'remote_field') and field.remote_field != None) or is_related_field(field) diff --git a/xadmin/views/__init__.py b/xadmin/views/__init__.py index 9e21b9fc2..a948134cd 100644 --- a/xadmin/views/__init__.py +++ b/xadmin/views/__init__.py @@ -20,6 +20,8 @@ ) # admin site-wide views + + def register_builtin_views(site): site.register_view(r'^$', IndexView, name='index') site.register_view(r'^login/$', LoginView, name='login') @@ -38,4 +40,4 @@ def register_builtin_views(site): site.register_modelview( r'^(.+)/dashboard/$', ModelDashboard, name='%s_%s_dashboard') - site.set_loginview(LoginView) \ No newline at end of file + site.set_loginview(LoginView) diff --git a/xadmin/views/base.py b/xadmin/views/base.py index 539ccbe4e..c7564c212 100644 --- a/xadmin/views/base.py +++ b/xadmin/views/base.py @@ -3,7 +3,7 @@ import datetime import decimal from functools import update_wrapper -from inspect import getargspec +from inspect import getfullargspec from django import forms from django.apps import apps @@ -12,7 +12,7 @@ from django.contrib.auth import get_permission_codename from django.core.exceptions import ValidationError from django.core.serializers.json import DjangoJSONEncoder -from django.core.urlresolvers import reverse +from django.urls.base import reverse from django.http import HttpResponse from django.template import Context, Template from django.template.response import TemplateResponse @@ -38,17 +38,19 @@ class IncorrectPluginArg(Exception): pass + def get_content_type_for_model(obj): from django.contrib.contenttypes.models import ContentType return ContentType.objects.get_for_model(obj, for_concrete_model=False) + def filter_chain(filters, token, func, *args, **kwargs): if token == -1: return func() else: def _inner_method(): fm = filters[token] - fargs = getargspec(fm)[0] + fargs = getfullargspec(fm)[0] if len(fargs) == 1: # Only self arg result = func() @@ -110,6 +112,7 @@ def method(self, context, nodes, *arg, **kwargs): class JSONEncoder(DjangoJSONEncoder): + def default(self, o): if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %H:%M:%S') @@ -217,7 +220,7 @@ def vendor(self, *tags): def log(self, flag, message, obj=None): log = Log( - user=self.user, + user=self.user, ip_addr=self.request.META['REMOTE_ADDR'], action_flag=flag, message=message @@ -253,7 +256,7 @@ def __init__(self, request, *args, **kwargs): self.request = request self.request_method = request.method.lower() self.user = request.user - + self.base_plugins = [p(self) for p in getattr(self, "plugin_classes", [])] @@ -317,8 +320,8 @@ class CommAdminView(BaseAdminView): base_template = 'xadmin/base_site.html' menu_template = 'xadmin/includes/sitemenu_default.html' - site_title = getattr(settings,"XADMIN_TITLE",_(u"Django Xadmin")) - site_footer = getattr(settings,"XADMIN_FOOTER_TITLE",_(u"my-company.inc")) + site_title = getattr(settings, "XADMIN_TITLE", _(u"Django Xadmin")) + site_footer = getattr(settings, "XADMIN_FOOTER_TITLE", _(u"my-company.inc")) global_models_icon = {} default_model_icon = None @@ -368,7 +371,7 @@ def get_url(menu, had_urls): app_title = self.apps_label_title[app_label.lower()] else: app_title = smart_text(apps.get_app_config(app_label).verbose_name) - #find app icon + # find app icon if app_label.lower() in self.apps_icons: app_icon = self.apps_icons[app_label.lower()] @@ -428,7 +431,7 @@ def filter_item(item): return item nav_menu = [filter_item(item) for item in menus if check_menu_permission(item)] - nav_menu = list(filter(lambda x:x, nav_menu)) + nav_menu = list(filter(lambda x: x, nav_menu)) if not settings.DEBUG: self.request.session['nav_menu'] = json.dumps(nav_menu, cls=JSONEncoder, ensure_ascii=False) @@ -476,7 +479,8 @@ def get_breadcrumb(self): return [{ 'url': self.get_admin_url('index'), 'title': _('Home') - }] + }] + class ModelAdminView(CommAdminView): @@ -522,11 +526,10 @@ def get_object(self, object_id): Get model object instance by object_id, used for change admin view """ # first get base admin view property queryset, return default model queryset - queryset = self.queryset() - model = queryset.model + model = self.model try: object_id = model._meta.pk.to_python(object_id) - return queryset.get(pk=object_id) + return model.objects.get(pk=object_id) except (model.DoesNotExist, ValidationError): return None @@ -542,7 +545,7 @@ def get_object_url(self, obj): def model_admin_url(self, name, *args, **kwargs): return reverse( "%s:%s_%s_%s" % (self.admin_site.app_name, self.opts.app_label, - self.model_name, name), args=args, kwargs=kwargs) + self.model_name, name), args=args, kwargs=kwargs) def get_model_perms(self): """ @@ -584,8 +587,8 @@ def has_view_permission(self, obj=None): view_codename = get_permission_codename('view', self.opts) change_codename = get_permission_codename('change', self.opts) - return ('view' not in self.remove_permissions) and (self.user.has_perm('%s.%s' % (self.app_label, view_codename)) or \ - self.user.has_perm('%s.%s' % (self.app_label, change_codename))) + return ('view' not in self.remove_permissions) and (self.user.has_perm('%s.%s' % (self.app_label, view_codename)) or + self.user.has_perm('%s.%s' % (self.app_label, change_codename))) def has_add_permission(self): codename = get_permission_codename('add', self.opts) @@ -595,6 +598,6 @@ def has_change_permission(self, obj=None): codename = get_permission_codename('change', self.opts) return ('change' not in self.remove_permissions) and self.user.has_perm('%s.%s' % (self.app_label, codename)) - def has_delete_permission(self, obj=None): + def has_delete_permission(self, request=None, obj=None): codename = get_permission_codename('delete', self.opts) return ('delete' not in self.remove_permissions) and self.user.has_perm('%s.%s' % (self.app_label, codename)) diff --git a/xadmin/views/dashboard.py b/xadmin/views/dashboard.py index 3056076ea..4e734324e 100644 --- a/xadmin/views/dashboard.py +++ b/xadmin/views/dashboard.py @@ -1,7 +1,7 @@ from django import forms from django.apps import apps from django.core.exceptions import PermissionDenied -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls.base import reverse, NoReverseMatch from django.template.context_processors import csrf from django.db.models.base import ModelBase from django.forms.forms import DeclarativeFieldsMetaclass @@ -23,7 +23,7 @@ from xadmin.views.base import CommAdminView, ModelAdminView, filter_hook, csrf_protect_m from xadmin.views.edit import CreateAdminView from xadmin.views.list import ListAdminView -from xadmin.util import unquote, DJANGO_11 +from xadmin.util import unquote import copy @@ -33,13 +33,10 @@ def __init__(self, widgets, attrs=None): super(WidgetTypeSelect, self).__init__(attrs) self._widgets = widgets - def render(self, name, value, attrs=None): + def render(self, name, value, attrs=None, renderer=None): if value is None: value = '' - if DJANGO_11: - final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) - else: - final_attrs = self.build_attrs(attrs, name=name) + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) final_attrs['class'] = 'nav nav-pills nav-stacked' output = [u'' % flatatt(final_attrs)] options = self.render_options(force_text(value), final_attrs['id']) @@ -265,6 +262,7 @@ def context(self, context): class ModelChoiceIterator(object): + def __init__(self, field): self.field = field @@ -277,12 +275,11 @@ def __iter__(self): class ModelChoiceField(forms.ChoiceField): - def __init__(self, required=True, widget=None, label=None, initial=None, - help_text=None, *args, **kwargs): + def __init__(self, *, required=True, widget=None, label=None, initial=None, + help_text=None, **kwargs): # Call Field instead of ChoiceField __init__() because we don't need # ChoiceField.__init__(). - forms.Field.__init__(self, required, widget, label, initial, help_text, - *args, **kwargs) + forms.Field.__init__(self, **kwargs) self.widget.choices = self.choices def __deepcopy__(self, memo): @@ -511,6 +508,7 @@ def get_widget(self, widget_or_id, data=None): wid = widget_manager.get(widget.widget_type) class widget_with_perm(wid): + def context(self, context): super(widget_with_perm, self).context(context) context.update({'has_change_permission': self.request.user.has_perm('xadmin.change_userwidget')}) diff --git a/xadmin/views/delete.py b/xadmin/views/delete.py index 77d49f5c3..2dc4fd06b 100644 --- a/xadmin/views/delete.py +++ b/xadmin/views/delete.py @@ -2,6 +2,7 @@ from django.db import transaction, router from django.http import Http404, HttpResponseRedirect from django.template.response import TemplateResponse +from django import VERSION as django_version from django.utils import six from django.utils.encoding import force_text from django.utils.html import escape @@ -17,6 +18,13 @@ class DeleteAdminView(ModelAdminView): delete_confirmation_template = None + def __init__(self, request, *args, **kwargs): + if django_version > (2, 0): + for model in self.admin_site._registry: + if not hasattr(self.admin_site._registry[model], 'has_delete_permission'): + setattr(self.admin_site._registry[model], 'has_delete_permission', self.has_delete_permission) + super(DeleteAdminView, self).__init__(request, *args, **kwargs) + def init_request(self, object_id, *args, **kwargs): "The 'delete' admin view for this model." self.obj = self.get_object(unquote(object_id)) @@ -31,8 +39,12 @@ def init_request(self, object_id, *args, **kwargs): # Populate deleted_objects, a data structure of all related objects that # will also be deleted. - (self.deleted_objects, model_count, self.perms_needed, self.protected) = get_deleted_objects( - [self.obj], self.opts, self.request.user, self.admin_site, using) + if django_version > (2, 1): + (self.deleted_objects, model_count, self.perms_needed, self.protected) = get_deleted_objects( + [self.obj], self.opts, self.admin_site) + else: + (self.deleted_objects, model_count, self.perms_needed, self.protected) = get_deleted_objects( + [self.obj], self.opts, self.request.user, self.admin_site, using) @csrf_protect_m @filter_hook diff --git a/xadmin/views/detail.py b/xadmin/views/detail.py index e9b642111..96f6aec1b 100644 --- a/xadmin/views/detail.py +++ b/xadmin/views/detail.py @@ -94,7 +94,7 @@ def init(self): else: self.text = smart_text(value) else: - if isinstance(f.rel, models.ManyToOneRel): + if isinstance(f.remote_field, models.ManyToOneRel): self.text = getattr(self.obj, f.name) else: self.text = display_for_field(value, f) diff --git a/xadmin/views/edit.py b/xadmin/views/edit.py index a52ea4d26..a5786a5f3 100644 --- a/xadmin/views/edit.py +++ b/xadmin/views/edit.py @@ -15,6 +15,7 @@ from django.utils.text import capfirst, get_text_list from django.template import loader from django.utils.translation import ugettext as _ +from django.forms.widgets import Media from xadmin import widgets from xadmin.layout import FormHelper, Layout, Fieldset, TabHolder, Container, Column, Col, Field from xadmin.util import unquote @@ -87,7 +88,7 @@ def __init__(self, request, *args, **kwargs): def formfield_for_dbfield(self, db_field, **kwargs): # If it uses an intermediary model that isn't auto created, don't show # a field in admin. - if isinstance(db_field, models.ManyToManyField) and not db_field.rel.through._meta.auto_created: + if isinstance(db_field, models.ManyToManyField) and not db_field.remote_field.through._meta.auto_created: return None attrs = self.get_field_attrs(db_field, **kwargs) @@ -199,8 +200,8 @@ def get_form_layout(self): if layout is None: layout = Layout(Container(Col('full', - Fieldset("", *fields, css_class="unsort no_title"), horizontal=True, span=12) - )) + Fieldset("", *fields, css_class="unsort no_title"), horizontal=True, span=12) + )) elif type(layout) in (list, tuple) and len(layout) > 0: if isinstance(layout[0], Column): fs = layout @@ -223,7 +224,6 @@ def get_form_layout(self): return layout - @filter_hook def get_form_helper(self): helper = FormHelper() helper.form_tag = False @@ -355,7 +355,11 @@ def get_error_list(self): @filter_hook def get_media(self): - return super(ModelFormAdminView, self).get_media() + self.form_obj.media + \ + try: + m = self.form_obj.media + except: + m = Media() + return super(ModelFormAdminView, self).get_media() + m + \ self.vendor('xadmin.page.form.js', 'xadmin.form.css') @@ -527,7 +531,7 @@ def post_response(self): return request.path elif "_addanother" in request.POST: self.message_user(msg + ' ' + (_("You may add another %s below.") - % force_text(verbose_name)), 'success') + % force_text(verbose_name)), 'success') return self.model_admin_url('add') else: self.message_user(msg, 'success') @@ -539,7 +543,7 @@ def post_response(self): elif self.has_view_permission(): change_list_url = self.model_admin_url('changelist') if 'LIST_QUERY' in self.request.session \ - and self.request.session['LIST_QUERY'][0] == self.model_info: + and self.request.session['LIST_QUERY'][0] == self.model_info: change_list_url += '?' + self.request.session['LIST_QUERY'][1] return change_list_url else: diff --git a/xadmin/views/list.py b/xadmin/views/list.py index 43128c8c3..7188cc7a2 100644 --- a/xadmin/views/list.py +++ b/xadmin/views/list.py @@ -1,8 +1,9 @@ from __future__ import absolute_import from collections import OrderedDict from django.core.exceptions import PermissionDenied, ObjectDoesNotExist +from django.core.exceptions import FieldDoesNotExist from django.core.paginator import InvalidPage, Paginator -from django.core.urlresolvers import NoReverseMatch +from django.urls.base import NoReverseMatch from django.db import models from django.http import HttpResponseRedirect from django.template.response import SimpleTemplateResponse, TemplateResponse @@ -35,6 +36,7 @@ class FakeMethodField(object): """ This class used when a column is an model function, wrap function as a fake field to display in select columns. """ + def __init__(self, name, verbose_name): # Initial comm field attrs self.name = name @@ -78,7 +80,7 @@ def label(self): def tagattrs(self): return mark_safe( '%s%s' % ((self.tag_attrs and ' '.join(self.tag_attrs) or ''), - (self.classes and (' class="%s"' % ' '.join(self.classes)) or ''))) + (self.classes and (' class="%s"' % ' '.join(self.classes)) or ''))) class ResultHeader(ResultItem): @@ -149,8 +151,8 @@ def get_list_display(self): """ Return a sequence containing the fields to be displayed on the list. """ - self.base_list_display = (COL_LIST_VAR in self.request.GET and self.request.GET[COL_LIST_VAR] != "" and \ - self.request.GET[COL_LIST_VAR].split('.')) or self.list_display + self.base_list_display = (COL_LIST_VAR in self.request.GET and self.request.GET[COL_LIST_VAR] != "" and + self.request.GET[COL_LIST_VAR].split('.')) or self.list_display return list(self.base_list_display) @filter_hook @@ -168,7 +170,6 @@ def get_list_display_links(self): def make_result_list(self): # Get search parameters from the query string. - self.base_queryset = self.queryset() self.list_queryset = self.get_list_queryset() self.ordering_field_columns = self.get_ordering_field_columns() self.paginator = self.get_paginator() @@ -222,10 +223,10 @@ def get_list_queryset(self): for field_name in self.list_display: try: field = self.opts.get_field(field_name) - except models.FieldDoesNotExist: + except FieldDoesNotExist: pass else: - if isinstance(field.rel, models.ManyToOneRel): + if isinstance(field.remote_field, models.ManyToOneRel): related_fields.append(field_name) if related_fields: queryset = queryset.select_related(*related_fields) @@ -259,7 +260,7 @@ def get_ordering_field(self, field_name): try: field = self.opts.get_field(field_name) return field.name - except models.FieldDoesNotExist: + except FieldDoesNotExist: # See whether field_name is a name of a non-field # that allows sorting. if callable(field_name): @@ -285,13 +286,13 @@ def get_ordering(self): if ORDER_VAR in self.params and self.params[ORDER_VAR]: # Clear ordering and used params ordering = [ - pfx + self.get_ordering_field(field_name) - for n, pfx, field_name in map( - lambda p: p.rpartition('-'), - self.params[ORDER_VAR].split('.') - ) - if self.get_ordering_field(field_name) - ] + pfx + self.get_ordering_field(field_name) + for n, pfx, field_name in map( + lambda p: p.rpartition('-'), + self.params[ORDER_VAR].split('.') + ) + if self.get_ordering_field(field_name) + ] # Ensure that the primary key is systematically present in the list of # ordering fields so we can guarantee a deterministic order across all @@ -505,10 +506,10 @@ def result_header(self, field_name, row): self.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}), 'sort-up' if order_type == "asc" else 'sort-down')) item.menus.extend([' %s' % - ( - (' class="active"' if sorted and order_type == i[ - 0] else ''), - self.get_query_string({ORDER_VAR: '.'.join(i[1])}), i[2], i[3]) for i in menus]) + ( + (' class="active"' if sorted and order_type == i[ + 0] else ''), + self.get_query_string({ORDER_VAR: '.'.join(i[1])}), i[2], i[3]) for i in menus]) item.classes.extend(th_classes) return item @@ -544,7 +545,7 @@ def result_item(self, obj, field_name, row): else: item.text = smart_text(value) else: - if isinstance(f.rel, models.ManyToOneRel): + if isinstance(f.remote_field, models.ManyToOneRel): field_val = getattr(obj, f.name) if field_val is None: item.text = mark_safe("%s" % EMPTY_CHANGELIST_VALUE) @@ -574,7 +575,7 @@ def result_item(self, obj, field_name, row): else: edit_url = "" item.wraps.append('%%s' - % (item_res_uri, edit_url, _(u'Details of %s') % str(obj))) + % (item_res_uri, edit_url, _(u'Details of %s') % str(obj))) else: url = self.url_for_result(obj) item.wraps.append(u'%%s' % url) diff --git a/xadmin/views/website.py b/xadmin/views/website.py index 172b99d90..c8b338c5f 100644 --- a/xadmin/views/website.py +++ b/xadmin/views/website.py @@ -2,8 +2,8 @@ from django.utils.translation import ugettext as _ from django.contrib.auth import REDIRECT_FIELD_NAME from django.views.decorators.cache import never_cache -from django.contrib.auth.views import login -from django.contrib.auth.views import logout +from django.contrib.auth.views import LoginView as login +from django.contrib.auth.views import LogoutView as logout from django.http import HttpResponse from .base import BaseAdminView, filter_hook @@ -58,12 +58,13 @@ def get(self, request, *args, **kwargs): }) defaults = { 'extra_context': context, - 'current_app': self.admin_site.name, + # 'current_app': self.admin_site.name, 'authentication_form': self.login_form or AdminAuthenticationForm, 'template_name': self.login_template or 'xadmin/views/login.html', } self.update_params(defaults) - return login(request, **defaults) + # return login(request, **defaults) + return login.as_view(**defaults)(request) @never_cache def post(self, request, *args, **kwargs): @@ -84,14 +85,15 @@ def get(self, request, *args, **kwargs): context = self.get_context() defaults = { 'extra_context': context, - 'current_app': self.admin_site.name, + # 'current_app': self.admin_site.name, 'template_name': self.logout_template or 'xadmin/views/logged_out.html', } if self.logout_template is not None: defaults['template_name'] = self.logout_template self.update_params(defaults) - return logout(request, **defaults) + # return logout(request, **defaults) + return logout.as_view(**defaults)(request) @never_cache def post(self, request, *args, **kwargs): diff --git a/xadmin/widgets.py b/xadmin/widgets.py index 3263ddc2a..7cdda51de 100644 --- a/xadmin/widgets.py +++ b/xadmin/widgets.py @@ -14,7 +14,7 @@ from django.utils.html import conditional_escape from django.utils.translation import ugettext as _ -from .util import vendor, DJANGO_11 +from .util import vendor class AdminDateWidget(forms.DateInput): @@ -29,8 +29,8 @@ def __init__(self, attrs=None, format=None): final_attrs.update(attrs) super(AdminDateWidget, self).__init__(attrs=final_attrs, format=format) - def render(self, name, value, attrs=None): - input_html = super(AdminDateWidget, self).render(name, value, attrs) + def render(self, name, value, attrs=None, renderer=None): + input_html = super(AdminDateWidget, self).render(name, value, attrs, renderer) return mark_safe('%s' '%s' % (input_html, _(u'Today'))) @@ -47,8 +47,8 @@ def __init__(self, attrs=None, format=None): final_attrs.update(attrs) super(AdminTimeWidget, self).__init__(attrs=final_attrs, format=format) - def render(self, name, value, attrs=None): - input_html = super(AdminTimeWidget, self).render(name, value, attrs) + def render(self, name, value, attrs=None, renderer=None): + input_html = super(AdminTimeWidget, self).render(name, value, attrs, renderer) return mark_safe('' '%s%s' % (input_html, _(u'Now'))) @@ -71,17 +71,13 @@ def __init__(self, attrs=None): # we want to define widgets. forms.MultiWidget.__init__(self, widgets, attrs) - def render(self, name, value, attrs=None): - if DJANGO_11: - input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).replace( - '/>\n%s' - '%s' - '' - '%s%s' % (input_html[0], _(u'Today'), input_html[1], _(u'Now'))) - else: - return super(AdminSplitDateTime, self).render(name, value, attrs) + def render(self, name, value, attrs=None, renderer=None): + input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs, renderer).replace('>\n%s' + '%s' + '' + '%s%s' % (input_html[0], _(u'Today'), input_html[1], _(u'Now'))) def format_output(self, rendered_widgets): return mark_safe(u'%s%s' % @@ -130,10 +126,7 @@ def render(self, name, value, attrs=None, choices=()): if value is None: value = [] has_id = attrs and 'id' in attrs - if DJANGO_11: - final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) - else: - final_attrs = self.build_attrs(attrs, name=name) + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) output = [] # Normalize to strings str_values = set([force_text(v) for v in value]) diff --git "a/\351\200\202\351\205\215django3.md" "b/\351\200\202\351\205\215django3.md" new file mode 100644 index 000000000..eb680f084 --- /dev/null +++ "b/\351\200\202\351\205\215django3.md" @@ -0,0 +1,121 @@ +# `xadmin修改记录,基于webDjango项目` + +# 20220123 + +* 复制可用版本,后面碰到问题再改 + +主要出错在plugins + +django3中变量导包位置变动 + +* 更新font-awesome + +前端图标文件 xadmin/static/xadmin/vendor/font-awesome + +原来是4.0.3,更新到4.7.0 + +* 3.x版本中django.uitls中移除了six,但是xadmin中大量这样使用,在xadmin.__init__.py顶部运行位置,增加 + +``` +import six +import django +setattr(django.utils, 'six', six) +``` + +# 20220122 + +1 + +``` + File "D:\0web\xadmin-django3\xadmin\views\list.py", line 225, in get_list_queryset + except models.FieldDoesNotExist: +AttributeError: module 'django.db.models' has no attribute 'FieldDoesNotExist' +``` + +``` +from django.core.exceptions import FieldDoesNotExist +``` + +2 + +``` + File "D:\0web\xadmin-django3\xadmin\plugins\filters.py", line 9, in + from django.db.models.fields import FieldDoesNotExist +``` + +``` +# from django.db.models.fields import FieldDoesNotExist +from django.core.exceptions import FieldDoesNotExist +``` + +3 + +``` +File "D:\0web\xadmin-django3\xadmin\models.py", line 19, in + from xadmin.util import quote + File "D:\0web\xadmin-django3\xadmin\util.py", line 7, in + from django.forms.forms import pretty_name +``` + +``` +# from django.forms.forms import pretty_name +from django.forms.utils import pretty_name +``` + +4 + +``` + File "D:\0web\1_muke\xadmin_ueditor_django\django3\xadmin\sites.py", line 7, in + from django.utils import six +``` + +3.x版本中django.uitls中移除了six,但是xadmin中大量这样使用,在xadmin.__init__.py顶部运行位置,增加 + +``` +import six +import django +setattr(django.utils, 'six', six) +``` + +5 + +``` + File "D:\0web\1_muke\xadmin_ueditor_django\django3\xadmin\models.py", line 11, in + from django.utils.encoding import python_2_unicode_compatible, smart_text +``` + +``` +# from django.utils.encoding import python_2_unicode_compatible, smart_text +from django.utils.encoding import smart_text +from six import python_2_unicode_compatible + +``` + +6 + +``` + File "D:\0web\1_muke\xadmin_ueditor_django\django3\xadmin\models.py", line 20, in + from xadmin.util import quote + File "D:\0web\1_muke\xadmin_ueditor_django\django3\xadmin\util.py", line 25, in + from django.contrib.staticfiles.templatetags.staticfiles import static + +``` + +``` + # from django.contrib.staticfiles.templatetags.staticfiles import static + from django.templatetags.static import static +``` + +7 + +``` +File "D:\0web\1_muke\xadmin_ueditor_django\django3\xadmin\plugins\filters.py", line 9, in + from django.db.models.fields import FieldDoesNotExist +ImportError: cannot import name 'FieldDoesNotExist' from 'django.db.models.fields' (D:\Anaconda3\envs\django3\lib\site-packages\django\db\models\fields\__init__.py) + +``` + +``` +# from django.db.models.fields import FieldDoesNotExist +from django.core.exceptions import FieldDoesNotExist +```
{% trans "Thanks for spending some quality time with the Web site today." %}
- {% trans 'Close Window' %} + {% trans 'Close Window' %} {% trans 'Log in again' %}