Finished converting grouping app to the linking app

This commit is contained in:
Roberto Rosario
2011-11-19 02:01:55 -04:00
parent d358bd991a
commit fbad8375b3
26 changed files with 106 additions and 102 deletions
+44
View File
@@ -0,0 +1,44 @@
from django.utils.translation import ugettext_lazy as _
from navigation.api import register_links, register_sidebar_template
from permissions.api import register_permission, set_namespace_title
from project_setup.api import register_setup
from documents.literals import PERMISSION_DOCUMENT_VIEW
from documents.models import Document
from linking.models import SmartLink, SmartLinkCondition
PERMISSION_SMART_LINK_VIEW = {'namespace': 'linking', 'name': 'group_view', 'label': _(u'View existing smart links')}
PERMISSION_SMART_LINK_CREATE = {'namespace': 'linking', 'name': 'group_create', 'label': _(u'Create new smart links')}
PERMISSION_SMART_LINK_DELETE = {'namespace': 'linking', 'name': 'group_delete', 'label': _(u'Delete smart links')}
PERMISSION_SMART_LINK_EDIT = {'namespace': 'linking', 'name': 'group_edit', 'label': _(u'Edit smart links')}
set_namespace_title('linking', _(u'Smart links'))
register_permission(PERMISSION_SMART_LINK_VIEW)
register_permission(PERMISSION_SMART_LINK_CREATE)
register_permission(PERMISSION_SMART_LINK_DELETE)
register_permission(PERMISSION_SMART_LINK_EDIT)
smart_link_instance_view_link = {'text': _(u'smart links actions'), 'view': 'smart_link_instance_view', 'famfam': 'page_link', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
smart_link_instances_for_document = {'text': _(u'smart links'), 'view': 'smart_link_instances_for_document', 'args': 'object.pk', 'famfam': 'page_link', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_groups_setup = {'text': _(u'smart links'), 'view': 'document_group_list', 'icon': 'link.png', 'permissions': [PERMISSION_SMART_LINK_CREATE]}
document_group_list = {'text': _(u'smart links list'), 'view': 'document_group_list', 'famfam': 'link', 'permissions': [PERMISSION_SMART_LINK_CREATE]}
document_group_create = {'text': _(u'create new smart link'), 'view': 'document_group_create', 'famfam': 'link_add', 'permissions': [PERMISSION_SMART_LINK_CREATE]}
document_group_edit = {'text': _(u'edit'), 'view': 'document_group_edit', 'args': 'smart_link.pk', 'famfam': 'link_edit', 'permissions': [PERMISSION_SMART_LINK_EDIT]}
document_group_delete = {'text': _(u'delete'), 'view': 'document_group_delete', 'args': 'smart_link.pk', 'famfam': 'link_delete', 'permissions': [PERMISSION_SMART_LINK_DELETE]}
smart_link_condition_list = {'text': _(u'conditions'), 'view': 'smart_link_condition_list', 'args': 'smart_link.pk', 'famfam': 'cog', 'permissions': [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_CREATE]}
smart_link_condition_create = {'text': _(u'create condition'), 'view': 'smart_link_condition_create', 'args': 'smart_link.pk', 'famfam': 'cog_add', 'permissions': [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]}
smart_link_condition_edit = {'text': _(u'edit'), 'view': 'smart_link_condition_edit', 'args': 'condition.pk', 'famfam': 'cog_edit', 'permissions': [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]}
smart_link_condition_delete = {'text': _(u'delete'), 'view': 'smart_link_condition_delete', 'args': 'condition.pk', 'famfam': 'cog_delete', 'permissions': [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]}
register_links(Document, [smart_link_instances_for_document], menu_name='form_header')
register_links(SmartLink, [document_group_edit, document_group_delete, smart_link_condition_list])
register_links(SmartLinkCondition, [smart_link_condition_edit, smart_link_condition_delete])
register_links(['document_group_list', 'document_group_create', 'document_group_edit', 'document_group_delete', 'smart_link_condition_list', 'smart_link_condition_create', 'smart_link_condition_edit', 'smart_link_condition_delete'], [document_group_list, document_group_create], menu_name='sidebar')
register_links(['smart_link_condition_list', 'smart_link_condition_create', 'smart_link_condition_edit', 'smart_link_condition_delete'], [smart_link_condition_create], menu_name='sidebar')
register_setup(document_groups_setup)
register_sidebar_template(['document_group_list'], 'smart_links_help.html')
+16
View File
@@ -0,0 +1,16 @@
from django.contrib import admin
from linking.models import SmartLink, SmartLinkCondition
class SmartLinkConditionInline(admin.StackedInline):
model = SmartLinkCondition
extra = 1
classes = ('collapse-open',)
allow_add = True
class SmartLinkAdmin(admin.ModelAdmin):
inlines = [SmartLinkConditionInline]
admin.site.register(SmartLink, SmartLinkAdmin)
View File
+13
View File
@@ -0,0 +1,13 @@
'''Configuration options for the linking app'''
from django.utils.translation import ugettext_lazy as _
from smart_settings.api import register_settings
register_settings(
namespace=u'linking',
module=u'linking.conf.settings',
settings=[
{'name': u'SHOW_EMPTY_SMART_LINKS', 'global_name': u'LINKING_SHOW_EMPTY_SMART_LINKS', 'default': True, 'description': _(u'Show smart link that don\'t return any documents.')},
]
)
+122
View File
@@ -0,0 +1,122 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.template.defaultfilters import capfirst
from django.conf import settings
from tags.widgets import get_tags_inline_widget
from linking.models import SmartLink, SmartLinkCondition
class SmartLinkForm(forms.ModelForm):
class Meta:
model = SmartLink
class SmartLinkConditionForm(forms.ModelForm):
class Meta:
model = SmartLinkCondition
exclude = ('smart_link',)
class SmartLinkImageWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None):
output = []
# TODO: convert to navigation app
if value['links']:
output.append(u'<div class="group navform wat-cf">')
for link in value['links']:
output.append(u'''
<button class="button" type="submit" name="action" value="%(action)s">
<span class="famfam active famfam-%(famfam)s"></span>%(text)s
</button>
''' % {
'famfam': link.get('famfam', u'link'),
'text': capfirst(link['text']),
'action': reverse(link.get('view'), args=[value['current_document'].pk, value['group'].pk])
})
output.append(u'</div>')
output.append(u'<div style="white-space:nowrap; overflow: auto;">')
for document in value['group_data']:
tags_template = get_tags_inline_widget(document)
try:
document.get_valid_image()
template = u'''<div style="display: inline-block; margin: 0px 10px 10px 10px; %(current)s">
<div class="tc">%(document_name)s</div>
<div class="tc">%(page_string)s: %(document_pages)d</div>
%(tags_template)s
<div class="tc">
<a rel="group_%(group_id)d_documents_gallery" class="fancybox-noscaling" href="%(view_url)s">
<img class="lazy-load" style="border: 1px solid black; margin: 10px;" src="%(static_url)s/images/ajax-loader.gif" data-href="%(img)s" alt="%(string)s" />
<noscript>
<img style="border: 1px solid black; margin: 10px;" src="%(img)s" alt="%(string)s" />
</noscript>
</a>
</div>
<div class="tc">
<a href="%(url)s"><span class="famfam active famfam-page_go"></span>%(details_string)s</a>
</div>
</div>'''
except:
template = u'''<div style="display: inline-block; margin: 0px 10px 10px 10px; %(current)s">
<div class="tc">%(document_name)s</div>
<div class="tc">%(page_string)s: %(document_pages)d</div>
%(tags_template)s
<div class="tc">
<img class="lazy-load" style="border: 1px solid black; margin: 10px;" src="%(static_url)s/images/ajax-loader.gif" data-href="%(img)s" alt="%(string)s" />
<noscript>
<img style="border: 1px solid black; margin: 10px;" src="%(img)s" alt="%(string)s" />
</noscript>
</div>
<div class="tc">
<a href="%(url)s"><span class="famfam active famfam-page_go"></span>%(details_string)s</a>
</div>
</div>'''
output.append(template % {
'url': reverse('document_view_simple', args=[document.pk]),
'img': reverse('document_preview_multipage', args=[document.pk]),
'current': u'border: 5px solid black; padding: 3px;' if value['current_document'] == document else u'',
'view_url': reverse('document_display', args=[document.pk]),
'document_pages': document.documentpage_set.count(),
'page_string': ugettext(u'Pages'),
'details_string': ugettext(u'Select'),
'group_id': value['group'].pk,
'document_name': document,
'static_url': settings.STATIC_URL,
'tags_template': tags_template if tags_template else u'',
'string': _(u'smart links'),
})
output.append(u'</div>')
output.append(
u'<br /><span class="famfam active famfam-magnifier"></span>%s' %
ugettext(u'Click on the image for full size view of the first page.'))
return mark_safe(u''.join(output))
class SmartLinkInstanceForm(forms.Form):
def __init__(self, *args, **kwargs):
smart_link_instances = kwargs.pop('smart_link_instances', None)
links = kwargs.pop('links', None)
current_document = kwargs.pop('current_document', None)
super(SmartLinkInstanceForm, self).__init__(*args, **kwargs)
for smart_link_instance, data in smart_link_instances.items():
self.fields['preview-%s' % smart_link_instance] = forms.CharField(
widget=SmartLinkImageWidget(),
label=u'%s (%d)' % (unicode(data['title']), len(data['documents'])),
required=False,
initial={
'group': smart_link_instance,
'group_data': data['documents'],
'current_document': current_document,
'links': links
}
)
+27
View File
@@ -0,0 +1,27 @@
from django.utils.translation import ugettext_lazy as _
INCLUSION_AND = u'&'
INCLUSION_OR = u'|'
INCLUSION_CHOICES = (
(INCLUSION_AND, _(u'and')),
(INCLUSION_OR, _(u'or')),
)
OPERATOR_CHOICES = (
(u'exact', _(u'is equal to')),
(u'iexact', _(u'is equal to (case insensitive)')),
(u'contains', _(u'contains')),
(u'icontains', _(u'contains (case insensitive)')),
(u'in', _(u'is in')),
(u'gt', _(u'is greater than')),
(u'gte', _(u'is greater than or equal to')),
(u'lt', _(u'is less than')),
(u'lte', _(u'is less than or equal to')),
(u'startswith', _(u'starts with')),
(u'istartswith', _(u'starts with (case insensitive)')),
(u'endswith', _(u'ends with')),
(u'iendswith', _(u'ends with (case insensitive)')),
(u'regex', _(u'is in regular expression')),
(u'iregex', _(u'is in regular expression (case insensitive)')),
)
@@ -0,0 +1,198 @@
# 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: 2011-09-29 18:45-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: __init__.py:8
msgid "group actions"
msgstr ""
#: __init__.py:9
msgid "groups"
msgstr ""
#: forms.py:55
msgid "Pages"
msgstr ""
#: forms.py:56
msgid "Select"
msgstr ""
#: forms.py:61
msgid "group document"
msgstr ""
#: forms.py:66
msgid "Click on the image for full size view of the first page."
msgstr ""
#: literals.py:7
msgid "and"
msgstr ""
#: literals.py:8
msgid "or"
msgstr ""
#: literals.py:12
msgid "is equal to"
msgstr ""
#: literals.py:13
msgid "is equal to (case insensitive)"
msgstr ""
#: literals.py:14
msgid "contains"
msgstr ""
#: literals.py:15
msgid "contains (case insensitive)"
msgstr ""
#: literals.py:16
msgid "is in"
msgstr ""
#: literals.py:17
msgid "is greater than"
msgstr ""
#: literals.py:18
msgid "is greater than or equal to"
msgstr ""
#: literals.py:19
msgid "is less than"
msgstr ""
#: literals.py:20
msgid "is less than or equal to"
msgstr ""
#: literals.py:21
msgid "starts with"
msgstr ""
#: literals.py:22
msgid "starts with (case insensitive)"
msgstr ""
#: literals.py:23
msgid "ends with"
msgstr ""
#: literals.py:24
msgid "ends with (case insensitive)"
msgstr ""
#: literals.py:25
msgid "is in regular expression"
msgstr ""
#: literals.py:26
msgid "is in regular expression (case insensitive)"
msgstr ""
#: models.py:10
msgid "title"
msgstr ""
#: models.py:11
msgid "dynamic title"
msgstr ""
#: models.py:12 models.py:33
msgid "enabled"
msgstr ""
#: models.py:20 models.py:25
msgid "document group"
msgstr ""
#: models.py:21
msgid "document groups"
msgstr ""
#: models.py:26
msgid "The inclusion is ignored for the first item."
msgstr ""
#: models.py:27
msgid "foreign document data"
msgstr ""
#: models.py:27
msgid ""
"This represents the metadata of all other documents. Available objects: "
"`document.<attribute>` and `metadata.<metadata_type_name>`."
msgstr ""
#: models.py:31
msgid "expression"
msgstr ""
#: models.py:31
msgid ""
"This expression will be evaluated against the current selected document. "
"The document metadata is available as variables `metadata` and document "
"properties under the variable `document`."
msgstr ""
#: models.py:32
msgid "negated"
msgstr ""
#: models.py:32
msgid "Inverts the logic of the operator."
msgstr ""
#: models.py:36
msgid "not"
msgstr ""
#: models.py:39
msgid "group item"
msgstr ""
#: models.py:40
msgid "group items"
msgstr ""
#: views.py:21
msgid "No action selected."
msgstr ""
#: views.py:34
#, python-format
msgid "documents in group: %(group)s"
msgstr ""
#: views.py:50
#, python-format
msgid "Document group query error: %s"
msgstr ""
#: views.py:61
#, python-format
msgid "document groups (%s)"
msgstr ""
#: views.py:75
msgid "There no defined groups for the current document."
msgstr ""
Binary file not shown.
@@ -0,0 +1,208 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-09-29 18:45-0400\n"
"PO-Revision-Date: 2011-11-04 00:55+0000\n"
"Last-Translator: rosarior <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/mayan-edms/team/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:8
msgid "group actions"
msgstr "acciones de grupo"
#: __init__.py:9
msgid "groups"
msgstr "grupos"
#: forms.py:55
msgid "Pages"
msgstr "Páginas"
#: forms.py:56
msgid "Select"
msgstr "Seleccionar"
#: forms.py:61
msgid "group document"
msgstr "documento del grupo"
#: forms.py:66
msgid "Click on the image for full size view of the first page."
msgstr ""
"Haga clic en la imagen para ver el tamaño completo de la primera página."
#: literals.py:7
msgid "and"
msgstr "y"
#: literals.py:8
msgid "or"
msgstr "o"
#: literals.py:12
msgid "is equal to"
msgstr "es igual a"
#: literals.py:13
msgid "is equal to (case insensitive)"
msgstr "es igual a (mayúsculas y minúsculas)"
#: literals.py:14
msgid "contains"
msgstr "contiene"
#: literals.py:15
msgid "contains (case insensitive)"
msgstr "contiene (mayúsculas y minúsculas)"
#: literals.py:16
msgid "is in"
msgstr "está en"
#: literals.py:17
msgid "is greater than"
msgstr "es mayor que"
#: literals.py:18
msgid "is greater than or equal to"
msgstr "es mayor o igual a"
#: literals.py:19
msgid "is less than"
msgstr "es menor que"
#: literals.py:20
msgid "is less than or equal to"
msgstr "es menor o igual a"
#: literals.py:21
msgid "starts with"
msgstr "comienza con"
#: literals.py:22
msgid "starts with (case insensitive)"
msgstr "comienza con (mayúsculas y minúsculas)"
#: literals.py:23
msgid "ends with"
msgstr "termina con"
#: literals.py:24
msgid "ends with (case insensitive)"
msgstr "termina con (mayúsculas y minúsculas)"
#: literals.py:25
msgid "is in regular expression"
msgstr "está en la expresión regular"
#: literals.py:26
msgid "is in regular expression (case insensitive)"
msgstr "está en la expresión regular (mayúsculas y minúsculas)"
#: models.py:10
msgid "title"
msgstr "título"
#: models.py:11
msgid "dynamic title"
msgstr "título dinámico"
#: models.py:12 models.py:33
msgid "enabled"
msgstr "habilitado"
#: models.py:20 models.py:25
msgid "document group"
msgstr "grupo de documento"
#: models.py:21
msgid "document groups"
msgstr "grupos de documentos"
#: models.py:26
msgid "The inclusion is ignored for the first item."
msgstr "La inclusión es ignorada para el primer artículo."
#: models.py:27
msgid "foreign document data"
msgstr "datos de documento foráneo"
#: models.py:27
msgid ""
"This represents the metadata of all other documents. Available objects: "
"`document.<attribute>` and `metadata.<metadata_type_name>`."
msgstr ""
"Esto representa los metadatos de todos los demás documentos. Objetos "
"disponibles: `document.<attributo>` y `metadata.<nombre de tipo de "
"metadata>`."
#: models.py:31
msgid "expression"
msgstr "expresión"
#: models.py:31
msgid ""
"This expression will be evaluated against the current selected document. "
"The document metadata is available as variables `metadata` and document "
"properties under the variable `document`."
msgstr ""
"Esta expresión sera evaluada con respecto al documento seleccionado actual."
" Los metadatos del documento están disponible como variables `metadata` y "
"las propiedades del documento en la variable `document`."
#: models.py:32
msgid "negated"
msgstr "negado"
#: models.py:32
msgid "Inverts the logic of the operator."
msgstr "Invierte la lógica del operador."
#: models.py:36
msgid "not"
msgstr "no"
#: models.py:39
msgid "group item"
msgstr "artículo del grupo"
#: models.py:40
msgid "group items"
msgstr "artículo del grupo"
#: views.py:21
msgid "No action selected."
msgstr "Ninguna acción seleccionada."
#: views.py:34
#, python-format
msgid "documents in group: %(group)s"
msgstr "documentos en el grupo: %(group)s "
#: views.py:50
#, python-format
msgid "Document group query error: %s"
msgstr "Error en consulta de grupo de documentos: %s"
#: views.py:61
#, python-format
msgid "document groups (%s)"
msgstr "grupos de documentos (%s)"
#: views.py:75
msgid "There no defined groups for the current document."
msgstr "No hay grupos definidos para el documento actual."
Binary file not shown.
@@ -0,0 +1,206 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# <dev.emerson@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-09-29 18:45-0400\n"
"PO-Revision-Date: 2011-11-02 05:05+0000\n"
"Last-Translator: emersonsoares <dev.emerson@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/team/pt/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:8
msgid "group actions"
msgstr "ações do grupo"
#: __init__.py:9
msgid "groups"
msgstr "grupos"
#: forms.py:55
msgid "Pages"
msgstr "Páginas"
#: forms.py:56
msgid "Select"
msgstr "Selecionar"
#: forms.py:61
msgid "group document"
msgstr "agrupar documento"
#: forms.py:66
msgid "Click on the image for full size view of the first page."
msgstr "Clique na imagem para ver em tamanho grande a primeira página."
#: literals.py:7
msgid "and"
msgstr "e"
#: literals.py:8
msgid "or"
msgstr "ou"
#: literals.py:12
msgid "is equal to"
msgstr "é igual a"
#: literals.py:13
msgid "is equal to (case insensitive)"
msgstr "é igual a (case insensitive)"
#: literals.py:14
msgid "contains"
msgstr "contém"
#: literals.py:15
msgid "contains (case insensitive)"
msgstr "contém (case insensitive)"
#: literals.py:16
msgid "is in"
msgstr "está em"
#: literals.py:17
msgid "is greater than"
msgstr "é maior do que"
#: literals.py:18
msgid "is greater than or equal to"
msgstr "é maior ou igual a"
#: literals.py:19
msgid "is less than"
msgstr "é inferior a"
#: literals.py:20
msgid "is less than or equal to"
msgstr "é menor ou igual a"
#: literals.py:21
msgid "starts with"
msgstr "começa com"
#: literals.py:22
msgid "starts with (case insensitive)"
msgstr "começa com (case insensitive)"
#: literals.py:23
msgid "ends with"
msgstr "termina com"
#: literals.py:24
msgid "ends with (case insensitive)"
msgstr "termina com (case insensitive)"
#: literals.py:25
msgid "is in regular expression"
msgstr "está em expressão regular"
#: literals.py:26
msgid "is in regular expression (case insensitive)"
msgstr "está em expressão regular (case insensitive)"
#: models.py:10
msgid "title"
msgstr "título"
#: models.py:11
msgid "dynamic title"
msgstr "título dinâmico"
#: models.py:12 models.py:33
msgid "enabled"
msgstr "habilitado"
#: models.py:20 models.py:25
msgid "document group"
msgstr "grupo de documentos"
#: models.py:21
msgid "document groups"
msgstr "grupos de documentos"
#: models.py:26
msgid "The inclusion is ignored for the first item."
msgstr "A inclusão é ignorada para o primeiro item."
#: models.py:27
msgid "foreign document data"
msgstr "dados de documentos estrangeiros"
#: models.py:27
msgid ""
"This represents the metadata of all other documents. Available objects: "
"`document.<attribute>` and `metadata.<metadata_type_name>`."
msgstr ""
"Isto representa os metadados de todos os outros documentos. Objetos "
"disponíveis: `document. <attribute> ` e ` metadata. <metadata_type_name> `."
#: models.py:31
msgid "expression"
msgstr "expressão"
#: models.py:31
msgid ""
"This expression will be evaluated against the current selected document. "
"The document metadata is available as variables `metadata` and document "
"properties under the variable `document`."
msgstr ""
"Esta expressão será avaliada em relação ao documento atual selecionado. Os "
"metadados do documento estão disponíveis como variáveis \"​metadados \" e "
"propriedades do documento em variáveis `documento`."
#: models.py:32
msgid "negated"
msgstr "negada"
#: models.py:32
msgid "Inverts the logic of the operator."
msgstr "Inverte a lógica do operador."
#: models.py:36
msgid "not"
msgstr "não"
#: models.py:39
msgid "group item"
msgstr "item do grupo"
#: models.py:40
msgid "group items"
msgstr "itens do grupo"
#: views.py:21
msgid "No action selected."
msgstr "Nenhuma ação selecionada."
#: views.py:34
#, python-format
msgid "documents in group: %(group)s"
msgstr "documentos no grupo: %(group)s "
#: views.py:50
#, python-format
msgid "Document group query error: %s"
msgstr "Erro na consulta de grupo do documento: %s"
#: views.py:61
#, python-format
msgid "document groups (%s)"
msgstr "grupos do documento (%s)"
#: views.py:75
msgid "There no defined groups for the current document."
msgstr "Não há grupos definidos para o documento atual."
Binary file not shown.
@@ -0,0 +1,207 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Sergey Glita <gsv70@mail.ru>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-09-29 18:45-0400\n"
"PO-Revision-Date: 2011-11-04 10:53+0000\n"
"Last-Translator: gsv70 <gsv70@mail.ru>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: 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"
#: __init__.py:8
msgid "group actions"
msgstr "групповые действия"
#: __init__.py:9
msgid "groups"
msgstr "группы"
#: forms.py:55
msgid "Pages"
msgstr "Страницы"
#: forms.py:56
msgid "Select"
msgstr "Выбрать"
#: forms.py:61
msgid "group document"
msgstr "group document"
#: forms.py:66
msgid "Click on the image for full size view of the first page."
msgstr ""
"Нажмите на изображение для просмотра первой страницы в полном размере."
#: literals.py:7
msgid "and"
msgstr "и"
#: literals.py:8
msgid "or"
msgstr "или"
#: literals.py:12
msgid "is equal to"
msgstr "равно"
#: literals.py:13
msgid "is equal to (case insensitive)"
msgstr "равно (без учета регистра)"
#: literals.py:14
msgid "contains"
msgstr "содержит"
#: literals.py:15
msgid "contains (case insensitive)"
msgstr "содержит (без учета регистра)"
#: literals.py:16
msgid "is in"
msgstr "находится в"
#: literals.py:17
msgid "is greater than"
msgstr "больше"
#: literals.py:18
msgid "is greater than or equal to"
msgstr "больше или равно"
#: literals.py:19
msgid "is less than"
msgstr "меньше"
#: literals.py:20
msgid "is less than or equal to"
msgstr "меньше или равно"
#: literals.py:21
msgid "starts with"
msgstr "начинается с"
#: literals.py:22
msgid "starts with (case insensitive)"
msgstr "начинается с (без учета регистра)"
#: literals.py:23
msgid "ends with"
msgstr "заканчивается на"
#: literals.py:24
msgid "ends with (case insensitive)"
msgstr "заканчивается на (без учета регистра)"
#: literals.py:25
msgid "is in regular expression"
msgstr "В регулярном выражении"
#: literals.py:26
msgid "is in regular expression (case insensitive)"
msgstr "В регулярном выражении (без учета регистра)"
#: models.py:10
msgid "title"
msgstr "название"
#: models.py:11
msgid "dynamic title"
msgstr "динамический заголовок"
#: models.py:12 models.py:33
msgid "enabled"
msgstr "разрешено"
#: models.py:20 models.py:25
msgid "document group"
msgstr "document group"
#: models.py:21
msgid "document groups"
msgstr "document groups"
#: models.py:26
msgid "The inclusion is ignored for the first item."
msgstr "Включение игнорируется для первого элемента."
#: models.py:27
msgid "foreign document data"
msgstr "foreign document data"
#: models.py:27
msgid ""
"This represents the metadata of all other documents. Available objects: "
"`document.<attribute>` and `metadata.<metadata_type_name>`."
msgstr ""
"Это представляет метаданные всех других документов. Доступные объекты: "
"`document. <attribute> ` и `metadata. <metadata_type_name> `."
#: models.py:31
msgid "expression"
msgstr "выражение"
#: models.py:31
msgid ""
"This expression will be evaluated against the current selected document. "
"The document metadata is available as variables `metadata` and document "
"properties under the variable `document`."
msgstr ""
"Это выражение будет вычислено вмето выбранного документа. Метаданные "
"документа доступны как переменные `metadata` и свойства документа в "
"переменной `document`."
#: models.py:32
msgid "negated"
msgstr "отрицание"
#: models.py:32
msgid "Inverts the logic of the operator."
msgstr "Инвертирует логику оператора."
#: models.py:36
msgid "not"
msgstr "не"
#: models.py:39
msgid "group item"
msgstr "член группы"
#: models.py:40
msgid "group items"
msgstr "члены группы"
#: views.py:21
msgid "No action selected."
msgstr "Никаких действий не выбрано."
#: views.py:34
#, python-format
msgid "documents in group: %(group)s"
msgstr "Документы в группе: %(group)s"
#: views.py:50
#, python-format
msgid "Document group query error: %s"
msgstr "Документ группы запросов ошибка: %s"
#: views.py:61
#, python-format
msgid "document groups (%s)"
msgstr "группы документов (%s)"
#: views.py:75
msgid "There no defined groups for the current document."
msgstr "Для текущего документа не выбрана группа"
+82
View File
@@ -0,0 +1,82 @@
from django.db import models
from django.db.models import Q
from metadata.classes import MetadataObject
from documents.models import Document
from linking.literals import INCLUSION_AND, INCLUSION_OR
class SmartLinkManager(models.Manager):
def get_smart_link_instances_for(self, document, smart_link_obj=None):
errors = []
result = {}
metadata_dict = {}
for document_metadata in document.documentmetadata_set.all():
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
if smart_link_obj:
smart_link_qs = self.model.objects.filter(Q(enabled=True) & Q(pk=smart_link_obj.pk))
else:
smart_link_qs = self.model.objects.filter(enabled=True)
for smart_link in smart_link_qs:
total_query = Q()
for condition in smart_link.smartlinkcondition_set.filter(enabled=True):
cls, attribute = condition.foreign_document_data.lower().split(u'.')
try:
if cls == u'metadata':
value_query = Q(**{'documentmetadata__value__%s' % condition.operator: eval(condition.expression, eval_dict)})
if condition.negated:
query = (Q(documentmetadata__metadata_type__name=attribute) & ~value_query)
else:
query = (Q(documentmetadata__metadata_type__name=attribute) & value_query)
if condition.inclusion == INCLUSION_AND:
total_query &= query
elif condition.inclusion == INCLUSION_OR:
total_query |= query
elif cls == u'document':
value_query = Q(**{
'%s__%s' % (attribute, condition.operator): eval(condition.expression, eval_dict)
})
if condition.negated:
query = ~value_query
else:
query = value_query
if condition.inclusion == INCLUSION_AND:
total_query &= query
elif condition.inclusion == INCLUSION_OR:
total_query |= query
except Exception, e:
errors.append(e)
value_query = Q()
query = Q()
if total_query:
try:
document_qs = Document.objects.filter(total_query)
result[smart_link] = {'documents': document_qs.order_by('file_filename') or []}
except Exception, e:
result[smart_link] = {'documents': []}
errors.append(e)
else:
result[smart_link] = {'documents': []}
if smart_link.dynamic_title:
try:
result[smart_link]['title'] = eval(smart_link.dynamic_title, eval_dict)
except Exception, e:
result[smart_link]['title'] = 'Error; %s' % e
else:
result[smart_link]['title'] = smart_link.title
if smart_link_obj:
# Return a single group if documents even if there were
# many matches
return result[smart_link_obj], errors
return result, errors
+38
View File
@@ -0,0 +1,38 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from linking.managers import SmartLinkManager
from linking.literals import OPERATOR_CHOICES, INCLUSION_AND, \
INCLUSION_CHOICES
class SmartLink(models.Model):
title = models.CharField(max_length=96, verbose_name=_(u'title'))
dynamic_title = models.CharField(blank=True, max_length=96, verbose_name=_(u'dynamic title'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables `metadata` and document properties under the variable `document`.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
objects = SmartLinkManager()
def __unicode__(self):
return self.title
class Meta:
verbose_name = _(u'smart link')
verbose_name_plural = _(u'smart links')
class SmartLinkCondition(models.Model):
smart_link = models.ForeignKey(SmartLink, verbose_name=_(u'smart link'))
inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_(u'The inclusion is ignored for the first item.'))
foreign_document_data = models.CharField(max_length=32, verbose_name=_(u'foreign document data'), help_text=_(u'This represents the metadata of all other documents. Available objects: `document.<attribute>` and `metadata.<metadata_type_name>`.'))
operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES)
expression = models.TextField(verbose_name=_(u'expression'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables `metadata` and document properties under the variable `document`.'))
negated = models.BooleanField(default=False, verbose_name=_(u'negated'), help_text=_(u'Inverts the logic of the operator.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
def __unicode__(self):
return u'%s foreign %s %s %s %s' % (self.get_inclusion_display(), self.foreign_document_data, _(u'not') if self.negated else u'', self.get_operator_display(), self.expression)
class Meta:
verbose_name = _(u'link condition')
verbose_name_plural = _(u'link conditions')
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,5 @@
{% load i18n %}
<div class="block notice">
<h4>{% trans "What are smart links?" %}</h4>
<p>{% blocktrans %}Smart links are a set of conditional statements that are used to query the database using the current document the user is accessing as the data source, the results of these queries are a list of documents that relate in some manner to the document being displayed and allow users the ability to jump to and from linked documents very easily.{% endblocktrans %}</p>
</div>
+23
View File
@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
+17
View File
@@ -0,0 +1,17 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('linking.views',
url(r'^action/$', 'smart_link_action', (), 'smart_link_action'),
url(r'^document/(?P<document_id>\d+)/smart_link/(?P<smart_link_pk>\d+)/$', 'smart_link_instance_view', (), 'smart_link_instance_view'),
url(r'^smart/for_document/(?P<document_id>\d+)/$', 'smart_link_instances_for_document', (), 'smart_link_instances_for_document'),
url(r'^setup/list/$', 'document_group_list', (), 'document_group_list'),
url(r'^setup/create/$', 'document_group_create', (), 'document_group_create'),
url(r'^setup/(?P<smart_link_pk>\d+)/delete/$', 'document_group_delete', (), 'document_group_delete'),
url(r'^setup/(?P<smart_link_pk>\d+)/edit/$', 'document_group_edit', (), 'document_group_edit'),
url(r'^setup/(?P<smart_link_pk>\d+)/condition/list/$', 'smart_link_condition_list', (), 'smart_link_condition_list'),
url(r'^setup/(?P<smart_link_pk>\d+)/condition/create/$', 'smart_link_condition_create', (), 'smart_link_condition_create'),
url(r'^setup/smart_link/condition/(?P<smart_link_condition_pk>\d+)/edit/$', 'smart_link_condition_edit', (), 'smart_link_condition_edit'),
url(r'^setup/smart_link/condition/(?P<smart_link_condition_pk>\d+)/delete/$', 'smart_link_condition_delete', (), 'smart_link_condition_delete'),
)
+294
View File
@@ -0,0 +1,294 @@
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.core.urlresolvers import reverse
from django.template import RequestContext
from common.utils import generate_choices_w_labels, encapsulate
from common.widgets import two_state_template
from documents.models import Document
from documents.views import document_list
from permissions.api import check_permissions
from linking.models import SmartLink, SmartLinkCondition
from linking.conf.settings import SHOW_EMPTY_SMART_LINKS
from linking.forms import (SmartLinkInstanceForm, SmartLinkForm,
SmartLinkConditionForm)
from linking import smart_link_instance_view_link
from linking import (PERMISSION_SMART_LINK_VIEW,
PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_DELETE,
PERMISSION_SMART_LINK_EDIT)
def smart_link_action(request):
check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
action = request.GET.get('action', None)
if not action:
messages.error(request, _(u'No action selected.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', u'/'))
return HttpResponseRedirect(action)
def smart_link_instance_view(request, document_id, smart_link_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
document = get_object_or_404(Document, pk=document_id)
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
object_list, errors = SmartLink.objects.get_smart_link_instances_for(document, smart_link)
return document_list(
request,
title=_(u'documents in smart link: %(group)s') % {
'group': object_list['title']
},
object_list=object_list['documents'],
extra_context={
'object': document
}
)
def smart_link_instances_for_document(request, document_id):
check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
subtemplates_list = []
document = get_object_or_404(Document, pk=document_id)
smart_link_instances, errors = SmartLink.objects.get_smart_link_instances_for(document)
if (request.user.is_staff or request.user.is_superuser) and errors:
for error in errors:
messages.warning(request, _(u'Smart link query error: %s' % error))
if not SHOW_EMPTY_SMART_LINKS:
#If SHOW_EMPTY_SMART_LINKS is False, remove empty groups from
#dictionary
smart_link_instances = dict([(group, data) for group, data in smart_link_instances.items() if data['documents']])
if smart_link_instances:
subtemplates_list = [{
'name': 'generic_form_subtemplate.html',
'context': {
'title': _(u'smart links (%s)') % len(smart_link_instances.keys()),
'form': SmartLinkInstanceForm(
smart_link_instances=smart_link_instances, current_document=document,
links=[smart_link_instance_view_link]
),
'form_action': reverse('smart_link_action'),
'submit_method': 'GET',
}
}]
else:
# If there are not group display a placeholder messages saying so
subtemplates_list = [{
'name': 'generic_subtemplate.html',
'context': {
'content': _(u'There no defined smart links for the current document.'),
}
}]
return render_to_response('generic_detail.html', {
'object': document,
'document': document,
'subtemplates_list': subtemplates_list,
}, context_instance=RequestContext(request))
def document_group_list(request):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE])
return render_to_response('generic_list.html', {
'title': _(u'smart links'),
'object_list': SmartLink.objects.all(),
'extra_columns': [
{'name': _(u'dynamic title'), 'attribute': 'dynamic_title'},
{'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))},
],
'hide_link': True,
'list_object_variable_name': 'smart_link',
}, context_instance=RequestContext(request))
def document_group_create(request):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE])
if request.method == 'POST':
form = SmartLinkForm(request.POST)
if form.is_valid():
document_group = form.save()
messages.success(request, _(u'Smart link: %s created successfully.') % document_group)
return HttpResponseRedirect(reverse('document_group_list'))
else:
form = SmartLinkForm()
return render_to_response('generic_form.html', {
'form': form,
'title': _(u'Create new smart link')
}, context_instance=RequestContext(request))
def document_group_edit(request, smart_link_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_EDIT])
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
if request.method == 'POST':
form = SmartLinkForm(request.POST, instance=smart_link)
if form.is_valid():
smart_link = form.save()
messages.success(request, _(u'Smart link: %s edited successfully.') % smart_link)
return HttpResponseRedirect(reverse('document_group_list'))
else:
form = SmartLinkForm(instance=smart_link)
return render_to_response('generic_form.html', {
'navigation_object_name': 'smart_link',
'smart_link': smart_link,
'form': form,
'title': _(u'Edit smart link: %s') % smart_link
}, context_instance=RequestContext(request))
def document_group_delete(request, smart_link_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_DELETE])
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
smart_link.delete()
messages.success(request, _(u'Smart link: %s deleted successfully.') % smart_link)
except Exception, error:
messages.error(request, _(u'Error deleting smart link: %(smart_link)s; %(error)s.') % {
'smart_link': smart_link,
'error': error
})
return HttpResponseRedirect(next)
return render_to_response('generic_confirm.html', {
'delete_view': True,
'navigation_object_name': 'smart_link',
'smart_link': smart_link,
'title': _(u'Are you sure you wish to delete smart link: %s?') % smart_link,
'next': next,
'previous': previous,
'form_icon': u'link_delete.png',
}, context_instance=RequestContext(request))
def smart_link_condition_list(request, smart_link_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
return render_to_response('generic_list.html', {
'title': _(u'conditions for smart link: %s') % smart_link,
'object_list': smart_link.smartlinkcondition_set.all(),
'extra_columns': [
{'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))},
],
'hide_link': True,
'smart_link': smart_link,
'navigation_object_name': 'smart_link',
'list_object_variable_name': 'condition',
}, context_instance=RequestContext(request))
def smart_link_condition_create(request, smart_link_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
if request.method == 'POST':
form = SmartLinkConditionForm(request.POST)
if form.is_valid():
new_smart_link_condition = form.save(commit=False)
new_smart_link_condition.smart_link = smart_link
new_smart_link_condition.save()
messages.success(request, _(u'Smart link condition: "%s" created successfully.') % new_smart_link_condition)
return HttpResponseRedirect(reverse('smart_link_condition_list', args=[smart_link.pk]))
else:
form = SmartLinkConditionForm(initial={'smart_link': smart_link})
return render_to_response('generic_form.html', {
'form': form,
'title': _(u'Add new conditions to smart link: "%s"') % smart_link,
'navigation_object_name': 'smart_link',
'smart_link': smart_link,
}, context_instance=RequestContext(request))
def smart_link_condition_edit(request, smart_link_condition_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
smart_link_condition = get_object_or_404(SmartLinkCondition, pk=smart_link_condition_pk)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
form = SmartLinkConditionForm(request.POST, instance=smart_link_condition)
if form.is_valid():
new_smart_link_condition = form.save(commit=False)
new_smart_link_condition.smart_link = smart_link_condition.smart_link
new_smart_link_condition.save()
messages.success(request, _(u'Smart link condition: "%s" edited successfully.') % new_smart_link_condition)
return HttpResponseRedirect(next)
else:
form = SmartLinkConditionForm(instance=smart_link_condition)
return render_to_response('generic_form.html', {
'form': form,
'title': _(u'Edit smart link condition'),
'next': next,
'previous': previous,
'condition': smart_link_condition,
'smart_link': smart_link_condition.smart_link,
'navigation_object_list': [
{'object': 'smart_link', 'name': _(u'smart link')},
{'object': 'condition', 'name': _(u'condition')}
],
}, context_instance=RequestContext(request))
def smart_link_condition_delete(request, smart_link_condition_pk):
check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
smart_link_condition = get_object_or_404(SmartLinkCondition, pk=smart_link_condition_pk)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
smart_link_condition.delete()
messages.success(request, _(u'Smart link condition: "%s" deleted successfully.') % smart_link_condition)
except Exception, error:
messages.error(request, _(u'Error deleting smart link condition: %(smart_link_condition)s; %(error)s.') % {
'smart_link_condition': smart_link_condition,
'error': error
})
return HttpResponseRedirect(next)
return render_to_response('generic_confirm.html', {
'delete_view': True,
'condition': smart_link_condition,
'smart_link': smart_link_condition.smart_link,
'navigation_object_list': [
{'object': 'smart_link', 'name': _(u'smart link')},
{'object': 'condition', 'name': _(u'condition')}
],
'title': _(u'Are you sure you wish to delete smart link condition: "%s"?') % smart_link_condition,
'next': next,
'previous': previous,
'form_icon': u'cog_delete.png',
}, context_instance=RequestContext(request))