Files
mayan-edms/mayan/apps/common/classes.py
Roberto Rosario 4d53c9aec7 Code clean up.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
2018-09-17 02:54:47 -04:00

403 lines
11 KiB
Python

from __future__ import unicode_literals
import hashlib
from django.apps import apps
from django.conf import settings
from django.db import models
from django.template import loader
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.translation import ugettext
@python_2_unicode_compatible
class Collection(object):
_registry = []
@classmethod
def get_all(cls):
return sorted(cls._registry, key=lambda entry: entry._order)
def __init__(self, label, icon=None, icon_class=None, link=None, queryset=None, model=None, order=None):
self._label = label
self._icon = icon
self._icon_class = icon_class
self._link = link
self._queryset = queryset
self._model = model
self._order = order or 99
self.__class__._registry.append(self)
def __str__(self):
return force_text(self.label)
def resolve(self):
self.children = self._get_children()
self.icon = self._icon
self.label = self._label
self.url = None
if self._link:
self.icon = getattr(self._link, 'icon', self._icon)
self.icon_class = getattr(self._link, 'icon_class', self._icon_class)
self.url = reverse(viewname=self._link.view, args=self._link.args)
return ''
def _get_children(self):
if self._queryset:
return self._queryset
else:
if self._model:
return self._model.objects.all()
class Dashboard(object):
_registry = {}
@classmethod
def get(cls, name):
return cls._registry[name]
def __init__(self, name, label):
self.name = name
self.label = label
self.widgets = {}
self.removed_widgets = []
self.__class__._registry[name] = self
def add_widget(self, widget, order=0):
self.widgets[widget] = {'widget': widget, 'order': order}
def get_widgets(self):
"""
Returns a list of widgets sorted by their 'order'.
If two or more widgets have the same 'order', sort by label.
"""
return map(
lambda x: x['widget'],
filter(
lambda x: x['widget'] not in self.removed_widgets,
sorted(
self.widgets.values(),
key=lambda x: (x['order'], x['widget'].label)
)
)
)
def remove_widget(self, widget):
self.removed_widgets.append(widget)
def render(self, request):
rendered_widgets = [widget().render(request=request) for widget in self.get_widgets()]
return loader.render_to_string(
template_name='dashboard/dashboard.html', context={
'widgets': rendered_widgets
}
)
class BaseDashboardWidget(object):
_registry = {}
context = {}
template_name = None
@classmethod
def get(cls, name):
return cls._registry[name]
@classmethod
def get_all(cls):
return cls._registry.items()
@classmethod
def register(cls, klass):
cls._registry[klass.name] = klass
def get_context(self):
return self.context
def render(self, request):
if self.template_name:
return loader.render_to_string(
template_name=self.template_name, context=self.get_context(),
)
class DashboardWidgetNumeric(BaseDashboardWidget):
count = 0
icon_class = None
label = None
link = None
template_name = 'dashboard/numeric_widget.html'
def get_context(self):
return {
'count': self.count,
'icon_class': self.icon_class,
'label': self.label,
'link': self.link,
}
@python_2_unicode_compatible
class ErrorLogNamespace(object):
def __init__(self, name, label=None):
self.name = name
self.label = label or name
def __str__(self):
return force_text(self.label)
def create(self, obj, result):
obj.error_logs.create(namespace=self.name, result=result)
def all(self):
ErrorLogEntry = apps.get_model(
app_label='common', model_name='ErrorLogEntry'
)
return ErrorLogEntry.objects.filter(namespace=self.name)
class MissingItem(object):
_registry = []
@classmethod
def get_all(cls):
return cls._registry
def __init__(self, label, condition, description, view):
self.label = label
self.condition = condition
self.description = description
self.view = view
self.__class__._registry.append(self)
@python_2_unicode_compatible
class ModelAttribute(object):
_registry = {}
@classmethod
def get_for(cls, model):
try:
return cls._registry[model]
except KeyError:
# We were passed a model instance, try again using the model of
# the instance
# If we are already in the model class, exit with an error
if model.__class__ == models.base.ModelBase:
raise
return cls.get_for(model=type(model))
@classmethod
def get_choices_for(cls, model):
return [
(attribute.name, attribute) for attribute in cls.get_for(model)
]
@classmethod
def get_help_text_for(cls, model, show_name=False):
result = []
for count, attribute in enumerate(cls.get_for(model=model), 1):
result.append(
'{}) {}'.format(
count, force_text(attribute.get_display(show_name=show_name))
)
)
return ' '.join(
[ugettext('Available attributes: \n'), '\n'.join(result)]
)
def __init__(self, model, name, label=None, description=None):
self.model = model
self.label = label
self.name = name
self.description = description
self._registry.setdefault(model, [])
self._registry[model].append(self)
def __str__(self):
return self.get_display()
def get_display(self, show_name=False):
if self.description:
return '{} - {}'.format(
self.name if show_name else self.label, self.description
)
else:
return force_text(self.name if show_name else self.label)
class ModelField(ModelAttribute):
"""Subclass to handle model database fields"""
_registry = {}
@classmethod
def get_help_text_for(cls, model, show_name=False):
result = []
for count, model_field in enumerate(cls.get_for(model=model), 1):
result.append(
'{}) {} - {}'.format(
count,
model_field.name if show_name else model_field.label,
model_field.description
)
)
return ' '.join(
[ugettext('Available fields: \n'), '\n'.join(result)]
)
def __init__(self, *args, **kwargs):
super(ModelField, self).__init__(*args, **kwargs)
self._final_model_verbose_name = None
if not self.label:
self.label = self.get_field_attribute(
attribute='verbose_name'
)
if self.label != self._final_model_verbose_name:
self.label = '{} {}'.format(
self._final_model_verbose_name, self.label
)
if not self.description:
self.description = self.get_field_attribute(
attribute='help_text'
)
def get_field_attribute(self, attribute, model=None, field_name=None):
if not model:
model = self.model
if not field_name:
field_name = self.name
parts = field_name.split('__')
if len(parts) > 1:
return self.get_field_attribute(
model=model._meta.get_field(parts[0]).related_model,
field_name='__'.join(parts[1:]), attribute=attribute
)
else:
self._final_model_verbose_name = model._meta.verbose_name
return getattr(
model._meta.get_field(field_name=field_name),
attribute
)
class ModelProperty(object):
_registry = []
@classmethod
def get_for(cls, model):
result = []
for klass in cls._registry:
result.extend(klass.get_for(model=model))
return result
@classmethod
def get_choices_for(cls, model):
result = []
for klass in cls._registry:
result.extend(klass.get_choices_for(model=model))
return result
@classmethod
def get_help_text_for(cls, model, show_name=False):
result = []
for klass in cls._registry:
result.append(
klass.get_help_text_for(model=model, show_name=show_name)
)
return '\n'.join(result)
@classmethod
def register(cls, klass):
cls._registry.append(klass)
class Package(object):
_registry = []
@classmethod
def get_all(cls):
return cls._registry
def __init__(self, label, license_text):
self.label = label
self.license_text = license_text
self.__class__._registry.append(self)
class PropertyHelper(object):
"""
Makes adding fields using __class__.add_to_class easier.
Each subclass must implement the `constructor` and the `get_result`
method.
"""
@staticmethod
@property
def constructor(source_object):
return PropertyHelper(source_object)
def __init__(self, instance):
self.instance = instance
def __getattr__(self, name):
return self.get_result(name=name)
def get_result(self, name):
"""
The method that produces the actual result. Must be implemented
by each subclass.
"""
raise NotImplementedError
class Template(object):
_registry = {}
@classmethod
def get(cls, name):
return cls._registry[name]
def __init__(self, name, template_name):
self.name = name
self.template_name = template_name
self.__class__._registry[name] = self
def get_absolute_url(self):
return reverse('rest_api:template-detail', args=(self.name,))
def render(self, request):
context = {
'home_view': settings.HOME_VIEW,
}
result = TemplateResponse(
request=request,
template=self.template_name,
context=context,
).render()
self.html = result.content
self.hex_hash = hashlib.sha256(result.content).hexdigest()
return self
ModelProperty.register(ModelAttribute)
ModelProperty.register(ModelField)