Ver a proveniência

Added cookie persistence for payment filter bar; improved home page content & site-wide layout

pull/3/head
Adrian Short há 14 anos
ascendente
cometimento
f4df815499
8 ficheiros alterados com 362 adições e 72 eliminações
  1. +10
    -1
      app.rb
  2. +191
    -0
      public/js/jquery.cookie.js
  3. +59
    -8
      public/style.css
  4. +2
    -0
      views/about.haml
  5. +0
    -9
      views/directorate.haml
  6. +57
    -12
      views/home.haml
  7. +17
    -13
      views/layout.haml
  8. +26
    -29
      views/servicepayments.haml

+ 10
- 1
app.rb Ver ficheiro

@@ -98,8 +98,17 @@ get '/services/:slug' do
end

get '/services/:slug/payments' do
@FILTER_VALUES = %w[ 500 1000 2500 5000 10000 ]
@service = Service.first(:slug => params[:slug])
@payments = Payment.all(:service_id => @service.id, :amount.gte => PAYMENTS_FILTER_MIN, :order => [ 'd' ])
# payments_filter_min cookie persists user selection of filter value
unless @min = request.cookies["payments_filter_min"]
@min = PAYMENTS_FILTER_MIN
response.set_cookie(
"payments_filter_min",
{ :value => @min, :expires => Time.now + (60 * 24 * 60 * 60) }
) # 60 days
end
@payments = Payment.all(:service_id => @service.id, :amount.gte => @min, :order => [ 'd' ])
@total = @payments.sum(:amount)
haml :servicepayments
end


+ 191
- 0
public/js/jquery.cookie.js Ver ficheiro

@@ -0,0 +1,191 @@
/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
* used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
* used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};

+ 59
- 8
public/style.css Ver ficheiro

@@ -29,10 +29,15 @@ input
{
font-size: 100%;
background-color: #fff;
text-align: left;
text-align: right;
margin: 40px 0 40px 0;
}

.top_border
{
border-top: 1px solid #eee;
}

a
{
background-color: #dce9b0;
@@ -57,11 +62,20 @@ a:hover

h1
{
margin-top: 20px;
margin: 0px 0 0 0;
line-height: 1.4em;
font-weight: bold;
color: #86a11d;
font-size: 170%;
}

h1.logo
{
margin: 20px 0 0 0;
line-height: 1.4em;
font-weight: bold;
color: #86a11d;
font-size: 180%;
font-size: 230%;
}

h2
@@ -139,9 +153,9 @@ tr
.callout
{

background-color: beige;
background-color: #eee;
padding: 0px;
font-size: 150%;
font-size: 120%;
line-height: 1.5em;
}

@@ -159,8 +173,6 @@ tr
{
margin: 0 0px 0 0;
padding: 5px 10px;
background-color: #333;
color: #fff;
}

.filter a:hover
@@ -170,6 +182,45 @@ tr

a.filter_selected
{
background-color: red;
widows: 0;
background-color: black;
color: #fff;
font-size: 100%;
}

#nav
{
background-color: #777;
margin: 0 0 20px 0;
padding: 2px 10px;
}

#nav a, #nav a:visited
{
background-color: #777;
color: #fff;
}

#nav a:hover
{
background-color: #fff;
color: #777;
}

#breadcrumb
{
display: none;
}

.hidden
{
display: none;
}

.home_subheads
{
margin: 0;
padding: 0;
background-color: #fff;
vertical-align: bottom;
}

+ 2
- 0
views/about.haml Ver ficheiro

@@ -8,6 +8,8 @@
<!-- http://news.bbc.co.uk/1/hi/politics/10241522.stm -->
%img{ :src => "http://www.gravatar.com/avatar/4a92f0a6447839dc0a9a2b850fe9ed86?s=80&d=http%3A%2F%2Fgithub.com%2Fimages%2Fgravatars%2Fgravatar-80.png", :alt => "Adrian Short", :width => 80, :height => 80 }
%p.vcard
This website was designed and written by
%a.fn.url{ :href => 'http://adrianshort.co.uk' }<


+ 0
- 9
views/directorate.haml Ver ficheiro

@@ -20,12 +20,3 @@
%p
%a{ :href => "/services/#{service.slug}" }
= service.name

.grid_6

%h3 Suppliers

- for supplier in @directorate.suppliers
%p
%a{ :href => "/suppliers/#{supplier.slug}" }
= supplier.name

+ 57
- 12
views/home.haml Ver ficheiro

@@ -7,7 +7,7 @@
.clear

.grid_6
%h2 Directorates
%h2 Council Directorates
- for directorate in @directorates
%p
@@ -15,18 +15,63 @@
= directorate.name

.grid_6
.callout
.callout{ :style => "padding: 5px 30px;" }
%p
Armchair Auditor lets you see how your council spends your money.
%p
We've got
= @payments_count
payments from
%a{ :href => "/services" }
= @services_count
services
at the Royal Borough of Windsor and Maidenhead to
%a{ :href => "/suppliers" }
= @suppliers_count
suppliers.
For the Royal Borough of Windsor and Maidenhead we've got:
%ul
%li
%a{ :href => "/services" }
= commify(@services_count)
services
%li
%a{ :href => "/suppliers" }
= commify(@suppliers_count)
suppliers
%li
= commify(@payments_count)
payments
.clear

.grid_3.home_subheads
%h3
Big picture,
%br
small details

.grid_3.home_subheads
%h3 Talk about it

.grid_3.home_subheads
%h3 Open data
.grid_3.home_subheads
%h3 Open source
.clear

.grid_3
%p Sometimes you want a high-level view of how much money is being spent by each council service or paid to each supplier. Other times you want to examine the details right down to individual payments.
%p Armchair Auditor lets you do both.

.grid_3
%p Armchair Auditor doesn't just let you see how your council spends its money &mdash; it lets you talk about it too.
%p There's a comments thread for every council service, supplier and even each individual payment so you can add more information and your opinions.

.grid_3
%p Open data is free for you to use in any way you choose. Armchair Auditor lets you download your council's spending data into an Excel spreadsheet and any other program that can read CSV files.

%p Every page prints beautifully, too.
.grid_3
%p If you want to use Armchair Auditor's software to publish your own council's data, it's free. Or you can use it as the starting point for your own custom project.
%p
%a{ :href => "http://github.com/adrianshort/Armchair-Auditor" }
Get the code on Github.



+ 17
- 13
views/layout.haml Ver ficheiro

@@ -4,10 +4,12 @@
%head
%title= @page_title ? @page_title + " - Armchair Auditor" : "Armchair Auditor"
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/style.css' }
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/breadcrumb/breadcrumb.css' }
-#
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/breadcrumb/breadcrumb.css' }
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/print.css', :media => 'print' }
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/grid.css' }
%script{:type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'}
%script{:type => 'text/javascript', :src => '/js/jquery.cookie.js'}
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-3042981-18']);
@@ -23,19 +25,21 @@
%body
.container_12
.grid_12
%p.highlight This is a demonstration website of &quot;alpha&quot; quality &mdash; don't rely on this data.
%h1 Royal Borough of Windsor &amp; Maidenhead Armchair Auditor
%p.highlight.hidden This is a demonstration website of &quot;alpha&quot; quality &mdash; don't rely on this data.
%h1.logo
Armchair Auditor
%span{ :style => "color: #777; font-size: 60%; padding-left: 20px;" }
Royal Borough of Windsor &amp; Maidenhead Spending
#nav.noprint
%a{ :href => '/' } Home
%a{ :href => '/services' } Services
%a{ :href => '/suppliers' } Suppliers
%a{ :href => '/about' } About
= yield
.clear
#footer
.grid_12
.grid_12.top_border
%p
%a{ :href => '/' } Home
%p
%a{ :href => '/services' } Services
%p
%a{ :href => '/suppliers' } Suppliers
%p
%a{ :href => '/about' } About this website
%p
%a{ :href => 'http://adrianshort.co.uk/' } Designed by Adrian Short
An independent website
%a{ :href => 'http://adrianshort.co.uk/' }
designed by Adrian Short

+ 26
- 29
views/servicepayments.haml Ver ficheiro

@@ -6,6 +6,7 @@
$('.spinner').hide()
$('.filter a').removeClass('filter_selected');
$(objj).addClass('filter_selected');
$.cookie("payments_filter_min", min, { expires: 60, path: '/' }); /* expires in n days */
});
}

@@ -46,37 +47,33 @@
Download data as CSV

.noprint
%p
Show payments over:&nbsp;&nbsp;
%img.spinner{ :src => "/spinner.gif" } <!-- Thanks, http://ajaxload.info/ -->
%p.filter
%a#min500{:href => '#'}
&pound;500
%a#min1000.filter_selected{:href => '#'}
&pound;1,000
%a#min2500{:href => '#'}
&pound;2,500
%a#min5000{:href => '#'}
&pound;5,000
%a#min10000{:href => '#'}
&pound;10,000
Show payments over
- for v in @FILTER_VALUES
- @min.to_i == v.to_i ? klass = "filter_selected" : klass = ""
%a{ :href => '#', :id => "min" + v.to_s, :class => klass }
= "&pound;" + commify(v)
&nbsp;&nbsp;
%img.spinner{ :src => "/spinner.gif" } <!-- Thanks, http://ajaxload.info/ -->

#payments= haml :servicepaymentsdetail, :layout => false
.clear
<div class="grid_9 noprint">
= haml_partial "comment_header"
<div id="disqus_thread" class="noprint"></div>
<script type="text/javascript">
var disqus_developer = 1;
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://armchairauditor.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript=armchairauditor">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink noprint">Comments powered by <span class="logo-disqus">Disqus</span></a>
</div>
-#
<div class="grid_9 noprint">
= haml_partial "comment_header"
<div id="disqus_thread" class="noprint"></div>
<script type="text/javascript">
var disqus_developer = 1;
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://armchairauditor.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript=armchairauditor">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink noprint">Comments powered by <span class="logo-disqus">Disqus</span></a>
</div>

Carregando…
Cancelar
Guardar