Browse Source

Melhorias no calendário de eventos. Gertiq #160528

pull/166/head
Sesóstris Vieira 1 year ago
parent
commit
008ea4f6f2
  1. 32
      sigi/apps/eventos/static/css/calendario.css
  2. 102
      sigi/apps/eventos/templates/eventos/calendario.html
  3. 80
      sigi/apps/eventos/templates/eventos/calendario_pdf.html
  4. 38
      sigi/apps/eventos/templates/eventos/snippets/calendario_cal.html
  5. 10
      sigi/apps/eventos/templates/eventos/snippets/calendario_lista.html
  6. 104
      sigi/apps/eventos/views.py

32
sigi/apps/eventos/static/css/calendario.css

@ -2,14 +2,18 @@
display: block; display: block;
} }
.evento {
padding: 0 6px;
}
.data-evento { .data-evento {
font-size: 0.6em; font-size: 0.9em;
color: var(--body-quiet-color); color: var(--body-quiet-color);
display: block; display: block;
} }
.tipo-evento { .tipo-evento {
font-size: 0.6em; font-size: 0.9em;
color: var(--body-quiet-color); color: var(--body-quiet-color);
display: block; display: block;
margin-bottom: 8px; margin-bottom: 8px;
@ -32,11 +36,27 @@ table {
table-layout: fixed; table-layout: fixed;
} }
table td, tr {
table td * { border-bottom: none;
vertical-align: top; }
tr td {
padding: 0px 10px;
}
tr.linha-dias {
background: var(--darkened-bg);
} }
span.numero-dia { span.numero-dia {
font-size: 0.5em; font-size: 1em;
}
tr.linha-evento {
background: var(--body-bg);
}
.calendar-wrapper {
width: 100%;
} }

102
sigi/apps/eventos/templates/eventos/calendario.html

@ -1,54 +1,79 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n %} {% load i18n static %}
{% load static %}
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<link rel="stylesheet" type="text/css" href="/static/css/calendario.css"> <link rel="stylesheet" type="text/css" href="/static/css/calendario.css">
{% endblock %} {% endblock %}
{% block breadcrumbs %}{% endblock %} {% block breadcrumbs %}{% endblock %}
{% block coltype %}colMS{% endblock %} {% block coltype %}colMS{% endblock %}
{% block content %} {% block content %}
<div class="fixed-action-btn"> <div class="fixed-action-btn">
<a class="btn-floating"> <a class="btn-floating">
<i class="large material-icons">mode_edit</i> <i class="large material-icons">mode_edit</i>
</a> </a>
<ul> <ul>
<li> <li>
{% if formato == 'cal' %} {% if formato == 'cal' %}
<a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&fmt=tab" title="{% trans 'Formato de lista' %}"><i class="material-icons">view_list</i></a> <a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&fmt=tab&categoria={{ sel_categorias|join:"&categoria=" }}&status={{ sel_status|join:"&status=" }}" title="{% trans 'Formato de lista' %}"><i class="material-icons">view_list</i></a>
{% else %} {% else %}
<a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&fmt=cal" title="{% trans 'Formato de calendário' %}"><i class="material-icons">date_range</i></a> <a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&fmt=cal&categoria={{ sel_categorias|join:"&categoria=" }}&status={{ sel_status|join:"&status=" }}" title="{% trans 'Formato de calendário' %}"><i class="material-icons">date_range</i></a>
{% endif %} {% endif %}
<li> </li>
<a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&pdf=1" target="_blank"><i class="material-icons">picture_as_pdf</i></a> <li>
</li> <a class="btn-floating btn-small" href="?ano={{ ano_pesquisa|safe }}&mes={{ mes_pesquisa|safe }}&pdf=1&categoria={{ sel_categorias|join:"&categoria=" }}&status={{ sel_status|join:"&status=" }}" target="_blank"><i class="material-icons">picture_as_pdf</i></a>
</ul> </li>
</ul>
</div>
<div class="row">
<div class="col s12">
<ul class="tabs">
{% for ano in meses %}
<li class="tab col"><a {% if ano == ano_pesquisa %}class="active"{% endif %} href="#tab-{{ ano|safe }}">{{ ano| safe }}</a></li>
{% endfor %}
</ul>
</div> </div>
{% for ano, lista in meses.items %}
<div id="tab-{{ ano|safe }}" class="col s12">
{% for mes, nome in lista.items %}
<a class="waves-effect waves-light btn-flat btn-small{% if ano == ano_pesquisa and mes == mes_pesquisa %} disabled{% endif %}" href="?ano={{ ano|safe }}&mes={{ mes|safe }}&fmt={{ formato }}&categoria={{ sel_categorias|join:"&categoria=" }}&status={{ sel_status|join:"&status=" }}">{{ nome }}</a>
{% endfor %}
</div>
{% endfor %}
</div>
<form id="form_flags" method="get" action="">
<input type="hidden" name="ano" value="{{ ano_pesquisa|safe }}"/>
<input type="hidden" name="mes" value="{{ mes_pesquisa|safe }}"/>
<input type="hidden" name="fmt" value="{{ formato }}"/>
<div class="row"> <div class="row">
<div class="col s12"> {% for key, data in categorias.items %}
<ul class="tabs"> <div class="col s{% widthratio 12 categorias|length 1%} {{ data.color }} lighten-4">
{% for ano in meses %} <label>
<li class="tab col"><a {% if ano == ano_pesquisa %}class="active"{% endif %} href="#tab-{{ ano|safe }}">{{ ano| safe }}</a></li> <input type="checkbox" class="filled-in" name="categoria" value="{{ key }}"{% if key in sel_categorias %} checked{% endif %}/>
{% endfor %} <span>{{ data.label }}</span>
</ul> </label>
</div> </div>
{% for ano, lista in meses.items %} {% endfor %}
<div id="tab-{{ ano|safe }}" class="col s12"> </div>
{% for mes, nome in lista.items %} <div class="row">
<a class="waves-effect waves-light btn-flat btn-small{% if ano == ano_pesquisa and mes == mes_pesquisa %} disabled{% endif %}" href="?ano={{ ano|safe }}&mes={{ mes|safe }}&fmt={{ formato }}">{{ nome }}</a> {% for key, data in status.items %}
{% endfor %} <div class="col s{% widthratio 12 status|length 1 %}">
<label>
<input type="checkbox" class="filled-in" name="status" value="{{ key }}"{% if key in sel_status %} checked{% endif %}/>
<span><i class="material-icons tiny"> {{ data.icon }}</i> {{ data.label }}</span>
</label>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% if formato == "cal" %} </form>
{% include "eventos/snippets/calendario_cal.html" %} {% if formato == "cal" %}
{% else %} {% include "eventos/snippets/calendario_cal.html" %}
{% include "eventos/snippets/calendario_lista.html" %} {% else %}
{% endif %} {% include "eventos/snippets/calendario_lista.html" %}
{% include "eventos/snippets/calendario_modals.html" %} {% endif %}
{% include "eventos/snippets/calendario_modals.html" %}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}
@ -58,6 +83,9 @@
M.Tabs.init($('.tabs'), {}); M.Tabs.init($('.tabs'), {});
M.Modal.init($(".modal"), {}); M.Modal.init($(".modal"), {});
M.FloatingActionButton.init($(".fixed-action-btn"), {hoverEnabled: false}); M.FloatingActionButton.init($(".fixed-action-btn"), {hoverEnabled: false});
$("input[name='categoria']").on("change", function() {
$("#form_flags").submit();
});
}); });
</script> </script>
{% endblock %} {% endblock %}

80
sigi/apps/eventos/templates/eventos/calendario_pdf.html

@ -9,13 +9,28 @@
} }
table { table {
table-layout: fixed; table-layout: fixed;
} }
.calendar-table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #d2d2d2;
}
.calendar-table td+td {
border-left: 1px solid #d2d2d2 !important;
}
table td, table td,
table td * { table td * {
vertical-align: top; vertical-align: top;
} }
.calendar-table tr:nth-child(even) {
background-color: white !important;
}
tr.linha-dias {
background: #d2d2d2;
border-top: 1px solid #d2d2d2;
}
span.numero-dia { span.numero-dia {
font-size: 0.5em; font-size: 1em;
} }
.card { .card {
background-color: #fff; background-color: #fff;
@ -33,27 +48,70 @@
margin-bottom: -6px !important; margin-bottom: -6px !important;
} }
.data-evento { .data-evento {
font-size: 0.7em; font-size: 1em;
display: block; display: block;
} }
.tipo-evento { .tipo-evento {
font-size: 0.7em; font-size: 1em;
color: var(--body-quiet-color); color: var(--body-quiet-color);
display: block; display: block;
margin-bottom: 8px; margin-bottom: 8px;
} }
.cyan.lighten-4 { background-color: #b2ebf2 !important; } .evento {
margin: 0;
padding: 5px 10px;
}
.cyan.lighten-4 { background-color: #b2ebf2!important; }
.red.lighten-4 { background-color: #ffcdd2!important; }
.purple.lighten-4 { background-color: #e1bee7!important; }
.blue.lighten-4 { background-color: #bbdefb!important; }
.orange.lighten-4 { background-color: #ffe0b2!important; }
.brown.lighten-4 { background-color: #d7ccc8 !important; } .brown.lighten-4 { background-color: #d7ccc8 !important; }
.deep-orange.lighten-4 { background-color: #ffccbc !important; } @font-face {
.cyan.lighten-4 { background-color: #b2ebf2 !important; } font-family: 'Material Icons';
.green.lighten-4 { background-color: #c8e6c9 !important; } font-style: normal;
.lime.lighten-4 { background-color: #f0f4c3 !important; } font-weight: 400;
src: url('/static/material/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2') format('woff2');
}
i.tiny { font-size: 1rem; }
.material-icons {
font-family: "Material Icons";
font-weight: 400;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: "liga";
-webkit-font-smoothing: antialiased;
}
{% endblock %} {% endblock %}
{% block main_content %} {% block main_content %}
<h1> <h1>
{% blocktrans with month=mes_pesquisa|stringformat:"02d" year=ano_pesquisa|stringformat:"04d" %}Ref: {{ month }}/{{year}}{% endblocktrans %} {% blocktrans with month=mes_pesquisa|stringformat:"02d" year=ano_pesquisa|stringformat:"04d" %}Mês: {{ month }}/{{year}}{% endblocktrans %}
</h1> </h1>
<table>
<tr>
<th style="width: 12em;">Categorias:</th>
{% for key, data in categorias.items %}
{% if key in sel_categorias %}<td class="{{ data.color }} lighten-4">{{ data.label }}</td>{% endif %}
{% endfor %}
</tr>
</table>
<table>
<tr>
<th style="width: 12em;">Status:</th>
{% for key, data in status.items %}
{% if key in sel_status %}<td><i class="material-icons tiny"> {{ data.icon }}</i> {{ data.label }}</td>{% endif %}
{% endfor %}
</tr>
</table>
<br/>
{% include "eventos/snippets/calendario_cal.html" %} {% include "eventos/snippets/calendario_cal.html" %}
{% include "eventos/snippets/calendario_lista.html" %} {% include "eventos/snippets/calendario_lista.html" %}
{% endblock main_content %} {% endblock main_content %}

38
sigi/apps/eventos/templates/eventos/snippets/calendario_cal.html

@ -1,8 +1,7 @@
{% load i18n %} {% load i18n static dict_get %}
{% load static %}
<div style="width: 100%;"> <div class="calendar-wrapper">
<table class=""> <table class="calendar-table">
<thead> <thead>
{% for name in day_names %} {% for name in day_names %}
<th>{{ name }}</th> <th>{{ name }}</th>
@ -10,18 +9,29 @@
</thead> </thead>
<tbody> <tbody>
{% for semana in semanas %} {% for semana in semanas %}
<tr> <tr class="linha-dias">
{% for dia in semana %} {% for dia in semana.datas %}
<td> <td>
<span class="numero-dia">{{ dia.0 }}</span> <span class="numero-dia">
{% for evento in dia.1 %} {% if dia.month == mes_pesquisa %}{{ dia.day }}{% endif %}
<p class="evento {% include 'eventos/snippets/calendario_status_color.html' with status=evento.status %}"> </span>
<a class="modal-trigger" href="#modal{{ evento.id|safe }}" title="{{ evento.nome }}">{{ evento.nome }}</a> </td>
</p>
{% endfor %} {% endfor %}
</td> </tr>
{% for evento, tupla in semana.eventos %}
<tr class="linha-evento">
{% for x in ""|ljust:tupla.0|make_list %}<td></td>{% endfor %}
<td colspan="{{ tupla.1 }}" class="{{ categorias|get:evento.tipo_evento.categoria|get:"color" }} lighten-4">
<p class="evento">
<i class="material-icons tiny">{{ status|get:evento.status|get:"icon" }}</i>
<a class="modal-trigger" href="#modal{{ evento.id|safe }}" title="{{ evento.nome }}">{{ evento.nome }}</a>
</p>
</td>
{% for x in ""|ljust:tupla.2|make_list %}<td></td>{% endfor %}
</tr>
{% empty %}
<td colspan="7">&nbsp;</td>
{% endfor %} {% endfor %}
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>

10
sigi/apps/eventos/templates/eventos/snippets/calendario_lista.html

@ -1,12 +1,14 @@
{% load i18n %} {% load i18n static dict_get %}
{% load static %}
{% for evento in eventos %} {% for evento in eventos %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<div class="card {% include 'eventos/snippets/calendario_status_color.html' with status=evento.status %}"> <div class="card {{ categorias|get:evento.tipo_evento.categoria|get:"color" }} lighten-4">
<div class="card-content"> <div class="card-content">
<span class="card-title">{{ evento.nome }}</span> <span class="card-title">
<i class="material-icons tiny">{{ status|get:evento.status|get:"icon" }}</i>
{{ evento.nome }}
</span>
<span class="data-evento">{{ evento.data_inicio }} a {{ evento.data_termino }}</span> <span class="data-evento">{{ evento.data_inicio }} a {{ evento.data_termino }}</span>
<span class="tipo-evento"> <span class="tipo-evento">
{{ evento.tipo_evento }} - {{ evento.tipo_evento }} -

104
sigi/apps/eventos/views.py

@ -27,7 +27,7 @@ from django_weasyprint.views import WeasyTemplateResponse
from weasyprint import HTML from weasyprint import HTML
from sigi.apps.casas.models import Funcionario, Orgao from sigi.apps.casas.models import Funcionario, Orgao
from sigi.apps.convenios.models import Projeto from sigi.apps.convenios.models import Projeto
from sigi.apps.eventos.models import Evento, Convite, Anexo from sigi.apps.eventos.models import TipoEvento, Evento
from sigi.apps.eventos.forms import ( from sigi.apps.eventos.forms import (
SelecionaModeloForm, SelecionaModeloForm,
ConviteForm, ConviteForm,
@ -44,6 +44,12 @@ from sigi.apps.servidores.models import Servidor
def calendario(request): def calendario(request):
mes_pesquisa = int(request.GET.get("mes", timezone.localdate().month)) mes_pesquisa = int(request.GET.get("mes", timezone.localdate().month))
ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year)) ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year))
sel_categorias = request.GET.getlist(
"categoria", [c[0] for c in TipoEvento.CATEGORIA_CHOICES]
)
sel_status = request.GET.getlist(
"status", [s[0] for s in Evento.STATUS_CHOICES]
)
formato = request.GET.get("fmt", "cal") formato = request.GET.get("fmt", "cal")
pdf = bool(request.GET.get("pdf", 0)) pdf = bool(request.GET.get("pdf", 0))
@ -66,49 +72,83 @@ def calendario(request):
Evento.objects.exclude(data_inicio=None) Evento.objects.exclude(data_inicio=None)
.exclude(data_termino=None) .exclude(data_termino=None)
.filter( .filter(
data_inicio__year=ano_pesquisa, data_inicio__month=mes_pesquisa data_inicio__year=ano_pesquisa,
data_inicio__month=mes_pesquisa,
status__in=sel_status,
tipo_evento__categoria__in=sel_categorias,
) )
.order_by("data_inicio")
) )
context = {} context = {
"ano_pesquisa": ano_pesquisa,
"mes_pesquisa": mes_pesquisa,
"formato": formato,
"sel_categorias": sel_categorias,
"categorias": dict(
map(
lambda x, y: (x[0], {"label": x[1], "color": y}),
TipoEvento.CATEGORIA_CHOICES,
["red", "purple", "blue", "orange", "brown"],
)
),
"sel_status": sel_status,
"status": dict(
map(
lambda x, y: (x[0], {"label": x[1], "icon": y}),
Evento.STATUS_CHOICES,
[
"assignment",
"hourglass_empty",
"access_time",
"thumbs_up_down",
"thumb_up",
"done_all",
"mood_bad",
"archive",
],
)
),
"meses": meses,
"day_names": calendar.day_abbr,
"eventos": eventos,
}
if formato == "cal" or pdf: if formato == "cal" or pdf:
semanas = calendar.Calendar().monthdatescalendar( semanas = [
ano_pesquisa, mes_pesquisa {"datas": s, "eventos": []}
) for s in calendar.Calendar().monthdatescalendar(
for semana in semanas: ano_pesquisa, mes_pesquisa
for dia in semana: )
if dia.month == mes_pesquisa: ]
semana[dia.weekday()] = (
dia.day, for e in eventos:
[ for s in semanas:
e if not (
for e in eventos (e.data_termino.date() < s["datas"][0])
if e.data_inicio.day or (e.data_inicio.date() > s["datas"][-1])
<= dia.day ):
<= e.data_termino.day start = max(s["datas"][0], e.data_inicio.date())
], end = min(s["datas"][-1], e.data_termino.date())
s["eventos"].append(
(
e,
(
start.weekday(),
end.weekday() - start.weekday() + 1,
6 - end.weekday(),
),
)
) )
else:
semana[dia.weekday()] = ("", [])
context["semanas"] = semanas
context.update( context["semanas"] = semanas
{
"ano_pesquisa": ano_pesquisa,
"mes_pesquisa": mes_pesquisa,
"formato": formato,
"meses": meses,
"day_names": calendar.day_abbr,
"eventos": eventos,
}
)
if pdf: if pdf:
context["title"] = _("Calendário de eventos") context["title"] = _("Calendário de eventos")
context["pdf"] = True context["pdf"] = True
# return render(request, "eventos/calendario_pdf.html", context)
return WeasyTemplateResponse( return WeasyTemplateResponse(
filename="calendario_mensal.pdf", filename=f"calendario_{ano_pesquisa:04}{mes_pesquisa:02}.pdf",
request=request, request=request,
template="eventos/calendario_pdf.html", template="eventos/calendario_pdf.html",
context=context, context=context,

Loading…
Cancel
Save