...
 
Commits (79)
......@@ -23,41 +23,41 @@ class AddViolation(forms.Form):
country = forms.ChoiceField(required=True, choices=(('',''),)+tuple(sorted(COUNTRIES,key=itemgetter(1))), label=_("Country"), help_text=_('EU member state where the restriction is reported.'))
operator = forms.CharField(required=True, max_length=256, label=_("Operator"), help_text=_('The ISP or operator providing the Internet service.'))
contract = forms.CharField(required=True, max_length=256, label=_("Contract"), help_text=_('The specific contract at the ISP provider. (please be as specific as possible)'))
media = forms.ChoiceField(required=True, choices=(('',''),)+tuple(sorted(MEDIA,key=itemgetter(1))), label=_('Is the Internet connection over mobile or fixed line?'))
media = forms.ChoiceField(required=True, choices=tuple(sorted(MEDIA,key=itemgetter(1))), label=_('Is the Internet connection over mobile or fixed line?'))
comment = forms.CharField(required=True, widget=AdvancedEditor(), label=_('Please describe the symptoms you are experiencing.'))
email = forms.EmailField(required=True, label=_('Email (set this to enable saving)'), help_text=_("We need your email to validate your report. Your email address is obligatory, but we will never use your personal data for anything else than checking the submission. (see next for an optional exception)"))
consent = forms.BooleanField(required=False, label=_("I want to help further"), help_text=_("We need your consent to contact you for clarifications regarding your report. This is optional, but helps us improve the quality of the reports. Thanks!"))
nick = forms.CharField(required=False, label=_("Name or nickname"), help_text=_("We need some name to display that instead of an email address."))
attachments = MultiFileField(required=False, label=_("Attach screenshot, document or any other relevant information."))
resource = forms.ChoiceField(required=False, choices=(('',''),)+tuple(sorted(RESOURCES,key=itemgetter(1))), label=_('What is the affected resource type. (optional)'))
type = forms.ChoiceField(required=False, choices=(('',''),)+tuple(sorted(TYPES,key=itemgetter(1))), label=_('Is the Resource Blocked or otherwise discrimated? (optional)'))
resource = forms.ChoiceField(required=False, choices=tuple(sorted(RESOURCES,key=itemgetter(1))), label=_('What is the affected resource type. (optional)'))
type = forms.ChoiceField(required=True, choices=tuple(sorted(TYPES,key=itemgetter(1))), label=_('What types of resctriction happens in this case?'))
temporary = forms.BooleanField(required=False, label=_('Is the restriction only temporary, e.g. due to network overload? (optional)'))
loophole = forms.BooleanField(required=False, label=_('Is there another offer provided by this Operator which removes this restriction? (optional)'))
contractual = forms.BooleanField(required=False, label=_('Is the restriction described in the subscribers contract? (optional)'))
contractual = forms.BooleanField(required=False, label=_('The restriction is described in the subscribers contract.'))
contract_excerpt = forms.CharField(required=False, widget=AdvancedEditor(), label=_('Please copy the relevant section describing the restriction from the user contract. (optional)'))
captcha = CaptchaField(label=_("In order to protect against spam, please fill in the result of the following calculation. (note the + and the * are somewhat confusing)"))
class SearchViolation(SearchForm):
country = forms.ChoiceField(required=True, choices=(('',''),)+tuple(sorted(COUNTRIES,key=itemgetter(1))), label=_("Country"), help_text=_('EU member state where the restriction is reported.'))
operator = forms.CharField(required=True, max_length=256, label=_("Operator"), help_text=_('The ISP or operator providing the Internet service.'))
contract = forms.CharField(required=True, max_length=256, label=_("Contract"), help_text=_('The specific contract at the ISP provider. (please be as specific as possible)'))
media = forms.ChoiceField(required=True, choices=(('',''),)+tuple(sorted(MEDIA,key=itemgetter(1))), label=_('Is the Internet connection over mobile or fixed line?'))
country = forms.ChoiceField(required=False, choices=(('',''),)+tuple(sorted(COUNTRIES,key=itemgetter(1))), label=_("Country"), help_text=_('EU member state where the restriction is reported.'))
operator = forms.CharField(required=False, max_length=256, label=_("Operator"), help_text=_('The ISP or operator providing the Internet service.'))
contract = forms.CharField(required=False, max_length=256, label=_("Contract"), help_text=_('The specific contract at the ISP provider. (please be as specific as possible)'))
media = forms.ChoiceField(required=False, choices=(('',''),)+tuple(sorted(MEDIA,key=itemgetter(1))), label=_('Is the Internet connection over mobile or fixed line?'))
def search(self):
# By default, teh search field is q. So let's check if it's empty
# By default, the search field is q. So let's check if it's empty
if not self.cleaned_data['q']:
sqs = SearchQuerySet().all()
sqs = SearchQuerySet().all().exclude(old=True)
else:
sqs = super(SearchViolation, self).search()
sqs = super(SearchViolation, self).search().exclude(old=True)
if not self.is_valid():
return self.no_query_found()
if self.cleaned_data['operator']:
sqs = sqs.filter(operator=self.cleaned_data['operator'])
sqs = sqs.filter(operator__icontains=self.cleaned_data['operator'])
if self.cleaned_data['contract']:
sqs = sqs.filter(contract=self.cleaned_data['contract'])
sqs = sqs.filter(contract__icontains=self.cleaned_data['contract'])
if self.cleaned_data['media']:
sqs = sqs.filter(media=self.cleaned_data['media'])
......
......@@ -64,11 +64,11 @@ class Migration(migrations.Migration):
('media', models.CharField(blank=True, max_length=20, choices=[(b'fixed', 'Fixed'), (b'mobile', 'Mobile')])),
('temporary', models.BooleanField()),
('contractual', models.BooleanField()),
('contract_excerpt', models.TextField(blank=True)),
('contract_excerpt', models.TextField(null=True, blank=True)),
('loophole', models.BooleanField()),
('activationid', models.CharField(max_length=128, blank=True)),
('state', models.CharField(default=b'new', max_length=20, blank=True, choices=[(b'moreinfo', 'Need more info'), (b'new', 'New'), (b'verified', 'Verified'), (b'duplicate', 'Duplicate'), (b'ooscope', 'Out of scope'), (b'closed', 'Closed')])),
('editorial', models.TextField(blank=True)),
('editorial', models.TextField(null=True, blank=True)),
('operator_ref', models.ForeignKey(related_name='violations', to='bt.Operator')),
],
),
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bt', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='violation',
name='old',
field=models.BooleanField(default=b'False'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def archive_old(apps, schema_editor):
Violation = apps.get_model("bt", "Violation")
for violation in Violation.objects.all():
violation.old = True
violation.save()
class Migration(migrations.Migration):
dependencies = [
('bt', '0002_violation_old'),
]
operations = [
migrations.RunPython(archive_old),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bt', '0003_auto_20160301_2032'),
]
operations = [
migrations.AlterField(
model_name='violation',
name='activationid',
field=models.CharField(max_length=128, null=True, blank=True),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bt', '0004_auto_20160301_2103'),
]
operations = [
migrations.AlterField(
model_name='violation',
name='country',
field=models.CharField(max_length=2, choices=[(b'BE', 'Belgium'), (b'BG', 'Bulgaria'), (b'CH', 'Switzerland'), (b'CZ', 'Czech Republic'), (b'DK', 'Denmark'), (b'DE', 'Germany'), (b'EE', 'Estonia'), (b'IE', 'Ireland'), (b'EL', 'Greece'), (b'ES', 'Spain'), (b'FR', 'France'), (b'IC', 'Iceland'), (b'IS', 'Iceland'), (b'IT', 'Italy'), (b'CY', 'Cyprus'), (b'LI', 'Liechtenstein'), (b'LV', 'Latvia'), (b'LT', 'Lithuania'), (b'LU', 'Luxembourg'), (b'HU', 'Hungary'), (b'MT', 'Malta'), (b'NL', 'Netherlands'), (b'NO', 'Norway'), (b'AT', 'Austria'), (b'PL', 'Poland'), (b'PT', 'Portugal'), (b'RO', 'Romania'), (b'SI', 'Slovenia'), (b'SK', 'Slovakia'), (b'FI', 'Finland'), (b'SE', 'Sweden'), (b'UK', 'United Kingdom')]),
),
migrations.AlterField(
model_name='violation',
name='resource',
field=models.CharField(blank=True, max_length=20, choices=[(b'port', 'port'), (b'protocol', 'protocol'), (b'service', 'service'), (b'site', 'website'), (b'user', 'user'), (b'ip', 'ip'), (b'video', 'video streaming'), (b'audio', 'audio streaming'), (b'class', 'class of application or contraint'), (b'other', 'other')]),
),
migrations.AlterField(
model_name='violation',
name='type',
field=models.CharField(blank=True, max_length=20, choices=[(b'zerorating', 'Zero Rating'), (b'blocking', 'Blocking'), (b'throttling', 'Throttling'), (b'prioritisation', 'Prioritisation'), (b'specialised', 'Specialised Service'), (b'other', 'Other')]),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import datetime
class Migration(migrations.Migration):
dependencies = [
('bt', '0005_auto_20160302_1202'),
]
operations = [
migrations.AddField(
model_name='violation',
name='creation_date',
field=models.DateField(default=datetime.datetime(2016, 3, 2, 12, 14, 23, 907012), auto_now_add=True),
preserve_default=False,
),
]
......@@ -5,6 +5,7 @@ from django_comments.moderation import CommentModerator, moderator
COUNTRIES = (
('BE', _('Belgium')),
('BG', _('Bulgaria')),
('CH', _('Switzerland')),
('CZ', _('Czech Republic')),
('DK', _('Denmark')),
('DE', _('Germany')),
......@@ -13,9 +14,11 @@ COUNTRIES = (
('EL', _('Greece')),
('ES', _('Spain')),
('FR', _('France')),
('IC', _('Iceland')),
('IS', _('Iceland')),
('IT', _('Italy')),
('CY', _('Cyprus')),
('LI', _('Liechtenstein')),
('LV', _('Latvia')),
('LT', _('Lithuania')),
('LU', _('Luxembourg')),
......@@ -38,13 +41,21 @@ RESOURCES = (
('port', _('port')),
('protocol', _('protocol')),
('service', _('service')),
('site', _('site')),
('site', _('website')),
('user', _('user')),
('ip', _('ip')),
('video', _('video streaming')),
('audio', _('audio streaming')),
('class', _('class of application or contraint')),
('other', _('other'))
)
TYPES = (
('zerorating', _('Zero Rating')),
('blocking', _('Blocking')),
('throttling', _('Throttling')),
('prioritisation', _('Prioritisation')),
('specialised', _('Specialised Service')),
('other', _('Other'))
)
MEDIA = (
('fixed', _('Fixed')),
......@@ -73,7 +84,6 @@ class Operator(models.Model):
def __unicode__(self):
return self.name
class Violation(models.Model):
country = models.CharField(max_length=2, choices=COUNTRIES)
operator_ref = models.ForeignKey(Operator, related_name="violations")
......@@ -84,11 +94,13 @@ class Violation(models.Model):
media = models.CharField( max_length=20, choices=MEDIA, blank=True)
temporary = models.BooleanField( )
contractual = models.BooleanField()
contract_excerpt = models.TextField(blank=True)
contract_excerpt = models.TextField(null=True, blank=True)
loophole = models.BooleanField()
activationid= models.CharField(max_length=128, blank=True)
activationid= models.CharField(max_length=128, null=True, blank=True)
state = models.CharField(max_length=20, choices=STATUS, default='new', blank=True)
editorial = models.TextField(blank=True)
editorial = models.TextField(null=True, blank=True)
old = models.BooleanField(default="False")
creation_date = models.DateField(auto_now_add=True)
def confirmations(self):
return self.confirmation_set.filter(key='').count()
......@@ -108,7 +120,6 @@ class Violation(models.Model):
def __unicode__(self):
return "#%s %s/%s" % (self.pk, self.country, self.operator)
class Comment(models.Model):
submitter_email = models.EmailField()
submitter_name = models.CharField(max_length=20)
......
......@@ -5,9 +5,12 @@ class ViolationIndexes(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
operator = indexes.CharField(model_attr="operator_ref")
country = indexes.CharField(model_attr="country")
contract = indexes.CharField(model_attr="contract_excerpt")
type = indexes.BooleanField(model_attr="contractual")
contract = indexes.CharField(model_attr="contract")
type = indexes.CharField(model_attr="contractual")
media = indexes.CharField(model_attr="media")
operator_name = indexes.CharField()
state = indexes.NgramField(model_attr="state")
old = indexes.BooleanField(model_attr="old")
def get_model(self):
return Violation
......
from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.template import Library
from haystack.models import SearchResult
import json
register = Library()
@register.filter(name='jsonify')
def jsonify(object):
if isinstance(object, QuerySet):
return serialize('json', object)
elif object == []:
return json.dumps(object)
elif isinstance(object[0], SearchResult):
return serialize('json', [x.object for x in object])
else:
return json.dumps(object)
......@@ -6,6 +6,7 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext, loader, Context
from django.core.files import File
from django.core.servers.basehttp import FileWrapper
from django.core import serializers
from django.conf import settings
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.exceptions import ObjectDoesNotExist
......@@ -15,7 +16,8 @@ from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.db.models import Count
from haystack.generic_views import SearchView
from models import Violation, Attachment, Comment, Confirmation, COUNTRIES, STATUS, Operator
from haystack.query import SearchQuerySet
from models import Violation, Attachment, Comment, Confirmation, COUNTRIES, STATUS, Operator, FeaturedCase
from tempfile import mkstemp
from datetime import datetime
import hashlib, os, re, json
......@@ -142,20 +144,10 @@ def sendverifymail(service,to,body):
return actid
class JSONMixin(object):
def get(self, request, *args, **kwargs):
qs = self.get_queryset()
if qs.count():
return HttpResponse(json.dumps(sorted([(x.id, x.resource_name) for x in qs])))
else:
return HttpResponse('')
class AddForm(FormView):
model = Violation
template_name = 'index.html'
form_class = AddViolation
success_url = '/'
context_object_name = 'violations'
def form_valid(self, form):
msg=_("Thank you for submitting a new report. To finalize your submission please confirm using your validation key.\nYour verification key is %s/%s%s\nPlease note that reports are moderated, it might take some time before your report appears online. Thank you for your patience.")
......@@ -173,7 +165,8 @@ class AddForm(FormView):
contractual = form.cleaned_data['contractual'],
contract_excerpt = sanitizeHtml(form.cleaned_data['contract_excerpt']),
loophole = form.cleaned_data['loophole'],
activationid = actid
activationid = actid,
old = False
)
v.save()
#c=Confirmation(key='', email=form.cleaned_data['email'], violation=v)
......@@ -187,7 +180,7 @@ class AddForm(FormView):
violation=v,
)
c.save()
for f in request.FILES.getlist('attachments[]'):
for f in self.request.FILES.getlist('attachments[]'):
a=Attachment(comment=c, name=f.name, type=f.content_type)
m = hashlib.sha256()
for chunk in f.chunks():
......@@ -195,27 +188,25 @@ class AddForm(FormView):
sname=m.hexdigest()
a.storage.save(sname,f)
a.save()
messages.add_message(request, messages.INFO, _('Thank you for submitting this report, you will receive a verification email immediately, if not check your spam folder.'))
messages.add_message(self.request, messages.INFO, _('Thank you for submitting this report, you will receive a verification email immediately, if not check your spam folder.'))
return super(AddForm, self).form_valid(form)
def get_queryset(self):
return Violation.objects.filter(activationid='',featuredcase__isnull=False).order_by('id').reverse()[:3]
def get_context_data(self, **kwargs):
context = super(AddForm, self).get_context_data(**kwargs)
reports = sorted([(i['total'],i['id'])
for i in Violation.objects.values('id').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).annotate(total=Count('confirmation'))],
for i in Violation.objects.values('id').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).exclude(old=True).annotate(total=Count('confirmation'))],
reverse=True)
confirms = sorted([(i['total'],i['country'])
for i in Violation.objects.values('country').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).annotate(total=Count('confirmation'))],
for i in Violation.objects.values('country').filter(activationid='').exclude(state__in=['closed', 'ooscope', 'duplicate']).exclude(old=True).annotate(total=Count('confirmation'))],
reverse=True)
operators = sorted([(i['total'],i['operator_ref__name'])
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']).exclude(old=True).annotate(total=Count('confirmation'))],
reverse=True)
context['stats'] = [
(_('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])),
(_('Operators with some confirmed reports'), len([i for i,z in operators if i>0]))]
context['violations'] = [fc.case for fc in FeaturedCase.objects.all() if not fc.case.old][:3]
return context
class ViolationsList(ListView):
......@@ -223,17 +214,17 @@ class ViolationsList(ListView):
context_object_name = 'violations'
def get_queryset(self):
queryset = Violation.objects.filter(activationid='')
queryset = Violation.objects.filter(activationid='').exclude(old=True)
if 'operator' in self.kwargs:
# If i Have operator I have a country
queryset = Violation.objects.filter(activationid='',
country=self.kwargs['country'],
operator_ref__name=self.kwargs['operator'])
operator_ref__name=self.kwargs['operator']).exclude(old=True)
if 'country' in self.kwargs:
queryset = Violation.objects.filter(activationid='',
country=self.kwargs['country'])
country=self.kwargs['country']).exclude(old=True)
if 'all' not in self.request.GET:
queryset = queryset.filter(activationid='').exclude(state__in=['duplicate', 'closed'])
queryset = queryset.filter(activationid='').exclude(state__in=['duplicate', 'closed']).exclude(old=False)
return queryset
def get_context_data(self, **kwargs):
......@@ -243,7 +234,7 @@ class ViolationsList(ListView):
context['country'] = self.kwargs['country']
else:
countries = sorted([(i['total'], i['country'])
for i in Violation.objects.values('country').filter(activationid='').exclude(state__in=['duplicate', 'closed']).annotate(total=Count('country'))],
for i in Violation.objects.values('country').filter(activationid='').exclude(state__in=['duplicate', 'closed']).exclude(old=True).annotate(total=Count('country'))],
reverse=True)
countryweights=json.dumps([{'iso2': y, 'w': x} for x, y in countries])
context['countries'] = countries
......@@ -262,11 +253,26 @@ class ViolationView(DetailView):
raise Http404
return object
class LookupView(JSONMixin, SearchView):
queryset = Violation.objects.filter(activationid='')
class LookupView(SearchView):
searchqueryset = SearchQuerySet().exclude(old=True)
form_class = SearchViolation
def get_queryset(self):
return super(LookupView, self).get_queryset().exclude(old=True)
def get_context_data(self, *args, **kwargs):
context = super(LookupView, self).get_context_data(*args, **kwargs)
if 'object_list' in context:
context['object_list'] = [obj for obj in context['object_list'] if not obj.object.old]
return context
class ViolationSearchView(SearchView):
searchqueryset = SearchQuerySet().exclude(old=True)
form_class = SearchViolation
def get_queryset(self):
return super(ViolationSearchView, self).get_queryset().exclude(old=True)
def get_context_data(self, *args, **kwargs):
context = super(ViolationSearchView, self).get_context_data(*args, **kwargs)
countries = sorted([(k, len(list(g)),) for k, g in groupby(sorted([i['country'] for i in self.queryset.values('country')]))])
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -4,13 +4,15 @@ BeautifulSoup==3.2.1
defusedxml==0.4.1
Django==1.8.6
django-ajax-selects==1.4.1
django-bootstrap3==7.0.0
django-contrib-comments==1.6.1
django-debug-toolbar==1.4
django-haystack==2.4.1
django-registration==2.0.3
django-simple-captcha==0.4.6
django-tastypie==0.12.2
django-tinymce==2.0.6
flup==1.0.3.dev20110405
flup
httplib2==0.9.2
lxml==3.5.0
oauth2==1.9.0.post1
......@@ -24,5 +26,6 @@ pytz==2015.7
simplejson==3.8.1
six==1.10.0
South==1.0.2
sqlparse==0.1.18
wheel==0.24.0
Whoosh==2.7.0
......@@ -145,6 +145,8 @@ INSTALLED_APPS = (
'haystack',
# Debugging bar
'debug_toolbar',
# Let's have fun with bootstrap
'bootstrap3',
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
......
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
body { border: 0; padding: 0; font-family: Verdana,Arial,Helvetica,sans-serif; }
img { border: 0; vertical-align: middle; }
h1, h2, h3, h4, div, ul { padding: 0; margin: 0; }
li { list-style: none; }
h1, h2, h3, h4, div { padding: 0; margin: 0; }
.fieldWrapper { width: 100%; position: relative; }
.fieldWrapper label { display: inline-block; }
......@@ -49,7 +48,8 @@ li { list-style: none; }
#addForm .fieldWrapper label { display: inline-block; min-width: 6em; }
#addForm.index .help_text { font-size: 0.7em; width: 30%; position: relative; float: right; left: 0; }
.index #add_attach { cursor: pointer; }
#id_captcha_1 { width: 2em; }
img.captcha {float: left; }
#id_captcha_1 { width: auto; }
.innerfield { display: inline-block; margin-top: 0.5em;}
.align-right { text-align: right;}
dd.text { width: 50%; display: block !important; }
......@@ -76,10 +76,10 @@ p label { width: 7em; display: inline-block; }
#footer {
text-align: center;
max-width: 960px;
clear: both;
margin: auto;
background-color: #f9f9f9;
padding-bottom:30px;
}
.errorlist { font-size: .8em; color: red; }
......@@ -237,26 +237,28 @@ blockquote {
}
#header {
background: #f9f9f9;
padding:3%
}
#header a {
color: #222;
color: white;
text-decoration: none;
}
h1 {
margin: 25px 0 0 0; padding: 30px 0;
margin: 25px 0 0 0;
padding: 3%;
font-family: 'DroidSansBold', Helvetica, Arial, "Liberation Sans", FreeSans, sans-serif;
font-size: 35px;
line-height: 1;
font-weight: normal;
font-weight: bold;
text-shadow:1px 2px 1px rgba(0, 0, 0, 0.4);
}
h1 span {
display: block;
font-family: 'DroidSansRegular', Helvetica, Arial, "Liberation Sans", FreeSans, sans-serif;
font-size: .8em;
font-weight: normal;
color: orange;
font-weight: bold;
}
/* User */
......@@ -279,7 +281,6 @@ h1 span {
}
#user p {
width: 960px;
margin: 0 auto;
text-align: right;
}
......@@ -288,61 +289,51 @@ h1 span {
color: orange;
}
/* Navigation menu */
#nav {
height: 36px;
margin: 0; padding: 0;
list-style-type: none;
border-bottom: 1px solid #ddd;
}
#nav li {
display: inline-block;
}
#nav #current {
color: #231f20;
background: #fff;
border: 1px solid #ddd;
border-bottom: 1px solid #fff;
}
#nav #current:hover, #nav #current:active, #nav #current:focus {
color: orange;
}
#nav a {
display: block;
height: 19px;
padding: 8px 1em;
text-decoration: none;
color: #ccc;
border: 1px solid #f0f0f0;
border-bottom-color: #ddd;
-moz-border-radius: 2px 2px 0 0;
-webkit-border-radius: 2px 2px 0 0;
-o-border-radius: 2px 2px 0 0;
border-radius: 2px 2px 0 0;
}
#nav a:hover, #nav a:active, #nav a:focus {
color: #231f20;
background: #fff;
border: 1px solid #ddd;
border-bottom-color: #fff;
outline: none;
}
/* Content layout
---------------------------*/
#global {
position: relative;
width: 960px;
margin: 25px auto 50px auto;
}
/* Content */
#content {
width: 610px;
width: 60%;
}
#add-case{
width: 40%;
}
#header{
background: rgba(11,145,194,1);
background: -moz-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background: -webkit-gradient(left top, right top, color-stop(0%, rgba(11,145,194,1)), color-stop(100%, rgba(4,220,227,1)));
background: -webkit-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background: -o-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background: -ms-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background: linear-gradient(to right, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0b91c2', endColorstr='#04dce3', GradientType=1 );
background-image: url("images/net-neutrality.png"), -moz-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background-image: url("images/net-neutrality.png"), -webkit-gradient(left top, right top, color-stop(0%, rgba(11,145,194,1)), color-stop(100%, rgba(4,220,227,1)));
background-image: url("images/net-neutrality.png"), -webkit-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background-image: url("images/net-neutrality.png"), -o-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background-image: url("images/net-neutrality.png"), -ms-linear-gradient(left, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
background-image: url("images/net-neutrality.png"), linear-gradient(to right, rgba(11,145,194,1) 0%, rgba(4,220,227,1) 100%);
}
h2{
margin: 1.5em 0 1em 0;
}
h2:first-child{
margin: 0.5em 0 1em 0;
}
#global h2:first-child {
margin-top: 0;
}
......@@ -373,6 +364,27 @@ h1 span {
margin-top: 1em;
}
.navbar-default {
background: #333;
border: none !important;
border-radius: 0;
}
.navbar-default .active a {
color:#555 !important;
}
.navbar-default a{
color:white !important;
}
.navbar-default li:hover{
background:#444 !important;
}
.navbar-default li.active{
background:#555 !important;
}
/* View page */
......@@ -455,7 +467,7 @@ div.comment {
input[type=submit], input[type=button], .button, input[type="text"], textarea, select {
font: 14.4px Helvetica, Arial, "Liberation Sans", FreeSans, sans-serif;
background: #fff;
border: 1px solid #ccc;
/*border: 1px solid #ccc;*/
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
-o-border-radius: 2px;
......@@ -693,7 +705,7 @@ ul.messages {
#map { float: right; }
.logo-org { display: inline-block; margin: 15px; text-align: center; vertical-align: top; background-color: #f9f9f9; }
.logo-org img { height: 80px; }
.logo-org img { height: 80px; margin-bottom:10px}
.dark { background-color: #212121; }
tr.duplicate-status td { background: #aaa !important; }
......@@ -722,6 +734,32 @@ input[type="text"], input[type="textarea"] {
#push { clear: both; }
#wrapper {
max-width: 960px;
margin: auto;
}
#table {
clear: both;
}
@media screen and (max-width: 700px) {
h1{font-size:30px}
h2{font-size:24px}
h1 span{font-size:16px}
}
@media screen and (max-width: 500px) {
#add-case {
width:100%;
}
#content {
width:100%;
}
}
@media screen and (max-width: 870px) {
.navbar-right input[type="text"]{
width:100px;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{% load json_filters %}
{{ object_list|jsonify|safe }}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.