Browse Source

Refatoração do dashboard

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
35f7ecfb5b
  1. 29
      sigi/apps/home/admin.py
  2. 8
      sigi/apps/home/apps.py
  3. 57
      sigi/apps/home/context_processors.py
  4. 1
      sigi/apps/home/fixtures/cards.json
  5. 53
      sigi/apps/home/migrations/0001_initial.py
  6. 0
      sigi/apps/home/migrations/__init__.py
  7. 69
      sigi/apps/home/models.py
  8. 44
      sigi/apps/home/templates/home/dashboard/card.html
  9. 3
      sigi/apps/home/tests.py
  10. 26
      sigi/apps/home/urls.py
  11. 96
      sigi/apps/home/views.py
  12. 1
      sigi/settings.py
  13. 90
      sigi/static/css/dashboard.css
  14. 49
      sigi/static/js/dashboard.js
  15. 40
      sigi/templates/material/admin/index.html
  16. 6
      sigi/templates/sigi/snippets/base_card.html
  17. 68
      sigi/templates/sigi/snippets/dashboard.html

29
sigi/apps/home/admin.py

@ -0,0 +1,29 @@
from django.contrib import admin
from sigi.apps.home.models import Cards, Dashboard
@admin.register(Cards)
class CardAdmin(admin.ModelAdmin):
list_display = ("codigo", "titulo", "categoria", "ordem", "default")
list_editable = ("titulo", "categoria", "ordem", "default")
search_fields = ("titulo", "codigo")
@admin.register(Dashboard)
class DashboardAdmin(admin.ModelAdmin):
list_display = ("card", "categoria", "ordem")
exclude = ("usuario",)
list_editable = ("categoria", "ordem")
autocomplete_fields = ("card",)
def save_model(self, request, obj, form, change):
if not change:
obj.usuario = request.user
if obj.categoria == "":
obj.categoria = obj.card.categoria
if obj.ordem == 0:
obj.ordem = obj.card.ordem
return super().save_model(request, obj, form, change)
def get_queryset(self, request):
return super().get_queryset(request).filter(usuario=request.user)

8
sigi/apps/home/apps.py

@ -0,0 +1,8 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class HomeConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "sigi.apps.home"
verbose_name = _("Home page do SIGI")

57
sigi/apps/home/context_processors.py

@ -0,0 +1,57 @@
from django.urls import reverse
from django.utils.text import slugify
from sigi.apps.home.models import Cards, Dashboard
def get_or_create_dash(usuario):
my_dash = Dashboard.objects.filter(usuario=usuario)
if my_dash.exists():
return [
{
"slug": slugify(categoria),
"label": categoria,
"cards": [d.card for d in my_dash.filter(categoria=categoria)],
}
for categoria in sorted(
set(my_dash.values_list("categoria", flat=True))
)
]
else:
cards = Cards.objects.filter(default=True)
my_dash = [
{
"slug": slugify(categoria),
"label": categoria,
"cards": [card for card in cards.filter(categoria=categoria)],
}
for categoria in sorted(
set(cards.values_list("categoria", flat=True))
)
]
if not usuario.is_anonymous:
for card in cards:
Dashboard(
usuario=usuario,
card=card,
categoria=card.categoria,
ordem=card.ordem,
).save()
return my_dash
def dashboard(request):
if request.path != reverse("admin:index"):
return {}
my_dash = get_or_create_dash(request.user)
selected = request.GET.get("dash", my_dash[0]["slug"])
return {
"sigi_dashes": my_dash,
"sigi_dash_selected": selected,
"sigi_dash_all_categories": [
(slugify(c), c)
for c in sorted(
set(Cards.objects.all().values_list("categoria", flat=True))
)
],
"sigi_dash_all_cards": Cards.objects.all(),
}

1
sigi/apps/home/fixtures/cards.json

@ -0,0 +1 @@
[{"model": "home.cards", "pk": 1, "fields": {"codigo": "resumoseit", "tipo": "T", "nome_url": "home_resumoseit", "query_string": "", "link_acao": false, "titulo": "Serviços hospedados no Interlegis (SEIT)", "descricao": "Tabela com os serviços criados no SEIT por mês", "categoria": "Serviços", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 2, "fields": {"codigo": "chartseit", "tipo": "C", "nome_url": "home_chartseit", "query_string": "", "link_acao": true, "titulo": "Sazonalidade da hospedagem de serviços", "descricao": "Gráfico com a sazonalidade das solicitações de serviços", "categoria": "Serviços", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 3, "fields": {"codigo": "carteira", "tipo": "T", "nome_url": "casas-carteira", "query_string": "snippet=resumo&s=sim", "link_acao": false, "titulo": "Resumo da carteira de relacionamentos", "descricao": "Tabela resumindo a carteira de gerência Interlegis", "categoria": "Gerente", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 4, "fields": {"codigo": "performance", "tipo": "C", "nome_url": "home_chartperformance", "query_string": "", "link_acao": true, "titulo": "Performance da gerência de carteiras", "descricao": "Performance da gerência de carteiras", "categoria": "Gerente", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 5, "fields": {"codigo": "chartcarteira", "tipo": "C", "nome_url": "home_chartcarteira", "query_string": "", "link_acao": false, "titulo": "Distribuição de Casas por Gerente", "descricao": "Distribuição de Casas por Gerente", "categoria": "Gerente", "ordem": 3, "default": true}}, {"model": "home.cards", "pk": 6, "fields": {"codigo": "resumoconvenios", "tipo": "T", "nome_url": "home_resumoconvenios", "query_string": "", "link_acao": false, "titulo": "Resumo de informações", "descricao": "Resumo de informações", "categoria": "Geral", "ordem": 1, "default": true}}]

53
sigi/apps/home/migrations/0001_initial.py

@ -0,0 +1,53 @@
# Generated by Django 4.0.4 on 2022-05-11 14:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Cards',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('codigo', models.CharField(max_length=20, verbose_name='código')),
('tipo', models.CharField(choices=[('T', 'Tabela de dados'), ('C', 'Gráfico')], max_length=1, verbose_name='tipo')),
('nome_url', models.CharField(max_length=30, verbose_name='nome da URL de dados')),
('query_string', models.CharField(blank=True, max_length=100, verbose_name='query string')),
('link_acao', models.BooleanField(default=False, verbose_name='possui link de ação')),
('titulo', models.CharField(max_length=100, verbose_name='título')),
('descricao', models.TextField(verbose_name='descrição')),
('categoria', models.CharField(default='Geral', max_length=40, verbose_name='categoria')),
('ordem', models.PositiveSmallIntegerField(default=0, verbose_name='posição na categoria')),
('default', models.BooleanField(default=False, help_text='Indica se este card deve ser mostrado para usuários anônimos ou que não personalizaram seu dashboard', verbose_name='card padrão')),
],
options={
'verbose_name': 'card',
'verbose_name_plural': 'cards',
'ordering': ('categoria', 'ordem', 'titulo'),
},
),
migrations.CreateModel(
name='Dashboard',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('categoria', models.CharField(blank=True, help_text='Deixando em branco será utilizada a categoria padrão do card', max_length=40, verbose_name='categoria personalizada')),
('ordem', models.PositiveSmallIntegerField(default=0, verbose_name='posição na categoria')),
('card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='home.cards')),
('usuario', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'dashboard',
'verbose_name_plural': 'dashboards',
'ordering': ('usuario', 'categoria', 'ordem'),
},
),
]

0
sigi/apps/home/migrations/__init__.py

69
sigi/apps/home/models.py

@ -0,0 +1,69 @@
from django.db import models
from django.conf import settings
from django.utils.translation import gettext as _
class Cards(models.Model):
TIPO_CHOICES = (
("T", _("Tabela de dados")),
("C", _("Gráfico")),
)
codigo = models.CharField(_("código"), max_length=20)
tipo = models.CharField(_("tipo"), max_length=1, choices=TIPO_CHOICES)
nome_url = models.CharField(_("nome da URL de dados"), max_length=30)
query_string = models.CharField(
_("query string"),
max_length=100,
blank=True,
)
link_acao = models.BooleanField(_("possui link de ação"), default=False)
titulo = models.CharField(_("título"), max_length=100)
descricao = models.TextField(_("descrição"))
categoria = models.CharField(
_("categoria"), max_length=40, default=_("Geral")
)
ordem = models.PositiveSmallIntegerField(
_("posição na categoria"), default=0
)
default = models.BooleanField(
_("card padrão"),
default=False,
help_text=_(
"Indica se este card deve ser mostrado para usuários anônimos ou "
"que não personalizaram seu dashboard"
),
)
class Meta:
ordering = ("categoria", "ordem", "titulo")
verbose_name = _("card")
verbose_name_plural = _("cards")
def __str__(self):
return _(f"{self.titulo} ({self.categoria})")
class Dashboard(models.Model):
usuario = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE
)
card = models.ForeignKey(Cards, on_delete=models.CASCADE)
categoria = models.CharField(
_("categoria personalizada"),
max_length=40,
blank=True,
help_text=_(
"Deixando em branco será utilizada a categoria padrão do card"
),
)
ordem = models.PositiveSmallIntegerField(
_("posição na categoria"), default=0
)
class Meta:
ordering = ("usuario", "categoria", "ordem")
verbose_name = _("dashboard")
verbose_name_plural = _("dashboards")
def __str__(self):
return _(f"{self.usuario.get_full_name()} - {self.card}")

44
sigi/apps/home/templates/home/dashboard/card.html

@ -0,0 +1,44 @@
{% load i18n static material %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"pt-br" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{{ card.titulo }}</title>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="robots" content="NONE,NOARCHIVE">
<link rel="stylesheet" href="{% static 'material/admin/css/materialize.min.css' %}">
<link href="{% static 'material/admin/css/material_icons.min.css' %}" rel="stylesheet">
<style>
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url('{% static 'material/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2' %}') format('woff2');
}
#footer {
font-size: 0.7em;
}
</style>
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/app_content.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site-responsive.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/jquery.jscrollpane.min.css' %}">
<script src="{% static '/material/admin/js/materialize.min.js' %}"></script>
<script src="{% static 'material/admin/js/jquery.min.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site-green.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'material/admin/css/base_site-theme.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/dashboard.css' %}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="{% static 'js/dashboard.js' %}"></script>
</head>
<body data-admin-utc-offset="{% now 'Z' %}">
<div id="container">
<div id="content" class="colM">
{% include 'sigi/snippets/dashboard.html' %}
<br class="clear">
</div>
<div id="footer">
<p>Fonte: <a href="{% url 'admin:index' %}">SIGI - Sistema de Informações Gerenciais do Interlegis</a></p>
</div>
</div>
</body>

3
sigi/apps/home/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

26
sigi/apps/home/urls.py

@ -28,6 +28,32 @@ urlpatterns = [
views.report_sem_convenio,
name="home_reportsemconvenio",
),
path(
"home/dashboard/card/<slug:card_code>/",
views.card_snippet,
name="home_cardsnippet",
),
path(
"home/dashboard/addtab/<slug:tab_slug>/",
views.card_add_tab,
name="home_card_add_tab",
),
path(
"home/dashboard/changetab/",
views.card_rename_tab,
name="home_card_rename_tab",
),
path(
"home/dashboard/reorder/",
views.card_reorder,
name="home_card_reorder",
),
path(
"home/dashboard/remove/<categoria>/<slug:codigo>/",
views.card_remove,
name="home_card_remove",
),
path("home/dashboard/addcard/", views.card_add, name="home_add_card"),
]
# from django.conf.urls import patterns, url

96
sigi/apps/home/views.py

@ -2,19 +2,28 @@ import calendar
import csv
import datetime
from itertools import cycle
from django.contrib import messages
from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.db import models
from django.db.models import Q, Count
from django.http import HttpResponse, HttpResponseForbidden, JsonResponse
from django.http import (
HttpResponse,
HttpResponseForbidden,
HttpResponseRedirect,
JsonResponse,
)
from django.shortcuts import render, get_object_or_404
from django.template.loader import render_to_string
from django.utils.text import slugify
from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import TipoOrgao, Orgao
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.home.models import Cards, Dashboard
from sigi.apps.servicos.models import TipoServico
from sigi.apps.servidores.models import Servidor
from sigi.apps.utils import to_ascii
@ -227,6 +236,91 @@ def openmapsearch(request):
return JsonResponse(list(dados), safe=False)
def card_snippet(request, card_code):
card = get_object_or_404(Cards, codigo=card_code)
if not card.default:
raise PermissionDenied()
return render(request, "home/dashboard/card.html", {"dash_cards": [card]})
@login_required
def card_add_tab(request, tab_slug):
for card in Cards.objects.all():
if slugify(card.categoria) == tab_slug:
Dashboard(
usuario=request.user,
card=card,
categoria=card.categoria,
ordem=card.ordem,
).save()
return HttpResponseRedirect(reverse("admin:index"))
@login_required
def card_rename_tab(request):
dados = request.POST.copy()
dados.pop("csrfmiddlewaretoken")
categoria_atual = dados.pop("categoria_atual")[0]
categoria_nova = dados.pop("categoria_nova")[0]
if categoria_nova != "" and categoria_nova != categoria_atual:
Dashboard.objects.filter(
usuario=request.user, categoria=categoria_atual
).update(categoria=categoria_nova)
messages.success(request, _("Tab renomeada com sucesso"))
else:
messages.warning(request, _("Não foi possível renomear a tab"))
return HttpResponseRedirect(reverse("admin:index"))
@login_required
def card_reorder(request):
dados = request.GET.copy()
categoria = dados.pop("categoria")[0]
for codigo, nova_ordem in dados.items():
Dashboard.objects.filter(
usuario=request.user, card__codigo=codigo, categoria=categoria
).update(ordem=nova_ordem)
return JsonResponse({"result": "Done"})
@login_required
def card_remove(request, categoria, codigo):
dash = get_object_or_404(
Dashboard, categoria=categoria, card__codigo=codigo
)
dash.delete()
messages.success(request, _("Card removido"))
return HttpResponseRedirect(reverse("admin:index"))
@login_required
def card_add(request):
categoria = request.POST.get("categoria", None)
codigos = request.POST.getlist("card_id", None)
if categoria is None or codigos is None:
messages.error(request, _("Nenhum card adicionado!"))
else:
criados = 0
for codigo in codigos:
card = get_object_or_404(Cards, codigo=codigo)
dash, created = Dashboard.objects.get_or_create(
{"ordem": card.ordem},
usuario=request.user,
card=card,
categoria=categoria,
)
if created:
criados += 1
if criados > 0:
messages.success(
request, _(f"{criados} card(s) adicionado(s) na aba")
)
else:
messages.info(request, _("Estes cards já estão na aba"))
return HttpResponseRedirect(reverse("admin:index"))
# @never_cache
# @login_required
# def index(request):

1
sigi/settings.py

@ -110,6 +110,7 @@ TEMPLATES = [
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.media",
"sigi.apps.home.context_processors.dashboard",
],
},
},

90
sigi/static/css/dashboard.css

@ -5,6 +5,7 @@ table.servicos {
table.numeros>tbody>tr>td {
text-align: right;
}
.app>.card>.card-content>.card-title {
font-size: 16px;
font-weight: bolder;
@ -13,7 +14,7 @@ table.numeros>tbody>tr>td {
.full-preloader {
width: 100%;
height: 100%;
background-color: rgb(255,255,255,0.8);
background-color: rgb(255, 255, 255, 0.8);
position: absolute;
z-index: 2;
display: flex;
@ -35,3 +36,90 @@ table.numeros>tbody>tr>td {
.card-links {
padding: 0 24px;
}
.tab-edit,
.tab-control {
display: inline-block;
text-align: center;
line-height: 48px;
height: 48px;
padding: 0;
margin: 0;
text-transform: uppercase;
}
.tab-edit a,
.tab-control a {
display: block;
width: 100%;
height: 100%;
padding: 0 24px;
font-size: 14px;
text-overflow: ellipsis;
overflow: hidden;
transition: color .28s ease, background-color .28s ease;
}
.dashbar {
background: var(--main-hover-color);
opacity: .8;
color: #fff;
padding: 10px;
border: none;
text-align: left;
}
.dashtabs {
position: relative;
overflow-x: auto;
overflow-y: hidden;
height: 48px;
width: 100%;
background-color: #fff;
margin: 0 auto;
white-space: nowrap;
list-style-type: none;
display: block;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 40px;
}
.dashtabs .tabitem {
display: inline-block;
font-weight: normal;
height: 48px;
line-height: 48px;
margin: 0;
padding: 0;
text-transform: uppercase;
text-align: center;
}
.dashtabs .tabitem .active {
font-weight: bolder;
}
.dashtabs .tabitem a,
.dashtabs .tabitem p {
display: block;
width: 100%;
height: 100%;
padding: 0 24px;
font-size: 14px;
text-overflow: ellipsis;
overflow: hidden;
}
.dashtabs .tabitem i {
line-height: unset;
color: var(--primary);
}
.dash-modal-header {
font-size: 1.2em;
display: block;
text-transform: uppercase;
}

49
sigi/static/js/dashboard.js

@ -1,12 +1,35 @@
$(document).ready(function () {
M.Tabs.init($('.tabs'), {});
$(".dash-control").hide();
$(".tab-edit a").off("click").on("click", function (e) {
e.preventDefault();
$(".dash-control").toggle();
if ($(".dash-control").is(':visible')) {
$(".sortable").sortable({
update: function (e, ui) {
var parent = ui.item.parent();
var url = parent.attr("data-target-url");
var dados = { 'categoria': parent.attr("data-tab-name") };
parent.children().each(function (pos) {
dados[$(this).attr("data-card-id")] = pos + 1;
})
$.get(url, dados, function () {
M.toast({ html: 'Ordem alterada' })
});
}
});
} else {
$(".sortable").sortable("disable");
}
})
Chart.defaults.plugins.legend.labels.usePointStyle = true;
setlinks();
$("div[data-source]").each(function(index, container) {
$("div[data-source]").each(function (index, container) {
var container = $(container);
var url = container.attr('data-source');
get_content(container, url);
});
$("canvas[data-source]").each(function(index, canvas) {
$("canvas[data-source]").each(function (index, canvas) {
var canvas = $(canvas)
var url = canvas.attr("data-source");
plot_chart(canvas, url);
@ -14,13 +37,17 @@ $(document).ready(function () {
});
function setlinks() {
$('.modal').modal();
$('.dropdown-trigger').dropdown();
$('.collapsible').collapsible();
$("a.dashlink[data-target]").off('click').on('click', function(e) {
try {
M.Modal.init($('.modal'), {});
M.Dropdown.init($('.dropdown-trigger'), {});
M.Collapsible.init($('.collapsible'), {});
} catch (e) {
console.log("A exception has ocurred", e)
}
$("a.dashlink[data-target]").off('click').on('click', function (e) {
e.preventDefault();
var $this = $(this);
var target = $("#"+$this.attr('data-target'));
var target = $("#" + $this.attr('data-target'));
var url = $this.attr('href');
if (target.is("canvas")) {
plot_chart(target, url);
@ -32,18 +59,18 @@ function setlinks() {
function get_content(container, url) {
container.closest('.card').find('.full-preloader').removeClass('hide');
$.get(url, function(data) {
$.get(url, function (data) {
container.html(data);
container.closest('.card').find('.full-preloader').addClass('hide');
setlinks();
}).fail(function() {
}).fail(function () {
container.closest('.card').find('.full-preloader').html("Ocorreu um erro. Tente recarregar a página");
});
}
function plot_chart(canvas, url) {
canvas.closest('.card').find('.full-preloader').removeClass('hide');
$.get(url, function(data) {
$.get(url, function (data) {
var chart_name = canvas.attr("data-chart-name");
var has_action_links = canvas.attr("data-has-action-links");
@ -66,7 +93,7 @@ function plot_chart(canvas, url) {
}
setlinks();
canvas.closest('.card').find('.full-preloader').addClass('hide');
}).fail(function() {
}).fail(function () {
canvas.closest('.card').find('.full-preloader').html("Ocorreu um erro. Tente recarregar a página");
});
}

40
sigi/templates/material/admin/index.html

@ -11,8 +11,46 @@
{{ block.super }}
{% endblock %}
{% block breadcrumbs %}
<div class="dashbar">
<ul class="tabs">
{% if sigi_dashes|length > 1 %}
{% for dash in sigi_dashes %}
<li class="tab">
<a href="#dashtab-{{ dash.slug }}"{% if sigi_dash_selected == dash.slug %} class="active"{% endif %}>{{ dash.label }}</a>
</li>
{% endfor %}
<li class="dash-control tab-control">
<a href="#dashcontrol-addtab" class="waves-effect waves-light modal-trigger"><i class="material-icons tiny">add</i>{% trans "Adicionar tab" %}</a>
</li>
<li class="tab-edit right">
<a href="#" title="{% trans 'Modo de ediçao' %}"><i class="material-icons tiny">edit</i></a>
</li>
{% endif %}
</ul>
</div>
{% endblock %}
{% block content %}
{% include 'sigi/snippets/dashboard.html' %}
<div id="dashcontrol-addtab" class="modal">
<div class="modal-content">
<h5>Adicionar nova tab</h5>
<p>{% trans "Selecione a categoria a ser adicionada" %}</p>
<ul class="collection">
{% for slug, label in sigi_dash_all_categories %}
<li class="collection-item"><div>{{ label }}<a href="{% url 'home_card_add_tab' slug %}" class="secondary-content" title="{% trans 'Adicionar' %}"><i class="material-icons">add</i></a></div></li>
{% endfor %}
</ul>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Agree</a>
</div>
</div>
{% for dash in sigi_dashes %}
<div id="dashtab-{{ dash.slug }}" class="col s12">
{% include 'sigi/snippets/dashboard.html' %}
</div>
{% endfor %}
{% endblock %}
{% block footer %}

6
sigi/templates/sigi/snippets/base_card.html

@ -18,7 +18,11 @@
</div>
</div>
<div class="card-content">
<div class="card-title">{% block card-title %}{% translate card_title|default:"" %}{% endblock %}</div>
<div class="card-title">
<i class="material-icons left dash-control" style="cursor: move;">drag_handle</i>
{% block card-title %}{% translate card_title|default:"" %}{% endblock %}
<a href="{% url 'home_card_remove' dash.label card.codigo %}" class="dash-control" title="{% trans 'Remove este card' %}"><i class="material-icons right">close</i></a>
</div>
<div class="card-content-wrapper">
{% block card-content %}{% endblock card-content %}
</div>

68
sigi/templates/sigi/snippets/dashboard.html

@ -1,23 +1,55 @@
{% load i18n %}
<div class="content-wrapper">
<div class="app-list">
{% url "home_resumoseit" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Serviços hospedados no Interlegis (SEIT)" data_source=source_url card_name="resumoseit" %}
{% url "home_chartseit" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Sazonalidade da hospedagem de serviços" data_source=source_url chart_name="evolucao-servicos" has_action_links="1" %}
{% url "casas-carteira" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Resumo da carteira de relacionamentos" data_source=source_url|add:"?snippet=resumo&s=sim" card_name="carteira" %}
{% url "home_chartperformance" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Performance da gerência de carteiras" data_source=source_url chart_name="performance" has_action_links="1" %}
{% url "home_chartcarteira" as source_url %}
{% include "sigi/snippets/base_card_chart.html" with card_title="Distribuição de Casas por Gerente" data_source=source_url chart_name="carteira" %}
{% url "home_resumoconvenios" as source_url %}
{% include "sigi/snippets/base_card_text.html" with card_title="Resumo de informações" data_source=source_url card_name="resumo-convenios" %}
<div class="app dash-control">
<div class="card lime lighten-3">
<form action="{% url 'home_card_rename_tab' %}" method="post">{% csrf_token %}
<div class="card-content white-text">
<input type="hidden" name="categoria_atual" value="{{ dash.label }}"/>
<div class="input-field">
<label for="id_categoria_nova">{% trans 'Renomear a aba' %}</label>
<input placeholder="{% trans 'Nome da aba' %}" id="id_categoria_nova" name="categoria_nova" type="text" class="validate" value="{{ dash.label }}" required>
</div>
</div>
<div class="card-action">
<button type="submit" class="waves-effect btn-flat right">{% trans "Renomear" %}</button>
</div>
</form>
</div>
</div>
<ul class="sortable" data-tab-name="{{ dash.label }}" data-target-url="{% url 'home_card_reorder' %}">
{% for card in dash.cards %}
<li data-card-id="{{ card.codigo }}">
{% url card.nome_url as source_url %}
{% if card.tipo == 'C' %}
{% include "sigi/snippets/base_card_chart.html" with card_title=card.titulo data_source=source_url|add:"?"|add:card.query_string chart_name=card.codigo has_action_links=card.link_acao %}
{% else %}
{% include "sigi/snippets/base_card_text.html" with card_title=card.titulo data_source=source_url|add:"?"|add:card.query_string card_name=card.codigo %}
{% endif %}
</li>
{% endfor %}
</ul>
<div class="app dash-control">
<div class="card lime lighten-3">
<form action="{% url 'home_add_card' %}" method="post">{% csrf_token %}
<div class="card-content white-text">
<input type="hidden" name="categoria" value="{{ dash.label }}"/>
<ul class="collection">
{% for card in sigi_dash_all_cards %}
<li class="collection-item">
<label>
<input type="checkbox" name="card_id" value="{{ card.codigo }}"/>
<span>{{ card.titulo }}</span>
</label>
</li>
{% endfor %}
</ul>
</div>
<div class="card-action">
<button type="submit" class="waves-effect btn-flat right">{% trans "Adicionar selecionados" %}</button>
</div>
</form>
</div>
</div>
</div>
</div>

Loading…
Cancel
Save