add css / templates for smsBEST
|
@ -94,7 +94,8 @@ class Area(models.Model):
|
|||
'slug': self.slug,
|
||||
'name': self.name,
|
||||
'name_mr': self.name_mr,
|
||||
'display_name': self.display_name
|
||||
'display_name': self.display_name,
|
||||
'url': self.get_absolute_url()
|
||||
#FIXME add alt_names and geometry
|
||||
}
|
||||
|
||||
|
@ -158,7 +159,8 @@ class Stop(models.Model):
|
|||
'name_mr': self.name_mr,
|
||||
'direction': self.dbdirection,
|
||||
'routes': ", ".join([r.alias for r in routes]),
|
||||
'alternative_names': ", ".join([a.name for a in self.alt_names.all().filter(typ='common')])
|
||||
'alternative_names': ", ".join([a.name for a in self.alt_names.all().filter(typ='common')]),
|
||||
'url': self.get_absolute_url()
|
||||
}
|
||||
|
||||
def get_geojson(self, srid=4326):
|
||||
|
@ -213,7 +215,7 @@ class Stop(models.Model):
|
|||
has_point.boolean = True
|
||||
|
||||
def get_absolute_url(self):
|
||||
return "/admin/mumbai/stop/%d/" % self.id
|
||||
return "/stop/%s" % self.slug
|
||||
|
||||
|
||||
class Route(models.Model):
|
||||
|
@ -242,7 +244,8 @@ class Route(models.Model):
|
|||
'code': self.code,
|
||||
'alias': self.alias,
|
||||
'slug': self.slug,
|
||||
'distance': str(self.distance)
|
||||
'distance': str(self.distance),
|
||||
'url': self.get_absolute_url()
|
||||
}
|
||||
|
||||
class RouteDetail(models.Model):
|
||||
|
|
|
@ -38,14 +38,24 @@ def area(request, name):
|
|||
return render_to_response("area.html", context)
|
||||
|
||||
|
||||
def stop(request, slug):
|
||||
stop = get_object_or_404(Stop, slug=slug)
|
||||
context = RequestContext(request, {
|
||||
'stop': stop
|
||||
})
|
||||
return render_to_response("stop.html", context)
|
||||
|
||||
|
||||
def editstops(request):
|
||||
context = RequestContext(request, {})
|
||||
return render_to_response("editstops.html", context)
|
||||
|
||||
|
||||
def buseditor(request):
|
||||
context = RequestContext(request, {})
|
||||
return render_to_response("buseditor.html", context)
|
||||
|
||||
|
||||
def stats(request):
|
||||
total_stops_left = Stop.objects.filter(point=None).count()
|
||||
total_stops = Stop.objects.count()
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script type="text/javascript" src="/static/js/jquery-1.7.1.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
console.firebug=true;//fix the openlayer problem
|
||||
</script>
|
||||
<script type="text/javascript" src="http://openlayers.org/dev/OpenLayers.js"></script>
|
||||
<title>ChaloBEST: {% block title %} {% endblock %}</title>
|
||||
{% block head %}
|
||||
|
||||
|
|
|
@ -15,19 +15,107 @@
|
|||
a:hover {
|
||||
color: #00f;
|
||||
}
|
||||
|
||||
#map {
|
||||
float: left;
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ROUTE_ALIAS = "{{ route.alias }}",
|
||||
API_BASE = "/1.0/";
|
||||
|
||||
$(document).ready(function() {
|
||||
// initMap();
|
||||
var url = API_BASE + "route/" + ROUTE_ALIAS;
|
||||
$.getJSON(url, {'srid': 3857}, function(obj) {
|
||||
initMap();
|
||||
var stopsGeoJSON = obj.stops;
|
||||
var stops = stopsGeoJSON.features;
|
||||
var stopsWithGeom = [];
|
||||
$.each(stops, function(i,v) {
|
||||
if (!$.isEmptyObject(v.geometry)) {
|
||||
stopsWithGeom.push(v);
|
||||
}
|
||||
});
|
||||
|
||||
stopsGeoJSON.features = stopsWithGeom;
|
||||
//console.log(jsonLayer);
|
||||
jsonLayer.addFeatures(geojson_format.read(stopsGeoJSON));
|
||||
var maxExtent = jsonLayer.getDataExtent();
|
||||
map.zoomToExtent(maxExtent);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function initMap() {
|
||||
var center = new OpenLayers.LonLat(8110203.9998955, 2170000.4068373);
|
||||
map = new OpenLayers.Map("map", {
|
||||
projection: new OpenLayers.Projection("EPSG:900913"),
|
||||
displayProjection: new OpenLayers.Projection("EPSG:4326")
|
||||
});
|
||||
var layers = [];
|
||||
// layers[0] = new OpenLayers.Layer.OSM();
|
||||
|
||||
layers[0] = new OpenLayers.Layer.OSM();
|
||||
layers[1] = new OpenLayers.Layer.Bing({
|
||||
name: "Bing Aerial",
|
||||
type: "Aerial",
|
||||
key: "AqGpO7N9ioFw3YHoPV3C8crGfJqW5YST4gGKgIOnijrUbitLlgcAS2A0M9SJrUv9",
|
||||
});
|
||||
geojson_format = new OpenLayers.Format.GeoJSON();
|
||||
//
|
||||
//yes, jsonLayer is global. Yes, I know it's wrong.
|
||||
jsonLayer = layers[2] = new OpenLayers.Layer.Vector("Bus Stops");
|
||||
map.addLayers(layers);
|
||||
jsonLayer.events.on({
|
||||
'featureselected': onFeatureSelect,
|
||||
'featureunselected': onFeatureUnselect
|
||||
});
|
||||
// Feature selection control
|
||||
mapControl = new OpenLayers.Control.SelectFeature(jsonLayer, {
|
||||
clickout: false,
|
||||
toggle: true
|
||||
});
|
||||
|
||||
//map.addControl(new OpenLayers.Control.ZoomPanel());
|
||||
map.addControl(mapControl);
|
||||
mapControl.activate();
|
||||
|
||||
// Add a LayerSwitcher since we now have Bing
|
||||
map.addControl(new OpenLayers.Control.LayerSwitcher());
|
||||
|
||||
// Add a permalink that opens the relevant view in OSM.org in a different window
|
||||
var permalink = new OpenLayers.Control.Permalink({base: "http://www.openstreetmap.org/"});
|
||||
map.addControl(permalink);
|
||||
}
|
||||
|
||||
function onFeatureSelect(obj) {
|
||||
window.location = obj.feature.attributes.url;
|
||||
}
|
||||
|
||||
function onFeatureUnselect(obj) {
|
||||
$.noop();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<ul id="stopList">
|
||||
{% for r in routeDetails %}
|
||||
<li>
|
||||
<a href="{{ r.stop.get_absolute_url }}" class="{% if r.stop.point %} has_point {% else %} no_point {% endif %}">{{ r.stop.name }}</a> - {{ r.stop.dbdirection }}
|
||||
<a href="{{ r.stop.get_absolute_url }}" class="{% if r.stop.point %} has_point {% else %} no_point {% endif %}">{{ r.stop.name }}</a>
|
||||
</li>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
|
||||
<div id="map">
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,6 +4,7 @@ from os.path import join
|
|||
# Uncomment the next two lines to enable the admin:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
from feeds import RouteFeed
|
||||
#import ox.django.api.urls
|
||||
#import mumbai
|
||||
|
||||
|
@ -16,8 +17,12 @@ urlpatterns = patterns('',
|
|||
url(r'^static/(?P<path>.*)$','django.views.static.serve', {'document_root':'./static'}),
|
||||
(r'^routes/$', 'mumbai.views.routes'),
|
||||
(r'^route/(?P<alias>[a-zA-Z0-9\s\-]*?)/$', 'mumbai.views.route'),
|
||||
(r'^route/(?P<alias>[a-zA-Z0-9\s\-]*?)/georss/$', RouteFeed()),
|
||||
(r'^areas/$', 'mumbai.views.areas'),
|
||||
(r'^area/(?P<name>.*?)/$', 'mumbai.views.area'),
|
||||
# (r'^area/(?P<name>.*?)/georss/$', AreaFeed()),
|
||||
(r'^stop/(?P<slug>.*?)/$', 'mumbai.views.stop'),
|
||||
# (r'^stop/(?P<slug>.*?)/georss/$', StopFeed()),
|
||||
(r'^buseditor/$', 'mumbai.views.buseditor'),
|
||||
(r'^editstops/$', 'mumbai.views.editstops'),
|
||||
(r'^1.0/', include('mumbai.apiurls')),
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
# -------------------------------------------------------------------- #
|
||||
# MAIN CONFIGURATION #
|
||||
# -------------------------------------------------------------------- #
|
||||
import os
|
||||
from os.path import join
|
||||
|
||||
PROJECT_PATH = os.path.dirname(__file__)
|
||||
|
||||
# you should configure your database here before doing any real work.
|
||||
# see: http://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||
|
@ -16,7 +19,8 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
MEDIA_ROOT = join(PROJECT_PATH, 'static')
|
||||
LOCAL_DEVELOPMENT = True
|
||||
# the rapidsms backend configuration is designed to resemble django's
|
||||
# database configuration, as a nested dict of (name, configuration).
|
||||
#
|
||||
|
@ -162,6 +166,13 @@ TEMPLATE_LOADERS = (
|
|||
'django.template.loaders.eggs.Loader'
|
||||
)
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
join(PROJECT_PATH, "templates"),
|
||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------- #
|
||||
# HERE BE DRAGONS! #
|
||||
# these settings are pure hackery, and will go away soon #
|
||||
|
|
BIN
smsBEST/static/rapidsms/icons/silk/accept--dull.png
Executable file
After Width: | Height: | Size: 691 B |
BIN
smsBEST/static/rapidsms/icons/silk/accept.png
Executable file
After Width: | Height: | Size: 781 B |
BIN
smsBEST/static/rapidsms/icons/silk/add.png
Executable file
After Width: | Height: | Size: 733 B |
BIN
smsBEST/static/rapidsms/icons/silk/building.png
Executable file
After Width: | Height: | Size: 556 B |
BIN
smsBEST/static/rapidsms/icons/silk/bullet_white.png
Executable file
After Width: | Height: | Size: 201 B |
BIN
smsBEST/static/rapidsms/icons/silk/decline.png
Executable file
After Width: | Height: | Size: 781 B |
BIN
smsBEST/static/rapidsms/icons/silk/delete.png
Executable file
After Width: | Height: | Size: 715 B |
BIN
smsBEST/static/rapidsms/icons/silk/email.png
Executable file
After Width: | Height: | Size: 641 B |
BIN
smsBEST/static/rapidsms/icons/silk/email_error.png
Executable file
After Width: | Height: | Size: 792 B |
BIN
smsBEST/static/rapidsms/icons/silk/email_go.png
Executable file
After Width: | Height: | Size: 754 B |
BIN
smsBEST/static/rapidsms/icons/silk/email_open.png
Executable file
After Width: | Height: | Size: 783 B |
BIN
smsBEST/static/rapidsms/icons/silk/exclamation.png
Executable file
After Width: | Height: | Size: 701 B |
BIN
smsBEST/static/rapidsms/icons/silk/help.png
Executable file
After Width: | Height: | Size: 786 B |
BIN
smsBEST/static/rapidsms/icons/silk/magnifier.png
Executable file
After Width: | Height: | Size: 615 B |
BIN
smsBEST/static/rapidsms/icons/silk/package_add.png
Executable file
After Width: | Height: | Size: 899 B |
BIN
smsBEST/static/rapidsms/icons/silk/package_go.png
Executable file
After Width: | Height: | Size: 898 B |
BIN
smsBEST/static/rapidsms/icons/silk/phone.png
Executable file
After Width: | Height: | Size: 488 B |
BIN
smsBEST/static/rapidsms/icons/silk/reload.png
Executable file
After Width: | Height: | Size: 643 B |
BIN
smsBEST/static/rapidsms/icons/silk/resultset_first.png
Executable file
After Width: | Height: | Size: 836 B |
BIN
smsBEST/static/rapidsms/icons/silk/resultset_last.png
Executable file
After Width: | Height: | Size: 827 B |
BIN
smsBEST/static/rapidsms/icons/silk/resultset_next.png
Executable file
After Width: | Height: | Size: 600 B |
BIN
smsBEST/static/rapidsms/icons/silk/resultset_previous.png
Executable file
After Width: | Height: | Size: 597 B |
BIN
smsBEST/static/rapidsms/icons/silk/section_collapsed--bright.png
Executable file
After Width: | Height: | Size: 253 B |
BIN
smsBEST/static/rapidsms/icons/silk/section_expanded--bright.png
Executable file
After Width: | Height: | Size: 271 B |
BIN
smsBEST/static/rapidsms/icons/silk/sort_ascending.png
Executable file
After Width: | Height: | Size: 506 B |
BIN
smsBEST/static/rapidsms/icons/silk/sort_descending.png
Executable file
After Width: | Height: | Size: 509 B |
BIN
smsBEST/static/rapidsms/icons/silk/user.png
Executable file
After Width: | Height: | Size: 741 B |
BIN
smsBEST/static/rapidsms/images/bessms_header07d.png
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
smsBEST/static/rapidsms/images/bestsms_header_final.jpg
Executable file
After Width: | Height: | Size: 18 KiB |
BIN
smsBEST/static/rapidsms/images/big-arrows/down.png
Executable file
After Width: | Height: | Size: 876 B |
BIN
smsBEST/static/rapidsms/images/big-arrows/error.png
Executable file
After Width: | Height: | Size: 774 B |
BIN
smsBEST/static/rapidsms/images/big-arrows/left.png
Executable file
After Width: | Height: | Size: 783 B |
BIN
smsBEST/static/rapidsms/images/big-arrows/right.png
Executable file
After Width: | Height: | Size: 806 B |
BIN
smsBEST/static/rapidsms/images/big-arrows/source.xcf
Executable file
BIN
smsBEST/static/rapidsms/images/big-arrows/up.png
Executable file
After Width: | Height: | Size: 737 B |
BIN
smsBEST/static/rapidsms/images/body-bg.png
Executable file
After Width: | Height: | Size: 9.1 KiB |
BIN
smsBEST/static/rapidsms/images/h2-bg-collapsed.png
Executable file
After Width: | Height: | Size: 825 B |
BIN
smsBEST/static/rapidsms/images/h2-bg.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
smsBEST/static/rapidsms/images/h3-bg.png
Executable file
After Width: | Height: | Size: 932 B |
BIN
smsBEST/static/rapidsms/images/header-bg.png
Executable file
After Width: | Height: | Size: 929 B |
BIN
smsBEST/static/rapidsms/images/rapidsms-logo.png
Executable file
After Width: | Height: | Size: 4.5 KiB |
BIN
smsBEST/static/rapidsms/images/tab-bg-active.png
Executable file
After Width: | Height: | Size: 142 B |
BIN
smsBEST/static/rapidsms/images/tab-bg-hover.png
Executable file
After Width: | Height: | Size: 101 B |
BIN
smsBEST/static/rapidsms/images/tab-bg.png
Executable file
After Width: | Height: | Size: 228 B |
BIN
smsBEST/static/rapidsms/images/table-footer-bg.png
Executable file
After Width: | Height: | Size: 125 B |
BIN
smsBEST/static/rapidsms/images/table-header-bg-highlight.png
Executable file
After Width: | Height: | Size: 226 B |
BIN
smsBEST/static/rapidsms/images/table-header-bg.png
Executable file
After Width: | Height: | Size: 535 B |
BIN
smsBEST/static/rapidsms/images/table-row-bg-active.png
Executable file
After Width: | Height: | Size: 179 B |
BIN
smsBEST/static/rapidsms/images/unicef-logo.png
Executable file
After Width: | Height: | Size: 3.6 KiB |
12
smsBEST/static/rapidsms/javascripts/collapse.js
Executable file
|
@ -0,0 +1,12 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
jQuery(function() {
|
||||
|
||||
/* allow module h2s with the 'collapsed' or 'expanded' classes to
|
||||
* collapse or expand the module. (see modules.css for more.) */
|
||||
jQuery("div.module.collapsed h2, div.module.expanded h2").each(function() {
|
||||
jQuery('<span class="toggler"></span>').click(function() {
|
||||
jQuery(this).parents("div.module").toggleClass("collapsed").toggleClass("expanded");
|
||||
}).appendTo(this);
|
||||
});
|
||||
});
|
29
smsBEST/static/rapidsms/javascripts/global/rs-module-help.js
Executable file
|
@ -0,0 +1,29 @@
|
|||
// vim: noet
|
||||
|
||||
jQuery(function() {
|
||||
|
||||
/* hide the help text for each module that contains
|
||||
* it, and add a "show help" button to the toolbar */
|
||||
jQuery(".module div.help").each(function() {
|
||||
var help_box = jQuery(this);
|
||||
help_box.hide();
|
||||
|
||||
var module = help_box.parent(".module");
|
||||
var toolbar = jQuery("div.toolbar", module);
|
||||
|
||||
/* create a toolbar, if this module
|
||||
* does not already have one */
|
||||
if(!toolbar.length) {
|
||||
toolbar = jQuery('<div class="toolbar"></div>')
|
||||
module.append(toolbar);
|
||||
}
|
||||
|
||||
/* add a tool button to show
|
||||
* the div that we just hid */
|
||||
toolbar.append(
|
||||
jQuery('<span class="help">Show Help</span>').click(function(ev) {
|
||||
help_box.slideToggle();
|
||||
})
|
||||
);
|
||||
})
|
||||
});
|
63
smsBEST/static/rapidsms/javascripts/global/rs-pagination.js
Executable file
|
@ -0,0 +1,63 @@
|
|||
// vim: noet
|
||||
|
||||
jQuery(function() {
|
||||
jQuery(document.body).click(function(e) {
|
||||
|
||||
/* ignore this click if it wasn't a link */
|
||||
var link = $(e.target);
|
||||
if(link.get(0).tagName.toLowerCase() != "a")
|
||||
return true;
|
||||
|
||||
/* find the paginator that this link lives within. if there
|
||||
* is none (ie, a link that isn't within a paginator was clicked),
|
||||
* we're not interested in this event */
|
||||
var paginator = link.parents("div.paginator");
|
||||
if(!paginator.length)
|
||||
return true;
|
||||
|
||||
/* as above, for the table that we will reload with the new
|
||||
* page of data. a paginator shouldn't exist outside of a
|
||||
* table, but let's not blow up if it does */
|
||||
var table = paginator.parents("table");
|
||||
if(!table.length)
|
||||
return true;
|
||||
|
||||
|
||||
/* this click was within a paginator link.
|
||||
* we'll take it from here, so kill the event */
|
||||
e.preventDefault();
|
||||
|
||||
/* wat */
|
||||
jQuery.ajax({
|
||||
dataType: "html",
|
||||
url: link.attr("href"),
|
||||
complete: function(res, status) {
|
||||
|
||||
/* if the request was successful... */
|
||||
if(status == "success" || status == "notmodified") {
|
||||
|
||||
/* create a dummy div, and inject the results into it. since the
|
||||
* page we just requested is the SAME PAGE that we're currently
|
||||
* viewing, only with a different page of objects, we can find
|
||||
* the new table the old paginator's DOM id.
|
||||
* --
|
||||
* NOTE: this is mostly ripped off from the jQuery.load
|
||||
* function, which removes SCRIPT tags to avoid a
|
||||
* permission error in internet exploder */
|
||||
var new_table =
|
||||
jQuery("<div />")
|
||||
.append(res.responseText.replace(
|
||||
/<script(.|\s)*?\/script>/g, ""))
|
||||
.find("#" + paginator.attr("id")) // <-- new paginator
|
||||
.closest("table");
|
||||
|
||||
/* replace the current table with the replacement
|
||||
* from the new page. this will destroy any events
|
||||
* currently attached, but will leave the rest of
|
||||
* the page alone */
|
||||
table.replaceWith(new_table);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
19
smsBEST/static/rapidsms/javascripts/jquery-1.3.2.min.js
vendored
Executable file
146
smsBEST/static/rapidsms/stylesheets/forms.css
Executable file
|
@ -0,0 +1,146 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
form {
|
||||
border: 1px solid #ddd;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
/* recursive models can be displayed as a tree within a <select>, by
|
||||
* ordering them cleverly and adding their "depth" to the class, to
|
||||
* bump them to the right, indicating their ancestry */
|
||||
form option.depth-1 { padding-left: 1em; }
|
||||
form option.depth-2 { padding-left: 2em; }
|
||||
form option.depth-3 { padding-left: 3em; }
|
||||
form option.depth-4 { padding-left: 4em; }
|
||||
form option.depth-5 { padding-left: 5em; }
|
||||
form option.depth-6 { padding-left: 6em; }
|
||||
form option.depth-7 { padding-left: 7em; }
|
||||
form option.depth-8 { padding-left: 8em; }
|
||||
|
||||
/* some options are less interesting than others; like None, or
|
||||
* Disabled, or Default; so mark them dull */
|
||||
form option.na {
|
||||
font-style: italic;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* TODO: wtf is this? */
|
||||
form .no-data {
|
||||
display: inline-block;
|
||||
background: #f8f8ff;
|
||||
text-align: center;
|
||||
padding: 2em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
form .no-data a.add {
|
||||
display: block;
|
||||
padding-top: 0.625em;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
|
||||
/* each field is wrapped in a div.field, which bundles together
|
||||
* everything related to it. in order:
|
||||
*
|
||||
* 1. text label
|
||||
* 2. list of errors
|
||||
* 3. the field itself
|
||||
* 4. help text
|
||||
*/
|
||||
form div.field {
|
||||
margin-top: 1em; }
|
||||
|
||||
form div.field label {
|
||||
margin-bottom: 0.5em;
|
||||
display: block;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* for fields that need a longer description, help text can be
|
||||
* added below. similar to django's models.Model.help_text */
|
||||
form div.field p.help {
|
||||
max-width: 30em;
|
||||
font-size: 80%;
|
||||
color: #aaa;
|
||||
|
||||
margin-top: 0;
|
||||
padding-top: 2px;
|
||||
margin-left: 0.625em;
|
||||
padding-left: 0.3125em;
|
||||
border-left: 0.625em solid #f8f8f8;
|
||||
}
|
||||
|
||||
/* highlight examples (usually examples of text that should
|
||||
* be sent over SMS, but could be anything) in help text */
|
||||
form div.field p.help span.example {
|
||||
font-family: monospace;
|
||||
background: #f8f8f8;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
form div.field.error { }
|
||||
|
||||
form div.field.error label {
|
||||
font-weight: bold;
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
form div.field.error ul.errors {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form div.field.error ul.errors li {
|
||||
background: #fff8f8 url("../icons/silk/exclamation.png") no-repeat 5px 50%;
|
||||
padding: 0.25em 5px 0.25em 25px;
|
||||
border: 1px solid #fdd;
|
||||
margin-top: 0.25em;
|
||||
min-height: 16px;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
color: #f44;
|
||||
}
|
||||
|
||||
/* wrap submission and/or action buttons separately */
|
||||
form div.submit {
|
||||
background: #f8f8f8 url("../images/table-footer-bg.png") repeat-x 0 0;
|
||||
border-top: 1px solid #eee;
|
||||
margin: 1em -1em 0 -1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
/* if the browser supports after (+) and :first-child...
|
||||
*
|
||||
* 1. do a bit of extra work to replace the usual `1em margin-top` of
|
||||
* the first div.field with padding-top on the form itself, to remove
|
||||
* the 1px border between the module h2 and the form
|
||||
*
|
||||
* 2. add some fancy rounded corners to the bottom of the form, and do
|
||||
* some margin jiggery-pokery to ensure that the div.submit doesn't
|
||||
* overlap and cause jagged edges. */
|
||||
body:last-child h2 + form {
|
||||
border-top: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: #f8f8f8;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
-moz-border-radius-bottomright: 5px;
|
||||
-moz-border-radius-bottomleft: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
h2 + form div.field:first-child {
|
||||
margin-top: 0; }
|
||||
|
||||
body:last-child form > div:first-child {
|
||||
background-color: #fff;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
body:last-child form div.submit {
|
||||
background-color: transparent;
|
||||
margin: 0;
|
||||
}
|
25
smsBEST/static/rapidsms/stylesheets/icons.css
Executable file
|
@ -0,0 +1,25 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
/* make the generated buttons look like tiny little icons. they're
|
||||
* seldom used, so should stay well out of the way */
|
||||
input.js-button {
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
text-indent: -9999px;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
/* from http://www.famfamfam.com/lab/icons/silk/
|
||||
* (licensed under Creative Commons Attribution) */
|
||||
input.js-button.add { background-image: url("../icons/silk/add.png"); }
|
||||
input.js-button.del { background-image: url("../icons/silk/delete.png"); }
|
||||
input.js-button.accept { background-image: url("../icons/silk/accept.png"); }
|
||||
input.js-button.unaccept { background-image: url("../icons/silk/accept--dull.png"); }
|
||||
input.js-button.clear { background-image: url("../icons/silk/decline.png"); }
|
||||
input.js-button.reload { background-image: url("../icons/silk/reload.png"); }
|
318
smsBEST/static/rapidsms/stylesheets/layout.css
Executable file
|
@ -0,0 +1,318 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
body {
|
||||
background: #eee url("../images/body-bg.png");
|
||||
font: 9pt "Lucida Grande", "Bitstream Vera Sans", Verdana, sans-serif;
|
||||
line-height: 1;
|
||||
color: #333;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #33a7d2;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline; }
|
||||
|
||||
abbr {
|
||||
cursor: help; }
|
||||
|
||||
p {
|
||||
line-height: 1.4; }
|
||||
|
||||
/* this is not okay. but it is, unfortunately, the least error-prone way
|
||||
* (that i know) of fixing broken floaty layouts in IE6 */
|
||||
div.clear-hack {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#wrapper {
|
||||
width: 80em;
|
||||
background: #fff;
|
||||
margin: 0.5em auto 0 auto;
|
||||
|
||||
/* a little pretty for the 10/dec demo */
|
||||
-moz-box-shadow: 4px 4px 8px #aaa;
|
||||
box-shadow: 4px 4px 8px #aaa;
|
||||
-moz-border-radius-bottomright: 1em;
|
||||
-moz-border-radius-bottomleft: 1em;
|
||||
}
|
||||
|
||||
/* no scaling for ie6 */
|
||||
* html #wrapper {
|
||||
width: 960px; }
|
||||
|
||||
|
||||
|
||||
|
||||
/* the header is based roughly upon unicef.org, with rapidsms colors */
|
||||
#header {
|
||||
height:122px;
|
||||
width:960px;
|
||||
text-align:right;
|
||||
position: relative;
|
||||
color: #CCF;
|
||||
background: #94997e; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #94997e 0%, #d2dab3 10%, #d2dab3 80%, #94997e 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#94997e), color-stop(10%,#d2dab3), color-stop(80%,#d2dab3), color-stop(100%,#94997e)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #94997e 0%,#d2dab3 10%,#d2dab3 80%,#94997e 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #94997e 0%,#d2dab3 10%,#d2dab3 80%,#94997e 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #94997e 0%,#d2dab3 10%,#d2dab3 80%,#94997e 100%); /* IE10+ */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#94997e', endColorstr='#94997e',GradientType=0 ); /* IE6-9 */
|
||||
background: linear-gradient(top, #94997e 0%,#d2dab3 10%,#d2dab3 80%,#94997e 100%); /* W3C */}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* hide the log in/out links in the top right. this doesn't need to
|
||||
* be especially discoverable; when the user tries to do something
|
||||
* requiring a login, they should be redirected automatically */
|
||||
#header #auth {
|
||||
font-size: 80%;
|
||||
position: absolute;
|
||||
line-height: 22px;
|
||||
margin: 0 10px;
|
||||
right: 0;
|
||||
top: 0;;}
|
||||
|
||||
#header #auth a {
|
||||
color: #000;
|
||||
padding-right:6px;
|
||||
font-size:80%;
|
||||
position:relative;
|
||||
z-index:1;
|
||||
}
|
||||
|
||||
|
||||
#branding {
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
/* align in the middle of the unicef blue stripe of header bg, and
|
||||
* display logo on the right. TODO: extract the unicef branding */
|
||||
#branding h1 {
|
||||
background: url(../images/bessms_header07d.png) no-repeat;
|
||||
height: 108px;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
width:960px;
|
||||
position:absolute;
|
||||
top:6px;
|
||||
left:0px;
|
||||
}
|
||||
|
||||
* html #branding h1 {
|
||||
width: 940px; }
|
||||
|
||||
#branding h1 a {
|
||||
height: 115px;
|
||||
width: 960px;
|
||||
display: block;
|
||||
/*background: url("../images/rapidsms-logo.png") no-repeat 0 50%;*/
|
||||
|
||||
/* float the RapidSMS logo, in case any app would like to
|
||||
* append anything to the light blue (empty) stripe */
|
||||
float: left;
|
||||
}
|
||||
|
||||
#branding h1 a span {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
}
|
||||
|
||||
#tabs,
|
||||
#page-tabs {
|
||||
position: absolute;
|
||||
height: 28px;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* global tabs sit on the right, page-specific tabs sit on the left.
|
||||
* to draw more attention. TODO: maybe re-think this */
|
||||
#tabs { right: 0; }
|
||||
#page-tabs { left: 0; }
|
||||
|
||||
#tabs li,
|
||||
#page-tabs li {
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
/* 5px spacing between each tab, to match the top gap, since
|
||||
* we're using pixel-positioned backgrounds there */
|
||||
#tabs li { margin-right: 5px; }
|
||||
#page-tabs li { margin-left: 5px; }
|
||||
|
||||
#tabs li a,
|
||||
#page-tabs li a {
|
||||
color: white;
|
||||
display: block;
|
||||
padding: 0 1em;
|
||||
border-right: 1px solid #FE0000;
|
||||
border-left: 1px solid #FE0000;
|
||||
outline: none;
|
||||
background-color:#CE0000;
|
||||
text-shadow: 1px 2px 1px #000; }
|
||||
|
||||
/* there are unread messages in this tab! TODO: is this just
|
||||
* for the training app? if so, move it there! */
|
||||
#tabs li.unread a span {
|
||||
display: block;
|
||||
padding-right: 21px;
|
||||
background: url("../icons/silk/email_open.png") no-repeat 100% 50%;
|
||||
}
|
||||
|
||||
/* always highlight the active (in the navigation sense, not
|
||||
* the css :active sense) tab, even when it's being hovered
|
||||
* or focused, since clicking it again is mostly useless */
|
||||
#tabs li.active a, #page-tabs li.active a,
|
||||
#tabs li.active a:hover, #page-tabs li.active a:hover,
|
||||
#tabs li.active a:focus, #page-tabs li.active a:focus {
|
||||
|
||||
background: #fff url("../images/tab-bg-active.png") repeat-x;
|
||||
text-decoration: none;
|
||||
text-shadow: #000 1px 1px 2px;
|
||||
color: #000;
|
||||
|
||||
|
||||
/* the same color as the strip in header-bg.png */
|
||||
border: 1px solid #cef1f5;
|
||||
border-bottom: 0;
|
||||
|
||||
/* nudge the active tab north by one pixel, to line it
|
||||
* up with the tops of the other tabs */
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
/* brighten up inactive tabs when hovering or tab-focusing
|
||||
* with the keyboard (we removed the outline, above) */
|
||||
#tabs li a:hover, #page-tabs li a:hover,
|
||||
#tabs li a:focus, #page-tabs li a:focus {
|
||||
/*background-image: url("../images/tab-bg-hover.png");*/
|
||||
text-shadow: #000 1px 1px 2px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#breadcrumbs {
|
||||
color: #ccc;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
padding: 0.5em;
|
||||
text-shadow: #eee 2px 2px 2px;
|
||||
border-bottom: 1px dotted #eee;
|
||||
}
|
||||
|
||||
#breadcrumbs a {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.module a
|
||||
{color:#CE0000;}
|
||||
|
||||
#inner {
|
||||
padding: 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* some parts of the page title are dynamic (or otherwise really
|
||||
* important), like search terms. highlight them! */
|
||||
#inner h1 span.highlight {
|
||||
background: #ffa;
|
||||
-moz-border-radius: 5px;
|
||||
border: 2px solid #ff0;
|
||||
padding: 0 4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
/* when an app has something really important to say, it can use the
|
||||
* apps/webui/templates/message.html template to display a huge blob
|
||||
* of text. this should probably be replaced with flash messages */
|
||||
#inner div.message {
|
||||
text-align: center;
|
||||
padding: 4em 25%;
|
||||
}
|
||||
|
||||
#inner div.message p {
|
||||
margin: 0 0 0.5em 0;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* some apps (erm, just the querylog, actually) add big triggers to the
|
||||
* bottom of the page to show or perform some action. */
|
||||
div.trigger {
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
padding: 0.625em;
|
||||
background: #f8f8f8;
|
||||
cursor: pointer;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
div.trigger.warn {
|
||||
background: #fdd;
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#footer {
|
||||
border-top: 1px dotted #eee;
|
||||
padding: 0.5em;
|
||||
clear: both;
|
||||
color: #ccc;
|
||||
|
||||
/* reserve space for at two lines of links @ LH=1.4 (for the
|
||||
* copyright and licensing/download info) */
|
||||
min-height: 2.8em;
|
||||
}
|
||||
|
||||
/* bump the footer links down a line, to align them with the second
|
||||
* line of legal junk on the right. reduce the opacity until hover,
|
||||
* to keep them out of view until they're needed. */
|
||||
#footer .footer-region {
|
||||
margin-top: 1.4em;
|
||||
line-height: 1.4;
|
||||
opacity: 0.25;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#footer .footer-region:hover {
|
||||
opacity: 1; }
|
||||
|
||||
#footer .footer-region a { margin-right: 0.5em; }
|
||||
#footer .footer-region a:last-child { margin-right: 0; }
|
||||
|
||||
|
||||
#footer a
|
||||
{color:#CE0000;}
|
||||
|
||||
#footer p.rights {
|
||||
text-align: right;
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
137
smsBEST/static/rapidsms/stylesheets/modules.css
Executable file
|
@ -0,0 +1,137 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
|
||||
#instruction h2/*THE CSS FOR THE INSTRUCTIONS FROM WIKI*/
|
||||
{font-weight:bold;}
|
||||
|
||||
div.module {
|
||||
margin-top: 2em;
|
||||
position: relative;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
div.module div.module {
|
||||
border: 1px solid #8fbcc9; }
|
||||
|
||||
div.module:first-child {
|
||||
margin-top: 0; }
|
||||
|
||||
|
||||
|
||||
|
||||
div.module.collapsed {
|
||||
overflow-y: hidden;
|
||||
height: 2.6em;
|
||||
}
|
||||
|
||||
div.module.collapsed h2 {
|
||||
background-image: url("../images/h2-bg-collapsed.png"); }
|
||||
|
||||
div.module.collapsed + div.module {
|
||||
margin-top: 1px; }
|
||||
|
||||
div.module.collapsed h2 span.toggler,
|
||||
div.module.expanded h2 span.toggler {
|
||||
background: no-repeat 50% 50%;
|
||||
text-indent: -9999px;
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
height: 2.6em;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
padding: 0 0.5em;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
div.module.collapsed h2 span.toggler { background-image: url("../icons/silk/section_collapsed--bright.png"); }
|
||||
div.module.expanded h2 span.toggler { background-image: url("../icons/silk/section_expanded--bright.png"); }
|
||||
|
||||
|
||||
|
||||
|
||||
/* module headers are mostly ripped off from django admin, although
|
||||
* here, we never use <caption>, to keep things simple. (they have
|
||||
* surprisingly confusing layout rules.) */
|
||||
div.module h2,
|
||||
div.module h3 {
|
||||
margin: 0;
|
||||
background-repeat: repeat-x;
|
||||
background-position: 0 100%;
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
div.module h2 {
|
||||
background-color: #000;
|
||||
background-image: url("../images/h2-bg.png");
|
||||
text-shadow: #000 2px 2px 1px;
|
||||
padding: 0.3125em;
|
||||
font-size: 160%;
|
||||
}
|
||||
|
||||
/* less important info can be wrapped in a span to dull it */
|
||||
div.module h2 span {
|
||||
text-shadow: none;
|
||||
font-size: 62.5%;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* subheaders are almost the same. to dull things, i just made the
|
||||
* h2-bg image 80% opaque and re-saved it. STILL TODO: ask meghana
|
||||
* to make this pretty */
|
||||
div.module h3 {
|
||||
background-image: url("../images/h3-bg.png");
|
||||
background-color: #333;
|
||||
padding: 0.5em;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* modules can (optionally) include help text, to explain how they can
|
||||
* be used. this is hidden by module-help.js, if it's available, but
|
||||
* shouldn't be too verbose, in case it isn't */
|
||||
div.module div.help,
|
||||
div.module form.search {
|
||||
border-right: 0.5em solid #ffb;
|
||||
border-left: 0.5em solid #ffb;
|
||||
background: #ffc;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
div.module div.help p {
|
||||
margin: 0; }
|
||||
|
||||
|
||||
/* modules can optionally contain a small "toolbar", which hangs in the
|
||||
* top right, overlapping the <h2>, if there is one */
|
||||
div.module div.toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
line-height: 2.6em;
|
||||
}
|
||||
|
||||
div.module div.toolbar a,
|
||||
div.module div.toolbar span {
|
||||
display: block;
|
||||
float: right;
|
||||
color: #eee;
|
||||
margin-right: 0.625em;
|
||||
padding-left: 21px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 50%;
|
||||
font-size: 80%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* various common toolbar icons. should be from the famfamfam
|
||||
* silk set, to fit in with the rest of RapidSMS. this will
|
||||
* probably grow (and be abstracted) as apps do more things */
|
||||
div.module div.toolbar .add { background-image: url("../icons/silk/add.png"); }
|
||||
div.module div.toolbar .help { background-image: url("../icons/silk/help.png"); }
|
||||
div.module div.toolbar .search { background-image: url("../icons/silk/magnifier.png"); }
|
52
smsBEST/static/rapidsms/stylesheets/splits.css
Executable file
|
@ -0,0 +1,52 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
|
||||
.col-1, .col-2, .col-3, .col-4, .col-5, .col-6 {
|
||||
margin-left: 1em;
|
||||
min-height: 1px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
.two-columns { padding-left: 1em; }
|
||||
.two-columns .col-1 { margin-left: -1em; }
|
||||
|
||||
.two-columns .col-1
|
||||
{
|
||||
width: 34%; }
|
||||
|
||||
.two-columns .col-2
|
||||
{
|
||||
width: 66%;
|
||||
overflow:auto; }
|
||||
|
||||
.three-columns { padding-left: 2em; }
|
||||
.three-columns .col-1 { margin-left: -2em; }
|
||||
|
||||
.three-columns .col-2 {
|
||||
width: 34%; }
|
||||
|
||||
.three-columns .col-1,
|
||||
.three-columns .col-3 {
|
||||
width: 33%; }
|
||||
|
||||
|
||||
.four-columns { padding-left: 3em; }
|
||||
.four-columns .col-1 { margin-left: -3em; }
|
||||
|
||||
.four-columns .col-1,
|
||||
.four-columns .col-2,
|
||||
.four-columns .col-3,
|
||||
.four-columns .col-4 {
|
||||
width: 25%; }
|
||||
|
||||
|
||||
.five-columns { padding-left: 4em; }
|
||||
.five-columns .col-1 { margin-left: -4em; }
|
||||
|
||||
.five-columns .col-1,
|
||||
.five-columns .col-2,
|
||||
.five-columns .col-3,
|
||||
.five-columns .col-4,
|
||||
.five-columns .col-5 {
|
||||
width: 20%; }
|
237
smsBEST/static/rapidsms/stylesheets/tables.css
Executable file
|
@ -0,0 +1,237 @@
|
|||
/* vim:set et ts=4 sw=4 */
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width:100%;}
|
||||
|
||||
col { }
|
||||
|
||||
/* highlight sorted columns just a little tiny bit. some people
|
||||
* won't be able to see it, but the header should contain some
|
||||
* kind of indication, too. darker colors interfere with the
|
||||
* grid lines, which are also very light. */
|
||||
col.sorted {
|
||||
background: #fcfcff; }
|
||||
|
||||
tr{ }
|
||||
|
||||
td, th {
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ddd;
|
||||
|
||||
/* reset the "look" of headers to match regular cells,
|
||||
* since they can appear anywhere (col or row scope) */
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* if this table is directly following a header, we don't
|
||||
* need a border top. it'd probably get lost, anyway */
|
||||
h2 + table thead th {
|
||||
border-top: none; }
|
||||
|
||||
thead th {
|
||||
background: #e1e1e1 url(../images/table-header-bg.png) repeat-x 100% 0;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
thead th a,
|
||||
thead th span.unsortable {
|
||||
color: #888;
|
||||
outline: 0;
|
||||
border-left: 1px solid #f8f8f8;
|
||||
|
||||
/* the padding/margin magic overlaps the padding
|
||||
* of the th, to make it all clickable */
|
||||
padding: 0.5em;
|
||||
margin: -0.5em;
|
||||
|
||||
/* if a sort marker is within this link, it'll
|
||||
* need to position absolutely within */
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* highlight it when the th is hovered, a bit
|
||||
* like (most) native controls. this is crappy,
|
||||
* since the background image is sitting on top
|
||||
* of the th bg, not replacing it */
|
||||
thead th a:hover {
|
||||
background-image: url(../images/table-header-bg-highlight.png);
|
||||
color: #000;
|
||||
}
|
||||
|
||||
thead th.sorted a {
|
||||
padding-right: 26px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* unfortunately, an extra element (a span) is
|
||||
* needed to display the sort marker. all of the
|
||||
* other backgrounds are already busy. snap it
|
||||
* to the right/middle of the th */
|
||||
thead th.sorted a span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -8px;
|
||||
overflow: hidden;
|
||||
text-indent: -9999px;
|
||||
}
|
||||
|
||||
thead th.asc a span { background-image: url("../icons/silk/sort_ascending.png"); }
|
||||
thead th.desc a span { background-image: url("../icons/silk/sort_descending.png"); }
|
||||
|
||||
/* make the grid lighter within the tbody, since it's
|
||||
* only a visual hint to distinguish the rows + cols */
|
||||
tbody th, tbody td {
|
||||
border-color: #f8f8f8; }
|
||||
|
||||
/* stripe the rows
|
||||
tbody tr:nth-child(odd) {
|
||||
background: #f8f8f8; }*/
|
||||
|
||||
/* restore the dark outer borders of the tbody */
|
||||
tbody tr:first-child th, tbody tr:first-child td { border-top-color: #ddd; }
|
||||
tbody th:last-child, tbody td:last-child { border-right-color: #ddd; }
|
||||
tbody tr:last-child th, tbody tr:last-child td { border-bottom-color: #ddd; }
|
||||
tbody th:first-child, tbody td:first-child { border-left-color: #ddd; }
|
||||
|
||||
/* some cells have nothing important to say, (like "none" or
|
||||
* "never"), but are required none the less. make them dull,
|
||||
* to highlight the rows which contain real data */
|
||||
td.na, th.na, td span.na, th span.na {
|
||||
font-style: italic;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* when a row is "active" (eg. it is being viewed, edited, etc), it
|
||||
* is dimly highlighted. the bgcolor is 10% of #33a7d2 (links)
|
||||
* applied to the cells (not the row), to mask the stripes */
|
||||
tr.active td, tr.active th {
|
||||
background: #ebf6fa url(../images/table-row-bg-active.png) repeat-x 100% 0; }
|
||||
|
||||
tr.no-data { }
|
||||
|
||||
tr.no-data td {
|
||||
text-align: center;
|
||||
background: #f8f8ff no-repeat 50% 50%;
|
||||
padding: 2em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* since no-data rows usually only have a single <td>, the
|
||||
* last-child rule above breaks their huge padding. this is
|
||||
* a hack to restore it. */
|
||||
body:last-child tr.no-data td:last-child {
|
||||
padding-right: 2em; }
|
||||
|
||||
tr.no-data td a.add {
|
||||
display: block;
|
||||
padding-top: 0.625em;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* since there is no data, it might be useful to point the
|
||||
* user in the right direction. these arrows are very light,
|
||||
* and displayed behind the "You haven't..." text. */
|
||||
tr.no-data.look-up td { background-image: url("../images/big-arrows/up.png"); }
|
||||
tr.no-data.look-right td { background-image: url("../images/big-arrows/right.png"); }
|
||||
tr.no-data.look-down td { background-image: url("../images/big-arrows/down.png"); }
|
||||
tr.no-data.look-left td { background-image: url("../images/big-arrows/left.png"); }
|
||||
|
||||
/* if there is no data because an error occurred, make the
|
||||
* table obviously busted by highlighting it in red. */
|
||||
tr.no-data.error td {
|
||||
color: #f66;
|
||||
background-color: #fff8f8;
|
||||
background-image: url("../images/big-arrows/error.png");
|
||||
}
|
||||
|
||||
tr.depth-1 td.indent { padding-left: 2em; }
|
||||
tr.depth-2 td.indent { padding-left: 4em; }
|
||||
tr.depth-3 td.indent { padding-left: 6em; }
|
||||
tr.depth-4 td.indent { padding-left: 8em; }
|
||||
tr.depth-5 td.indent { padding-left: 10em; }
|
||||
tr.depth-6 td.indent { padding-left: 12em; }
|
||||
tr.depth-7 td.indent { padding-left: 14em; }
|
||||
tr.depth-8 td.indent { padding-left: 16em; }
|
||||
|
||||
tfoot {
|
||||
background: #f8f8f8 url("../images/table-footer-bg.png") repeat-x 0 0;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* no padding in the footer cell; the links will float and pad
|
||||
* themselves, so the clickable blocks are easier to hit */
|
||||
tfoot td {
|
||||
padding: 0; }
|
||||
|
||||
/* footer links are dull, because they're less important
|
||||
* than the data. TODO: is this totally stupid? (i don't
|
||||
* really care, it's pretty) */
|
||||
tfoot a,
|
||||
tfoot span {
|
||||
display: block;
|
||||
float: right;
|
||||
padding: 0.625em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* footer links can be broken up with spans, which look
|
||||
* the same, except super dull (for things like disabled
|
||||
* pagination links */
|
||||
tfoot span {
|
||||
color: #ddd; }
|
||||
|
||||
/* highlight hover links brighter than usual, since
|
||||
* they're harder to spot */
|
||||
tfoot a:hover {
|
||||
background: #fff; }
|
||||
|
||||
/* move all paginator links to the left, to separate from
|
||||
* additional views and export, which lives on the right */
|
||||
tfoot .paginator,
|
||||
tfoot .paginator a,
|
||||
tfoot .paginator span {
|
||||
float: left; }
|
||||
|
||||
tfoot .paginator a.active {
|
||||
background: #ddd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
tfoot .paginator .first,
|
||||
tfoot .paginator .prev,
|
||||
tfoot .paginator .next,
|
||||
tfoot .paginator .last {
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 50%;
|
||||
text-indent: -9999px;
|
||||
overflow: hidden;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
/* links look something like:
|
||||
* << < 1 2 3 4 > >> */
|
||||
tfoot .paginator .first { background-image: url("../icons/silk/resultset_first.png"); }
|
||||
tfoot .paginator .prev { background-image: url("../icons/silk/resultset_previous.png"); }
|
||||
tfoot .paginator .next { background-image: url("../icons/silk/resultset_next.png"); }
|
||||
tfoot .paginator .last { background-image: url("../icons/silk/resultset_last.png"); }
|
||||
|
||||
/* when a link is disabled, move the background image
|
||||
* over to reveal the transparent sprite to the left */
|
||||
tfoot .paginator span.na {
|
||||
background-position: -16px 50%; }
|
||||
|
||||
/* the ... to indicate that page links have been hidden
|
||||
* (because there were too many) should be quite dull */
|
||||
tfoot .paginator span.elipsis {
|
||||
letter-spacing: 1px;
|
||||
color: #888;
|
||||
}
|
195
smsBEST/templates/dashboard.html
Executable file
|
@ -0,0 +1,195 @@
|
|||
{% extends "layout.html" %}
|
||||
{% block title %}Dashboard{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
{{ block.super }}
|
||||
<style type="text/css">
|
||||
#inner {
|
||||
margin: 0px 25%;
|
||||
|
||||
}
|
||||
|
||||
div.module div {
|
||||
border: 1px solid #ddd;
|
||||
border-top-color: #636363;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
div.module p {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
background: #ffe;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Start Our CSS */
|
||||
|
||||
#languageBtns {
|
||||
position:absolute;
|
||||
top:32px;
|
||||
left:-205px;
|
||||
}
|
||||
|
||||
|
||||
#languageBtns span {
|
||||
display:block;
|
||||
font-size:18px;
|
||||
cursor:pointer;
|
||||
line-height:28px;
|
||||
}
|
||||
|
||||
#selectedLanguage {
|
||||
color:#CE0000;}
|
||||
|
||||
#instruction {
|
||||
border:2px solid #ce0000;}
|
||||
|
||||
|
||||
#instruction h2 /*THE CSS FOR THE INSTRUCTIONS FROM WIKI*/
|
||||
{font-size:16px;
|
||||
font-weight:normal;
|
||||
margin-bottom:16px;
|
||||
background: #ce0000; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #ce0000 0%, #ce0000 44%, #ff4400 88%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ce0000), color-stop(44%,#ce0000), color-stop(88%,#ff4400)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #ce0000 0%,#ce0000 44%,#ff4400 88%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ce0000 0%,#ce0000 44%,#ff4400 88%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #ce0000 0%,#ce0000 44%,#ff4400 88%); /* IE10+ */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ce0000', endColorstr='#ff4400',GradientType=0 ); /* IE6-9 */
|
||||
background: linear-gradient(top, #ce0000 0%,#ce0000 44%,#ff4400 88%); /* W3C */
|
||||
text-shadow: #000 1px 2px 1px;}
|
||||
|
||||
#instruction ul
|
||||
{list-style:none;
|
||||
margin-bottom:16px;
|
||||
margin-right:20px;
|
||||
font-size:16px;}
|
||||
|
||||
#instruction ul li
|
||||
{margin-bottom:8px;}
|
||||
|
||||
#instruction p
|
||||
{margin-bottom:8px;}
|
||||
|
||||
code {
|
||||
font-weight:bold;
|
||||
font-size:14px;
|
||||
margin-left:17px;}
|
||||
|
||||
number {
|
||||
font-weight:bold;
|
||||
font-family:monospace;
|
||||
font-size:14px;}
|
||||
|
||||
#footer p {
|
||||
text-align:center;
|
||||
color:#000;}
|
||||
|
||||
/* END Our CSS */
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#languageBtns span').click(function() {
|
||||
var langString = '.english, .marathi, .hindi, .gujarati';
|
||||
$(langString).hide();
|
||||
var lang = $(this).attr("data-lang");
|
||||
$('.' + lang).show();
|
||||
});
|
||||
$('span[data-lang=english]').click();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div id="languageBtns">
|
||||
<span data-lang="english">English</span> <span data-lang="marathi">मराठी</span> <span data-lang="hindi">हिन्दी</span> <span data-lang="gujarati">ગુજરાતી</span>
|
||||
</div>
|
||||
<div id="instruction" class="module">
|
||||
|
||||
<!-- <h1> Short Instructions</h1> -->
|
||||
<h2> Welcome!</h2>
|
||||
<ul><li class="english"> With this service, you can send and receive simple queries by SMS about bus stops, bus numbers and routing on BEST.<br><br>Send SMS to <number>9619524420</number> and you will receive a return SMS with the information you need.
|
||||
</li><li class="marathi"> चलोबेस्टद्वारे आपल्याला वेगवेगळ्या बेस्ट बसस्थानकांची, बसक्रमांकाची तसेच बसमार्गांची माहिती SMS ने मिळू शकते. <br><br>आपला SMS <number>९६१९५२४४२०</number> या क्रमांकावर पाठवावा, आम्ही आपल्याला पाहिजे असलेली माहिती SMS द्वारे परत पाठवू.
|
||||
</li><li class="hindi"> इस सुविधा से आप साधारण SMS के ज़रिये बेस्ट बस स्टॉप, बस क्रमांक और मार्गों की जानकारी पा सकते हैं| <br><br><number>9619524420</number> ईस नंबर पर SMS भेजनेपर आपको जवाबी SMS से जरुरी जानकारी मिलेगी।
|
||||
</li><li class="gujarati"> આ સુવિધા થકી એક સામાન્ય SMS કરીને આપ કોઈ પણ બસ સ્ટોપ, નંબર અથવા માર્ગ ની માહિતી મેળવી શકો છો.<br><br> <number>9619524420</number> પર SMS કરવાથી તમને વળતા SMS દ્વારા પૂછાવેલી માહિતી મોકલવામાં આવશે.
|
||||
</li></ul>
|
||||
<h2> How-To Use </h2>
|
||||
<ul><li class="english"> To see the route of any bus, send an SMS with "BUS " and any bus number. Example:
|
||||
</li><li class="marathi"> कोणत्याही बेस्ट बसमार्गाची माहिती करून घेण्यासाठी, "BUS" व त्यानंतर बसक्रमांक लिहून वरील क्रमांकावर SMS पाठवावा। उदाहरणार्थ:
|
||||
</li><li class="hindi"> किसी भी बस मार्ग के सभी स्टॉप जानने के लिए BUS और ऊसके बाद बस क्रमांक उपर दिए हुए नंबर पर SMS करें। उदहारण:
|
||||
</li><li class="gujarati"> કોઈ પણ નંબર ની બસ નું માર્ગ જાણવા માટે BUS પછી એનું નંબર SMS કરો. દાખલો:
|
||||
</li></ul>
|
||||
<p><span>▸ </span><code> BUS 21</code>
|
||||
</p>
|
||||
<ul><li class="english"> To see all the bus routes served by a stop, send an SMS with "STOP " and the name of any bus stop or area. Example:
|
||||
</li><li class="marathi"> एखाद्या बसस्थानकावर येणाऱ्या सर्व बसेसची माहिती मिळवण्यासाठी, "STOP" व त्यानंतर बसस्थानकाचे नाव किंवा विभागाचे नाव लिहून वरील क्रमांकावर SMS पाठवावा| उदाहरणार्थ:
|
||||
</li><li class="hindi"> कोई भी स्टॉप पर रुकनेवाली सारी बसों की जानकारी के लिए STOP एवं उसका नाम या इलाके का नाम SMS करें| उदहारण:
|
||||
</li><li class="gujarati"> કોઈ પણ સ્ટોપ પર પસાર થતી બસો ની માહિતી માટે STOP પછી બસ સ્ટોપ નું નામ અથવા વિસ્તાર નું નામ SMS કરો. દાખલો:
|
||||
</li></ul>
|
||||
<p><span>▸ </span><code>STOP MAHIM</code>
|
||||
</p>
|
||||
<ul><li class="english"> To find out how to go from one stop to another, send an SMS with "FROM " any stop name "TO " any stop name. Example:
|
||||
</li><li class="marathi"> एका स्थानकावरून दुस-या स्थानकापर्यंत कोणत्या बसने जावे हे माहित करण्यासाठी, "FROM" (कुठून) "TO" (कुठपर्यंत) लिहून वरील क्रमांकावर SMS पाठवावा| उदाहरणार्थ:
|
||||
</li><li class="hindi"> कोई भी स्टॉप से अन्य स्टॉप तक जानेवाली बसों की जानकारी के किये FROM एवं स्टॉप का नाम और TO एवं स्टॉप का नाम SMS करें| उदहारण:
|
||||
</li><li class="gujarati"> * કોઈ પણ બસ સ્ટોપ થી બીજે જતી બસો ના નંબર જાણવા માટે "FROM" પછી સ્ટોપ નું નામ અને "TO" પછી બીજા સ્ટોપ નું નામ SMS કરો. દાખલો:
|
||||
</li></ul>
|
||||
<p><span>▸ </span><code>FROM COLABA TO MAHIM</code>
|
||||
</p>
|
||||
<h2> Feedback </span></h2>
|
||||
<ul><li class="english"> ChaloBEST is still being tested, we plan to release a public beta soon. We welcome your feedback and comments via email to info@chalobest.in
|
||||
</li><li class="marathi"> चलोबेस्टची सध्या तपासणी सुरु आहे. आम्ही लवकरच ही लोकसेवा पूर्णपणे सुरू करणार आहोत. चलोबेस्टविषयी आपल्या प्रतिक्रिया आणि विचार कळविल्यास आम्हाला आंनद होईल. आपण आम्हाला इमेलद्वारे info@chalobest.in या पत्त्यावर संपर्क साधु शकता.
|
||||
</li><li class="hindi"> चलोबेस्ट सेवा की फिलहाल जाँच शुरु है। जल्दही हम ये सेवा पुरी तरह से शुरु करेंगे। ईस सेवा के बारे में आपके विचार और प्रतिक्रिया जानने पर हमें खुशी होगी। आप हमें info@chalobest.in ईस ईमेल पर अपनी राय दे सकते है।
|
||||
</li><li class="gujarati"> ચલોબેસ્ટ હાલ પ્રાયોગિક ધોરણે દાખલ કરેલ છે. જાહેર ઉપયોગ માટે ટૂંક સમય માં એનું વિમોચન થશે. info@chalobest.in પર ઈ-મેઈલ દ્વારા તમારી પ્રતિક્રિયા તેમજ સૂચન નું આવકાર છે.
|
||||
</li></ul>
|
||||
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="module">
|
||||
<h2>Installation Successful!</h2>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
See <a href="http://docs.rapidsms.org/Installation">the RapidSMS wiki</a>
|
||||
to learn how to install community apps or create your own.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To replace this message with a different view, add a pattern in app's
|
||||
<code>urls</code> module with the pattern: <code>r'^$</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
|
||||
<pre>from django.conf.urls.defaults import *
|
||||
from myproject.myapp import views
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.dashboard)
|
||||
)</pre>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<div id="footer">
|
||||
<p><a href="http://chalobest.in">ChaloBEST</a> is a collaboration of <a href="http://mesn.org">Mumbai Environmental Social Network (MESN)</a>, <a href="http://sparcsys.com">SPARC Systems</a>, <a href="http://camputer.org">CAMP</a>, and <br> <a href="http://www.hbcse.tifr.res.in">Homi Bhabha Centre for Science Education, TIFR</a>, with a little help from <a href="http://bestundertaking.com">our friends</a>.</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
89
smsBEST/templates/layout.html
Executable file
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
{% load region_tags %}
|
||||
{% load tabs_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<title>{% block title %}RapidSMS{% endblock %}</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
{% block stylesheets %}
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/layout.css" />
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/splits.css" />
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/modules.css" />
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/tables.css" />
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/forms.css" />
|
||||
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}rapidsms/stylesheets/icons.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}rapidsms/javascripts/jquery-1.3.2.min.js"></script>
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}rapidsms/javascripts/collapse.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
{% region "top" %}
|
||||
|
||||
{% block header %}
|
||||
<div id="header">
|
||||
<div id="branding">
|
||||
<h1>
|
||||
<a title="{% trans "Return to the Dashboard" %}" href="{% url rapidsms-dashboard %}">
|
||||
<span>RapidSMS</span>
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{% block auth %}
|
||||
<div id="auth">{% if user.is_authenticated %}
|
||||
<a href="{% url rapidsms-logout %}">{% trans "Log out" %} {{ user.username }}</a>{% else %}
|
||||
<a href="{% url rapidsms-login %}">{% trans "Log in" %}</a>{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% get_tabs as tabs %}
|
||||
|
||||
<ul id="tabs">{% for tab in tabs %}
|
||||
<li class="app-{{ tab.name }}{% if tab.is_active %} active{% endif %}">
|
||||
<a href="{{ tab.url }}"><span>{{ tab.caption }}</span></a>
|
||||
</li>{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% block page_tabs %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}{% if breadcrumbs %}
|
||||
<div id="breadcrumbs">{% for caption, url in breadcrumbs %}
|
||||
<a href="{{ url }}">{{ caption }}</a>{% if not forloop.last %}
|
||||
<span>»</span>{% endif %}{% endfor %}
|
||||
</div>{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<div id="inner">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% block footer %}
|
||||
<div id="footer">
|
||||
<p class="rights">
|
||||
Copyright © 2008 – 2010
|
||||
<a href="http://unicef.org">UNICEF</a> et al.<br />
|
||||
<a href="http://github.com/rapidsms/rapidsms">RapidSMS</a> is available under
|
||||
<a href="http://github.com/rapidsms/rapidsms/raw/master/LICENSE">the BSD license</a>.
|
||||
</p>
|
||||
|
||||
{% region "footer" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% region "bottom" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +1,8 @@
|
|||
from django.conf.urls.defaults import *
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from os.path import join
|
||||
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
|
@ -28,10 +30,10 @@ urlpatterns = patterns('',
|
|||
(r'^scheduler/', include('rapidsms.contrib.scheduler.urls')),
|
||||
)
|
||||
|
||||
if settings.DEBUG:
|
||||
if settings.LOCAL_DEVELOPMENT:
|
||||
#
|
||||
urlpatterns += patterns('',
|
||||
# helper URLs file that automatically serves the 'static' folder in
|
||||
# INSTALLED_APPS via the Django static media server (NOT for use in
|
||||
# production)
|
||||
(r'^', include('rapidsms.urls.static_media')),
|
||||
#
|
||||
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': join(settings.PROJECT_PATH, "static")}),
|
||||
#
|
||||
)
|
||||
|
|