master
parent
e0ff6eba08
commit
16fad0ad7d
@ -0,0 +1,8 @@
|
||||
/.vscode/
|
||||
/dbs/
|
||||
/doc/
|
||||
/eggs/
|
||||
/logs/
|
||||
pythonÃüÁî.txt
|
||||
/webview/node_modules/
|
||||
/webview/.vscode/
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 hsp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,14 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[xadmin-core.django]
|
||||
file_filter = locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
[xadmin-core.djangojs]
|
||||
file_filter = locale/<lang>/LC_MESSAGES/djangojs.po
|
||||
source_file = locale/en/LC_MESSAGES/djangojs.po
|
||||
source_lang = en
|
||||
type = PO
|
@ -0,0 +1,70 @@
|
||||
|
||||
VERSION = (0,6,0)
|
||||
|
||||
from xadmin.sites import AdminSite, site
|
||||
|
||||
class Settings(object):
|
||||
pass
|
||||
|
||||
|
||||
def autodiscover():
|
||||
"""
|
||||
Auto-discover INSTALLED_APPS admin.py modules and fail silently when
|
||||
not present. This forces an import on them to register any admin bits they
|
||||
may want.
|
||||
"""
|
||||
|
||||
from importlib import import_module
|
||||
from django.conf import settings
|
||||
from django.utils.module_loading import module_has_submodule
|
||||
from django.apps import apps
|
||||
|
||||
setattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap3')
|
||||
setattr(settings, 'CRISPY_CLASS_CONVERTERS', {
|
||||
"textinput": "textinput textInput form-control",
|
||||
"fileinput": "fileinput fileUpload form-control",
|
||||
"passwordinput": "textinput textInput form-control",
|
||||
})
|
||||
|
||||
from xadmin.views import register_builtin_views
|
||||
register_builtin_views(site)
|
||||
|
||||
# load xadmin settings from XADMIN_CONF module
|
||||
try:
|
||||
xadmin_conf = getattr(settings, 'XADMIN_CONF', 'xadmin_conf.py')
|
||||
conf_mod = import_module(xadmin_conf)
|
||||
except Exception:
|
||||
conf_mod = None
|
||||
|
||||
if conf_mod:
|
||||
for key in dir(conf_mod):
|
||||
setting = getattr(conf_mod, key)
|
||||
try:
|
||||
if issubclass(setting, Settings):
|
||||
site.register_settings(setting.__name__, setting)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
from xadmin.plugins import register_builtin_plugins
|
||||
register_builtin_plugins(site)
|
||||
|
||||
for app_config in apps.get_app_configs():
|
||||
mod = import_module(app_config.name)
|
||||
# Attempt to import the app's admin module.
|
||||
try:
|
||||
before_import_registry = site.copy_registry()
|
||||
import_module('%s.adminx' % app_config.name)
|
||||
except:
|
||||
# Reset the model registry to the state before the last import as
|
||||
# this import will have to reoccur on the next request and this
|
||||
# could raise NotRegistered and AlreadyRegistered exceptions
|
||||
# (see #8245).
|
||||
site.restore_registry(before_import_registry)
|
||||
|
||||
# Decide whether to bubble up this error. If the app just
|
||||
# doesn't have an admin module, we can ignore the error
|
||||
# attempting to import it, otherwise we want it to bubble up.
|
||||
if module_has_submodule(mod, 'adminx'):
|
||||
raise
|
||||
|
||||
default_app_config = 'xadmin.apps.XAdminConfig'
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
from __future__ import absolute_import
|
||||
import xadmin
|
||||
from .models import UserSettings, Log
|
||||
from xadmin.layout import *
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _, ugettext
|
||||
|
||||
class UserSettingsAdmin(object):
|
||||
model_icon = 'fa fa-cog'
|
||||
hidden_menu = True
|
||||
|
||||
xadmin.site.register(UserSettings, UserSettingsAdmin)
|
||||
|
||||
class LogAdmin(object):
|
||||
|
||||
def link(self, instance):
|
||||
if instance.content_type and instance.object_id and instance.action_flag != 'delete':
|
||||
admin_url = self.get_admin_url('%s_%s_change' % (instance.content_type.app_label, instance.content_type.model),
|
||||
instance.object_id)
|
||||
return "<a href='%s'>%s</a>" % (admin_url, _('Admin Object'))
|
||||
else:
|
||||
return ''
|
||||
link.short_description = ""
|
||||
link.allow_tags = True
|
||||
link.is_column = False
|
||||
|
||||
list_display = ('action_time', 'user', 'ip_addr', '__str__', 'link')
|
||||
list_filter = ['user', 'action_time']
|
||||
search_fields = ['ip_addr', 'message']
|
||||
model_icon = 'fa fa-cog'
|
||||
|
||||
xadmin.site.register(Log, LogAdmin)
|
@ -0,0 +1,15 @@
|
||||
from django.apps import AppConfig
|
||||
from django.core import checks
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import xadmin
|
||||
|
||||
|
||||
class XAdminConfig(AppConfig):
|
||||
"""Simple AppConfig which does not do automatic discovery."""
|
||||
|
||||
name = 'xadmin'
|
||||
verbose_name = _("Administration")
|
||||
|
||||
def ready(self):
|
||||
self.module.autodiscover()
|
||||
setattr(xadmin,'site',xadmin.site)
|
@ -0,0 +1,573 @@
|
||||
from __future__ import absolute_import
|
||||
from django.db import models
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils import timezone
|
||||
from django.template.loader import get_template
|
||||
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.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
|
||||
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)
|
||||
|
||||
|
||||
class BaseFilter(object):
|
||||
title = None
|
||||
template = 'xadmin/filters/list.html'
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
pass
|
||||
|
||||
def __init__(self, request, params, model, admin_view):
|
||||
self.used_params = {}
|
||||
self.request = request
|
||||
self.params = params
|
||||
self.model = model
|
||||
self.admin_view = admin_view
|
||||
|
||||
if self.title is None:
|
||||
raise ImproperlyConfigured(
|
||||
"The filter '%s' does not specify "
|
||||
"a 'title'." % self.__class__.__name__)
|
||||
|
||||
def query_string(self, new_params=None, remove=None):
|
||||
return self.admin_view.get_query_string(new_params, remove)
|
||||
|
||||
def form_params(self):
|
||||
arr = map(lambda k: FILTER_PREFIX + k, self.used_params.keys())
|
||||
if six.PY3:
|
||||
arr = list(arr)
|
||||
return self.admin_view.get_form_params(remove=arr)
|
||||
|
||||
def has_output(self):
|
||||
"""
|
||||
Returns True if some choices would be output for this filter.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def is_used(self):
|
||||
return len(self.used_params) > 0
|
||||
|
||||
def do_filte(self, queryset):
|
||||
"""
|
||||
Returns the filtered queryset.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_context(self):
|
||||
return {'title': self.title, 'spec': self, 'form_params': self.form_params()}
|
||||
|
||||
def __str__(self):
|
||||
tpl = get_template(self.template)
|
||||
return mark_safe(tpl.render(context=self.get_context()))
|
||||
|
||||
|
||||
class FieldFilterManager(object):
|
||||
_field_list_filters = []
|
||||
_take_priority_index = 0
|
||||
|
||||
def register(self, list_filter_class, take_priority=False):
|
||||
if take_priority:
|
||||
# This is to allow overriding the default filters for certain types
|
||||
# of fields with some custom filters. The first found in the list
|
||||
# is used in priority.
|
||||
self._field_list_filters.insert(
|
||||
self._take_priority_index, list_filter_class)
|
||||
self._take_priority_index += 1
|
||||
else:
|
||||
self._field_list_filters.append(list_filter_class)
|
||||
return list_filter_class
|
||||
|
||||
def create(self, field, request, params, model, admin_view, field_path):
|
||||
for list_filter_class in self._field_list_filters:
|
||||
if not list_filter_class.test(field, request, params, model, admin_view, field_path):
|
||||
continue
|
||||
return list_filter_class(field, request, params,
|
||||
model, admin_view, field_path=field_path)
|
||||
|
||||
manager = FieldFilterManager()
|
||||
|
||||
|
||||
class FieldFilter(BaseFilter):
|
||||
|
||||
lookup_formats = {}
|
||||
|
||||
def __init__(self, field, request, params, model, admin_view, field_path):
|
||||
self.field = field
|
||||
self.field_path = field_path
|
||||
self.title = getattr(field, 'verbose_name', field_path)
|
||||
self.context_params = {}
|
||||
|
||||
super(FieldFilter, self).__init__(request, params, model, admin_view)
|
||||
|
||||
for name, format in self.lookup_formats.items():
|
||||
p = format % field_path
|
||||
self.context_params["%s_name" % name] = FILTER_PREFIX + p
|
||||
if p in params:
|
||||
value = prepare_lookup_value(p, params.pop(p))
|
||||
self.used_params[p] = value
|
||||
self.context_params["%s_val" % name] = value
|
||||
else:
|
||||
self.context_params["%s_val" % name] = ''
|
||||
|
||||
arr = map(
|
||||
lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]),
|
||||
self.context_params.items()
|
||||
)
|
||||
if six.PY3:
|
||||
list(arr)
|
||||
|
||||
def get_context(self):
|
||||
context = super(FieldFilter, self).get_context()
|
||||
context.update(self.context_params)
|
||||
obj = map(lambda k: FILTER_PREFIX + k, self.used_params.keys())
|
||||
if six.PY3:
|
||||
obj = list(obj)
|
||||
context['remove_url'] = self.query_string({}, obj)
|
||||
return context
|
||||
|
||||
def has_output(self):
|
||||
return True
|
||||
|
||||
def do_filte(self, queryset):
|
||||
return queryset.filter(**self.used_params)
|
||||
|
||||
|
||||
class ListFieldFilter(FieldFilter):
|
||||
template = 'xadmin/filters/list.html'
|
||||
|
||||
def get_context(self):
|
||||
context = super(ListFieldFilter, self).get_context()
|
||||
context['choices'] = list(self.choices())
|
||||
return context
|
||||
|
||||
|
||||
@manager.register
|
||||
class BooleanFieldListFilter(ListFieldFilter):
|
||||
lookup_formats = {'exact': '%s__exact', 'isnull': '%s__isnull'}
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return isinstance(field, (models.BooleanField, models.NullBooleanField))
|
||||
|
||||
def choices(self):
|
||||
for lookup, title in (
|
||||
('', _('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,
|
||||
}
|
||||
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'),
|
||||
}
|
||||
|
||||
|
||||
@manager.register
|
||||
class ChoicesFieldListFilter(ListFieldFilter):
|
||||
lookup_formats = {'exact': '%s__exact'}
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return bool(field.choices)
|
||||
|
||||
def choices(self):
|
||||
yield {
|
||||
'selected': self.lookup_exact_val is '',
|
||||
'query_string': self.query_string({}, [self.lookup_exact_name]),
|
||||
'display': _('All')
|
||||
}
|
||||
for lookup, title in self.field.flatchoices:
|
||||
yield {
|
||||
'selected': smart_text(lookup) == self.lookup_exact_val,
|
||||
'query_string': self.query_string({self.lookup_exact_name: lookup}),
|
||||
'display': title,
|
||||
}
|
||||
|
||||
|
||||
@manager.register
|
||||
class TextFieldListFilter(FieldFilter):
|
||||
template = 'xadmin/filters/char.html'
|
||||
lookup_formats = {'in': '%s__in', 'search': '%s__contains'}
|
||||
|
||||
@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)
|
||||
)
|
||||
|
||||
|
||||
@manager.register
|
||||
class NumberFieldListFilter(FieldFilter):
|
||||
template = 'xadmin/filters/number.html'
|
||||
lookup_formats = {'equal': '%s__exact', 'lt': '%s__lt', 'gt': '%s__gt',
|
||||
'ne': '%s__ne', 'lte': '%s__lte', 'gte': '%s__gte',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return isinstance(field, (models.DecimalField, models.FloatField, models.IntegerField))
|
||||
|
||||
def do_filte(self, queryset):
|
||||
params = self.used_params.copy()
|
||||
ne_key = '%s__ne' % self.field_path
|
||||
if ne_key in params:
|
||||
queryset = queryset.exclude(
|
||||
**{self.field_path: params.pop(ne_key)})
|
||||
return queryset.filter(**params)
|
||||
|
||||
|
||||
@manager.register
|
||||
class DateFieldListFilter(ListFieldFilter):
|
||||
template = 'xadmin/filters/date.html'
|
||||
lookup_formats = {'since': '%s__gte', 'until': '%s__lt',
|
||||
'year': '%s__year', 'month': '%s__month', 'day': '%s__day',
|
||||
'isnull': '%s__isnull'}
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return isinstance(field, models.DateField)
|
||||
|
||||
def __init__(self, field, request, params, model, admin_view, field_path):
|
||||
self.field_generic = '%s__' % field_path
|
||||
self.date_params = dict([(FILTER_PREFIX + k, v) for k, v in params.items()
|
||||
if k.startswith(self.field_generic)])
|
||||
|
||||
super(DateFieldListFilter, self).__init__(
|
||||
field, request, params, model, admin_view, field_path)
|
||||
|
||||
now = timezone.now()
|
||||
# When time zone support is enabled, convert "now" to the user's time
|
||||
# zone so Django's definition of "Today" matches what the user expects.
|
||||
if now.tzinfo is not None:
|
||||
current_tz = timezone.get_current_timezone()
|
||||
now = now.astimezone(current_tz)
|
||||
if hasattr(current_tz, 'normalize'):
|
||||
# available for pytz time zones
|
||||
now = current_tz.normalize(now)
|
||||
|
||||
if isinstance(field, models.DateTimeField):
|
||||
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
else: # field is a models.DateField
|
||||
today = now.date()
|
||||
tomorrow = today + datetime.timedelta(days=1)
|
||||
|
||||
self.links = (
|
||||
(_('Any date'), {}),
|
||||
(_('Has date'), {
|
||||
self.lookup_isnull_name: False
|
||||
}),
|
||||
(_('Has no date'), {
|
||||
self.lookup_isnull_name: 'True'
|
||||
}),
|
||||
(_('Today'), {
|
||||
self.lookup_since_name: str(today),
|
||||
self.lookup_until_name: str(tomorrow),
|
||||
}),
|
||||
(_('Past 7 days'), {
|
||||
self.lookup_since_name: str(today - datetime.timedelta(days=7)),
|
||||
self.lookup_until_name: str(tomorrow),
|
||||
}),
|
||||
(_('This month'), {
|
||||
self.lookup_since_name: str(today.replace(day=1)),
|
||||
self.lookup_until_name: str(tomorrow),
|
||||
}),
|
||||
(_('This year'), {
|
||||
self.lookup_since_name: str(today.replace(month=1, day=1)),
|
||||
self.lookup_until_name: str(tomorrow),
|
||||
}),
|
||||
)
|
||||
|
||||
def get_context(self):
|
||||
context = super(DateFieldListFilter, self).get_context()
|
||||
context['choice_selected'] = bool(self.lookup_year_val) or bool(self.lookup_month_val) \
|
||||
or bool(self.lookup_day_val)
|
||||
return context
|
||||
|
||||
def choices(self):
|
||||
for title, param_dict in self.links:
|
||||
yield {
|
||||
'selected': self.date_params == param_dict,
|
||||
'query_string': self.query_string(
|
||||
param_dict, [FILTER_PREFIX + self.field_generic]),
|
||||
'display': title,
|
||||
}
|
||||
|
||||
|
||||
@manager.register
|
||||
class RelatedFieldSearchFilter(FieldFilter):
|
||||
template = 'xadmin/filters/fk_search.html'
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
if not is_related_field2(field):
|
||||
return False
|
||||
related_modeladmin = admin_view.admin_site._registry.get(
|
||||
get_model_from_relation(field))
|
||||
return related_modeladmin and getattr(related_modeladmin, 'relfield_style', None) in ('fk-ajax', 'fk-select')
|
||||
|
||||
def __init__(self, field, request, params, model, model_admin, field_path):
|
||||
other_model = get_model_from_relation(field)
|
||||
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}
|
||||
super(RelatedFieldSearchFilter, self).__init__(
|
||||
field, request, params, model, model_admin, field_path)
|
||||
|
||||
related_modeladmin = self.admin_view.admin_site._registry.get(other_model)
|
||||
self.relfield_style = related_modeladmin.relfield_style
|
||||
|
||||
if hasattr(field, 'verbose_name'):
|
||||
self.lookup_title = field.verbose_name
|
||||
else:
|
||||
self.lookup_title = other_model._meta.verbose_name
|
||||
self.title = self.lookup_title
|
||||
self.search_url = model_admin.get_admin_url('%s_%s_changelist' % (
|
||||
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.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):
|
||||
try:
|
||||
obj = other_model._default_manager.get(**{rel_name: value})
|
||||
return '%s' % escape(Truncator(obj).words(14, truncate='...'))
|
||||
except (ValueError, other_model.DoesNotExist):
|
||||
return ""
|
||||
|
||||
def get_context(self):
|
||||
context = super(RelatedFieldSearchFilter, self).get_context()
|
||||
context['search_url'] = self.search_url
|
||||
context['label'] = self.label
|
||||
context['choices'] = self.choices
|
||||
context['relfield_style'] = self.relfield_style
|
||||
return context
|
||||
|
||||
|
||||
@manager.register
|
||||
class RelatedFieldListFilter(ListFieldFilter):
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return is_related_field2(field)
|
||||
|
||||
def __init__(self, field, request, params, model, model_admin, field_path):
|
||||
other_model = get_model_from_relation(field)
|
||||
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, 'isnull': '%s__isnull'}
|
||||
self.lookup_choices = field.get_choices(include_blank=False)
|
||||
super(RelatedFieldListFilter, self).__init__(
|
||||
field, request, params, model, model_admin, field_path)
|
||||
|
||||
if hasattr(field, 'verbose_name'):
|
||||
self.lookup_title = field.verbose_name
|
||||
else:
|
||||
self.lookup_title = other_model._meta.verbose_name
|
||||
self.title = self.lookup_title
|
||||
|
||||
def has_output(self):
|
||||
if (is_related_field(self.field)
|
||||
and self.field.field.null or hasattr(self.field, 'remote_field')
|
||||
and self.field.null):
|
||||
extra = 1
|
||||
else:
|
||||
extra = 0
|
||||
return len(self.lookup_choices) + extra > 1
|
||||
|
||||
def expected_parameters(self):
|
||||
return [self.lookup_kwarg, self.lookup_kwarg_isnull]
|
||||
|
||||
def choices(self):
|
||||
yield {
|
||||
'selected': self.lookup_exact_val == '' and not self.lookup_isnull_val,
|
||||
'query_string': self.query_string({},
|
||||
[self.lookup_exact_name, self.lookup_isnull_name]),
|
||||
'display': _('All'),
|
||||
}
|
||||
for pk_val, val in self.lookup_choices:
|
||||
yield {
|
||||
'selected': self.lookup_exact_val == smart_text(pk_val),
|
||||
'query_string': self.query_string({
|
||||
self.lookup_exact_name: pk_val,
|
||||
}, [self.lookup_isnull_name]),
|
||||
'display': val,
|
||||
}
|
||||
if (is_related_field(self.field)
|
||||
and self.field.field.null or hasattr(self.field, 'remote_field')
|
||||
and self.field.null):
|
||||
yield {
|
||||
'selected': bool(self.lookup_isnull_val),
|
||||
'query_string': self.query_string({
|
||||
self.lookup_isnull_name: 'True',
|
||||
}, [self.lookup_exact_name]),
|
||||
'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'}
|
||||
|
||||
@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):
|
||||
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)
|
||||
|
||||
# Check for it in the cachce
|
||||
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().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:
|
||||
queryset = queryset[:field_limit]
|
||||
|
||||
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)
|
||||
|
||||
if self.cache_config['enabled']:
|
||||
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)
|
||||
yield {
|
||||
'selected': len(self.lookup_in_val) == 0,
|
||||
'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]), }),
|
||||
'display': val,
|
||||
}
|
||||
|
||||
|
||||
@manager.register
|
||||
class AllValuesFieldListFilter(ListFieldFilter):
|
||||
lookup_formats = {'exact': '%s__exact', 'isnull': '%s__isnull'}
|
||||
|
||||
@classmethod
|
||||
def test(cls, field, request, params, model, admin_view, field_path):
|
||||
return True
|
||||
|
||||
def __init__(self, field, request, params, model, admin_view, field_path):
|
||||
parent_model, reverse_path = reverse_field_path(model, field_path)
|
||||
queryset = parent_model._default_manager.all()
|
||||
# optional feature: limit choices base on existing relationships
|
||||
# queryset = queryset.complex_filter(
|
||||
# {'%s__isnull' % reverse_path: False})
|
||||
limit_choices_to = get_limit_choices_to_from_path(model, field_path)
|
||||
queryset = queryset.filter(limit_choices_to)
|
||||
|
||||
self.lookup_choices = (queryset
|
||||
.distinct()
|
||||
.order_by(field.name)
|
||||
.values_list(field.name, flat=True))
|
||||
super(AllValuesFieldListFilter, self).__init__(
|
||||
field, request, params, model, admin_view, field_path)
|
||||
|
||||
def choices(self):
|
||||
yield {
|
||||
'selected': (self.lookup_exact_val is '' and self.lookup_isnull_val is ''),
|
||||
'query_string': self.query_string({}, [self.lookup_exact_name, self.lookup_isnull_name]),
|
||||
'display': _('All'),
|
||||
}
|
||||
include_none = False
|
||||
for val in self.lookup_choices:
|
||||
if val is None:
|
||||
include_none = True
|
||||
continue
|
||||
val = smart_text(val)
|
||||
yield {
|
||||
'selected': self.lookup_exact_val == val,
|
||||
'query_string': self.query_string({self.lookup_exact_name: val},
|
||||
[self.lookup_isnull_name]),
|
||||
'display': val,
|
||||
}
|
||||
if include_none:
|
||||
yield {
|
||||
'selected': bool(self.lookup_isnull_val),
|
||||
'query_string': self.query_string({self.lookup_isnull_name: 'True'},
|
||||
[self.lookup_exact_name]),
|
||||
'display': EMPTY_CHANGELIST_VALUE,
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
from django import forms
|
||||
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
|
||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
ERROR_MESSAGE = ugettext_lazy("Please enter the correct username and password "
|
||||
"for a staff account. Note that both fields are case-sensitive.")
|
||||
|
||||
|
||||
class AdminAuthenticationForm(AuthenticationForm):
|
||||
"""
|
||||
A custom authentication form used in the admin app.
|
||||
|
||||
"""
|
||||
this_is_the_login_form = forms.BooleanField(
|
||||
widget=forms.HiddenInput, initial=1,
|
||||
error_messages={'required': ugettext_lazy("Please log in again, because your session has expired.")})
|
||||
|
||||
def clean(self):
|
||||
username = self.cleaned_data.get('username')
|
||||
password = self.cleaned_data.get('password')
|
||||
message = ERROR_MESSAGE
|
||||
|
||||
if username and password:
|
||||
self.user_cache = authenticate(
|
||||
username=username, password=password)
|
||||
if self.user_cache is None:
|
||||
if u'@' in username:
|
||||
User = get_user_model()
|
||||
# Mistakenly entered e-mail address instead of username? Look it up.
|
||||
try:
|
||||
user = User.objects.get(email=username)
|
||||
except (User.DoesNotExist, User.MultipleObjectsReturned):
|
||||
# Nothing to do here, moving along.
|
||||
pass
|
||||
else:
|
||||
if user.check_password(password):
|
||||
message = _("Your e-mail address is not your username."
|
||||
" Try '%s' instead.") % user.username
|
||||
raise forms.ValidationError(message)
|
||||
elif not self.user_cache.is_active or not self.user_cache.is_staff:
|
||||
raise forms.ValidationError(message)
|
||||
return self.cleaned_data
|
@ -0,0 +1,113 @@
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import *
|
||||
from crispy_forms.bootstrap import *
|
||||
from crispy_forms.utils import render_field, flatatt, TEMPLATE_PACK
|
||||
|
||||
from crispy_forms import layout
|
||||
from crispy_forms import bootstrap
|
||||
|
||||
import math
|
||||
|
||||
|
||||
class Fieldset(layout.Fieldset):
|
||||
template = "xadmin/layout/fieldset.html"
|
||||
|
||||
def __init__(self, legend, *fields, **kwargs):
|
||||
self.description = kwargs.pop('description', None)
|
||||
self.collapsed = kwargs.pop('collapsed', None)
|
||||
super(Fieldset, self).__init__(legend, *fields, **kwargs)
|
||||
|
||||
|
||||
class Row(layout.Div):
|
||||
|
||||
def __init__(self, *fields, **kwargs):
|
||||
css_class = 'form-inline form-group'
|
||||
new_fields = [self.convert_field(f, len(fields)) for f in fields]
|
||||
super(Row, self).__init__(css_class=css_class, *new_fields, **kwargs)
|
||||
|
||||
def convert_field(self, f, counts):
|
||||
col_class = "col-sm-%d" % int(math.ceil(12 / counts))
|
||||
if not (isinstance(f, Field) or issubclass(f.__class__, Field)):
|
||||
f = layout.Field(f)
|
||||
if f.wrapper_class:
|
||||
f.wrapper_class += " %s" % col_class
|
||||
else:
|
||||
f.wrapper_class = col_class
|
||||
return f
|
||||
|
||||
|
||||
class Col(layout.Column):
|
||||
|
||||
def __init__(self, id, *fields, **kwargs):
|
||||
css_class = ['column', 'form-column', id, 'col col-sm-%d' %
|
||||
kwargs.get('span', 6)]
|
||||
if kwargs.get('horizontal'):
|
||||
css_class.append('form-horizontal')
|
||||
super(Col, self).__init__(css_class=' '.join(css_class), *
|
||||
fields, **kwargs)
|
||||
|
||||
|
||||
class Main(layout.Column):
|
||||
css_class = "column form-column main col col-sm-9 form-horizontal"
|
||||
|
||||
|
||||
class Side(layout.Column):
|
||||
css_class = "column form-column sidebar col col-sm-3"
|
||||
|
||||
|
||||
class Container(layout.Div):
|
||||
css_class = "form-container row clearfix"
|
||||
|
||||
|
||||
# Override bootstrap3
|
||||
class InputGroup(layout.Field):
|
||||
|
||||
template = "xadmin/layout/input_group.html"
|
||||
|
||||
def __init__(self, field, *args, **kwargs):
|
||||
self.field = field
|
||||
self.inputs = list(args)
|
||||
if '@@' not in args:
|
||||
self.inputs.append('@@')
|
||||
|
||||
self.input_size = None
|
||||
css_class = kwargs.get('css_class', '')
|
||||
if 'input-lg' in css_class:
|
||||
self.input_size = 'input-lg'
|
||||
if 'input-sm' in css_class:
|
||||
self.input_size = 'input-sm'
|
||||
|
||||
super(InputGroup, self).__init__(field, **kwargs)
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
classes = form.fields[self.field].widget.attrs.get('class', '')
|
||||
extra_context = {
|
||||
'inputs': self.inputs,
|
||||
'input_size': self.input_size,
|
||||
'classes': classes.replace('form-control', '')
|
||||
}
|
||||
if hasattr(self, 'wrapper_class'):
|
||||
extra_context['wrapper_class'] = self.wrapper_class
|
||||
|
||||
return render_field(
|
||||
self.field, form, form_style, context, template=self.template,
|
||||
attrs=self.attrs, template_pack=template_pack, extra_context=extra_context, **kwargs)
|
||||
|
||||
|
||||
class PrependedText(InputGroup):
|
||||
|
||||
def __init__(self, field, text, **kwargs):
|
||||
super(PrependedText, self).__init__(field, text, '@@', **kwargs)
|
||||
|
||||
|
||||
class AppendedText(InputGroup):
|
||||
|
||||
def __init__(self, field, text, **kwargs):
|
||||
super(AppendedText, self).__init__(field, '@@', text, **kwargs)
|
||||
|
||||
|
||||
class PrependedAppendedText(InputGroup):
|
||||
|
||||
def __init__(self, field, prepended_text=None, appended_text=None, *args, **kwargs):
|
||||
super(PrependedAppendedText, self).__init__(
|
||||
field, prepended_text, '@@', appended_text, **kwargs)
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,72 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Azd325 <tim.kleinschmidt@gmail.com>, 2013
|
||||
# Azd325 <tim.kleinschmidt@gmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: Azd325 <tim.kleinschmidt@gmail.com>\n"
|
||||
"Language-Team: German (Germany) (http://www.transifex.com/projects/p/xadmin/language/de_DE/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de_DE\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] "%(sel)s von %(cnt)s markiert"
|
||||
msgstr[1] "%(sel)s von %(cnt)s markiert"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr "Neues Element"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr "Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr "So Mo Di Mi Do Fr Sa So"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr "So Mo Di Mi Do Fr Sa So"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr "Januar Februar März April Mai Juni Juli August September Oktober November Dezember"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr "Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr "Heute"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr "%a %d %b %Y %T %Z"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr "vorm nachm"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr "vorm nachm"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr "%T"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,69 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
"December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,71 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# unaizalakain <unai@gisa-elkartea.org>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: unaizalakain <unai@gisa-elkartea.org>\n"
|
||||
"Language-Team: Basque (http://www.transifex.com/projects/p/xadmin/language/eu/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: eu\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] "%(cnt)stik %(sel)s aukeratua"
|
||||
msgstr[1] "%(cnt)stik %(sel)s aukeratuak"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr "Elementu Berria"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr "Igandea Astelehena Asteartea Asteazkena Osteguna Ostirala Larunbata Igandea"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr "Iga Atl Atr Atz Otg Otr Lar Iga"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr "Ig At Ar Az Og Or La Ig"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr "Urtarrila Otsaila Martxoa Apirila Maiatza Ekaina Uztaila Abuztua Iraila Urria Azaroa Abendua"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr "Urt Ots Mar Api Mai Eka Uzt Abu Ira Urr Aza Abe"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr "Gaur"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr "%a %d %b %Y %T %Z"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr "AM PM"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr "am pm"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr "%T"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,69 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/xadmin/language/id_ID/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: id_ID\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,69 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Japanese (http://www.transifex.com/projects/p/xadmin/language/ja/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ja\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,71 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Lithuanian (http://www.transifex.com/projects/p/xadmin/language/lt/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: lt\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,70 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/xadmin/language/nl_NL/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: nl_NL\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,83 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-xadmin\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-08-12 21:07+0200\n"
|
||||
"PO-Revision-Date: 2014-08-12 21:23+0100\n"
|
||||
"Last-Translator: Michał Szpadzik <mszpadzik@gmail.com>\n"
|
||||
"Language-Team: Polish translators <mszpadzik@gmail.com>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:11
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] "%(sel)s z %(cnt)s wybranych"
|
||||
msgstr[1] "%(sel)s z %(cnt)s wybranych"
|
||||
msgstr[2] "%(sel)s z %(cnt)s wybranych"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.quick-form.js:172
|
||||
msgid "Close"
|
||||
msgstr "Zamknij"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.quick-form.js:173
|
||||
msgid "Add"
|
||||
msgstr "Dodaj"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr "Nowy obiekt"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr "niedziela poniedziałek wtorek środa czwartek piątek sobota niedziela"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr "niedz. pon. wt. śr. czw. pt. sob. niedz."
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr "niedz. pn. wt. śr. czw. pt. sob. niedz."
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
"December"
|
||||
msgstr ""
|
||||
"styczeń luty marzec kwiecień maj czerwiec lipiec sierpień wrzesień "
|
||||
"październik "
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr "sty. lut. marz. kwie. maj czerw. lip. sier. wrze. paź. list. grudz."
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr "Dzisiaj"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr "%a %d %b %Y %T %Z"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr "AM PM"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr "am pm"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr "%T"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,71 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# korndorfer <codigo.aberto@dorfer.com.br>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: korndorfer <codigo.aberto@dorfer.com.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/xadmin/language/pt_BR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt_BR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] "%(sel)s de %(cnt)s selecionado"
|
||||
msgstr[1] "%(sel)s de %(cnt)s selecionados"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr "Novo Item"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr "Domingo Segunda Terça Quarta Quinta Sexta Sábado Domingo"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr "Dom Seg Ter Qua Qui Sex Sáb Dom"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr "Do Sg Te Qa Qi Sx Sa Do"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr "Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro Dezembro"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr "Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr "Hoje"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr "%a %d %b %Y %T %Z"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr "AM PM"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr "am pm"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr "%T"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,71 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-30 23:11+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/xadmin/language/ru_RU/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru_RU\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:20
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid ""
|
||||
"January February March April May June July August September October November"
|
||||
" December"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr ""
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,87 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# sshwsfc <sshwsfc@gmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: xadmin-core\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-05-22 16:02+0800\n"
|
||||
"PO-Revision-Date: 2013-11-20 12:41+0000\n"
|
||||
"Last-Translator: sshwsfc <sshwsfc@gmail.com>\n"
|
||||
"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/xadmin/language/zh_CN/)\n"
|
||||
"Language: zh_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: static/xadmin/js/xadmin.page.dashboard.js:14
|
||||
#: static/xadmin/js/xadmin.plugin.details.js:24
|
||||
#: static/xadmin/js/xadmin.plugin.quick-form.js:172
|
||||
msgid "Close"
|
||||
msgstr "关闭"
|
||||
|
||||
#: static/xadmin/js/xadmin.page.dashboard.js:15
|
||||
msgid "Save changes"
|
||||
msgstr "保存修改"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.actions.js:11
|
||||
msgid "%(sel)s of %(cnt)s selected"
|
||||
msgid_plural "%(sel)s of %(cnt)s selected"
|
||||
msgstr[0] "选中了 %(cnt)s 个中的 %(sel)s 个"
|
||||
msgstr[1] "选中了 %(cnt)s 个中的 %(sel)s 个"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.details.js:25
|
||||
msgid "Edit"
|
||||
msgstr "编辑"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.quick-form.js:173
|
||||
msgid "Add"
|
||||
msgstr "添加"
|
||||
|
||||
#: static/xadmin/js/xadmin.plugin.revision.js:25
|
||||
msgid "New Item"
|
||||
msgstr "新项目"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:32
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
||||
msgstr "星期日 星期一 星期二 星期三 星期四 星期五 星期六"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:33
|
||||
msgid "Sun Mon Tue Wed Thu Fri Sat Sun"
|
||||
msgstr "日 一 二 三 四 五 六"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:34
|
||||
msgid "Su Mo Tu We Th Fr Sa Su"
|
||||
msgstr "日 一 二 三 四 五 六"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:35
|
||||
msgid "January February March April May June July August September October November December"
|
||||
msgstr "一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:36
|
||||
msgid "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
|
||||
msgstr "一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一 十二"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:37
|
||||
msgid "Today"
|
||||
msgstr "今天"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:38
|
||||
msgid "%a %d %b %Y %T %Z"
|
||||
msgstr ""
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:39
|
||||
msgid "AM PM"
|
||||
msgstr "上午 下午"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:40
|
||||
msgid "am pm"
|
||||
msgstr "上午 下午"
|
||||
|
||||
#: static/xadmin/js/xadmin.widget.datetime.js:43
|
||||
msgid "%T"
|
||||
msgstr "%T"
|
@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.2 on 2016-03-20 13:46
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL)
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Bookmark',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=128, verbose_name='Title')),
|
||||
('url_name', models.CharField(max_length=64, verbose_name='Url Name')),
|
||||
('query', models.CharField(blank=True, max_length=1000, verbose_name='Query String')),
|
||||
('is_share', models.BooleanField(default=False, verbose_name='Is Shared')),
|
||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Bookmark',
|
||||
'verbose_name_plural': 'Bookmarks',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserSettings',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.CharField(max_length=256, verbose_name='Settings Key')),
|
||||
('value', models.TextField(verbose_name='Settings Content')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'User Setting',
|
||||
'verbose_name_plural': 'User Settings',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserWidget',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('page_id', models.CharField(max_length=256, verbose_name='Page')),
|
||||
('widget_type', models.CharField(max_length=50, verbose_name='Widget Type')),
|
||||
('value', models.TextField(verbose_name='Widget Params')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'User Widget',
|
||||
'verbose_name_plural': 'User Widgets',
|
||||
},
|
||||
),
|
||||
]
|
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.7 on 2016-07-15 05:50
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('xadmin', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Log',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('action_time', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='action time')),
|
||||
('ip_addr', models.GenericIPAddressField(blank=True, null=True, verbose_name='action ip')),
|
||||
('object_id', models.TextField(blank=True, null=True, verbose_name='object id')),
|
||||
('object_repr', models.CharField(max_length=200, verbose_name='object repr')),
|
||||
('action_flag', models.PositiveSmallIntegerField(verbose_name='action flag')),
|
||||
('message', models.TextField(blank=True, verbose_name='change message')),
|
||||
('content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contenttypes.ContentType', verbose_name='content type')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('-action_time',),
|
||||
'verbose_name': 'log entry',
|
||||
'verbose_name_plural': 'log entries',
|
||||
},
|
||||
),
|
||||
]
|
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.7 on 2016-07-15 06:00
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('xadmin', '0002_log'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='log',
|
||||
name='action_flag',
|
||||
field=models.CharField(max_length=32, verbose_name='action flag'),
|
||||
),
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,190 @@
|
||||
import json
|
||||
import django
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_lazy as _, ugettext
|
||||
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.db.models.signals import post_migrate
|
||||
from django.contrib.auth.models import Permission
|
||||
|
||||
import datetime
|
||||
import decimal
|
||||
from xadmin.util import quote
|
||||
|
||||
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
|
||||
content types.
|
||||
"""
|
||||
# for each of our content types
|
||||
for content_type in ContentType.objects.all():
|
||||
# build our permission slug
|
||||
codename = "view_%s" % content_type.model
|
||||
|
||||
# if it doesn't exist..
|
||||
if not Permission.objects.filter(content_type=content_type, codename=codename):
|
||||
# add it
|
||||
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
|
||||
|
||||
# check for all our view permissions after a syncdb
|
||||
post_migrate.connect(add_view_permissions)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Bookmark(models.Model):
|
||||
title = models.CharField(_(u'Title'), max_length=128)
|
||||
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, on_delete=models.CASCADE)
|
||||
query = models.CharField(_(u'Query String'), max_length=1000, blank=True)
|
||||
is_share = models.BooleanField(_(u'Is Shared'), default=False)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
base_url = reverse(self.url_name)
|
||||
if self.query:
|
||||
base_url = base_url + '?' + self.query
|
||||
return base_url
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'Bookmark')
|
||||
verbose_name_plural = _('Bookmarks')
|
||||
|
||||
|
||||
class JSONEncoder(DjangoJSONEncoder):
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, datetime.datetime):
|
||||
return o.strftime('%Y-%m-%d %H:%M:%S')
|
||||
elif isinstance(o, datetime.date):
|
||||
return o.strftime('%Y-%m-%d')
|
||||
elif isinstance(o, decimal.Decimal):
|
||||
return str(o)
|
||||
elif isinstance(o, ModelBase):
|
||||
return '%s.%s' % (o._meta.app_label, o._meta.model_name)
|
||||
else:
|
||||
try:
|
||||
return super(JSONEncoder, self).default(o)
|
||||
except Exception:
|
||||
return smart_text(o)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class UserSettings(models.Model):
|
||||
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'))
|
||||
|
||||
def json_value(self):
|
||||
return json.loads(self.value)
|
||||
|
||||
def set_json(self, obj):
|
||||
self.value = json.dumps(obj, cls=JSONEncoder, ensure_ascii=False)
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s" % (self.user, self.key)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'User Setting')
|
||||
verbose_name_plural = _('User Settings')
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class UserWidget(models.Model):
|
||||
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"))
|
||||
|
||||
def get_value(self):
|
||||
value = json.loads(self.value)
|
||||
value['id'] = self.id
|
||||
value['type'] = self.widget_type
|
||||
return value
|
||||
|
||||
def set_value(self, obj):
|
||||
self.value = json.dumps(obj, cls=JSONEncoder, ensure_ascii=False)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
created = self.pk is None
|
||||
super(UserWidget, self).save(*args, **kwargs)
|
||||
if created:
|
||||
try:
|
||||
portal_pos = UserSettings.objects.get(
|
||||
user=self.user, key="dashboard:%s:pos" % self.page_id)
|
||||
portal_pos.value = "%s,%s" % (self.pk, portal_pos.value) if portal_pos.value else self.pk
|
||||
portal_pos.save()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s widget" % (self.user, self.widget_type)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'User Widget')
|
||||
verbose_name_plural = _('User Widgets')
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Log(models.Model):
|
||||
action_time = models.DateTimeField(
|
||||
_('action time'),
|
||||
default=timezone.now,
|
||||
editable=False,
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
AUTH_USER_MODEL,
|
||||
models.CASCADE,
|
||||
verbose_name=_('user'),
|
||||
)
|
||||
ip_addr = models.GenericIPAddressField(_('action ip'), blank=True, null=True)
|
||||
content_type = models.ForeignKey(
|
||||
ContentType,
|
||||
models.SET_NULL,
|
||||
verbose_name=_('content type'),
|
||||
blank=True, null=True,
|
||||
)
|
||||
object_id = models.TextField(_('object id'), blank=True, null=True)
|
||||
object_repr = models.CharField(_('object repr'), max_length=200)
|
||||
action_flag = models.CharField(_('action flag'), max_length=32)
|
||||
message = models.TextField(_('change message'), blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('log entry')
|
||||
verbose_name_plural = _('log entries')
|
||||
ordering = ('-action_time',)
|
||||
|
||||
def __repr__(self):
|
||||
return smart_text(self.action_time)
|
||||
|
||||
def __str__(self):
|
||||
if self.action_flag == 'create':
|
||||
return ugettext('Added "%(object)s".') % {'object': self.object_repr}
|
||||
elif self.action_flag == 'change':
|
||||
return ugettext('Changed "%(object)s" - %(changes)s') % {
|
||||
'object': self.object_repr,
|
||||
'changes': self.message,
|
||||
}
|
||||
elif self.action_flag == 'delete' and self.object_repr:
|
||||
return ugettext('Deleted "%(object)s."') % {'object': self.object_repr}
|
||||
|
||||
return self.message
|
||||
|
||||
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)
|
@ -0,0 +1,41 @@
|
||||
|
||||
PLUGINS = (
|
||||
'actions',
|
||||
'filters',
|
||||
'bookmark',
|
||||
'export',
|
||||
'layout',
|
||||
'refresh',
|
||||
'details',
|
||||
'editable',
|
||||
'relate',
|
||||
'chart',
|
||||
'ajax',
|
||||
'relfield',
|
||||
'inline',
|
||||
'topnav',
|
||||
'portal',
|
||||
'quickform',
|
||||
'wizard',
|
||||
'images',
|
||||
'auth',
|
||||
'multiselect',
|
||||
'themes',
|
||||
'aggregation',
|
||||
# 'mobile',
|
||||
'passwords',
|
||||
'sitemenu',
|
||||
'language',
|
||||
'quickfilter',
|
||||
'sortablelist',
|
||||
'importexport'
|
||||
)
|
||||
|
||||
|
||||
def register_builtin_plugins(site):
|
||||
from importlib import import_module
|
||||
from django.conf import settings
|
||||
|
||||
exclude_plugins = getattr(settings, 'XADMIN_EXCLUDE_PLUGINS', [])
|
||||
|
||||
[import_module('xadmin.plugins.%s' % plugin) for plugin in PLUGINS if plugin not in exclude_plugins]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue