Marcos Dumay de Medeiros hace 9 años
padre
commit
0d85a29836
Se han modificado 30 ficheros con 649 adiciones y 620 borrados
  1. 1 0
      src/rapid/__init__.py
  2. 8 8
      src/rapid/fixtures/initial_data.json
  3. 2 1
      src/rapid/migrations/0001_initial.py
  4. 1 1
      src/rapid/migrations/0002_auto_20150918_1921.py
  5. 1 0
      src/rapid/migrations/__init__.py
  6. 1 0
      src/rapid/officedocs/__init__.py
  7. 9 7
      src/rapid/officedocs/rtf.py
  8. 7 7
      src/rapid/templates/rapid/bare/create.html
  9. 4 4
      src/rapid/templates/rapid/bare/delete.html
  10. 31 31
      src/rapid/templates/rapid/bare/detail.html
  11. 84 84
      src/rapid/templates/rapid/bare/select.html
  12. 26 26
      src/rapid/templates/rapid/bare/update.html
  13. 13 13
      src/rapid/templates/rapid/filters/column_selector.html
  14. 2 2
      src/rapid/templates/rapid/filters/key_value.html
  15. 22 22
      src/rapid/templates/rapid/filters/model_filters.html
  16. 51 51
      src/rapid/templates/rapid/filters/register.html
  17. 8 8
      src/rapid/templates/rapid/list/field_header.html
  18. 22 22
      src/rapid/templates/rapid/list/pagination.html
  19. 9 9
      src/rapid/templates/rapid/list/show_value.html
  20. 15 15
      src/rapid/templates/rapid/main_window.html
  21. 44 44
      src/rapid/templates/rapid/overlay/text.html
  22. 53 53
      src/rapid/templates/rapid/widgets/multiple-selector.html
  23. 22 22
      src/rapid/templates/rapid/widgets/single-selector.html
  24. 1 0
      src/rapid/templatetags/__init__.py
  25. 0 1
      src/rapid/templatetags/rapid_basics.py
  26. 74 61
      src/rapid/templatetags/rapid_crud.py
  27. 36 31
      src/rapid/templatetags/rapid_filters.py
  28. 28 27
      src/rapid/templatetags/rapid_list.py
  29. 73 70
      src/rapid/templatetags/rapid_menu.py
  30. 1 0
      src/rapid/tests.py

+ 1 - 0
src/rapid/__init__.py

@@ -0,0 +1 @@
+# coding=utf-8

+ 8 - 8
src/rapid/fixtures/initial_data.json

@@ -1,11 +1,11 @@
 [
-    {
-	"model": "rapid.application",
-	"pk": 1,
-	"fields": {
-	    "name": "applications",
-	    "python_name": "rapid",
-	    "enabled": true
-	}
+  {
+  "model": "rapid.application",
+  "pk": 1,
+  "fields": {
+    "name": "applications",
+    "python_name": "rapid",
+    "enabled": true
     }
+}
 ]

+ 2 - 1
src/rapid/migrations/0001_initial.py

@@ -19,7 +19,8 @@ class Migration(migrations.Migration):
                 ('name', models.CharField(unique=True, max_length=60, verbose_name='nome')),
                 ('python_name', models.CharField(unique=True, max_length=255, verbose_name='Nome no Python')),
                 ('enabled', models.BooleanField(default=True, verbose_name='ativa')),
-                ('managers', models.ManyToManyField(related_name='managed_applications', verbose_name='gestores', to=settings.AUTH_USER_MODEL)),
+                ('managers', models.ManyToManyField(related_name='managed_applications', verbose_name='gestores',
+                                                    to=settings.AUTH_USER_MODEL)),
             ],
             options={
                 'verbose_name': 'aplica\xe7\xe3o',

+ 1 - 1
src/rapid/migrations/0002_auto_20150918_1921.py

@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
 
-from django.db import models, migrations
+from django.db import migrations
 
 from django_migration_fixture import fixture
 import rapid

+ 1 - 0
src/rapid/migrations/__init__.py

@@ -0,0 +1 @@
+# coding=utf-8

+ 1 - 0
src/rapid/officedocs/__init__.py

@@ -0,0 +1 @@
+# coding=utf-8

+ 9 - 7
src/rapid/officedocs/rtf.py

@@ -1,3 +1,4 @@
+# coding=utf-8
 __author__ = 'marcos.medeiros'
 
 
@@ -15,15 +16,15 @@ class RtfTemplate(object):
     Brackets were chosen because they aren't parsed by the RTF format, and thus can be inserted
     directly from WYSIWYG editors.
     """
-    def __init__(self, file, context):
+    def __init__(self, file_name, context):
         """
         Open the template for reading, replacing the variables with the values from the
         given context.
-        :param file: Template that will be read.
+        :param file_name: Template that will be read.
         :param context: Values that will be inserted at the place of the variables.
         """
-        self.name = file
-        self.template = open(file, 'r')
+        self.name = file_name
+        self.template = open(file_name, 'r')
         self.encoding = self.template.encoding
         self.context = context
         self.pattern = ''
@@ -74,6 +75,7 @@ class RtfTemplate(object):
         return self._next_with(self.template.next)
 
     def __next__(self):
+        # noinspection PyUnresolvedReferences
         return self._next_with(self.template.__next__)
 
     def _read_by(self, func, size):
@@ -118,15 +120,15 @@ class RtfTemplate(object):
         return self.template.newlines
 
     @classmethod
-    def format_into(cls, template, context, file):
+    def format_into(cls, template, context, file_name):
         """
         Formats the template, writing the resulting data into the given file.
         :param template: Name of the template file.
         :param context: Context where variables will be evaluated.
-        :param file: Name of the file that will be written with the formatted data.
+        :param file_name: Name of the file that will be written with the formatted data.
         """
         t = RtfTemplate(template, context)
-        f = open(file, 'w')
+        f = open(file_name, 'w')
         for l in t:
             f.write(l)
         f.close()

+ 7 - 7
src/rapid/templates/rapid/bare/create.html

@@ -1,7 +1,7 @@
-<h2>{{object_data.model_name.title}}</h2>
-
-<form method="POST" action="" enctype="multipart/form-data">
-    {% csrf_token %}
-    {{ form.as_p }}
-    <p><a class="btn btn-default rapid-submit-form">Adicionar</a></p>
-</form>
+<h2>{{object_data.model_name.title}}</h2>
+
+<form method="POST" action="" enctype="multipart/form-data">
+    {% csrf_token %}
+    {{ form.as_p }}
+    <p><a class="btn btn-default rapid-submit-form">Adicionar</a></p>
+</form>

+ 4 - 4
src/rapid/templates/rapid/bare/delete.html

@@ -1,4 +1,4 @@
-<form method="post" action="">{% csrf_token %}
-    <p>Você tem certeza que deseja apagar "{{ object }}"?</p>
-    <p><a class="btn btn-default rapid-submit-form">Apagar</a></p>
-</form>
+<form method="post" action="">{% csrf_token %}
+    <p>Você tem certeza que deseja apagar "{{ object }}"?</p>
+    <p><a class="btn btn-default rapid-submit-form">Apagar</a></p>
+</form>

+ 31 - 31
src/rapid/templates/rapid/bare/detail.html

@@ -1,31 +1,31 @@
-<span class="must_reload"></span>
-<h2>{{object_data.model_name.title}}</h2>
-
-<div>
-    {% for f, v, iter in object_data.fields_and_values %}
-        <p><span class="field_label">{{ f.name.capitalize }}:</span>
-        {% if iter %}
-            {% for val, link in v %}
-                {% if link and link.can_read %}
-                    <span class="field_value"><a href="{{ link.view_url }}">{{ val }}</a></span>
-                {% else %}
-                    <span class="field_value">{{ val }}</span>
-                {% endif %}
-            {% endfor %}
-        {% else %}
-            {% if v.1 and v.1.can_read %}
-                <span class="field_value"><a href="{{ v.1.view_url }}">{{ v.0 }}</a></span>
-            {% else %}
-                <span class="field_value">{{ v.0 }}</span>
-            {% endif %}
-        {% endif %}
-        </p>
-    {% endfor %}
-</div>
-{% if object_data.can_write %}
-<div>
-    {% for a, u in object_data.instance_actions %}{% if a.action.name != 'view' %}
-        <a href="{{ u }}" class="btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
-    {% endif %}{% endfor %}
-</div>
-{% endif %}
+<span class="must_reload"></span>
+<h2>{{object_data.model_name.title}}</h2>
+
+<div>
+    {% for f, v, iter in object_data.fields_and_values %}
+        <p><span class="field_label">{{ f.name.capitalize }}:</span>
+        {% if iter %}
+            {% for val, link in v %}
+                {% if link and link.can_read %}
+                    <span class="field_value"><a href="{{ link.view_url }}">{{ val }}</a></span>
+                {% else %}
+                    <span class="field_value">{{ val }}</span>
+                {% endif %}
+            {% endfor %}
+        {% else %}
+            {% if v.1 and v.1.can_read %}
+                <span class="field_value"><a href="{{ v.1.view_url }}">{{ v.0 }}</a></span>
+            {% else %}
+                <span class="field_value">{{ v.0 }}</span>
+            {% endif %}
+        {% endif %}
+        </p>
+    {% endfor %}
+</div>
+{% if object_data.can_write %}
+<div>
+    {% for a, u in object_data.instance_actions %}{% if a.action.name != 'view' %}
+        <a href="{{ u }}" class="btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
+    {% endif %}{% endfor %}
+</div>
+{% endif %}

+ 84 - 84
src/rapid/templates/rapid/bare/select.html

@@ -1,84 +1,84 @@
-{% load rapid_list %}<span class="must_reload"></span>
-<style scoped>
-    table.object_list > thead > tr > td{
-        padding-left: 0.5em;
-        padding-right: 0.5em;
-        padding-top: 0.5em;
-        padding-bottom: 0.5em;
-        vertical-align: middle;
-    }
-    table.object_list > tbody > tr > td{
-        padding-left: 0.5em;
-        padding-right: 0.5em;
-        vertical-align: middle;
-    }
-    td.list-icons > *{
-        margin-right: 1em;
-    }
-    tr.selectable-row > .selectable-check{
-        font-family: FontAwesome;
-        margin-right: 6pt;
-        font-size: 32pt;
-    }
-    tr.selectable-row:not(.selected) > .selectable-check{
-        zoom: 1;
-        filter: alpha(opacity=0);
-        opacity: 0;
-    }
-    tr.selectable-row.selected{
-        border-radius: 5pt;
-        box-shadow: 0pt 0pt 3pt 5pt #00ff00;
-    }
-</style>
-<h2>{{model.model_name_plural.capitalize}}</h2>
-<p>{% for a, u in model.actions %}
-	{% if a.action.name != 'list' %}
-		<a href="{{ u }}" class="better-in-overlay btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
-	{% endif %}
-{% endfor %}</p>
-{% load rapid_filters %}
-{% model_filters model %}
-<table class="object_list rapid-object-selector table table-striped table-condensed">
-    <thead><tr class="selectable-head">
-        <td class="selectable-check"><!-- Espaço para um check -->&nbsp;</td>
-        {% for f in view.fields %}
-        {% field_header f %}
-        {% endfor %}
-    </tr></thead>
-    <tbody>
-    {% for o in view.values %}
-    <tr class="selectable-row" id="{{ o.instance.pk }}">
-        <td class="selectable-check"><!-- Espaço para um check -->&#xf00c;
-        <input type="hidden" name="{{ o.instance }}" value="{{ o.instance.pk }}" class="rapid-select-id-marker"></inputhidden></td>
-        {% for v, iter in o.values %}
-        {% if iter %}
-            <td>
-            {% for val, val_data in v %}
-                {{ val }}
-                {% if not forloop.last %}<br>{% endif %}
-            {% endfor %}
-            </td>
-        {% else %}
-            <td>{{ v.0 }}</td>
-        {% endif %}
-        {% endfor %}
-    </tr>
-    </tbody>
-    {% endfor %}
-</table>
-<p><a class="overlay-commit btn btn-default">Adicionar na seleção</a></p>
-<p>{% for a, u in model.actions %}
-	{% if a.action.name != 'list' %}
-		<a href="{{ u }}" class="better-in-overlay btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
-	{% endif %}
-{% endfor %}</p>
-{% pagination %}
-<script>
-     $(document).ready(function(){
-        $("tr.selectable-row").click(function(){
-            $(this).toggleClass("selected");
-            //$(this).filter(".selected").children(".selectable-check").text("\f00c");
-            //$(this).not(".selected").children(".selectable-check").text(" ");
-        });
-     });
- </script>
+{% load rapid_list %}<span class="must_reload"></span>
+<style scoped>
+    table.object_list > thead > tr > td{
+        padding-left: 0.5em;
+        padding-right: 0.5em;
+        padding-top: 0.5em;
+        padding-bottom: 0.5em;
+        vertical-align: middle;
+    }
+    table.object_list > tbody > tr > td{
+        padding-left: 0.5em;
+        padding-right: 0.5em;
+        vertical-align: middle;
+    }
+    td.list-icons > *{
+        margin-right: 1em;
+    }
+    tr.selectable-row > .selectable-check{
+        font-family: FontAwesome;
+        margin-right: 6pt;
+        font-size: 32pt;
+    }
+    tr.selectable-row:not(.selected) > .selectable-check{
+        zoom: 1;
+        filter: alpha(opacity=0);
+        opacity: 0;
+    }
+    tr.selectable-row.selected{
+        border-radius: 5pt;
+        box-shadow: 0pt 0pt 3pt 5pt #00ff00;
+    }
+</style>
+<h2>{{model.model_name_plural.capitalize}}</h2>
+<p>{% for a, u in model.actions %}
+    {% if a.action.name != 'list' %}
+        <a href="{{ u }}" class="better-in-overlay btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
+    {% endif %}
+{% endfor %}</p>
+{% load rapid_filters %}
+{% model_filters model %}
+<table class="object_list rapid-object-selector table table-striped table-condensed">
+    <thead><tr class="selectable-head">
+        <td class="selectable-check"><!-- Espaço para um check -->&nbsp;</td>
+        {% for f in view.fields %}
+        {% field_header f %}
+        {% endfor %}
+    </tr></thead>
+    <tbody>
+    {% for o in view.values %}
+    <tr class="selectable-row" id="{{ o.instance.pk }}">
+        <td class="selectable-check"><!-- Espaço para um check -->&#xf00c;
+        <input type="hidden" name="{{ o.instance }}" value="{{ o.instance.pk }}" class="rapid-select-id-marker"></td>
+        {% for v, iter in o.values %}
+        {% if iter %}
+            <td>
+            {% for val, val_data in v %}
+                {{ val }}
+                {% if not forloop.last %}<br>{% endif %}
+            {% endfor %}
+            </td>
+        {% else %}
+            <td>{{ v.0 }}</td>
+        {% endif %}
+        {% endfor %}
+    </tr>
+    </tbody>
+    {% endfor %}
+</table>
+<p><a class="overlay-commit btn btn-default">Adicionar na seleção</a></p>
+<p>{% for a, u in model.actions %}
+    {% if a.action.name != 'list' %}
+        <a href="{{ u }}" class="better-in-overlay btn btn-default"><span class="fa {{ a.action.icon }}">{{ a.action.verbose_name.capitalize }}</span></a>
+    {% endif %}
+{% endfor %}</p>
+{% pagination %}
+<script>
+     $(document).ready(function(){
+        $("tr.selectable-row").click(function(){
+            $(this).toggleClass("selected");
+            //$(this).filter(".selected").children(".selectable-check").text("\f00c");
+            //$(this).not(".selected").children(".selectable-check").text(" ");
+        });
+     });
+ </script>

+ 26 - 26
src/rapid/templates/rapid/bare/update.html

@@ -1,26 +1,26 @@
-<h2>{{object_data.model_name.title}}</h2>
-
-<form method="POST" action=""  enctype="multipart/form-data">
-    {% csrf_token %}
-    {{ form.as_p }}
-    {% for field, v, iter in object_data.related_fields_and_values %}
-        <p><span class="field_label">{{ field.name.title }}:</span>
-        {% if iter %}
-            {% for val, link in v %}
-                {% if link %}
-                    <span class="field_value"><a href="{{ link }}">{{ val }}</a></span>
-                {% else %}
-                    <span class="field_value">{{ val }}</span>
-                {% endif %}
-            {% endfor %}
-        {% else %}
-            {% if v.1 %}
-                <span class="field_value"><a href="{{ v.1 }}">{{ v.0 }}</a></span>
-            {% else %}
-                <span class="field_value">{{ v.0 }}</span>
-            {% endif %}
-        {% endif %}
-        </p>
-    {% endfor %}
-    <p><a class="btn btn-default rapid-submit-form">Alterar</a></p>
-</form>
+<h2>{{object_data.model_name.title}}</h2>
+
+<form method="POST" action=""  enctype="multipart/form-data">
+    {% csrf_token %}
+    {{ form.as_p }}
+    {% for field, v, iter in object_data.related_fields_and_values %}
+        <p><span class="field_label">{{ field.name.title }}:</span>
+        {% if iter %}
+            {% for val, link in v %}
+                {% if link %}
+                    <span class="field_value"><a href="{{ link }}">{{ val }}</a></span>
+                {% else %}
+                    <span class="field_value">{{ val }}</span>
+                {% endif %}
+            {% endfor %}
+        {% else %}
+            {% if v.1 %}
+                <span class="field_value"><a href="{{ v.1 }}">{{ v.0 }}</a></span>
+            {% else %}
+                <span class="field_value">{{ v.0 }}</span>
+            {% endif %}
+        {% endif %}
+        </p>
+    {% endfor %}
+    <p><a class="btn btn-default rapid-submit-form">Alterar</a></p>
+</form>

+ 13 - 13
src/rapid/templates/rapid/filters/column_selector.html

@@ -1,13 +1,13 @@
-<div class="rapid-column-filter">
-    <span class="hidden rapid-field-name">{{ field.bare_name }}</span>
-	<p>{{ field.name.capitalize }}</p>
-	<select class="rapid-operator {{ field.bare_name }}">
-        {% for o, s in selectors %}
-        <option class="{{ o.query }}" value="{{ o.query }}">{{ o.display }}</option>
-        {% endfor %}
-    </select>
-	{% for o, s in selectors %}
-		<div class="{{ o.query }} {% if not forloop.first %}hidden{% endif %}">{{ s }}</div>
-	{% endfor %}
-    <a class="rapid-add-filter interaction">Filtrar</a>
-</div>
+<div class="rapid-column-filter">
+    <span class="hidden rapid-field-name">{{ field.bare_name }}</span>
+    <p>{{ field.name.capitalize }}</p>
+    <select class="rapid-operator {{ field.bare_name }}">
+        {% for o, s in selectors %}
+        <option class="{{ o.query }}" value="{{ o.query }}">{{ o.display }}</option>
+        {% endfor %}
+    </select>
+    {% for o, s in selectors %}
+        <div class="{{ o.query }} {% if not forloop.first %}hidden{% endif %}">{{ s }}</div>
+    {% endfor %}
+    <a class="rapid-add-filter interaction">Filtrar</a>
+</div>

+ 2 - 2
src/rapid/templates/rapid/filters/key_value.html

@@ -1,2 +1,2 @@
-<label for="{{ id }}-filter-value">{{ operator.display }}</label>
-<input type="text" id="{{ id }}-filter-value" name="{{ field.bare_name }}-{{ operator.query }}" value="{{ default_value }}">
+<label for="{{ id }}-filter-value">{{ operator.display }}</label>
+<input type="text" id="{{ id }}-filter-value" name="{{ field.bare_name }}-{{ operator.query }}" value="{{ default_value }}">

+ 22 - 22
src/rapid/templates/rapid/filters/model_filters.html

@@ -1,22 +1,22 @@
-<style scoped>
-    div.rapid-column-filter{
-        position: absolute;
-        border-radius: 15px;
-        box-shadow: 3px 3px 2px #000000;
-        padding-top: 3em;
-        padding-bottom: 3em;
-        padding-left: 2em;
-        padding-right: 2em;
-        background-color: #dddddd;
-        z-index: 200;
-    }
-</style>
-<form class="rapid-filterset">
-    <style scoped>.hidden{display: none;}</style>
-    {{ filters }}
-	<a class="rapid-submit-form btn btn-default {% if not has_filters %}hidden{% endif %}">Atualizar Filtros</a>
-</form>
-<div class="rapid-filter-selection">
-    <style scoped>.hidden{display: none;}</style>
-    {{ selectors }}
-</div>
+<style scoped>
+    div.rapid-column-filter{
+        position: absolute;
+        border-radius: 15px;
+        box-shadow: 3px 3px 2px #000000;
+        padding-top: 3em;
+        padding-bottom: 3em;
+        padding-left: 2em;
+        padding-right: 2em;
+        background-color: #dddddd;
+        z-index: 200;
+    }
+</style>
+<form class="rapid-filterset">
+    <style scoped>.hidden{display: none;}</style>
+    {{ filters }}
+    <a class="rapid-submit-form btn btn-default {% if not has_filters %}hidden{% endif %}">Atualizar Filtros</a>
+</form>
+<div class="rapid-filter-selection">
+    <style scoped>.hidden{display: none;}</style>
+    {{ selectors }}
+</div>

+ 51 - 51
src/rapid/templates/rapid/filters/register.html

@@ -1,51 +1,51 @@
-<script>
-    $(document).ready(function(){
-        $("body").on("change", "select.rapid-operator", function(){
-            $(this).siblings("div").addClass("hidden");
-            var op = $(this).val();
-            $(this).siblings("div." + op).removeClass("hidden");
-        });
-        $("body").on("click", "a.rapid-add-filter", function(event){
-            event.preventDefault(true);
-            var op = $(this).siblings("select.rapid-operator").val();
-            var field = $(this).siblings("span.rapid-field-name").text();
-            var dv = $(this).siblings("div." + op);
-            var frm = $(this).closest("div.rapid-filter-selection").parent().siblings("form.rapid-filterset")
-            var target = frm.children("div.rapid-field-filters." + field);
-			var dv_clone = dv.clone();
-			//dv_clone.append($("<a>", {"class": "rapid-remove-filter"}).html('<span class="fa fa-times"></span>'));
-            target.append(dv.clone());
-            target.removeClass("hidden");
-            $(this).closest("div.rapid-filter-selection").addClass("hidden");
-            frm.submit();
-        });
-        $("body").on("click", "a.rapid-filter", function(event){
-            event.preventDefault(true);
-            var act = $(this).children(".rapid-filter-field-name").text();
-            var f = $(this).closest("table").siblings("div.rapid-filter-selection").children("div.rapid-filter-selection." + act);
-            var pos = $(this).parent().offset();
-            pos.left -= 10;
-            pos.top += $(this).parent().height() + 10;
-            f.toggleClass("hidden");
-            var w = f.children("div").outerWidth();
-            if(pos.left + w > $(window).width()){
-                pos.left = $(window).width() - w;
-                if(pos.left < 0){
-                    pos.left = 0;
-                }
-            }
-            f.offset(pos);
-        });
-		$("body").on("click", "a.rapid-remove-filter", function(event){
-			event.preventDefault(true);
-			var e = $(this).closest("div");
-			var f = $(this).closest("form");
-			e.remove();
-			f.submit();
-		});
-		$("body").on("click", ".rapid-submit-form", function(event){
-			event.preventDefault(true);
-			$(this).closest("form").submit();
-		});
-    })
-</script>
+<script>
+    $(document).ready(function(){
+        $("body").on("change", "select.rapid-operator", function(){
+            $(this).siblings("div").addClass("hidden");
+            var op = $(this).val();
+            $(this).siblings("div." + op).removeClass("hidden");
+        });
+        $("body").on("click", "a.rapid-add-filter", function(event){
+            event.preventDefault(true);
+            var op = $(this).siblings("select.rapid-operator").val();
+            var field = $(this).siblings("span.rapid-field-name").text();
+            var dv = $(this).siblings("div." + op);
+            var frm = $(this).closest("div.rapid-filter-selection").parent().siblings("form.rapid-filterset")
+            var target = frm.children("div.rapid-field-filters." + field);
+            var dv_clone = dv.clone();
+            //dv_clone.append($("<a>", {"class": "rapid-remove-filter"}).html('<span class="fa fa-times"></span>'));
+            target.append(dv.clone());
+            target.removeClass("hidden");
+            $(this).closest("div.rapid-filter-selection").addClass("hidden");
+            frm.submit();
+        });
+        $("body").on("click", "a.rapid-filter", function(event){
+            event.preventDefault(true);
+            var act = $(this).children(".rapid-filter-field-name").text();
+            var f = $(this).closest("table").siblings("div.rapid-filter-selection").children("div.rapid-filter-selection." + act);
+            var pos = $(this).parent().offset();
+            pos.left -= 10;
+            pos.top += $(this).parent().height() + 10;
+            f.toggleClass("hidden");
+            var w = f.children("div").outerWidth();
+            if(pos.left + w > $(window).width()){
+                pos.left = $(window).width() - w;
+                if(pos.left < 0){
+                    pos.left = 0;
+                }
+            }
+            f.offset(pos);
+        });
+        $("body").on("click", "a.rapid-remove-filter", function(event){
+            event.preventDefault(true);
+            var e = $(this).closest("div");
+            var f = $(this).closest("form");
+            e.remove();
+            f.submit();
+        });
+        $("body").on("click", ".rapid-submit-form", function(event){
+            event.preventDefault(true);
+            $(this).closest("form").submit();
+        });
+    })
+</script>

+ 8 - 8
src/rapid/templates/rapid/list/field_header.html

@@ -1,8 +1,8 @@
-{% load rapid_filters %}
-<td>{{f.name.capitalize}}<br>
-    {% if not f.is_multiple %}
-    <a href="{{ f.view.order_up_url }}"><span class="fa fa-sort-amount-asc" title="Ordem Crescente"></span></a>
-    <a href="{{ f.view.order_down_url }}"><span class="fa fa-sort-amount-desc" title="Ordem Decrescente"></span></a>
-    {% endif %}
-    {% filter_icon f %}
-</td>
+{% load rapid_filters %}
+<td>{{f.name.capitalize}}<br>
+    {% if not f.is_multiple %}
+    <a href="{{ f.view.order_up_url }}"><span class="fa fa-sort-amount-asc" title="Ordem Crescente"></span></a>
+    <a href="{{ f.view.order_down_url }}"><span class="fa fa-sort-amount-desc" title="Ordem Decrescente"></span></a>
+    {% endif %}
+    {% filter_icon f %}
+</td>

+ 22 - 22
src/rapid/templates/rapid/list/pagination.html

@@ -1,22 +1,22 @@
-<p class="pagination">
-    Página:
-    {% for n,l in pages.start %}
-        <a href="{{ l }}" class="same-overlay">{{n}}</a>
-    {% endfor %}
-    {% if pages.separate_start %}
-    .....
-    {% endif %}
-    {% for n,l in pages.before %}
-        <a href="{{ l }}" class="same-overlay">{{n}}</a>
-    {% endfor %}
-    {{pages.page}}
-    {% for n,l in pages.after %}
-        <a href="{{ l }}" class="same-overlay">{{n}}</a>
-    {% endfor %}
-    {% if pages.separate_end %}
-    .....
-    {% endif %}
-    {% for n,l in pages.end %}
-        <a href="{{ l }}" class="same-overlay">{{n}}</a>
-    {% endfor %}
-</p>
+<p class="pagination">
+    Página:
+    {% for n,l in pages.start %}
+        <a href="{{ l }}" class="same-overlay">{{n}}</a>
+    {% endfor %}
+    {% if pages.separate_start %}
+    .....
+    {% endif %}
+    {% for n,l in pages.before %}
+        <a href="{{ l }}" class="same-overlay">{{n}}</a>
+    {% endfor %}
+    {{pages.page}}
+    {% for n,l in pages.after %}
+        <a href="{{ l }}" class="same-overlay">{{n}}</a>
+    {% endfor %}
+    {% if pages.separate_end %}
+    .....
+    {% endif %}
+    {% for n,l in pages.end %}
+        <a href="{{ l }}" class="same-overlay">{{n}}</a>
+    {% endfor %}
+</p>

+ 9 - 9
src/rapid/templates/rapid/list/show_value.html

@@ -1,9 +1,9 @@
-{% if val_data and val_data.can_read %}
-    <a href="{{ val_data.view_url }}" class="better-in-overlay">{{ val }}</a>{% for a, u in val_data.list_actions %}
-        <a href={{ u }} class="better-in-overlay"><span class="fa {{ a.action.icon }}" label="{{ a.action.verbose_name.capitalize }}"></span></a>
-    {% endfor %}
-{% else %}
-    {{ val }}{% for a, u in val_data.list_actions %}
-        <a href={{ u }} class="better-in-overlay"><span class="fa {{ a.action.icon }}" label="{{ a.action.verbose_name.capitalize }}"></span></a>
-    {% endfor %}
-{% endif %}
+{% if val_data and val_data.can_read %}
+    <a href="{{ val_data.view_url }}" class="better-in-overlay">{{ val }}</a>{% for a, u in val_data.list_actions %}
+        <a href={{ u }} class="better-in-overlay"><span class="fa {{ a.action.icon }}" label="{{ a.action.verbose_name.capitalize }}"></span></a>
+    {% endfor %}
+{% else %}
+    {{ val }}{% for a, u in val_data.list_actions %}
+        <a href={{ u }} class="better-in-overlay"><span class="fa {{ a.action.icon }}" label="{{ a.action.verbose_name.capitalize }}"></span></a>
+    {% endfor %}
+{% endif %}

+ 15 - 15
src/rapid/templates/rapid/main_window.html

@@ -1,15 +1,15 @@
-{% extends 'base.html' %}
-
-{% block body %}
-{% load rapid_filters %}{% register_filters %}
-{% load rapid_crud %}{% register_overlay %}
-<div class="data">
-    <style scoped>
-        a.reload{
-            display: none;
-        }
-    </style>
-    <a class="reload" href="{{ this_url }}"></a>
-    <div class="reload-here">{{ body_text|safe }}</div>
-</div>
-{% endblock %}
+{% extends 'base.html' %}
+
+{% block body %}
+{% load rapid_filters %}{% register_filters %}
+{% load rapid_crud %}{% register_overlay %}
+<div class="data">
+    <style scoped>
+        a.reload{
+            display: none;
+        }
+    </style>
+    <a class="reload" href="{{ this_url }}"></a>
+    <div class="reload-here">{{ body_text|safe }}</div>
+</div>
+{% endblock %}

+ 44 - 44
src/rapid/templates/rapid/overlay/text.html

@@ -1,44 +1,44 @@
-<style scoped>
-    div.darkener{
-        position: fixed;
-        left: 0pt;
-        right: 0pt;
-        top: 0pt;
-        bottom: 0pt;
-        z-index: 10;
-        background-color: RGBA(0, 0, 0, 0.5);
-    }
-    a.reload{
-        display: none;
-    }
-    div.overlay{
-        //position: fixed;
-        background-color: RGBA(255, 255, 255, 1);
-        //margin: auto;
-        //top: 4em;
-        z-index: 11;
-        //width: 90%;
-        left: 5%;
-        //margin-left: -45ex;
-        //overflow: visible;
-        padding: 3ex;
-    }
-    div.overlay-data{
-        //overflow: auto;
-    }
-    div.overlay > a.overlay-close{
-        position: absolute;
-        right: -5pt;
-        top: -5pt;
-        font-size: 20pt;
-        border-radius: 20pt;
-        background-color: RGBA(255, 255, 255, 1);
-    }
-</style>
-
-<div class="darkener"></div>
-<div class="overlay data">
-    <a class="reload" href="#"></a>
-    <a href="#" class="overlay-close fa fa-times-circle-o Fechar"></a>
-    <div class="overlay-data reload-here"></div>
-</div>
+<style scoped>
+    div.darkener{
+        position: fixed;
+        left: 0pt;
+        right: 0pt;
+        top: 0pt;
+        bottom: 0pt;
+        z-index: 10;
+        background-color: RGBA(0, 0, 0, 0.5);
+    }
+    a.reload{
+        display: none;
+    }
+    div.overlay{
+        //position: fixed;
+        background-color: RGBA(255, 255, 255, 1);
+        //margin: auto;
+        //top: 4em;
+        z-index: 11;
+        //width: 90%;
+        left: 5%;
+        //margin-left: -45ex;
+        //overflow: visible;
+        padding: 3ex;
+    }
+    div.overlay-data{
+        //overflow: auto;
+    }
+    div.overlay > a.overlay-close{
+        position: absolute;
+        right: -5pt;
+        top: -5pt;
+        font-size: 20pt;
+        border-radius: 20pt;
+        background-color: RGBA(255, 255, 255, 1);
+    }
+</style>
+
+<div class="darkener"></div>
+<div class="overlay data">
+    <a class="reload" href="#"></a>
+    <a href="#" class="overlay-close fa fa-times-circle-o Fechar"></a>
+    <div class="overlay-data reload-here"></div>
+</div>

+ 53 - 53
src/rapid/templates/rapid/widgets/multiple-selector.html

@@ -1,54 +1,54 @@
-<div class="rapid-select {{ id }} data reload-here">
-    <input type="hidden" id="{{ id }}" name="{{ name }}" value="{{ value }}" {% for k, v in attrs %} {{ k }} = "{{ v }}" {% endfor %}>
-    <ul class="rapid-select-selected">
-        {% for e in selected %}
-        <li name="{{ e.pk }}">{{ e }} <a class="rapid-select-remove interaction"><span class="fa {{ icon }}"></span></a></li>
-        {% endfor %}
-    </ul>
-    <a class="rapid-select-add interaction"><span class="fa fa-plus">Adicionar</span></a>
-</div>
-<script>
-    function add_ids_to_{{ id }}(source){
-        var sel = source.find("table.rapid-object-selector");
-        var markers = sel.children("tbody").children("tr.selected").children("td").children("input.rapid-select-id-marker");
-        var old_ids = [];
-        if($("input#{{ id }}").val()){
-            old_ids = $("input#{{ id }}").val().split(",");
-        }
-        var new_ids = [];
-        var new_names = [];
-        markers.each(function(){
-            if (old_ids.indexOf($(this).val()) < 0){
-                new_ids.push($(this).val());
-                new_names.push($(this).attr("name"));
-            }
-        });
-        $("input#{{ id }}").val(old_ids.concat(new_ids).join(","));
-        var widget_root = $("div.rapid-select.{{ id }}").children("ul.rapid-select-selected")
-        for(i = 0; i < new_names.length; i++){
-            var li = $("<li>", {id: new_ids[i]}).html(
-                new_names[i] + " <a class=\"rapid-select-remove\">" +
-                "<span class=\"fa {{ icon }}\"></span></a>");
-            widget_root.append(li);
-        }
-    };
-    function add_elements_to_{{ id }}(){
-        show_overlay("{{ select_url }}", $("div.rapid-select.{{ id }}").find("a.rapid-select-add"), add_ids_to_{{ id }}, false);
-    };
-    $(document).ready(function(){
-        var d = $("div.rapid-select.{{ id }}")
-        d.on("click", ".rapid-select-remove", function(){
-            var rem_id = $(this).closest("li").attr("name");
-            var old_ids = $("input#{{ id }}").val().split(",");
-            for(i = 0; i < old_ids.length; i++){
-                if(old_ids[i] = rem_id){
-                    old_ids.splice(i, 1);
-                    break;
-                }
-            }
-            $("input#{{ id }}").val(old_ids.join(","));
-            $(this).closest("li").remove();
-        });
-        d.find(".rapid-select-add").click(add_elements_to_{{ id }});
-    });
+<div class="rapid-select {{ id }} data reload-here">
+    <input type="hidden" id="{{ id }}" name="{{ name }}" value="{{ value }}" {% for k, v in attrs %} {{ k }} = "{{ v }}" {% endfor %}>
+    <ul class="rapid-select-selected">
+        {% for e in selected %}
+        <li name="{{ e.pk }}">{{ e }} <a class="rapid-select-remove interaction"><span class="fa {{ icon }}"></span></a></li>
+        {% endfor %}
+    </ul>
+    <a class="rapid-select-add interaction"><span class="fa fa-plus">Adicionar</span></a>
+</div>
+<script>
+    function add_ids_to_{{ id }}(source){
+        var sel = source.find("table.rapid-object-selector");
+        var markers = sel.children("tbody").children("tr.selected").children("td").children("input.rapid-select-id-marker");
+        var old_ids = [];
+        if($("input#{{ id }}").val()){
+            old_ids = $("input#{{ id }}").val().split(",");
+        }
+        var new_ids = [];
+        var new_names = [];
+        markers.each(function(){
+            if (old_ids.indexOf($(this).val()) < 0){
+                new_ids.push($(this).val());
+                new_names.push($(this).attr("name"));
+            }
+        });
+        $("input#{{ id }}").val(old_ids.concat(new_ids).join(","));
+        var widget_root = $("div.rapid-select.{{ id }}").children("ul.rapid-select-selected")
+        for(i = 0; i < new_names.length; i++){
+            var li = $("<li>", {id: new_ids[i]}).html(
+                new_names[i] + " <a class=\"rapid-select-remove\">" +
+                "<span class=\"fa {{ icon }}\"></span></a>");
+            widget_root.append(li);
+        }
+    };
+    function add_elements_to_{{ id }}(){
+        show_overlay("{{ select_url }}", $("div.rapid-select.{{ id }}").find("a.rapid-select-add"), add_ids_to_{{ id }}, false);
+    };
+    $(document).ready(function(){
+        var d = $("div.rapid-select.{{ id }}")
+        d.on("click", ".rapid-select-remove", function(){
+            var rem_id = $(this).closest("li").attr("name");
+            var old_ids = $("input#{{ id }}").val().split(",");
+            for(i = 0; i < old_ids.length; i++){
+                if(old_ids[i] = rem_id){
+                    old_ids.splice(i, 1);
+                    break;
+                }
+            }
+            $("input#{{ id }}").val(old_ids.join(","));
+            $(this).closest("li").remove();
+        });
+        d.find(".rapid-select-add").click(add_elements_to_{{ id }});
+    });
 </script>

+ 22 - 22
src/rapid/templates/rapid/widgets/single-selector.html

@@ -1,22 +1,22 @@
-<div class="rapid-select {{ id }} data reload-here">
-    <input type="hidden" id="{{ id }}" name="{{ name }}" value="{{ value }}" {% for k, v in attrs %} {{ k }} = "{{ v }}" {% endfor %}>
-    <span class="value-{{ id }}">{{ selected }}</span>
-    <a class="rapid-select-search interaction"><span class="fa {{ icon }}"></span></a></li>
-</div>
-<script>
-    function select_id_in_{{ id }}(source){
-        var sel = source.find("table.rapid-object-selector");
-        var marker = sel.children("tbody").children("tr.selected").children("td").children("input.rapid-select-id-marker");
-        var new_id = marker.val();
-        var new_name = marker.attr("name");
-        $("input#{{ id }}").val(new_id);
-        $("span.value-{{ id }}").text(new_name);
-    };
-    function search_{{ id }}(){
-        show_overlay("{{ select_url }}", $("div.rapid-select.{{ id }}").find("a.rapid-select-search"), select_id_in_{{ id }});
-    };
-    $(document).ready(function(){
-        var d = $("div.rapid-select.{{ id }}");
-        d.find(".rapid-select-search").click(search_{{ id }});
-    });
-</script>
+<div class="rapid-select {{ id }} data reload-here">
+    <input type="hidden" id="{{ id }}" name="{{ name }}" value="{{ value }}" {% for k, v in attrs %} {{ k }} = "{{ v }}" {% endfor %}>
+    <span class="value-{{ id }}">{{ selected }}</span>
+    <a class="rapid-select-search interaction"><span class="fa {{ icon }}"></span></a>
+</div>
+<script>
+    function select_id_in_{{ id }}(source){
+        var sel = source.find("table.rapid-object-selector");
+        var marker = sel.children("tbody").children("tr.selected").children("td").children("input.rapid-select-id-marker");
+        var new_id = marker.val();
+        var new_name = marker.attr("name");
+        $("input#{{ id }}").val(new_id);
+        $("span.value-{{ id }}").text(new_name);
+    };
+    function search_{{ id }}(){
+        show_overlay("{{ select_url }}", $("div.rapid-select.{{ id }}").find("a.rapid-select-search"), select_id_in_{{ id }});
+    };
+    $(document).ready(function(){
+        var d = $("div.rapid-select.{{ id }}");
+        d.find(".rapid-select-search").click(search_{{ id }});
+    });
+</script>

+ 1 - 0
src/rapid/templatetags/__init__.py

@@ -0,0 +1 @@
+# coding=utf-8

+ 0 - 1
src/rapid/templatetags/rapid_basics.py

@@ -4,7 +4,6 @@ __author__ = 'marcos.medeiros'
 
 from django import template
 from django.template import loader, Context
-import random
 from django.utils.safestring import mark_safe
 
 register = template.Library()

+ 74 - 61
src/rapid/templatetags/rapid_crud.py

@@ -1,61 +1,74 @@
-__author__ = 'marcos.medeiros'
-
-from django import template
-from django.template import loader, Context
-import random
-from django.utils.safestring import mark_safe
-
-register = template.Library()
-
-@register.inclusion_tag('rapid/bare/list.html', takes_context=True)
-def crud_list(context):
-    return context
-
-@register.inclusion_tag('rapid/bare/select.html', takes_context=True)
-def crud_select(context):
-    return context
-
-@register.inclusion_tag('rapid/bare/detail.html', takes_context=True)
-def crud_view(context):
-    return context
-
-@register.inclusion_tag('rapid/bare/update.html', takes_context=True)
-def crud_update(context):
-    return context
-
-@register.inclusion_tag('rapid/bare/create.html', takes_context=True)
-def crud_create(context):
-    return context
-
-@register.inclusion_tag('rapid/bare/delete.html', takes_context=True)
-def crud_delete(context):
-    return context
-
-def random_name():
-    s = "abcdefghijklmnopqrustuvwxyz"
-    return "".join([random.choice(s) for x in xrange(30)])
-
-def render_to_javascript_string(template, context={}):
-    t = loader.get_template(template)
-    c = Context(context)
-    str = t.render(c)
-    str = str.replace("\"", "\\\"")
-    str = str.replace("\n", "\\n")
-    return mark_safe(str)
-
-@register.inclusion_tag('rapid/overlay/register.html')
-def register_overlay():
-    overlay_text = render_to_javascript_string('rapid/overlay/text.html')
-    return {'overlay_text': overlay_text}
-
-@register.inclusion_tag('rapid/overlay/call.html')
-def overlay(target_url, on_commit=None, on_close=None):
-    if not on_commit:
-        on_commit = 'function(){}'
-    if not on_close:
-        on_close = 'function(){}'
-    return {
-        'target_url': target_url,
-        'on_commit': on_commit,
-        'on_close': on_close,
-        }
+# coding=utf-8
+__author__ = 'marcos.medeiros'
+
+from django import template
+from django.template import loader, Context
+import random
+from django.utils.safestring import mark_safe
+
+register = template.Library()
+
+
+@register.inclusion_tag('rapid/bare/list.html', takes_context=True)
+def crud_list(context):
+    return context
+
+
+@register.inclusion_tag('rapid/bare/select.html', takes_context=True)
+def crud_select(context):
+    return context
+
+
+@register.inclusion_tag('rapid/bare/detail.html', takes_context=True)
+def crud_view(context):
+    return context
+
+
+@register.inclusion_tag('rapid/bare/update.html', takes_context=True)
+def crud_update(context):
+    return context
+
+
+@register.inclusion_tag('rapid/bare/create.html', takes_context=True)
+def crud_create(context):
+    return context
+
+
+@register.inclusion_tag('rapid/bare/delete.html', takes_context=True)
+def crud_delete(context):
+    return context
+
+
+def random_name():
+    s = "abcdefghijklmnopqrustuvwxyz"
+    # noinspection PyUnusedLocal
+    return "".join([random.choice(s) for x in range(30)])
+
+
+def render_to_javascript_string(template_name, context=None):
+    context = context if context else {}
+    t = loader.get_template(template_name)
+    c = Context(context)
+    txt = t.render(c)
+    txt = txt.replace("\"", "\\\"")
+    txt = txt.replace("\n", "\\n")
+    return mark_safe(txt)
+
+
+@register.inclusion_tag('rapid/overlay/register.html')
+def register_overlay():
+    overlay_text = render_to_javascript_string('rapid/overlay/text.html')
+    return {'overlay_text': overlay_text}
+
+
+@register.inclusion_tag('rapid/overlay/call.html')
+def overlay(target_url, on_commit=None, on_close=None):
+    if not on_commit:
+        on_commit = 'function(){}'
+    if not on_close:
+        on_close = 'function(){}'
+    return {
+        'target_url': target_url,
+        'on_commit': on_commit,
+        'on_close': on_close,
+        }

+ 36 - 31
src/rapid/templatetags/rapid_filters.py

@@ -1,31 +1,36 @@
-__author__ = 'marcos.medeiros'
-
-from django import template
-from django.utils.safestring import mark_safe
-from django.template import loader, Context
-from rapid import filters
-
-register = template.Library()
-
-_base = 'rapid/filters/'
-
-@register.inclusion_tag(_base+'model_filters.html', takes_context=True)
-def model_filters(context, model):
-    ff = filters.FilterSet.from_request(model, context.request)
-    return {
-        'filters': mark_safe(ff.render_filters(context.request)),
-        'has_filters': ff.has_filters(),
-        'selectors': mark_safe(ff.render_selectors(context.request)),
-    }
-
-@register.inclusion_tag(_base+'register.html', takes_context=True)
-def register_filters(context):
-    return {}
-
-@register.simple_tag(takes_context=True)
-def filter_icon(context, field):
-    if filters.FilterSet.can_filter(field):
-        c = Context({'f': field})
-        t = loader.get_template(_base+'icon.html')
-        return mark_safe(t.render(c))
-    return ''
+# coding=utf-8
+__author__ = 'marcos.medeiros'
+
+from django import template
+from django.utils.safestring import mark_safe
+from django.template import loader, Context
+from rapid import filters
+
+register = template.Library()
+
+_base = 'rapid/filters/'
+
+
+@register.inclusion_tag(_base+'model_filters.html', takes_context=True)
+def model_filters(context, model):
+    ff = filters.FilterSet.from_request(model, context.request)
+    return {
+        'filters': mark_safe(ff.render_filters(context.request)),
+        'has_filters': ff.has_filters(),
+        'selectors': mark_safe(ff.render_selectors(context.request)),
+    }
+
+
+# noinspection PyUnusedLocal
+@register.inclusion_tag(_base+'register.html', takes_context=True)
+def register_filters(context):
+    return {}
+
+
+@register.simple_tag(takes_context=False)
+def filter_icon(field):
+    if filters.FilterSet.can_filter(field):
+        c = Context({'f': field})
+        t = loader.get_template(_base+'icon.html')
+        return mark_safe(t.render(c))
+    return ''

+ 28 - 27
src/rapid/templatetags/rapid_list.py

@@ -1,27 +1,28 @@
-__author__ = 'marcos.medeiros'
-
-from django import template
-
-register = template.Library()
-
-_base = 'rapid/list/'
-
-
-@register.inclusion_tag(_base+'field_header.html')
-def field_header(field):
-    return {'f': field}
-
-
-@register.inclusion_tag(_base+'pagination.html', takes_context=True)
-def pagination(context):
-    return context
-
-
-@register.inclusion_tag(_base+'show_value.html')
-def show_value(val, val_data):
-    return {'val': val, 'val_data': val_data}
-
-
-@register.inclusion_tag(_base+'instance_actions.html')
-def instance_actions(instance):
-    return {'o': instance}
+# coding=utf-8
+__author__ = 'marcos.medeiros'
+
+from django import template
+
+register = template.Library()
+
+_base = 'rapid/list/'
+
+
+@register.inclusion_tag(_base+'field_header.html')
+def field_header(field):
+    return {'f': field}
+
+
+@register.inclusion_tag(_base+'pagination.html', takes_context=True)
+def pagination(context):
+    return context
+
+
+@register.inclusion_tag(_base+'show_value.html')
+def show_value(val, val_data):
+    return {'val': val, 'val_data': val_data}
+
+
+@register.inclusion_tag(_base+'instance_actions.html')
+def instance_actions(instance):
+    return {'o': instance}

+ 73 - 70
src/rapid/templatetags/rapid_menu.py

@@ -1,70 +1,73 @@
-__author__ = 'marcos.medeiros'
-
-import locale
-from django import template
-from django.utils.safestring import mark_safe
-from django.utils.html import escape
-from rapid.registry import registry
-from rapid.wrappers import ModelData
-from django.utils.translation import to_locale, get_language
-
-register = template.Library()
-
-try:
-    locale.setlocale(locale.LC_ALL, str(to_locale(get_language())))
-except:
-    locale.setlocale(locale.LC_ALL, str('C'))
-
-def _app_menu(app, request):
-    models = list(app.models)
-    models.sort(key=lambda m: ModelData(m).model_name(), cmp=locale.strcoll)
-    sub = '<li class="menu-group"><div>%s</div><ul class="submenu">\n' % escape(app.menu_name.capitalize())
-    has_model = False
-    for m in models:
-        st = registry.model_entry(m).get('list')
-        if st:
-            read = st.permission.model(request)
-            if read:
-                has_model = True
-                cd = ModelData(st.model)
-                sub += '<li><a href="%s">%s</a></li>\n' % (
-                    registry.get_url_of_action(m, 'list'),
-                    escape(cd.model_name_plural().title()),
-                )
-    sub += '</ul></li>\n'
-    if has_model:
-        return sub
-    return ""
-
-
-
-@register.simple_tag
-def menu(request):
-    ret = u"""
-    <nav id="menu">
-    <style scoped>
-        nav li.menu-group{
-            cursor: pointer;
-        }
-        nav li.menu-group.collapsed > ul{
-            display: none;
-        }
-    </style>
-    """
-    ret += '<ul class="menu">\n'
-    mm = registry.modules()
-    mm.sort(key=lambda a: a.menu_name, cmp=locale.strcoll)
-    for m in mm:
-        ret += _app_menu(m, request)
-    ret += u"""
-    </ul>
-    <script>
-        $(document).ready(function(){
-            $("nav li.menu-group").addClass("collapsed");
-            $("nav li.menu-group > div").click(function(){$(this).parent().toggleClass("collapsed")});
-        });
-    </script>
-    </nav>
-    """
-    return mark_safe(ret)
-
+# coding=utf-8
+__author__ = 'marcos.medeiros'
+
+import locale
+from django import template
+from django.utils.safestring import mark_safe
+from django.utils.html import escape
+from rapid.registry import registry
+from rapid.wrappers import ModelData
+from django.utils.translation import to_locale, get_language
+
+register = template.Library()
+
+# noinspection PyBroadException
+try:
+    locale.setlocale(locale.LC_ALL, str(to_locale(get_language())))
+except:
+    locale.setlocale(locale.LC_ALL, str('C'))
+
+
+def _app_menu(app, request):
+    models = list(app.models)
+    # noinspection PyTypeChecker
+    models.sort(key=lambda md: ModelData(md).model_name(), cmp=locale.strcoll)
+    sub = '<li class="menu-group"><div>%s</div><ul class="submenu">\n' % escape(app.menu_name.capitalize())
+    has_model = False
+    for m in models:
+        st = registry.model_entry(m).get('list')
+        if st:
+            read = st.permission.model(request)
+            if read:
+                has_model = True
+                cd = ModelData(st.model)
+                sub += '<li><a href="%s">%s</a></li>\n' % (
+                    registry.get_url_of_action(m, 'list'),
+                    escape(cd.model_name_plural().title()),
+                )
+    sub += '</ul></li>\n'
+    if has_model:
+        return sub
+    return ""
+
+
+@register.simple_tag
+def menu(request):
+    ret = u"""
+    <nav id="menu">
+    <style scoped>
+        nav li.menu-group{
+            cursor: pointer;
+        }
+        nav li.menu-group.collapsed > ul{
+            display: none;
+        }
+    </style>
+    """
+    ret += '<ul class="menu">\n'
+    mm = registry.modules()
+    mm.sort(key=lambda a: a.menu_name, cmp=locale.strcoll)
+    for m in mm:
+        ret += _app_menu(m, request)
+    ret += u"""
+    </ul>
+    <script>
+        $(document).ready(function(){
+            $("nav li.menu-group").addClass("collapsed");
+            $("nav li.menu-group > div").click(function(){$(this).parent().toggleClass("collapsed")});
+        });
+    </script>
+    </nav>
+    """
+    return mark_safe(ret)
+

+ 1 - 0
src/rapid/tests.py

@@ -1,3 +1,4 @@
+# coding=utf-8
 from django.test import TestCase
 
 # Create your tests here.