| @@ -0,0 +1,4 @@ | |||
| *.sqlite | |||
| *.zip | |||
| .ruby-* | |||
| _site | |||
| @@ -0,0 +1,6 @@ | |||
| source 'https://rubygems.org' | |||
| ruby '2.3.1' | |||
| gem 'scraperwiki', :git => 'https://github.com/openaustralia/scraperwiki-ruby/', :branch => 'morph_defaults' | |||
| gem 'haml' | |||
| @@ -0,0 +1,34 @@ | |||
| GIT | |||
| remote: https://github.com/openaustralia/scraperwiki-ruby/ | |||
| revision: fc50176812505e463077d5c673d504a6a234aa78 | |||
| branch: morph_defaults | |||
| specs: | |||
| scraperwiki (3.0.1) | |||
| httpclient | |||
| sqlite_magic | |||
| GEM | |||
| remote: https://rubygems.org/ | |||
| specs: | |||
| haml (5.0.4) | |||
| temple (>= 0.8.0) | |||
| tilt | |||
| httpclient (2.8.3) | |||
| sqlite3 (1.3.13) | |||
| sqlite_magic (0.0.6) | |||
| sqlite3 | |||
| temple (0.8.0) | |||
| tilt (2.0.8) | |||
| PLATFORMS | |||
| ruby | |||
| DEPENDENCIES | |||
| haml | |||
| scraperwiki! | |||
| RUBY VERSION | |||
| ruby 2.3.1p112 | |||
| BUNDLED WITH | |||
| 1.16.5 | |||
| @@ -0,0 +1,69 @@ | |||
| #!/usr/bin/env ruby | |||
| require 'scraperwiki' | |||
| require 'haml' | |||
| require 'pp' | |||
| require 'logger' | |||
| require_relative '../lib/helpers' | |||
| OUTPUT_DIR = '_site' | |||
| VIEWS_DIR = File.join('views') | |||
| LAYOUT_FN = File.join(VIEWS_DIR, 'layout.haml') | |||
| def write_page(path_items, template, locals = {}) | |||
| dir = File.join(OUTPUT_DIR, path_items) | |||
| FileUtils.mkdir_p(dir) | |||
| @log.debug dir | |||
| fn = File.join(dir, 'index.html') | |||
| # https://stackoverflow.com/questions/6125265/using-layouts-in-haml-files-independently-of-rails | |||
| html = Haml::Engine.new(File.read(LAYOUT_FN)).render do | |||
| Haml::Engine.new(File.read(File.join(VIEWS_DIR, "#{template}.haml"))).render(Object.new, locals) | |||
| end | |||
| File.write(fn, html) | |||
| @log.info fn | |||
| @pages += 1 | |||
| # TODO - add page to sitemap.xml or sitemap.txt | |||
| # https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190 | |||
| end | |||
| def create_output_dir | |||
| # Recursively delete working directory to ensure no redundant files are left behind from previous builds. | |||
| # FileUtils.rm_rf(@working_dir) | |||
| Dir.mkdir(@working_dir) unless File.directory?(@working_dir) | |||
| # Dir.chdir(@working_dir) | |||
| # Copy `public` dir to output dir | |||
| FileUtils.copy_entry('public', @working_dir) | |||
| end | |||
| def gen_homepage | |||
| decisions = ScraperWiki.select("* from `applications` order by date_decision desc limit 20") | |||
| write_page('.', 'index', { decisions: decisions }) | |||
| end | |||
| def gen_authorities | |||
| auths = ScraperWiki.select("distinct(authority_name) as authority_name from applications order by authority_name") | |||
| write_page('authorities', 'authorities', { auths: auths }) | |||
| auths.each do |auth| | |||
| summary = ScraperWiki.select(" | |||
| status, decision, appeal_status, appeal_decision, count(*) as qty | |||
| from applications | |||
| where authority_name = '#{auth['authority_name']}' | |||
| group by status, decision, appeal_status, appeal_decision | |||
| ") | |||
| apps = ScraperWiki.select("* from applications where authority_name='#{auth['authority_name']}' order by date_received") | |||
| write_page(['authorities', slug(auth['authority_name'])], 'authority', { apps: apps, auth: auth, summary: summary }) | |||
| end | |||
| end | |||
| @working_dir = File.join(Dir.pwd, OUTPUT_DIR) | |||
| puts @working_dir | |||
| # exit | |||
| @log = Logger.new($stdout) | |||
| @pages = 0 | |||
| create_output_dir | |||
| gen_homepage | |||
| gen_authorities | |||
| @@ -0,0 +1,17 @@ | |||
| def short_date(s) | |||
| return if s.nil? | |||
| Date.parse(s).strftime("%e %b %Y").gsub(' ', ' ') | |||
| end | |||
| def cleanup(s) | |||
| return if s.nil? | |||
| s.sub!('Unknown', '') | |||
| s.sub!('Not Available', '') | |||
| # s = "<span class=grant>#{s}</span>" if s.match(/approve/i) | |||
| # s = "<span class=refuse>#{s}</span>" if s.match(/refuse/i) | |||
| s | |||
| end | |||
| def slug(s) | |||
| s.downcase.gsub(' ', '-') | |||
| end | |||
| @@ -0,0 +1,192 @@ | |||
| body | |||
| { | |||
| background-color: #fff; | |||
| color: #555; | |||
| font-family: Helvetica, Arial, sans-serif; | |||
| font-size: 100%; | |||
| width: 100%; | |||
| line-height: 1.5em; | |||
| margin: 0; | |||
| padding: 0; | |||
| } | |||
| .warning { | |||
| padding: 10px 15px; | |||
| background-color: #fcfcfc; | |||
| margin: 25px 0; | |||
| } | |||
| p | |||
| { | |||
| font-size: 110%; | |||
| } | |||
| #main | |||
| { | |||
| width: 920px; | |||
| margin: 50px auto; | |||
| } | |||
| tr.footer { | |||
| border-top: 1px solid #eee; | |||
| border-bottom: 0px solid black; | |||
| } | |||
| tr.header { | |||
| border-bottom: 1px solid #eee; | |||
| } | |||
| #header | |||
| { | |||
| font-size: 100%; | |||
| /* background-color: #e8f3f4; */ | |||
| color: #999; | |||
| text-align: left; | |||
| margin: 0 0 0px 0; | |||
| height: 100%; | |||
| } | |||
| #header_inner { | |||
| margin: 0 auto; | |||
| padding: 10px 0; | |||
| width: 930px; | |||
| } | |||
| #header h1 { | |||
| font-size: 180%; | |||
| color: #555; | |||
| } | |||
| .grant { | |||
| color: green; | |||
| } | |||
| .refuse { | |||
| color: red; | |||
| } | |||
| a | |||
| { | |||
| padding: 1px 4px; | |||
| color: #999; | |||
| text-decoration: none; | |||
| } | |||
| a:visited | |||
| { | |||
| padding: 1px 4px; | |||
| color: #111; | |||
| text-decoration: none; | |||
| } | |||
| a:hover | |||
| { | |||
| background-color: #4f4f4f; | |||
| color: #fff; | |||
| } | |||
| h1 | |||
| { | |||
| margin: 40px 0; | |||
| line-height: 1.4em; | |||
| font-weight: bold; | |||
| color: #555; | |||
| } | |||
| h2 | |||
| { | |||
| margin: 20px 0 0 0; | |||
| line-height: 1.5em; | |||
| font-weight: bold; | |||
| color: #555; | |||
| } | |||
| h3 | |||
| { | |||
| margin: 30px 0 0 0; | |||
| line-height: 1.5em; | |||
| font-weight: bold; | |||
| color: #555; | |||
| } | |||
| .highlight | |||
| { | |||
| background-color: #e8f3f4; | |||
| } | |||
| strong | |||
| { | |||
| color: #000; | |||
| } | |||
| table | |||
| { | |||
| border-collapse: collapse; | |||
| margin: 20px 0 60px 0; | |||
| } | |||
| td, th | |||
| { | |||
| padding: 6px; | |||
| } | |||
| th { | |||
| font-weight: bold; | |||
| text-align: left; | |||
| } | |||
| tr | |||
| { | |||
| border-bottom: 1px solid #eee; | |||
| } | |||
| nav | |||
| { | |||
| font-size: 85%; | |||
| margin: 0 0 0 0; | |||
| } | |||
| .right | |||
| { | |||
| text-align: right; | |||
| } | |||
| .noborder | |||
| { | |||
| border: 0; | |||
| } | |||
| #notice { | |||
| background-color: green; | |||
| color: white; | |||
| padding: 10px 20px; | |||
| } | |||
| .menu { | |||
| margin: 0; | |||
| padding: 0; | |||
| } | |||
| .menu li { | |||
| list-style-type: none; | |||
| display: inline; | |||
| margin: 20px 0; | |||
| padding: 0 10px 0 0; | |||
| } | |||
| @media print { | |||
| .noprint, #footer, .nav, nav | |||
| { | |||
| display: none; | |||
| } | |||
| body | |||
| { | |||
| margin: 0 auto; | |||
| color: black; | |||
| } | |||
| a, a:visited { | |||
| background-color: #fff; | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| %h1 Authorities | |||
| %table | |||
| - auths.each do |auth| | |||
| %tr | |||
| %td | |||
| %a{ :href => slug(auth['authority_name']) } | |||
| = auth['authority_name'] | |||
| @@ -0,0 +1,42 @@ | |||
| %h1= auth['authority_name'] | |||
| %h2 Summary | |||
| %table | |||
| %thead | |||
| %tr | |||
| %th Status | |||
| %th Decision | |||
| %th Appeal status | |||
| %th Appeal decision | |||
| %th Quantity | |||
| %tbody | |||
| - summary.each do |row| | |||
| %tr | |||
| %td= cleanup(row['status']) | |||
| %td= cleanup(row['decision']) | |||
| %td= cleanup(row['appeal_status']) | |||
| %td= cleanup(row['appeal_decision']) | |||
| %td= row['qty'] | |||
| %h2 Applications | |||
| %table | |||
| %thead | |||
| %tr | |||
| %th Received | |||
| %th Reference | |||
| %th Address | |||
| -# %th Proposal | |||
| %th Status | |||
| %th Decision | |||
| - apps.each do |app| | |||
| %tr | |||
| %td= short_date(app['date_received']) | |||
| %td | |||
| %a{ href: app['info_url']} | |||
| = app['council_reference'] | |||
| %td= app['address'] | |||
| -# %td= app['description'] | |||
| %td= cleanup(app['status']) | |||
| %td= cleanup(app['decision']) | |||
| @@ -0,0 +1,22 @@ | |||
| %h2 Latest decisions | |||
| %table | |||
| %thead | |||
| %tr | |||
| %th Authority | |||
| %th Reference | |||
| %th Date | |||
| %th Address | |||
| %th Decision | |||
| %tbody | |||
| - decisions.each do |app| | |||
| %tr | |||
| %td | |||
| %a{ :href => "/authorities/#{ slug(app['authority_name'])}" } | |||
| = app['authority_name'] | |||
| %td | |||
| %a{ href: app['info_url']} | |||
| = app['council_reference'] | |||
| %td= short_date(app['date_decision']) | |||
| %td= app['address'] | |||
| %td= app['decision'] | |||
| @@ -0,0 +1,22 @@ | |||
| !!!5 | |||
| %html | |||
| %head | |||
| %title InLink kiosks planning applications | |||
| %link{ :href => '/style.css', :rel => 'stylesheet'} | |||
| %body | |||
| #main | |||
| #header | |||
| %h1 InLink kiosks planning applications | |||
| %ul.menu | |||
| %li | |||
| %a{ :href => '/' } | |||
| Home | |||
| %li | |||
| %a{ :href => '/authorities' } | |||
| Authorities | |||
| = yield | |||
| #footer | |||
| %a{ :href => 'https://twitter.com/adrianshort'} | |||
| @adrianshort made this. | |||