diff --git a/maraudes/templates/maraudes/compterendu.html b/maraudes/templates/maraudes/compterendu.html index 15228a1..1892673 100644 --- a/maraudes/templates/maraudes/compterendu.html +++ b/maraudes/templates/maraudes/compterendu.html @@ -23,6 +23,13 @@ {% bootstrap_icon "ok-circle" %} Finaliser +
+
+

{% bootstrap_icon "warning-sign" %} Attention

+

Si vous devez créer un nouveau sujet ou lieu, pensez à le faire avant de rentrer des données ! (ou pensez à copier les notes pour les reproduire ensuite)

+

En effet, la page sera rafraîchie après la création, effaçant toutes les données de formulaire qui n'ont pas été enregistrées

+
+
{% endblock %} {% block page_content %} diff --git a/notes/templates/notes/table_inline.html b/notes/templates/notes/table_inline.html index 1693627..e24db4d 100644 --- a/notes/templates/notes/table_inline.html +++ b/notes/templates/notes/table_inline.html @@ -12,5 +12,5 @@ {% endfor %} -

{{text | linebreaks }}

+

{{text | linebreaks }}

diff --git a/notes/views.py b/notes/views.py index 2b71cab..88cb767 100644 --- a/notes/views.py +++ b/notes/views.py @@ -92,6 +92,39 @@ class MaraudeListView(ListView): ] + +def info_completed_filter(qs): + completed_ratio = 70 # % of total fields completed + + excluded_set = set() + for sujet in qs: + if sujet.statistiques.info_completed >= completed_ratio: + excluded_set.add(sujet.pk) + + return qs.exclude(pk__in=excluded_set) + +def rencontre_dans_le_mois(qs): + """ Renvoie les sujets du queryset pour lesquelles une observation a été enregistrée + au cours des 30 derniers jours """ + days_number = 30 + limit_date = timezone.now().date() - datetime.timedelta(days_number) + included_set = set() + for sujet in qs: + # Try to find an observation in the range + most_recent_obs = Observation.objects.filter(sujet=sujet).order_by("-created_date").first() + if most_recent_obs and most_recent_obs.created_date >= limit_date: + included_set.add(sujet.pk) + return qs.filter(pk__in=included_set) + +def a_revoir_avant_bilan(qs): + year_of_bilan = 2017 + included_set = set() + for sujet in qs: + most_recent_obs = Observation.objects.filter(sujet=sujet).order_by("-created_date").first() + if most_recent_obs and most_recent_obs.created_date.year >= year_of_bilan: + included_set.add(sujet.pk) + return qs.filter(pk__in=included_set) + class SujetListView(ListView): # ListView model = Sujet @@ -99,29 +132,6 @@ class SujetListView(ListView): cell_template = "notes/table_cell_sujets.html" table_header = "Liste des sujets" - def info_completed_filter(qs): - completed_ratio = 70 # % of total fields completed - - excluded_set = set() - for sujet in qs: - if sujet.statistiques.info_completed >= completed_ratio: - excluded_set.add(sujet.pk) - - return qs.exclude(pk__in=excluded_set) - - def rencontre_dans_le_mois(qs): - """ Renvoie les sujets du queryset pour lesquelles une observation a été enregistrée - au cours des 30 derniers jours """ - days_number = 30 - limit_date = timezone.now().date() - datetime.timedelta(days_number) - included_set = set() - for sujet in qs: - # Try to find an observation in the range - most_recent_obs = Observation.objects.filter(sujet=sujet).order_by("-created_date").first() - if most_recent_obs and most_recent_obs.created_date >= limit_date: - included_set.add(sujet.pk) - return qs.filter(pk__in=included_set) - filters = [ ("Connu(e)s cette année", lambda qs: qs.filter( @@ -129,6 +139,7 @@ class SujetListView(ListView): ), ("Rencontré(e)s dans le mois", rencontre_dans_le_mois), ("Statistiques incomplètes", info_completed_filter), + ("Revoir avant bilan", lambda qs: a_revoir_avant_bilan(info_completed_filter(qs))), ("Signalements", lambda qs: qs.filter(pk__in=Signalement.objects.all().values_list('sujet'))), ] diff --git a/statistiques/charts.py b/statistiques/charts.py index 3c9134a..d6d2922 100644 --- a/statistiques/charts.py +++ b/statistiques/charts.py @@ -8,6 +8,7 @@ from django.db.models import (Field, NullBooleanField, from graphos.sources.simple import SimpleDataSource from graphos.renderers import gchart +from maraudes.models import Rencontre from notes.models import Sujet from .models import GroupeLieux @@ -186,6 +187,27 @@ class AgePieChart(PieWrapper): super().__init__(data=data, title="Âge") + +class IndividuGroupeChart(PieWrapper): + + def __init__(self, queryset): + data = [("individu/groupe", "count")] + + # Cast parent Rencontre objects + queryset = Rencontre.objects.filter( + pk__in=queryset.values_list('rencontre') + ) + + counts = collections.defaultdict(lambda: 0) + for rencontre in queryset: + counts[rencontre.groupe_ou_individu()] += 1 + print(counts) + + for label, count in counts.items(): + data += [(label, count)] + super().__init__(data=data, title="Individu ou Groupe") + + class RencontreParSujetChart(PieWrapper): labels = (('Rencontre unique', (1,)), @@ -229,6 +251,17 @@ class RencontreParMoisChart(gchart.ColumnChart): ) + +def gen_heure_minute(_from, to): + start_hour = _from.hour + stop_hour, stop_min = to.hour, to.minute + + for hour in range(start_hour, stop_hour + 1): + yield datetime.time(hour, 0) + if not (hour == stop_hour and 30 > stop_min): + yield datetime.time(hour, 30) + + class RencontreParHeureChart(gchart.AreaChart): def __init__(self, queryset): data = [("Heure", "Rencontres démarrées", "Au total (démarré + en cours)")] @@ -238,9 +271,10 @@ class RencontreParHeureChart(gchart.AreaChart): data += [(heure, par_heure[heure], en_continu[heure]) for heure in sorted(par_heure.keys())] else: data += [("Heure", 0, 0)] + super().__init__(SimpleDataSource(data), options={ - "title": "Fréquentation de la maraude en fonction de l'heure (par quart d'heure)" + "title": "Fréquentation de la maraude en fonction de l'heure (par quart d'heure)", } ) diff --git a/statistiques/urls.py b/statistiques/urls.py index 62a627a..01ef255 100644 --- a/statistiques/urls.py +++ b/statistiques/urls.py @@ -8,4 +8,5 @@ urlpatterns = [ url(r'^details/(?P[0-9]+)/$', views.StatistiquesDetailsView.as_view(), name="details"), url(r'^update/(?P[0-9]+)/$', views.StatistiquesUpdateView.as_view(), name="update"), url(r'^frequentation/$', views.FrequentationChartsView.as_view(), name="frequentation"), + url(r'^comparatif/$', views.ComparatifHeures.as_view(), name="comparatif"), ] diff --git a/statistiques/views.py b/statistiques/views.py index d4c1412..9e68d67 100644 --- a/statistiques/views.py +++ b/statistiques/views.py @@ -1,3 +1,4 @@ +import datetime from collections import OrderedDict from django.core.exceptions import ImproperlyConfigured @@ -141,13 +142,42 @@ class FrequentationChartsView(MultipleChartsView): ('Par mois', charts.RencontreParMoisChart), ('Par heure', charts.RencontreParHeureChart), ('Par sujet', charts.RencontreParSujetChart), - ('Par lieu', charts.RencontreParLieuChart) + ('Par lieu', charts.RencontreParLieuChart), + ('Individu ou Groupe', charts.IndividuGroupeChart), ]) def get_queryset(self): return self.get_observations_queryset() +class ComparatifHeures(MultipleChartsView): + title = "Comparaison décalage heures" + _charts = OrderedDict([ + ('Par mois', charts.RencontreParMoisChart), + ('Par heure', charts.RencontreParHeureChart), + ('Par sujet', charts.RencontreParSujetChart), + ('Par lieu', charts.RencontreParLieuChart) + ]) + + def get_queryset(self): + #return self.get_observations_queryset() + debut_essai = datetime.datetime(2017, 11, 23) + + # Horaires démarrés le 23novembre 2017, calcul de la période effective d'application + duree_periode_essai = datetime.datetime.now() - debut_essai + + if self.year == 2017: + debut_periode = debut_essai.replace(year=2016) + fin_periode = debut_periode + duree_periode_essai + elif self.year == 2018: + debut_periode = debut_essai + fin_periode = debut_essai + duree_periode_essai + else: + debut_periode, fin_periode = (None, None) + + print(debut_periode, fin_periode) + return Observation.objects.filter(created_date__range=(debut_periode, fin_periode)) + # AjaxMixin class AjaxOrRedirectMixin(object): """ For view that should be retrieved by Ajax only. If not, diff --git a/website/static/css/base-admin.css b/website/static/css/base-admin.css new file mode 100644 index 0000000..f3c591e --- /dev/null +++ b/website/static/css/base-admin.css @@ -0,0 +1,979 @@ +/* + Copy of DJANGO Admin styles +*/ + +/* Replaced @import url(fonts.css); +with bootstrap's : */ +@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700"); + +body { + margin: 0; + padding: 0; + font-size: 14px; + font-family: "Open Sans", sans-serif; + color: #333; + background: #fff; +} + +/* LINKS */ + +a:link, a:visited { + color: #447e9b; + text-decoration: none; +} + +a:focus, a:hover { + color: #036; +} + +a:focus { + text-decoration: underline; +} + +a img { + border: none; +} + +a.section:link, a.section:visited { + color: #fff; + text-decoration: none; +} + +a.section:focus, a.section:hover { + text-decoration: underline; +} + +/* GLOBAL DEFAULTS */ + +p, ol, ul, dl { + margin: .2em 0 .8em 0; +} + +p { + padding: 0; + line-height: 140%; +} + +h1,h2,h3,h4,h5 { + font-weight: bold; +} + +h1 { + margin: 0 0 20px; + font-weight: 300; + font-size: 20px; + color: #666; +} + +h2 { + font-size: 16px; + margin: 1em 0 .5em 0; +} + +h2.subhead { + font-weight: normal; + margin-top: 0; +} + +h3 { + font-size: 14px; + margin: .8em 0 .3em 0; + color: #666; + font-weight: bold; +} + +h4 { + font-size: 12px; + margin: 1em 0 .8em 0; + padding-bottom: 3px; +} + +h5 { + font-size: 10px; + margin: 1.5em 0 .5em 0; + color: #666; + text-transform: uppercase; + letter-spacing: 1px; +} + +ul li { + list-style-type: square; + padding: 1px 0; +} + +/* Remove squares from bootstrap navbar */ + +.dropdown-menu > li { + list-style-type: none; +} + +li ul { + margin-bottom: 0; +} + +li, dt, dd { + font-size: 13px; + line-height: 20px; +} + +dt { + font-weight: bold; + margin-top: 4px; +} + +dd { + margin-left: 0; +} + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + padding: 0; + border: none; + border-top: 1px solid #eee; +} + +blockquote { + font-size: 11px; + color: #777; + margin-left: 2px; + padding-left: 10px; + border-left: 5px solid #ddd; +} + +code, pre { + font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; + color: #666; + font-size: 12px; +} + +pre.literal-block { + margin: 10px; + background: #eee; + padding: 6px 8px; +} + +code strong { + color: #930; +} + +hr { + clear: both; + color: #eee; + background-color: #eee; + height: 1px; + border: none; + margin: 0; + padding: 0; + font-size: 1px; + line-height: 1px; +} + +/* TEXT STYLES & MODIFIERS */ + +.small { + font-size: 11px; +} + +.tiny { + font-size: 10px; +} + +p.tiny { + margin-top: -2px; +} + +.mini { + font-size: 10px; +} + +p.mini { + margin-top: -3px; +} + +.help, p.help, form p.help { + font-size: 11px; + color: #999; +} + +.help-tooltip { + cursor: help; +} + +p img, h1 img, h2 img, h3 img, h4 img, td img { + vertical-align: middle; +} + +.quiet, a.quiet:link, a.quiet:visited { + color: #999; + font-weight: normal; +} + +.float-right { + float: right; +} + +.float-left { + float: left; +} + +.clear { + clear: both; +} + +.align-left { + text-align: left; +} + +.align-right { + text-align: right; +} + +.example { + margin: 10px 0; + padding: 5px 10px; + background: #efefef; +} + +.nowrap { + white-space: nowrap; +} + +/* TABLES */ + +table { + border-collapse: collapse; + border-color: #ccc; +} + +td, th { + font-size: 13px; + line-height: 16px; + border-bottom: 1px solid #eee; + vertical-align: top; + padding: 8px; + font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif; +} + +th { + font-weight: 600; + text-align: left; +} + +thead th, +tfoot td { + color: #666; + padding: 5px 10px; + font-size: 11px; + background: #fff; + border: none; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; +} + +tfoot td { + border-bottom: none; + border-top: 1px solid #eee; +} + +thead th.required { + color: #000; +} + +tr.alt { + background: #f6f6f6; +} + +.row1 { + background: #fff; +} + +.row2 { + background: #f9f9f9; +} + +/* SORTABLE TABLES */ + +thead th { + padding: 5px 10px; + line-height: normal; + text-transform: uppercase; + background: #f6f6f6; +} + +thead th a:link, thead th a:visited { + color: #666; +} + +thead th.sorted { + background: #eee; +} + +thead th.sorted .text { + padding-right: 42px; +} + +table thead th .text span { + padding: 8px 10px; + display: block; +} + +table thead th .text a { + display: block; + cursor: pointer; + padding: 8px 10px; +} + +table thead th .text a:focus, table thead th .text a:hover { + background: #eee; +} + +thead th.sorted a.sortremove { + visibility: hidden; +} + +table thead th.sorted:hover a.sortremove { + visibility: visible; +} + +table thead th.sorted .sortoptions { + display: block; + padding: 9px 5px 0 5px; + float: right; + text-align: right; +} + +table thead th.sorted .sortpriority { + font-size: .8em; + min-width: 12px; + text-align: center; + vertical-align: 3px; + margin-left: 2px; + margin-right: 2px; +} + +table thead th.sorted .sortoptions a { + position: relative; + width: 14px; + height: 14px; + display: inline-block; + background: url(../admin/img/sorting-icons.svg) 0 0 no-repeat; + background-size: 14px auto; +} + +table thead th.sorted .sortoptions a.sortremove { + background-position: 0 0; +} + +table thead th.sorted .sortoptions a.sortremove:after { + content: '\\'; + position: absolute; + top: -6px; + left: 3px; + font-weight: 200; + font-size: 18px; + color: #999; +} + +table thead th.sorted .sortoptions a.sortremove:focus:after, +table thead th.sorted .sortoptions a.sortremove:hover:after { + color: #447e9b; +} + +table thead th.sorted .sortoptions a.sortremove:focus, +table thead th.sorted .sortoptions a.sortremove:hover { + background-position: 0 -14px; +} + +table thead th.sorted .sortoptions a.ascending { + background-position: 0 -28px; +} + +table thead th.sorted .sortoptions a.ascending:focus, +table thead th.sorted .sortoptions a.ascending:hover { + background-position: 0 -42px; +} + +table thead th.sorted .sortoptions a.descending { + top: 1px; + background-position: 0 -56px; +} + +table thead th.sorted .sortoptions a.descending:focus, +table thead th.sorted .sortoptions a.descending:hover { + background-position: 0 -70px; +} + +/* FORM DEFAULTS */ + +input, textarea, select, .form-row p, form .button { + margin: 2px 0; + padding: 2px 3px; + vertical-align: middle; + font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif; + font-weight: normal; + font-size: 13px; +} + +textarea { + vertical-align: top; +} + +input[type=text], input[type=password], input[type=email], input[type=url], +input[type=number], textarea, select, .vTextField { + border: 1px solid #ccc; + border-radius: 4px; + padding: 5px 6px; + margin-top: 0; +} + +input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, +input[type=url]:focus, input[type=number]:focus, textarea:focus, select:focus, +.vTextField:focus { + border-color: #999; +} + +select { + height: 30px; +} + +select[multiple] { + min-height: 150px; +} + +/* FORM BUTTONS */ + +.button, input[type=submit], input[type=button], .submit-row input, a.button { + background: #79aec8; + padding: 10px 15px; + border: none; + border-radius: 4px; + color: #fff; + cursor: pointer; +} + +a.button { + padding: 4px 5px; +} + +.button:active, input[type=submit]:active, input[type=button]:active, +.button:focus, input[type=submit]:focus, input[type=button]:focus, +.button:hover, input[type=submit]:hover, input[type=button]:hover { + background: #609ab6; +} + +.button[disabled], input[type=submit][disabled], input[type=button][disabled] { + opacity: 0.4; +} + +.button.default, input[type=submit].default, .submit-row input.default { + float: right; + border: none; + font-weight: 400; + background: #417690; +} + +.button.default:active, input[type=submit].default:active, +.button.default:focus, input[type=submit].default:focus, +.button.default:hover, input[type=submit].default:hover { + background: #205067; +} + +.button[disabled].default, +input[type=submit][disabled].default, +input[type=button][disabled].default { + opacity: 0.4; +} + + +/* MODULES */ + +.module { + border: none; + margin-bottom: 30px; + background: #fff; +} + +.module p, .module ul, .module h3, .module h4, .module dl, .module pre { + padding-left: 10px; + padding-right: 10px; +} + +.module blockquote { + margin-left: 12px; +} + +.module ul, .module ol { + margin-left: 1.5em; +} + +.module h3 { + margin-top: .6em; +} + +.module h2, .module caption, .inline-group h2 { + margin: 0; + padding: 8px; + font-weight: 400; + font-size: 13px; + text-align: left; + background: #79aec8; + color: #fff; +} + +.module caption, +.inline-group h2 { + font-size: 12px; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +.module table { + border-collapse: collapse; +} + +/* MESSAGES & ERRORS */ + +ul.messagelist { + padding: 0; + margin: 0; +} + +ul.messagelist li { + display: block; + font-weight: 400; + font-size: 13px; + padding: 10px 10px 10px 65px; + margin: 0 0 10px 0; + background: #dfd url(../admin/img/icon-yes.svg) 40px 12px no-repeat; + background-size: 16px auto; + color: #333; +} + +ul.messagelist li.warning { + background: #ffc url(../admin/img/icon-alert.svg) 40px 14px no-repeat; + background-size: 14px auto; +} + +ul.messagelist li.error { + background: #ffefef url(../admin/img/icon-no.svg) 40px 12px no-repeat; + background-size: 16px auto; +} + +.errornote { + font-size: 14px; + font-weight: 700; + display: block; + padding: 10px 12px; + margin: 0 0 10px 0; + color: #ba2121; + border: 1px solid #ba2121; + border-radius: 4px; + background-color: #fff; + background-position: 5px 12px; +} + +ul.errorlist { + margin: 0 0 4px; + padding: 0; + color: #ba2121; + background: #fff; +} + +ul.errorlist li { + font-size: 13px; + display: block; + margin-bottom: 4px; +} + +ul.errorlist li:first-child { + margin-top: 0; +} + +ul.errorlist li a { + color: inherit; + text-decoration: underline; +} + +td ul.errorlist { + margin: 0; + padding: 0; +} + +td ul.errorlist li { + margin: 0; +} + +.form-row.errors { + margin: 0; + border: none; + border-bottom: 1px solid #eee; + background: none; +} + +.form-row.errors ul.errorlist li { + padding-left: 0; +} + +.errors input, .errors select, .errors textarea { + border: 1px solid #ba2121; +} + +div.system-message { + background: #ffc; + margin: 10px; + padding: 6px 8px; + font-size: .8em; +} + +div.system-message p.system-message-title { + padding: 4px 5px 4px 25px; + margin: 0; + color: #c11; + background: #ffefef url(../admin/img/icon-no.svg) 5px 5px no-repeat; +} + +.description { + font-size: 12px; + padding: 5px 0 0 12px; +} + +/* BREADCRUMBS */ + +div.breadcrumbs { + background: #79aec8; + padding: 10px 40px; + border: none; + font-size: 14px; + color: #c4dce8; + text-align: left; +} + +div.breadcrumbs a { + color: #fff; +} + +div.breadcrumbs a:focus, div.breadcrumbs a:hover { + color: #c4dce8; +} + +/* ACTION ICONS */ + +.addlink { + padding-left: 16px; + background: url(../admin/img/icon-addlink.svg) 0 1px no-repeat; +} + +.changelink, .inlinechangelink { + padding-left: 16px; + background: url(../admin/img/icon-changelink.svg) 0 1px no-repeat; +} + +.deletelink { + padding-left: 16px; + background: url(../admin/img/icon-deletelink.svg) 0 1px no-repeat; +} + +a.deletelink:link, a.deletelink:visited { + color: #CC3434; +} + +a.deletelink:focus, a.deletelink:hover { + color: #993333; + text-decoration: none; +} + +/* OBJECT TOOLS */ + +.object-tools { + font-size: 10px; + font-weight: bold; + padding-left: 0; + float: right; + position: relative; + margin-top: -48px; +} + +.form-row .object-tools { + margin-top: 5px; + margin-bottom: 5px; + float: none; + height: 2em; + padding-left: 3.5em; +} + +.object-tools li { + display: block; + float: left; + margin-left: 5px; + height: 16px; +} + +.object-tools a { + border-radius: 15px; +} + +.object-tools a:link, .object-tools a:visited { + display: block; + float: left; + padding: 3px 12px; + background: #999; + font-weight: 400; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.5px; + color: #fff; +} + +.object-tools a:focus, .object-tools a:hover { + background-color: #417690; +} + +.object-tools a:focus{ + text-decoration: none; +} + +.object-tools a.viewsitelink, .object-tools a.golink,.object-tools a.addlink { + background-repeat: no-repeat; + background-position: 93% center; + padding-right: 26px; +} + +.object-tools a.viewsitelink, .object-tools a.golink { + background-image: url(../admin/img/tooltag-arrowright.svg); +} + +.object-tools a.addlink { + background-image: url(../admin/img/tooltag-add.svg); +} + +/* OBJECT HISTORY */ + +table#change-history { + width: 100%; +} + +table#change-history tbody th { + width: 16em; +} + +/* PAGE STRUCTURE */ + +#container { + position: relative; + width: 100%; + min-width: 980px; + padding: 0; +} + +#content { + padding: 20px 40px; +} + +.dashboard #content { + width: 600px; +} + +#content-main { + float: left; + width: 100%; +} + +#content-related { + float: left; + width: 240px; + position: relative; + /*margin-right: -300px;*/ +} + +#footer { + clear: both; + padding: 10px; +} + +/* COLUMN TYPES */ + +.colMS { + margin-right: 300px; +} + +.colSM { + margin-left: 300px; +} + +.colSM #content-related { + float: left; + margin-right: 0; + margin-left: -300px; +} + +.colSM #content-main { + float: right; +} + +.popup .colM { + width: auto; +} + +/* HEADER */ + +#header { + width: auto; + height: 40px; + padding: 10px 40px; + background: #417690; + line-height: 40px; + color: #ffc; + overflow: hidden; +} + +#header a:link, #header a:visited { + color: #fff; +} + +#header a:focus , #header a:hover { + text-decoration: underline; +} + +#branding { + float: left; +} + +#branding h1 { + padding: 0; + margin: 0 20px 0 0; + font-weight: 300; + font-size: 24px; + color: #f5dd5d; +} + +#branding h1, #branding h1 a:link, #branding h1 a:visited { + color: #f5dd5d; +} + +#branding h2 { + padding: 0 10px; + font-size: 14px; + margin: -8px 0 8px 0; + font-weight: normal; + color: #ffc; +} + +#branding a:hover { + text-decoration: none; +} + +#user-tools { + float: right; + padding: 0; + margin: 0 0 0 20px; + font-weight: 300; + font-size: 11px; + letter-spacing: 0.5px; + text-transform: uppercase; + text-align: right; +} + +#user-tools a { + border-bottom: 1px solid rgba(255, 255, 255, 0.25); +} + +#user-tools a:focus, #user-tools a:hover { + text-decoration: none; + border-bottom-color: #79aec8; + color: #79aec8; +} + +/* SIDEBAR */ + +/*#content-related { + background: #f8f8f8; +} + +#content-related .module { + background: none; +} + +#content-related h3 { + font-size: 14px; + color: #666; + padding: 0 16px; + margin: 0 0 16px; +} + +#content-related h4 { + font-size: 13px; +} + +#content-related p { + padding-left: 16px; + padding-right: 16px; +}*/ + +#content-related .actionlist { + padding: 0; + margin: 16px; +} + +#content-related .actionlist li { + line-height: 1.2; + margin-bottom: 10px; + padding-left: 18px; +} + +#content-related .module h2 { + background: none; + padding: 16px; + margin-bottom: 16px; + border-bottom: 1px solid #eaeaea; + font-size: 18px; + color: #333; +} + +.delete-confirmation form input[type="submit"] { + background: #ba2121; + border-radius: 4px; + padding: 10px 15px; + color: #fff; +} + +.delete-confirmation form input[type="submit"]:active, +.delete-confirmation form input[type="submit"]:focus, +.delete-confirmation form input[type="submit"]:hover { + background: #a41515; +} + +.delete-confirmation form .cancel-link { + display: inline-block; + vertical-align: middle; + height: 15px; + line-height: 15px; + background: #ddd; + border-radius: 4px; + padding: 10px 15px; + color: #333; + margin: 0 0 0 10px; +} + +.delete-confirmation form .cancel-link:active, +.delete-confirmation form .cancel-link:focus, +.delete-confirmation form .cancel-link:hover { + background: #ccc; +} + +/* POPUP */ +.popup #content { + padding: 20px; +} + +.popup #container { + min-width: 0; +} + +.popup #header { + padding: 10px 20px; +} diff --git a/website/static/favicon.ico b/website/static/favicon.ico new file mode 100644 index 0000000..3bbab40 Binary files /dev/null and b/website/static/favicon.ico differ