Commit 9475f340 authored by Okhin's avatar Okhin

Improving the search page with map coloration and stats

parent a45c07ef
...@@ -25,6 +25,7 @@ from email.header import Header ...@@ -25,6 +25,7 @@ from email.header import Header
from urlparse import urljoin from urlparse import urljoin
from BeautifulSoup import BeautifulSoup, Comment as BComment from BeautifulSoup import BeautifulSoup, Comment as BComment
from operator import itemgetter from operator import itemgetter
from itertools import groupby
def sanitizeHtml(value, base_url=None): def sanitizeHtml(value, base_url=None):
rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:')) rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:'))
...@@ -212,7 +213,7 @@ class AddForm(FormView): ...@@ -212,7 +213,7 @@ class AddForm(FormView):
for i in Violation.objects.values('operator_ref__name').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).annotate(total=Count('confirmation'))], for i in Violation.objects.values('operator_ref__name').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).annotate(total=Count('confirmation'))],
reverse=True) reverse=True)
context['stats'] = [ context['stats'] = [
(_('Total confirmed reorts'), len([i for i,z in reports if i>0])), (_('Total confirmed reports'), len([i for i,z in reports if i>0])),
(_('Countries with some confirmed reports'), len([i for i,z in confirms if i>0])), (_('Countries with some confirmed reports'), len([i for i,z in confirms if i>0])),
(_('Operators with some confirmed reports'), len([i for i,z in operators if i>0]))] (_('Operators with some confirmed reports'), len([i for i,z in operators if i>0]))]
return context return context
...@@ -265,6 +266,25 @@ class LookupView(JSONMixin, SearchView): ...@@ -265,6 +266,25 @@ class LookupView(JSONMixin, SearchView):
queryset = Violation.objects.filter(activationid='') queryset = Violation.objects.filter(activationid='')
form_class = SearchViolation form_class = SearchViolation
class ViolationSearchView(SearchView):
def get_queryset(self):
"""Let's strip the queryset form the non needed items."""
queryset = super(ViolationSearchView, self).get_queryset()
return queryset.filter(annotationid='').exclude(state__in=['closed', 'ooscope', 'duplicate'])
def get_context_data(self, *args, **kwargs):
context = super(ViolationSearchView, self).get_context_data(*args, **kwargs)
countries = [(k, len(g),) for k,g in groupby(sorted([i['country'] for i in self.queryset.values('country')]))]
countryweights=json.dumps([{'iso2': y, 'w': x} for x, y in countries])
context['countries'] = countries
context['countryweights'] = countryweights
context['stats'] = [
(_('Number of reports in this search'), self.queryset.count()),
(_('Countries with some confirmed reports'), self.queryset.values('country').count()),
(_('Operators with some confirmed reports'), self.queryset.values('operator_ref__name').count()),
]
return context
def get_attach(request,id): def get_attach(request,id):
f = get_object_or_404(Attachment, pk=id) f = get_object_or_404(Attachment, pk=id)
wrapper = FileWrapper(f.storage) wrapper = FileWrapper(f.storage)
......
...@@ -3,137 +3,137 @@ ...@@ -3,137 +3,137 @@
{% load i18n %} {% load i18n %}
{% block active_tab_home %}id="current"{% endblock %} {% block active_tab_home %}id="current"{% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" type="text/css" media="all" href="/static/css/jquery-ui.css" /> <link rel="stylesheet" type="text/css" media="all" href="/static/css/jquery-ui.css" />
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script type="text/javascript"> <script type="text/javascript">
function focushandlers(ed) { function focushandlers(ed) {
var s = ed.settings; var s = ed.settings;
var realID = $('#'+ed.id+'_tbl'); var realID = $('#'+ed.id+'_tbl');
tinymce.dom.EventUtils.bind(ed.getWin(), 'focus', function(e) { tinymce.dom.EventUtils.bind(ed.getWin(), 'focus', function(e) {
if($(realID)) { if($(realID)) {
/console.log(realID); /console.log(realID);
realID.parents('.fieldWrapper').find('.help_text').show(); realID.parents('.fieldWrapper').find('.help_text').show();
} }
}); });
tinymce.dom.EventUtils.bind(ed.getWin(), 'blur', function(e) { tinymce.dom.EventUtils.bind(ed.getWin(), 'blur', function(e) {
if($(realID)) { if($(realID)) {
/console.log(realID); /console.log(realID);
realID.parents('.fieldWrapper').find('.help_text').hide(); realID.parents('.fieldWrapper').find('.help_text').hide();
} }
}); });
} }
$(document).ready(function(){ $(document).ready(function(){
{% if not form.is_bound %} {% if not form.is_bound %}
$(".fieldWrapper").hide(); $(".fieldWrapper").hide();
$("#id_resource_name").parent().parent().show(); $("#id_resource_name").parent().parent().show();
$("#id_country").parent().parent().show(); $("#id_country").parent().parent().show();
$("#id_operator").parent().parent().show(); $("#id_operator").parent().parent().show();
$("#id_contract").parent().parent().show(); $("#id_contract").parent().parent().show();
$("#id_media").parent().parent().show(); $("#id_media").parent().parent().show();
$("#save_button").hide(); $("#save_button").hide();
{% else %} {% else %}
if($("#id_contractual").attr('checked')==false) { if($("#id_contractual").attr('checked')==false) {
$("#id_contract_excerpt").parent().parent().hide(); $("#id_contract_excerpt").parent().parent().hide();
} }
$("#show_optionals").show(); $("#show_optionals").show();
$("#optional .fieldWrapper").hide(); $("#optional .fieldWrapper").hide();
if ($('#id_email').val().length>0) { if ($('#id_email').val().length>0) {
$('#id_captcha_0').parent().parent().show(); $('#id_captcha_0').parent().parent().show();
$('#save_button').removeAttr('disabled'); $('#save_button').removeAttr('disabled');
$("#show_optionals").show(); $("#show_optionals").show();
} }
{% endif %} {% endif %}
</script> </script>
{% endblock %} {% endblock %}
{%block content%} {%block content%}
<div id='global'> <div id='global'>
{% if messages %} {% if messages %}
<ul class="messages"> <ul class="messages">
{% for message in messages %} {% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|safe }}</li> <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|safe }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
<div id='addForm' class='index'> <div id='addForm' class='index'>
<h2>{% trans "Add New Case" %}</h2> <h2>{% trans "Add New Case" %}</h2>
<p>{% trans "Please report cases of operators restricting or throttling access to content, services or applications. For a more precise description of what to report, check our <a href='/about/#guidelines'>guidelines</a>." %} <p>{% trans "Please report cases of operators restricting or throttling access to content, services or applications. For a more precise description of what to report, check our <a href='/about/#guidelines'>guidelines</a>." %}
<form name="addForm" enctype="multipart/form-data" action="{% root_url %}/add/" method="post"> <form name="addForm" enctype="multipart/form-data" action="{% root_url %}/add/" method="post">
{% for field in form %} {% for field in form %}
{% if field.html_name = 'comment' %}<div class="hidden errorlist">{% trans "There are already some reports for this Operator/Contract, please check if yours is already among them:" %}<ul id="similar_cases"></ul></div>{%endif%} {% if field.html_name = 'comment' %}<div class="hidden errorlist">{% trans "There are already some reports for this Operator/Contract, please check if yours is already among them:" %}<ul id="similar_cases"></ul></div>{%endif%}
{% if field.html_name = 'resource' %}<div id="show_optionals">{% trans "Provide optional details" %}</div><div id="optional">{%endif%} {% if field.html_name = 'resource' %}<div id="show_optionals">{% trans "Provide optional details" %}</div><div id="optional">{%endif%}
<div class="fieldWrapper"> <div class="fieldWrapper">
{% if field.help_text %}<span class="help_text">{{ field.help_text }}</span>{% endif %} {% if field.help_text %}<span class="help_text">{{ field.help_text }}</span>{% endif %}
<span class="innerfield"> <span class="innerfield">
{{ field.errors }} {{ field.errors }}
{{ field.label_tag }} {{ field }} {{ field.label_tag }} {{ field }}
</span> </span>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% csrf_token %} {% csrf_token %}
<input id="save_button" type="submit" value="{% trans "save" %}" /> <input id="save_button" type="submit" value="{% trans "save" %}" />
</form> </form>
</div> </div>
<div id='content'> <div id='content'>
<h2>{% trans "On the Internet, <strong>you</strong> decide what you do, right? <i>Not anymore!</i>" %}</h2> <h2>{% trans "On the Internet, <strong>you</strong> decide what you do, right? <i>Not anymore!</i>" %}</h2>
<p>{% trans "Large telecommunication providers want to control what you do online. They want to block and throttle some of your communications, and charge you to use certain online services, content and applications." %}</p> <p>{% trans "Large telecommunication providers want to control what you do online. They want to block and throttle some of your communications, and charge you to use certain online services, content and applications." %}</p>
<p>{% trans "Now is the time to fight back!" %}</p> <p>{% trans "Now is the time to fight back!" %}</p>
<p>{% trans "Help us chart all the ways that internet providers are violating our online freedom. Tell us about how your landline or mobile operator Internet provider restricts your connection. You can do so in less than two minutes!" %} <p>{% trans "Help us chart all the ways that internet providers are violating our online freedom. Tell us about how your landline or mobile operator Internet provider restricts your connection. You can do so in less than two minutes!" %}
<p>{% trans "We will report these violations to the European Commission and national authorities and demand action to address them." %}</p> <p>{% trans "We will report these violations to the European Commission and national authorities and demand action to address them." %}</p>
<p>{% trans "Don't hesitate to give us feedback on this application by reporting any idea or issue with RespectMyNet.eu here : <a href='https://nnmon.quadpad.lqdn.fr/feedback'>Feedback pad page</a>" %}</p> <p>{% trans "Don't hesitate to give us feedback on this application by reporting any idea or issue with RespectMyNet.eu here : <a href='https://nnmon.quadpad.lqdn.fr/feedback'>Feedback pad page</a>" %}</p>
<h2 id="stats-title">{% trans "Statistics" %}</h2> <h2 id="stats-title">{% trans "Statistics" %}</h2>
<div id="stats_graph" ></div> <div id="stats_graph" ></div>
<ul id="stats"> <ul id="stats">
{% for t, n in stats %} {% for t, n in stats %}
<li class="stat"><dl><dt class="inline">{{t}}</dt><dd class="inline"><strong>{{n}}</strong></dd></dl></li> <li class="stat"><dl><dt class="inline">{{t}}</dt><dd class="inline"><strong>{{n}}</strong></dd></dl></li>
{% endfor %} {% endfor %}
</ul> </ul>
<h2 id="featured-title">{% trans "Featured Cases" %}</h2> <h2 id="featured-title">{% trans "Featured Cases" %}</h2>
<table id="featured_cases"> <table id="featured_cases">
<thead> <thead>
<tr> <tr>
<th style="width: 70%;">{% trans "Infringing offering" %}</th> <th style="width: 70%;">{% trans "Infringing offering" %}</th>
<th>{% trans "Confirmed" %}</th> <th>{% trans "Confirmed" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for violation in violations %} {% for violation in violations %}
<tr> <tr>
<td><a href="{{ violation.get_absolute_url }}">{{ violation.operator }} ({{ violation.country|country }}) {{ violation.contract }}</a> <td><a href="{{ violation.get_absolute_url }}">{{ violation.operator }} ({{ violation.country|country }}) {{ violation.contract }}</a>
<div class="info-validate"> <div class="info-validate">
<form method="get" id="{{ violation.pk }}" class="confirm_form" > <form method="get" id="{{ violation.pk }}" class="confirm_form" >
<label>{% trans "In order to <strong>confirm</strong> this report, please enter your email address" %}</label> <label>{% trans "In order to <strong>confirm</strong> this report, please enter your email address" %}</label>
<br/><input type="text" name="email" /> <br/><input type="text" name="email" />
<input type="submit" value="{% trans "OK" %}" /> <input type="submit" value="{% trans "OK" %}" />
<input type="button" value="{% trans "Cancel" %}" class="cancel-button" /> <input type="button" value="{% trans "Cancel" %}" class="cancel-button" />
<input type="hidden" value="{{ violation.pk }}" /> <input type="hidden" value="{{ violation.pk }}" />
</form> </form>
</div> </div>
</td> </td>
<td class='align-right'>{{ violation.confirmations }}</td> <td class='align-right'>{{ violation.confirmations }}</td>
<td class='align-right'><input type="button" class="confirm button" value="{% trans "Me too!" %}" /> <td class='align-right'><input type="button" class="confirm button" value="{% trans "Me too!" %}" />
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="3"> <td colspan="3">
<div id="description" class='round-box'> <div id="description" class='round-box'>
<strong>{% trans "Affected Resource" %}:</strong> {{violation.resource_name}} <strong>{% trans "Affected Resource" %}:</strong> {{violation.resource_name}}
{%for c in violation.comment_set.all%} {%for c in violation.comment_set.all%}
<div class="description">{{c.comment|safe}}</div> <div class="description">{{c.comment|safe}}</div>
<span class="submitter">{%if c.submitter_name%}{{c.submitter_name}}{%else%}{{c.submitter_email}}{%endif%}</span> - <span class="comment_date">{{c.timestamp|date:"SHORT_DATE_FORMAT" }}</span> <span class="submitter">{%if c.submitter_name%}{{c.submitter_name}}{%else%}{{c.submitter_email}}{%endif%}</span> - <span class="comment_date">{{c.timestamp|date:"SHORT_DATE_FORMAT" }}</span>
</div> </div>
{%endfor%} {%endfor%}
</div> </div>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
{%endblock%} {%endblock%}
...@@ -3,139 +3,115 @@ ...@@ -3,139 +3,115 @@
{% load i18n %} {% load i18n %}
{% block active_tab_search %}id="current"{% endblock %} {% block active_tab_search %}id="current"{% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="/static/css/map.css" type="text/css" /> <link rel="stylesheet" href="/static/css/map.css" type="text/css" />
{% endblock %} {% endblock %}
{% block head %} {% block head %}
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script type="text/javascript" src="/static/js/jquery.min.js"></script> <script type="text/javascript">
<script type="text/javascript" src="/static/js/jquery.tablesorter.js"></script> var data={% if countryweights %}{{countryweights|safe}}{%else%}[]{% endif %};
<script type="text/javascript" src="/static/js/picnet.table.filter.min.js"></script> var country="{{country}}";
<script type="text/javascript" src='/static/js/d3.min.js'></script> $.tablesorter.addParser({
<script type="text/javascript" src='/static/js/topojson.min.js'></script> // set a unique id
<script type="text/javascript" src='/static/js/datamaps.js'></script> id: 'stateparser',
<script type="text/javascript" src="/static/js/map.js"></script> is: function(s) {
<script type="text/javascript"> // return false so this parser is not auto detected
var data={% if countryweights %}{{countryweights|safe}}{%else%}[]{% endif %}; return false;
var country="{{country}}"; },
$(document).ready(function() { format: function(s) {
$.tablesorter.addParser({ // format your data for normalization
/ set a unique id return s{% for s, translation in status %}.replace(/{{translation}}/,{{forloop.counter}}){% endfor %};
id: 'stateparser', },
is: function(s) { // set type, either numeric or text
/ return false so this parser is not auto detected type: 'numeric'
return false; });
}, </script>
format: function(s) {
/ format your data for normalization
return s{% for s, translation in status %}.replace(/{{translation}}/,{{forloop.counter}}){% endfor %};
},
/ set type, either numeric or text
type: 'numeric'
});
$("#sortedlist").tablesorter({
headers: { 8: { sorter: false },
0: { sorter: 'stateparser' }},
sortList: [[1,0],[0,0],[7,1]],
});
var options = { enableCookies: false };
$('#sortedlist').tableFilter(options);
$('.confirm_form').submit(function() {
var self=this;
var email=$(this).find('input:first').attr('value');
if( email.length>0) {
$.ajax({url: '/confirm/'+$(this).attr('id').slice(1)+'/'+email, success: function(data) { $(self).html(data); }});
} else {
$(this).find('[type=text]').focus();
}
return false;
});
$(".confirm > .button").click(function(){
$(this).parent().parent().parent().find('.info-validate').toggle();
});
$(".cancel-button").click(function(){
$(this).parent().hide();
});
});
</script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="global"> <div id="global">
{% if messages %} {% if messages %}
<ul class="messages"> <ul class="messages">
{% for message in messages %} {% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
{% trans "Search through cases" %} {% trans "Search through cases" %}
<div id="map"> </div> <div id="map"> </div>
<form method="get" action="."> <form method="get" action=".">
{{ form.as_p }} {{ form.as_p }}
<input type="submit" value="Search"> <input type="submit" value="Search">
</form> </form>
{% if query %}
<h3>Results</h3>
{% if query %} <h2 id="stats-title">{% trans "Statistics" %}</h2>
<h3>Results</h3> <ul id="stats">
{% for t, n in stats %}
<li class="stat"><dl><dt class="inline">{{t}}</dt><dd class="inline"><strong>{{n}}</strong></dd></dl></li>
{% endfor %}
</ul>
</div>
<table class="listing tablesorter zebra-striped" id='sortedlist'> <table class="listing tablesorter zebra-striped" id='sortedlist'>
<thead> <thead>
<tr> <tr>
<th filter-type='ddl'>{% trans "Status" %}</th> <th filter-type='ddl'>{% trans "Status" %}</th>
<th filter-type='ddl'>{% trans "country" %}</th> <th filter-type='ddl'>{% trans "country" %}</th>
<th filter-type='ddl'>{% trans "operator" %}</th> <th filter-type='ddl'>{% trans "operator" %}</th>
<th filter-type='ddl'>{% trans "contract" %}</th> <th filter-type='ddl'>{% trans "contract" %}</th>
<th filter-type='ddl'>{% trans "resource" %}</th> <th filter-type='ddl'>{% trans "resource" %}</th>
<th filter-type='ddl'>{% trans "type" %}</th> <th filter-type='ddl'>{% trans "type" %}</th>
<th filter-type='ddl'>{% trans "fixed / wireless" %}</th> <th filter-type='ddl'>{% trans "fixed / wireless" %}</th>
<th filter='false'>{% trans "confirmations" %}</th> <th filter='false'>{% trans "confirmations" %}</th>
<th filter='false'></th> <th filter='false'></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for result in page.object_list %} {% for result in object_list %}
<tr class="{%if result.object.state%}{{result.object.state}}{%else%}new{%endif%}-status"> <tr class="{%if result.object.state%}{{result.object.state}}{%else%}new{%endif%}-status">
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{%if result.object.state%}{{result.object.state|status}}{%else%}{% trans "New" %}{%endif%}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{%if result.object.state%}{{result.object.state|status}}{%else%}{% trans "New" %}{%endif%}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.country|country }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.country|country }}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.operator }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.operator }}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.contract }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.contract }}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.resource_name }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.resource_name }}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.type|type }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.type|type }}</a></td>
<td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.media|media }}</a></td> <td><a class="cell-link" href="{{ result.object.get_absolute_url }}">{{ result.object.media|media }}</a></td>
<td>{{ result.object.confirmations }}</td> <td>{{ result.object.confirmations }}</td>
<td> <td>
<div class="confirm"><a class="button">{% trans "Me too!" %}</a> <div class="confirm"><a class="button">{% trans "Me too!" %}</a>
<div class="info-validate float-confirm"> <div class="info-validate float-confirm">
<form method="get" action="" id="i{{ violation.pk }}" class="confirm_form" > <form method="get" action="" id="i{{ violation.pk }}" class="confirm_form" >
<div> <div>
<label>{% trans "In order to <strong>confirm</strong> this report, please enter your email address" %}</label> <label>{% trans "In order to <strong>confirm</strong> this report, please enter your email address" %}</label>
<input type="text" name="email" /> <input type="text" name="email" />
<input type="hidden" value="{{ violation.pk }}" /> <input type="hidden" value="{{ violation.pk }}" />
<input type="submit" value="{% trans "OK" %}" /> <input type="submit" value="{% trans "OK" %}" />
</div> </div>
</form> </form>
<input class="cancel-button" type="button" value="{% trans "Close" %}" /> <input class="cancel-button" type="button" value="{% trans "Close" %}" />
</div> </div>
</div> </div>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if page.has_previous or page.has_next %} {% if page.has_previous or page.has_next %}
<div> <div>
{% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %} {% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %}
| |
{% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %} {% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
</div> </div>
{% endif %} {% endif %}
{% else %} {% else %}
{# Show some example queries to run, maybe query syntax, something else? #} </div>
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}
...@@ -81,7 +81,7 @@ urlpatterns = patterns('', ...@@ -81,7 +81,7 @@ urlpatterns = patterns('',
url(r'^api/', url(r'^api/',
include(operator_api_resource.urls)), include(operator_api_resource.urls)),
url(r'^search/', url(r'^search/',
include('haystack.urls')), bt.ViolationSearchView.as_view(template_name='search/search.html')),
) )
if settings.DEV_SERVER == True: if settings.DEV_SERVER == True:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment