Skip to content
Extraits de code Groupes Projets

Comparer les révisions

Les modifications sont affichées comme si la révision source était fusionnée avec la révision cible. En savoir plus sur la comparaison des révisions.

Source

Sélectionner le projet cible
No results found
Sélectionner une révision Git

Cible

Sélectionner le projet cible
  • la-quadrature-du-net/memopol/memopol
  • lnclt/political_memory
  • arthur/political_memory
  • agrausem/political_memory
  • periode/memopol
  • Anthony/memopol
  • Porkepix/memopol
  • jaster/memopol
  • luxcem/memopol
  • TAlone/memopol
10 résultats
Sélectionner une révision Git
Afficher les modifications
Affichage de
avec 203 ajouts et 722 suppressions
- extends 'base.html'
- load representatives_extras
- block content
- include 'legislature/search.html'
- include 'core/blocks/pagination.html'
%table.table
%tr
%th
Photo
%th
Name
%th
Country
%th
Group
%th
Score
- for representative in object_list
%tr
%td
%a{'href': "{% url 'legislature:representative-detail' name=representative.slug %}"}
%img{'src': '={representative.photo}', 'width': '80'}/
%td
%a{'href': "{% url 'legislature:representative-detail' name=representative.slug %}"}
= representative.full_name
%td
%a{'href': "{% url 'legislature:representative-index' group_kind='country' group=representative.country.code %}"}
= representative.country|country_flag
%td
%a{'href': "{{ representative.main_mandate|by_group_url }}"}
= representative.main_mandate.group.abbreviation
%td
= representative.score|score_label
- include "core/blocks/pagination.html"
<form action="" method="get">
{% csrf_token %}
<label for="search">Search : </label>
<input id="search" type="text" name="search">
<input type="submit" value="Go">
</form>
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
"""
This file contains all templatetags used by the representative app
"""
from django import template
from django.contrib.humanize.templatetags.humanize import naturalday
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from representatives.models import Group, Mandate
register = template.Library()
@register.filter
def mandate_date(date, arg=None):
if date.year == 9999:
return 'present'
else:
return naturalday(date, arg)
@register.filter
def position_icon(position):
if position == 'for':
return mark_safe(
'<i \
aria-label="for" \
class="fa fa-thumbs-up vote_positive" \
title="for" \
></i>')
elif position == 'against':
return mark_safe(
'<i \
aria-label="against" \
class="fa fa-thumbs-down vote_negative" \
title="against" \
></i>')
else:
return mark_safe(
'<i \
aria-label="abstain" \
class="fa fa-circle-o vote_abstain" \
title="abstain" \
></i>')
@register.filter
def score_label(score):
if score > 0:
return mark_safe(
'<span class="label label-success">{}</span>'.format(score))
elif score < 0:
return mark_safe(
'<span class="label label-danger">{}</span>'.format(score))
else:
return mark_safe(
'<span class="label label-default">{}</span>'.format(score))
@register.filter
def country_flag(country):
return mark_safe(
'<span class="flag-icon flag-icon-{code}"></span> {name}'.format(
name=country.name,
code=country.code.lower()))
@register.filter
def by_group_url(group):
if isinstance(group, Mandate):
group = group.group
if not isinstance(group, Group):
return ''
kwargs = {'group_kind': group.kind}
if group.abbreviation:
kwargs['group'] = group.abbreviation
else:
kwargs['group'] = group.name
# kwargs['group_id'] = group.id
return reverse(
'legislature:representative-index',
kwargs=kwargs
)
# Create your tests here.
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from __future__ import absolute_import
from django.conf.urls import url
from .views import group, representative
urlpatterns = [
# List of groups by group kind
url(
r'^groups/(?P<kind>\w+)?$',
group.index,
name='group-index'
),
# Representative detail by representative name
url(
r'^(?P<name>[-\w]+)$',
representative.detail,
name='representative-detail'
),
# Representative detail by representative pk
url(
r'^(?P<pk>\d+)$',
representative.detail,
name='representative-detail'
),
# List of representatives by group kind and group name or pk
url(
r'^(?P<group_kind>\w+)/(?P<group>.+)$',
representative.index,
name='representative-index'
),
# List all representatives by default
url(
r'',
representative.index,
name='representative-index'
),
]
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.shortcuts import render
def render_paginate_list(request, object_list, template_name, num_by_page=30):
"""
Render a paginated list of representatives
"""
paginator = Paginator(object_list, num_by_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages)
context = {}
queries_without_page = request.GET.copy()
if 'page' in queries_without_page:
del queries_without_page['page']
context['queries'] = queries_without_page
context['object_list'] = objects
context['object_count'] = paginator.count
return render(
request,
template_name,
context
)
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from datetime import datetime
from django.shortcuts import render
from representatives.models import Group
def index(request, kind=None):
groups = Group.objects.filter(
mandates__end_date__gte=datetime.now()
)
if kind:
groups = groups.filter(
kind=kind
)
groups = groups.distinct().order_by('name')
return render(
request,
'legislature/groups_list.html',
{'groups': groups}
)
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from __future__ import absolute_import
from datetime import datetime
from django.db.models import Q
from django.http import Http404
from django.shortcuts import render
from django.utils.text import slugify
from core.utils import render_paginate_list
from positions.forms import PositionForm
from ..models import MemopolRepresentative
def index(request, group_kind=None, group=None):
# Fetch active representatives
representative_list = MemopolRepresentative.objects.select_related(
'country',
'main_mandate',
'main_mandate__group',
).filter(
active=True
)
# Filter the list by group if group information is provided
if group_kind:
if group.isnumeric():
representative_list = representative_list.filter(
mandates__group_id=int(group),
mandates__end_date__gte=datetime.now()
)
else:
# Search group based on abbreviation or name
representative_list = representative_list.filter(
Q(mandates__group__abbreviation=group) |
Q(mandates__group__name=group),
mandates__group__kind=group_kind,
mandates__end_date__gte=datetime.now()
)
# Filter the list by search
representative_list = _filter_by_search(
request,
representative_list
).order_by('-score', 'last_name')
# Grid or list
if request.GET.get('display') in ('grid', 'list'):
request.session['display'] = request.GET.get('display')
if 'display' not in request.session:
request.session['display'] = 'grid'
# Render the paginated template
return render_paginate_list(
request,
representative_list,
'legislature/representative_{}.html'.format(
request.session['display']
)
)
def detail(request, pk=None, name=None):
try:
query_set = MemopolRepresentative.objects.select_related(
'country',
'main_mandate'
)
if pk:
representative = query_set.get(
id=pk
)
elif name:
representative = query_set.get(
slug=name
)
else:
return Http404()
except MemopolRepresentative.DoesNotExist:
return Http404()
position_form = PositionForm()
return render(
request,
'legislature/representative_detail.html',
{
'representative': representative,
'position_form': position_form
}
)
def _filter_by_search(request, representative_list):
"""
Return a representative_list filtered by
the representative name provided in search form
"""
search = request.GET.get('search')
if search:
return representative_list.filter(
Q(slug__icontains=slugify(search))
)
else:
return representative_list
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.shortcuts import render
def render_paginate_list(request, object_list, template_name, num_by_page=30):
"""
Render a paginated list of representatives
"""
paginator = Paginator(object_list, num_by_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages)
context = {}
queries_without_page = request.GET.copy()
if 'page' in queries_without_page:
del queries_without_page['page']
context['queries'] = queries_without_page
context['object_list'] = objects
context['object_count'] = paginator.count
return render(
request,
template_name,
context
)
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.conf.urls import include, patterns, url
from django.contrib import admin
import core.views
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', core.views.HomeView.as_view(), name='index'),
url(r'^legislature/', include('legislature.urls',
namespace='legislature')),
url(r'^votes/', include('votes.urls', namespace='votes')),
url(r'^positions/', include('positions.urls', namespace='positions')),
url(r'^autocomplete/', include('autocomplete_light.urls')),
url(r'^admin/', include(admin.site.urls)),
)
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from datetimewidget.widgets import DateWidget
from django import forms
from .models import Position
class PositionForm(forms.ModelForm):
class Meta:
model = Position
fields = ['tags', 'datetime', 'text', 'link']
widgets = {
# Use localization and bootstrap 3
'datetime': DateWidget(
attrs={
'id': 'yourdatetimeid'
},
usel10n=True,
bootstrap_version=3,
)
}
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.db import models
from django.template.defaultfilters import truncatewords
from taggit.managers import TaggableManager
from legislature.models import MemopolRepresentative
class PositionManager(models.Manager):
"""A simple model manager for querying published Positions"""
use_for_related_fields = True
def published(self, **kwargs):
return self.filter(published=True, **kwargs)
class Position(models.Model):
representative = models.ForeignKey(
MemopolRepresentative,
related_name='positions')
datetime = models.DateField()
text = models.TextField()
link = models.URLField()
published = models.BooleanField(default=False)
tags = TaggableManager()
# Adds our custom manager
objects = PositionManager()
@property
def short_text(self):
return truncatewords(self.text, 5)
def publish(self):
self.published = True
def unpublish(self):
self.published = False
- extends 'base.html'
- block content
- extends 'base.html'
- load humanize
- block content
- include 'legislature/blocks/representative_block.html' with representative=object.representative
.quote
%p.quote-header
{{object.datetime|naturalday:"The d/m/Y"}}, {{object.representative.full_name}} declared :
.long-quote
= object.text|linebreaks
%p.tags
- for tag in object.tags.all
%span.label.label-default
= tag
%p
Source :
%a{:href => '{{object.link}}'}
= object.link
Test
# Create your tests here.
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.conf.urls import url
from views import PositionCreate, PositionDetail
urlpatterns = [
# Create a Position
url(
r'^create',
PositionCreate.as_view(),
name='position-create'
),
url(
r'^(?P<pk>\d+)/$',
PositionDetail.as_view(),
name='position-detail'
)
]
# coding: utf-8
# This file is part of memopol.
#
# memopol is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or any later version.
#
# memopol is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU General Affero Public
# License along with django-representatives.
# If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
from django.core.urlresolvers import reverse
from django.views.generic import CreateView
from django.views.generic.detail import DetailView
from .forms import PositionForm
from .models import Position
class PositionCreate(CreateView):
"""Create a position"""
model = Position
fields = PositionForm.Meta.fields + ['representative']
def get_success_url(self):
return reverse('legislature:representative-detail',
kwargs={'name': self.object.representative.slug})
class PositionDetail(DetailView):
"""Display a position"""
model = Position
queryset = Position.objects.filter(published=True)
[pytest]
DJANGO_SETTINGS_MODULE=memopol.settings
addopts = --cov-config .coveragerc --cov=src --create-db
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Memopol</title>
<!-- Bootstrap core CSS -->
<link href="./css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="./css/custom.css" rel="stylesheet">
<style>
</style>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container-fluid">
<!--div class="row custom-header">
<div class="col-sm-5">
<h1>[LOGO] Memopol</h1>
</div>
<div class="col-sm-7">
<p class="lead">What is Memopol ?</p>
<p>Memopol is a tool designed by La Quadrature du Net to help European citizens to reach members of European Parliament (MEPs) and track their voting records on issues related to fundamental freedoms online. </p>
<p class="text-right custom-plus"><a class="btn btn-sm btn-default"><span class="glyphicon glyphicon-plus"></span></a></p>
</div>
</div-->
<div class="row">
<div class="col-xs-12">
<!---------------------------------------------------------
NAV TAB
---------------------------------------------------------->
<ul class="nav nav-tabs nav-justified">
<li role="presentation"><a href="MEP-votes.html"><h3>Votes</h3></a></li>
<li role="presentation" class="active"><a href="MEP-mandates.html"><h3>Mandates</h3></a></li>
<li role="presentation"><a href="MEP-positions.html"><h3>Public positions</h3></a></li>
</ul>
<!---------------------------------------------------------
FIN DE LA NAV TAB
---------------------------------------------------------->
<br/>
<div class="row">
<div class="col-sm-6 col-md-4">
<!---------------------------------------------------------
MANDAT IMPORTANT
---------------------------------------------------------->
<div class="thumbnail">
<div class="caption">
<h3 class="text-center">Committee on Civil Liberties, Justice and Home Affairs</h3>
<hr>
<p class="lead text-center">Vice-Chair since July 7, 2014</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT IMPORTANT
---------------------------------------------------------->
<!---------------------------------------------------------
MANDAT PEU IMPORTANT
---------------------------------------------------------->
<div class="thumbnail">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not so interesting</h5>
<hr>
<p class="text-center">Member since July 7, 2014</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT PEU IMPORTANT
---------------------------------------------------------->
<!---------------------------------------------------------
MANDAT TERMINÉ
---------------------------------------------------------->
<div class="thumbnail mandat-fini">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not relevant anymore</h5>
<hr>
<p class="text-center">Member from July 7, 2014 to August 16, 2015</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT TERMINÉ
---------------------------------------------------------->
</div>
<div class="col-sm-6 col-md-4">
<!---------------------------------------------------------
MANDAT IMPORTANT
---------------------------------------------------------->
<div class="thumbnail">
<div class="caption">
<h3 class="text-center">Committee on Civil Liberties, Justice and Home Affairs</h3>
<hr>
<p class="lead text-center">Vice-Chair since July 7, 2014</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT IMPORTANT
---------------------------------------------------------->
<!---------------------------------------------------------
MANDAT TERMINÉ
---------------------------------------------------------->
<div class="thumbnail mandat-fini">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not relevant anymore</h5>
<hr>
<p class="text-center">Member from July 7, 2014 to August 16, 2015</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT TERMINÉ
---------------------------------------------------------->
</div>
<div class="col-sm-6 col-md-4">
<!---------------------------------------------------------
MANDAT PEU IMPORTANT
---------------------------------------------------------->
<div class="thumbnail">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not so interesting</h5>
<hr>
<p class="text-center">Member since July 7, 2014</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT PEU IMPORTANT
---------------------------------------------------------->
<!---------------------------------------------------------
MANDAT PEU IMPORTANT
---------------------------------------------------------->
<div class="thumbnail">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not so interesting</h5>
<hr>
<p class="text-center">Member since July 7, 2014</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT PEU IMPORTANT
---------------------------------------------------------->
<!---------------------------------------------------------
MANDAT TERMINÉ
---------------------------------------------------------->
<div class="thumbnail mandat-fini">
<div class="caption">
<h5 class="text-center">Committee on an other topic that is not relevant anymore</h5>
<hr>
<p class="text-center">Member from July 7, 2014 to August 16, 2015</p>
</div>
</div>
<!---------------------------------------------------------
FIN DU MANDAT TERMINÉ
---------------------------------------------------------->
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="./js/bootstrap.min.js"></script>
<script src="./js/docs.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="./js/ie10-viewport-bug-workaround.js"></script>
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
</body>
</html>