remove placeholder
remove placeholder

file:a/README.rst -> file:b/README.rst
This CKAN Extension customises a CKAN instance for the hosting of data.gov.au. This CKAN Extension customises a CKAN instance for the hosting of data.gov.au.
   
It comprises: It comprises:
   
* A CKAN Extension "plugin" at ``ckanext/datagovau/plugin.py`` which, when * A custom Package edit form that defaults to cc-by licence
loaded, overrides various settings in the core ``ini``-file to provide: * Replaces links with http/https protocol independent versions
* A path to local customisations of the core templates to include AGLS/Dublin Core minimum metadata * Provides HTML to users to embed data previews on their own website
* A custom Package edit form that defaults to cc-by licence * A cut down licenses.json file
* A custom n3/rdf output format  
* Replaces links with http/https protocol independent versions  
* Provides HTML to users to embed data previews on their own website  
   
* A cut down licenses.json file This extension is complemented by ckanext-agls for AGLS metadata, ckanext-googleanalytics for Google Analytics tracking of API usage and ckanext-dga-stats for the customised site statistics page.
   
Installation Installation
============ ============
   
To install this package, from your CKAN virtualenv, run the following from your CKAN base folder (e.g. ``pyenv/``):: To install this package, from your CKAN virtualenv, run the following from your CKAN base folder (e.g. ``pyenv/``)::
   
pip install -e git+https://github.com/okfn/ckanext-datagovau#egg=ckanext-datagovau pip install -e git+https://github.com/okfn/ckanext-datagovau#egg=ckanext-datagovau
   
Then activate it by setting ``ckan.plugins = datagovau`` in your main ``ini``-file. Then activate it by setting ``ckan.plugins = datagovau`` in your main ``ini``-file.
   
To add the cut down licenses.json set ``licenses_group_url = http://%(ckan.site_url)/licenses.json`` To add the cut down licenses.json set ``licenses_group_url = http://%(ckan.site_url)/licenses.json``
or copy ``ckanext/datagovau/theme/public/licenses.json`` to the same folder as your CKAN config ini file or copy ``ckanext/datagovau/theme/public/licenses.json`` to the same folder as your CKAN config ini file
and set ``licenses_group_url = file://%(here)s/licenses.json`` and set ``licenses_group_url = file://%(here)s/licenses.json``
   
   
   
# This is a basic VCL configuration file for varnish. See the vcl(7) # This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics. # man page for details on VCL syntax and semantics.
# #
# Default backend definition. Set this to point to your content # Default backend definition. Set this to point to your content
# server. # server.
# #
backend default { backend default {
.host = "127.0.0.1"; .host = "127.0.0.1";
.port = "8080"; .port = "8080";
} }
  backend geoserver {
  .host = "172.31.18.207";
  .port = "8983";
  }
   
sub vcl_fetch { sub vcl_fetch {
set beresp.grace = 1h; set beresp.grace = 1h;
  unset beresp.http.Server;
if (beresp.http.content-type ~ "(text|application)") { # These status codes should always pass through and never cache.
  if ( beresp.status >= 500 ) {
  set beresp.ttl = 0s;
  }
  if (beresp.http.content-type ~ "(text|javascript|json|xml|html)") {
set beresp.do_gzip = true; set beresp.do_gzip = true;
} }
  # CKAN cache headers are used by Varnish cache, but should not be propagated to
  # the Internet. Tell browsers and proxies not to cache. This means Varnish always
  # gets the responsibility to server the right content at all times.
  if (beresp.http.Cache-Control ~ "max-age") {
  unset beresp.http.set-cookie;
  set beresp.http.Cache-Control = "no-cache";
  }
   
  # Encourage assets to be cached by proxies and browsers
  # JS and CSS may be gzipped depending on headers
  # see https://developers.google.com/speed/docs/best-practices/caching
  if (req.url ~ "\.(css|js)") {
  set beresp.http.Vary = "Accept-Encoding";
  }
   
  # Encourage assets to be cached by proxies and browsers for 1 day
  if (req.url ~ "\.(png|gif|jpg|swf|css|js)") {
  unset beresp.http.set-cookie;
  set beresp.http.Cache-Control = "public, max-age=86400";
  set beresp.ttl = 1d;
  }
   
  # Encourage CKAN vendor assets (which are versioned) to be cached by
  # by proxies and browsers for 1 year
  if (req.url ~ "^/scripts/vendor/") {
  unset beresp.http.set-cookie;
  set beresp.http.Cache-Control = "public, max-age=31536000";
  set beresp.ttl = 12m;
  }
  }
  sub vcl_recv {
  if (req.http.user-agent ~ "Ezooms" || req.http.user-agent ~ "Ahrefs") {
  error 403;
  }
  if (req.url ~ "^/geoserver/") {
  set req.backend = geoserver;
  } else {
  set req.backend = default;
  #redirect secure traffic to https
  if ( (req.http.Cookie ~ "auth_tkt" || req.http.Cookie ~ "ckan" || req.url ~ "user/(reset|login)") && req.http.X-Forwarded-Proto !~ "(?i)https") {
  set req.http.x-Redir-Url = "https://data.gov.au" + req.url;
  error 753 req.http.x-Redir-Url;
  }
  # remove locale links
  if (req.url ~ "/((?!js)..|.._..|sr_Latn)/") {
  set req.http.x-Redir-Url = regsub(req.url, "/((?!js)..|.._..|sr_Latn)/", "/");
  error 751 req.http.x-Redir-Url;
  }
  # rewrite broken resources
  if (req.url ~ "leaflet") {
  set req.url = regsub(req.url, "fanstatic/ckanext-spatial/:version:2013-09-13T02:32:17.87/:bundle:js/vendor/leaflet/images", "js/vendor/leaflet/images");
  }
  # remove old hostnames
  if (req.http.host ~ "data.australia.gov.au") {
  set req.http.x-Redir-Url = "http://data.gov.au" + req.url;
  error 751 req.http.x-Redir-Url;
  }
   
  if (req.url ~ "^/_tracking") {
  // exclude web spiders from statistics
  if (req.http.user-agent ~ "Googlebot" || req.http.user-agent ~ "baidu" || req.http.user-agent ~ "bing") {
  error 200;
  } else {
  return (pass);
  }
  }
if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|woff|eot)$") { if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|woff|eot)$") {
unset beresp.http.set-cookie; //Varnish to deliver content from cache even if the request othervise indicates that the request should be passed
  return(lookup);
} }
} }
sub vcl_recv { // Remove has_js and Google Analytics cookies. Evan added sharethis cookies
if (req.url ~ "^/_tracking") { set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js|cookie-agreed-en|_csoot|_csuid|_chartbeat2)=[^;]*", "");
return (pass);  
} // Remove a ";" prefix, if present.
if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|woff|eot)$") { set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
return(lookup); // Remove empty cookies.
} if (req.http.Cookie ~ "^\s*$") {
if (req.url ~ "/(..|.._..)/") { unset req.http.Cookie;
set req.url = regsub(req.url, "/((?!js)..|.._..)/", "/"); }
}  
if (req.http.Cookie) { remove req.http.X-Forwarded-For;
set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1"); # removes all cookies named __utm? (utma, utmb...) - tracking thing set req.http.X-Forwarded-For = req.http.X-Real-IP;
   
if (req.http.Cookie == "") {  
remove req.http.Cookie;  
}  
}  
} }
sub vcl_hash { sub vcl_hash {
# http://serverfault.com/questions/112531/ignoring-get-parameters-in-varnish-vcl # http://serverfault.com/questions/112531/ignoring-get-parameters-in-varnish-vcl
set req.url = regsub(req.url, "(?:(.com|.au))/((?!js)..|.._..)/", "/"); set req.url = regsub(req.url, "(?:(.com|.au))/((?!js)..|.._..|sr_Latn)/", "/");
hash_data(req.url); hash_data(req.url);
if (req.http.host) { if (req.http.host) {
hash_data(req.http.host); hash_data(req.http.host);
} else { } else {
hash_data(server.ip); hash_data(server.ip);
} }
return (hash); if (req.http.Cookie) {
  hash_data(req.http.Cookie);
  }
} }
sub vcl_deliver { sub vcl_deliver {
if (!resp.http.Vary) { if (!resp.http.Vary) {
set resp.http.Vary = "Accept-Encoding"; set resp.http.Vary = "Accept-Encoding";
} else if (resp.http.Vary !~ "(?i)Accept-Encoding") { } else if (resp.http.Vary !~ "(?i)Accept-Encoding") {
set resp.http.Vary = resp.http.Vary + ",Accept-Encoding"; set resp.http.Vary = resp.http.Vary + ",Accept-Encoding";
} }
if (obj.hits > 0) { remove resp.http.X-Varnish;
set resp.http.X-Cache = "HIT"; remove resp.http.Via;
} else { remove resp.http.Age;
set resp.http.X-Cache = "MISS"; remove resp.http.X-Powered-By;
} if (req.url ~ "^/geoserver/") {
  set resp.http.Access-Control-Allow-Origin = "*";
  set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE";
  set resp.http.Access-Control-Allow-Headers = "Origin, X-Requested-With, Content-Type, Accept";
  }
} }
  sub vcl_error {
  remove obj.http.Server;
  if (obj.status == 751) {
  set obj.http.Location = obj.response;
  set obj.status = 301;
  return (deliver);
  }
  if (obj.status == 753) {
  set obj.http.Location = obj.response;
  set obj.status = 301;
  return (deliver);
  }
  }
# #
# Below is a commented-out copy of the default VCL logic. If you # Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be # redefine any of these subroutines, the built-in logic will be
# appended to your code. # appended to your code.
# sub vcl_recv { # sub vcl_recv {
# if (req.restarts == 0) { # if (req.restarts == 0) {
# if (req.http.x-forwarded-for) { # if (req.http.x-forwarded-for) {
# set req.http.X-Forwarded-For = # set req.http.X-Forwarded-For =
# req.http.X-Forwarded-For + ", " + client.ip; # req.http.X-Forwarded-For + ", " + client.ip;
# } else { # } else {
# set req.http.X-Forwarded-For = client.ip; # set req.http.X-Forwarded-For = client.ip;
# } # }
# } # }
# if (req.request != "GET" && # if (req.request != "GET" &&
# req.request != "HEAD" && # req.request != "HEAD" &&
# req.request != "PUT" && # req.request != "PUT" &&
# req.request != "POST" && # req.request != "POST" &&
# req.request != "TRACE" && # req.request != "TRACE" &&
# req.request != "OPTIONS" && # req.request != "OPTIONS" &&
# req.request != "DELETE") { # req.request != "DELETE") {
# /* Non-RFC2616 or CONNECT which is weird. */ # /* Non-RFC2616 or CONNECT which is weird. */
# return (pipe); # return (pipe);
# } # }
# if (req.request != "GET" && req.request != "HEAD") { # if (req.request != "GET" && req.request != "HEAD") {
# /* We only deal with GET and HEAD by default */ # /* We only deal with GET and HEAD by default */
# return (pass); # return (pass);
# } # }
# if (req.http.Authorization || req.http.Cookie) { # if (req.http.Authorization || req.http.Cookie) {
# /* Not cacheable by default */ # /* Not cacheable by default */
# return (pass); # return (pass);
# } # }
# return (lookup); # return (lookup);
# } # }
# #
# sub vcl_pipe { # sub vcl_pipe {
# # Note that only the first request to the backend will have # # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to # # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have: # # have it set for all requests, make sure to have:
# # set bereq.http.connection = "close"; # # set bereq.http.connection = "close";
# # here. It is not set by default as it might break some broken web # # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication. # # applications, like IIS with NTLM authentication.
# return (pipe); # return (pipe);
# } # }
# #
# sub vcl_pass { # sub vcl_pass {
# return (pass); # return (pass);
# } # }
# #
# sub vcl_hash { # sub vcl_hash {
# hash_data(req.url); # hash_data(req.url);
# if (req.http.host) { # if (req.http.host) {
# hash_data(req.http.host); # hash_data(req.http.host);
# } else { # } else {
# hash_data(server.ip); # hash_data(server.ip);
# } # }
# return (hash); # return (hash);
# } # }
# #
# sub vcl_hit { # sub vcl_hit {
# return (deliver); # return (deliver);
# } # }
# #
# sub vcl_miss { # sub vcl_miss {
# return (fetch); # return (fetch);
# } # }
# #
# sub vcl_fetch { # sub vcl_fetch {
# if (beresp.ttl <= 0s || # if (beresp.ttl <= 0s ||
# beresp.http.Set-Cookie || # beresp.http.Set-Cookie ||
# beresp.http.Vary == "*") { # beresp.http.Vary == "*") {
# /* # /*
# * Mark as "Hit-For-Pass" for the next 2 minutes # * Mark as "Hit-For-Pass" for the next 2 minutes
# */ # */
# set beresp.ttl = 120 s; # set beresp.ttl = 120 s;
# return (hit_for_pass); # return (hit_for_pass);
# } # }
# return (deliver); # return (deliver);
# } # }
# #
# sub vcl_deliver { # sub vcl_deliver {
# return (deliver); # return (deliver);
# } # }
# #
# sub vcl_error { # sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8"; # set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5"; # set obj.http.Retry-After = "5";
# synthetic {" # synthetic {"
# <?xml version="1.0" encoding="utf-8"?> # <?xml version="1.0" encoding="utf-8"?>
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> # "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# <html> # <html>
# <head> # <head>
# <title>"} + obj.status + " " + obj.response + {"</title> # <title>"} + obj.status + " " + obj.response + {"</title>
# </head> # </head>
# <body> # <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1> # <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p> # <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3> # <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p> # <p>XID: "} + req.xid + {"</p>
# <hr> # <hr>
# <p>Varnish cache server</p> # <p>Varnish cache server</p>
# </body> # </body>
# </html> # </html>
# "}; # "};
# return (deliver); # return (deliver);
# } # }
# #
# sub vcl_init { # sub vcl_init {
# return (ok); # return (ok);
# } # }
# #
# sub vcl_fini { # sub vcl_fini {
# return (ok); # return (ok);
# } # }
   
file:b/admin/start.sh (new)
  export NEW_RELIC_CONFIG_FILE="newrelic.ini"
  export VIRTUAL_ENV="/var/lib/ckan/dga/pyenv"
  export PATH="/var/lib/ckan/dga/pyenv:/var/lib/ckan/dga/pyenv/bin:$PATH"
  cd /var/lib/ckan/dga/pyenv/src/ckan
  newrelic-admin run-program paster serve development.ini
 
import urllib  
import json  
from pprint import pprint  
import logging  
import ckan.logic as logic  
import hashlib  
import threading  
from ckan.common import _, c, request, response  
from pylons import config  
from webob.multidict import UnicodeMultiDict  
from paste.util.multidict import MultiDict  
 
log = logging.getLogger(__name__)  
 
from ckan.controllers.api import ApiController  
 
class DGAApiController(ApiController):  
 
def _post_analytics(self,user,request_obj_type,request_function,request_id):  
if (config.get('googleanalytics.id') != None):  
data = urllib.urlencode({  
"v":1,  
"tid":config.get('googleanalytics.id'),  
"cid":hashlib.md5(user).hexdigest(),  
"t":"event",  
"dh":c.environ['HTTP_HOST'],  
"dp":c.environ['PATH_INFO'],  
"dr":c.environ.get('HTTP_REFERER',''),  
"ec":"CKAN API Request",  
"ea":request_obj_type+request_function,  
"el":request_id,  
})  
log.debug("Sending API Analytics Data: "+data)  
# send analytics asynchronously  
threading.Thread(target=urllib.urlopen,args=("http://www.google-analytics.com/collect", data)).start()  
 
 
def action(self, logic_function, ver=None):  
try:  
function = logic.get_action(logic_function)  
except Exception,e:  
log.debug(e)  
pass  
try:  
side_effect_free = getattr(function, 'side_effect_free', False)  
request_data = self._get_request_data(try_url_params=side_effect_free)  
if isinstance(request_data, dict):  
id = request_data.get('id','')  
if 'q' in request_data.keys():  
id = request_data['q']  
if 'query' in request_data.keys():  
id = request_data['query']  
self._post_analytics(c.user,logic_function,'', id)  
except Exception,e:  
print log.debug(e)  
pass  
 
return ApiController.action(self,logic_function, ver)  
 
def list(self, ver=None, register=None, subregister=None, id=None):  
self._post_analytics(c.user,register+("_"+str(subregister) if subregister else ""),"list",id)  
return ApiController.list(self,ver, register, subregister, id)  
def show(self, ver=None, register=None, subregister=None, id=None, id2=None):  
self._post_analytics(c.user,register+("_"+str(subregister) if subregister else ""),"show",id)  
return ApiController.show(self,ver, register, subregister, id,id2)  
def update(self, ver=None, register=None, subregister=None, id=None, id2=None):  
self._post_analytics(c.user,register+("_"+str(subregister) if subregister else ""),"update",id)  
return ApiController.update(self,ver, register, subregister, id,id2)  
def delete(self, ver=None, register=None, subregister=None, id=None, id2=None):  
self._post_analytics(c.user,register+("_"+str(subregister) if subregister else ""),"delete",id)  
return ApiController.delete(self,ver, register, subregister, id,id2)  
def search(self, ver=None, register=None):  
id = None  
try:  
params = MultiDict(self._get_search_params(request.params))  
if 'q' in params.keys():  
id = params['q']  
if 'query' in params.keys():  
id = params['query']  
except ValueError, e:  
print str(e)  
pass  
self._post_analytics(c.user,register,"search",id)  
 
import logging import logging
   
import ckan.plugins as plugins import ckan.plugins as plugins
import ckan.lib as lib import ckan.lib as lib
import ckan.lib.dictization.model_dictize as model_dictize import ckan.lib.dictization.model_dictize as model_dictize
import ckan.plugins.toolkit as tk import ckan.plugins.toolkit as tk
import ckan.model as model import ckan.model as model
from pylons import config from pylons import config
from routes.mapper import SubMapper, Mapper as _Mapper  
   
from sqlalchemy import orm from sqlalchemy import orm
import ckan.model import ckan.model
   
#parse the activity feed for last active non-system user  
def get_last_active_user(id):  
system_user = lib.helpers.get_action('user_show',{'id': config.get('ckan.site_id', 'ckan_site_user')})  
user_list = [x for x in lib.helpers.get_action('package_activity_list',{'id':id}) if x['user_id'] != system_user['id']]  
user = None  
if len(user_list) > 0:  
user = user_list[0].get('user_id', None)  
if user is None:  
return system_user  
else:  
return lib.helpers.get_action('user_show',{'id':user})  
   
# get user created datasets and those they have edited # get user created datasets and those they have edited
def get_user_datasets(user_dict): def get_user_datasets(user_dict):
created_datasets_list = user_dict['datasets'] created_datasets_list = user_dict['datasets']
active_datasets_list = [x['data']['package'] for x in active_datasets_list = [x['data']['package'] for x in
lib.helpers.get_action('user_activity_list',{'id':user_dict['id']}) if x['data'].get('package')] lib.helpers.get_action('user_activity_list',{'id':user_dict['id']}) if x['data'].get('package')]
return created_datasets_list + active_datasets_list raw_list = created_datasets_list + active_datasets_list
  filtered_dict = {}
  for dataset in raw_list:
  if dataset['id'] not in filtered_dict.keys():
  filtered_dict[dataset['id']] = dataset
  return filtered_dict.values()
   
class DataGovAuPlugin(plugins.SingletonPlugin, class DataGovAuPlugin(plugins.SingletonPlugin,
tk.DefaultDatasetForm): tk.DefaultDatasetForm):
'''An example IDatasetForm CKAN plugin. '''An example IDatasetForm CKAN plugin.
   
Uses a tag vocabulary to add a custom metadata field to datasets. Uses a tag vocabulary to add a custom metadata field to datasets.
   
''' '''
plugins.implements(plugins.IConfigurer, inherit=False) plugins.implements(plugins.IConfigurer, inherit=False)
plugins.implements(plugins.IDatasetForm, inherit=False)  
plugins.implements(plugins.ITemplateHelpers, inherit=False) plugins.implements(plugins.ITemplateHelpers, inherit=False)
plugins.implements(plugins.IRoutes, inherit=True)  
   
def before_map(self, map):  
   
# Helpers to reduce code clutter  
GET = dict(method=['GET'])  
PUT = dict(method=['PUT'])  
POST = dict(method=['POST'])  
DELETE = dict(method=['DELETE'])  
GET_POST = dict(method=['GET', 'POST'])  
# intercept API calls that we want to capture analytics on  
register_list = [  
'package',  
'dataset',  
'resource',  
'tag',  
'group',  
'related',  
'revision',  
'licenses',  
'rating',  
'user',  
'activity'  
]  
register_list_str = '|'.join(register_list)  
# /api ver 3 or none  
with SubMapper(map, controller='ckanext.datagovau.controller:DGAApiController', path_prefix='/api{ver:/3|}',  
ver='/3') as m:  
m.connect('/action/{logic_function}', action='action',  
conditions=GET_POST)  
   
# /api ver 1, 2, 3 or none  
with SubMapper(map, controller='ckanext.datagovau.controller:DGAApiController', path_prefix='/api{ver:/1|/2|/3|}',  
ver='/1') as m:  
m.connect('/search/{register}', action='search')  
   
# /api/rest ver 1, 2 or none  
with SubMapper(map, controller='ckanext.datagovau.controller:DGAApiController', path_prefix='/api{ver:/1|/2|}',  
ver='/1', requirements=dict(register=register_list_str)  
) as m:  
   
m.connect('/rest/{register}', action='list', conditions=GET)  
m.connect('/rest/{register}', action='create', conditions=POST)  
m.connect('/rest/{register}/{id}', action='show', conditions=GET)  
m.connect('/rest/{register}/{id}', action='update', conditions=PUT)  
m.connect('/rest/{register}/{id}', action='update', conditions=POST)  
m.connect('/rest/{register}/{id}', action='delete', conditions=DELETE)  
   
return map  
   
def update_config(self, config): def update_config(self, config):
# Add this plugin's templates dir to CKAN's extra_template_paths, so # Add this plugin's templates dir to CKAN's extra_template_paths, so
# that CKAN will use this plugin's custom templates. # that CKAN will use this plugin's custom templates.
# here = os.path.dirname(__file__) # here = os.path.dirname(__file__)
# rootdir = os.path.dirname(os.path.dirname(here)) # rootdir = os.path.dirname(os.path.dirname(here))
   
tk.add_template_directory(config, 'templates') tk.add_template_directory(config, 'templates')
tk.add_public_directory(config, 'theme/public') tk.add_public_directory(config, 'theme/public')
tk.add_resource('theme/public', 'ckanext-datagovau') tk.add_resource('theme/public', 'ckanext-datagovau')
# config['licenses_group_url'] = 'http://%(ckan.site_url)/licenses.json' # config['licenses_group_url'] = 'http://%(ckan.site_url)/licenses.json'
   
def get_helpers(self): def get_helpers(self):
return {'get_last_active_user': get_last_active_user, 'get_user_datasets': get_user_datasets} return {'get_user_datasets': get_user_datasets}
   
def is_fallback(self):  
# Return True to register this plugin as the default handler for  
# package types not handled by any other IDatasetForm plugin.  
return True  
   
def package_types(self):  
# This plugin doesn't handle any special package types, it just  
# registers itself as the default (above).  
return []  
   
   
def create_package_schema(self):  
schema = super(DataGovAuPlugin, self).create_package_schema()  
schema = self._modify_package_schema(schema)  
return schema  
   
def update_package_schema(self):  
schema = super(DataGovAuPlugin, self).update_package_schema()  
schema = self._modify_package_schema(schema)  
return schema  
   
def show_package_schema(self):  
schema = super(DataGovAuPlugin, self).show_package_schema()  
   
# Don't show vocab tags mixed in with normal 'free' tags  
# (e.g. on dataset pages, or on the search page)  
schema['tags']['__extras'].append(tk.get_converter('free_tags_only'))  
   
# Add our custom_text field to the dataset schema.  
# ignore_missing == optional  
# ignore_empty == mandatory but not for viewing  
# !!! always convert_from_extras first  
schema.update({  
'agency_program': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_missing')],  
'contact_point': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'spatial_coverage': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'granularity': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'jurisdiction': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'temporal_coverage': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'data_state': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')],  
'update_freq': [tk.get_converter('convert_from_extras'),  
tk.get_validator('ignore_empty')]  
})  
return schema  
   
def _modify_package_schema(self, schema):  
# Add our custom_test metadata field to the schema, this one will use  
# convert_to_extras instead of convert_to_tags.  
# ignore_missing == optional  
# not_empty == mandatory, enforced here while modifying  
   
schema.update({  
'agency_program': [tk.get_validator('ignore_missing'),  
tk.get_converter('convert_to_extras')],  
'contact_point': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'spatial_coverage': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'granularity': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'jurisdiction': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'temporal_coverage': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'data_state': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')],  
'update_freq': [tk.get_converter('convert_to_extras'),  
tk.get_validator('not_empty')]  
})  
return schema  
   
# These methods just record how many times they're called, for testing  
# purposes.  
# TODO: It might be better to test that custom templates returned by  
# these methods are actually used, not just that the methods get  
# called.  
   
def setup_template_variables(self, context, data_dict):  
return super(DataGovAuPlugin, self).setup_template_variables(  
context, data_dict)  
   
def new_template(self):  
return super(DataGovAuPlugin, self).new_template()  
   
def read_template(self):  
return super(DataGovAuPlugin, self).read_template()  
   
def edit_template(self):  
return super(DataGovAuPlugin, self).edit_template()  
   
def search_template(self):  
return super(DataGovAuPlugin, self).search_template()  
   
def history_template(self):  
return super(DataGovAuPlugin, self).history_template()  
   
def package_form(self):  
return super(DataGovAuPlugin, self).package_form()  
   
   
  {% ckan_extends %}
 
  {% block header_site_navigation %}
  <nav class="section navigation">
  <ul class="nav nav-pills">
  {% block header_site_navigation_tabs %}
  {{ h.build_nav_main(
  ('search', _('Datasets')),
  ('organizations_index', _('Organizations')),
  ('about', _('About'))
  ) }}
  <li><a href="//data.gov.au/stats">Site Statistics</a></li>
  <li><a href="https://datagovau.ideascale.com/">Feedback/Request Data</a></li>
  {% endblock %}
  </ul>
  </nav>
  {% endblock %}
 
  {% ckan_extends %}
  {% block home_secondary_content %}
  <script type="text/javascript" src="//www.google.com/jsapi">
  </script>
  <script type="text/javascript">
  google.load("feeds", "1") //Load Google Ajax Feed API (version 1)
  </script>
 
  <div id="feeddiv"></div>
 
  <script type="text/javascript">
 
  var feedcontainer=document.getElementById("feeddiv")
  var feedurl="http://www.finance.gov.au/taxonomy/term/1274/feed"
  var feedlimit=3
  var rssoutput="<div class='module module-shallow module-narrow module-dark info box' style='color:black'><h2>Latest data.gov.au News</h2><i class='ckan-icon ckan-icon-feed'></i><a href='http://www.finance.gov.au/taxonomy/term/1274/feed/'>&nbsp;Subscribe to the blog </a></div>"
 
 
  function rssfeedsetup(){
  var feedpointer=new google.feeds.Feed(feedurl) //Google Feed API method
  feedpointer.setNumEntries(feedlimit) //Google Feed API method
  feedpointer.load(displayfeed) //Google Feed API method
  }
 
  function displayfeed(result){
  if (!result.error){
  var thefeeds=result.feed.entries
  for (var i=0; i<thefeeds.length; i++) {
  rssoutput+="<div class='module module-shallow module-narrow module-dark info box'><h3><a href='" + thefeeds[i].link + "'>" + thefeeds[i].title + "</a></h3>"
  rssoutput+= " <font color='black'>Posted on " + new Date(thefeeds[i].publishedDate).toDateString() + "</font></div>"
  }
  rssoutput+=""
  feedcontainer.innerHTML=rssoutput
  }
  else
  alert("Error fetching feeds!")
  }
 
  window.onload=function(){
  rssfeedsetup()
  }
 
  </script>
 
  {{ super() }}
  {% endblock %}
 
  {% set intro = g.site_intro_text %}
 
  <div class="module-content box">
  <header>
  {% if intro %}
  {{ h.render_markdown(intro) }}
  {% else %}
  <h1 class="page-heading">{{ _("Welcome to CKAN") }}</h1>
  <p>
  {% trans %}This is a nice introductory paragraph about CKAN or the site
  in general. We don't have any copy to go here yet but soon we will
  {% endtrans %}
  </p>
  {% endif %}
  </header>
  </div>
 
 
  {% set stats = h.get_site_statistics() %}
 
  <div class="box stats">
  <div class="inner">
  <h3>{{ _('{0} statistics').format(g.site_title) }}</h3>
  <ul>
  <li>
  <a href="{{ h.url_for(controller='package', action='search') }}">
  <b>{{ h.SI_number_span(stats.dataset_count) }}</b>
  {{ _('dataset') if stats.dataset_count == 1 else _('datasets') }}
  </a>
  </li>
  <li>
  <a href="{{ h.url_for(controller='organization', action='index') }}">
  <b>{{ h.SI_number_span(stats.organization_count) }}</b>
  {{ _('organisation') if stats.organization_count == 1 else _('organisations') }}
  </a>
  </li>
  <li>
  <a href="{{ h.url_for(controller='group', action='index') }}">
  <b>{{ h.SI_number_span(stats.group_count) }}</b>
  {{ _('group') if stats.group_count == 1 else _('groups') }}
  </a>
  </li>
  <!--<li>
  <a href="{{ h.url_for(controller='related', action='dashboard') }}">
  <b>{{ h.SI_number_span(stats.related_count) }}</b>
  {{ _('related item') if stats.related_count == 1 else _('related items') }}
  </a>
  </li>-->
  </ul>
  </div>
  </div>
 
  <div id="feeddiv">
  </div>
 
  <script type="text/javascript" src="//www.google.com/jsapi">
  </script>
  <script type="text/javascript">
  google.load("feeds", "1") //Load Google Ajax Feed API (version 1)
  </script>
 
  <script type="text/javascript">
 
  var feedcontainer=document.getElementById("feeddiv")
  var feedurl="http://www.finance.gov.au/taxonomy/term/1274/feed"
  var feedlimit=4
  var rssoutput="<div class='module module-shallow module-narrow module-dark info box' style='color:black'><h2>Latest data.gov.au News</h2><i class='ckan-icon ckan-icon-feed'></i><a href='http://www.finance.gov.au/taxonomy/term/1274/feed/'>&nbsp;Subscribe to the blog </a></div>"
 
 
  function rssfeedsetup(){
  var feedpointer=new google.feeds.Feed(feedurl) //Google Feed API method
  feedpointer.setNumEntries(feedlimit) //Google Feed API method
  feedpointer.load(displayfeed) //Google Feed API method
  }
 
  function displayfeed(result){
  if (!result.error){
  var thefeeds=result.feed.entries
  for (var i=0; i<thefeeds.length; i++) {
  rssoutput+="<div class='module module-shallow module-narrow module-dark info box'><h3><a href='" + thefeeds[i].link + "'>" + thefeeds[i].title + "</a></h3>"
  rssoutput+= " <font color='black'>Posted on " + new Date(thefeeds[i].publishedDate).toDateString() + "</font></div>"
  }
  rssoutput+=""
  feedcontainer.innerHTML=rssoutput
  }
  else
  alert("Error fetching feeds!")
  }
 
  window.onload=function(){
  rssfeedsetup()
  }
 
  </script>
 
{% ckan_extends %} {% ckan_extends %}
{% block primary_content_inner %} {% block primary_content_inner %}
{{ super() }} {{ super() }}
<div class="module-content"> <div class="module-content">
{{ h.disqus_comments() }} {{ h.disqus_comments() }}
</div> </div>
{% endblock %}  
{% block package_additional_info %}  
<section class="additional-info" prefix="dc: http://purl.org/dc/elements/1.1/ dcat: http://www.w3.org/ns/dcat#  
dcam: http://purl.org/dc/dcam/  
aglsterms: http://www.agls.gov.au/agls/terms/  
agentterms: http://www.agls.gov.au/agls/agentterms/  
availterms: http://www.agls.gov.au/agls/availterms/  
adminterms: http://www.agls.gov.au/agls/adminterms/  
dct: http://purl.org/dc/terms/">  
<h3>{{ _('Additional Info') }}</h3>  
<table class="table table-striped table-bordered table-condensed">  
<thead>  
<tr>  
<th scope="col">{{ _('Field') }}</th>  
<th scope="col">{{ _('Value') }}</th>  
</tr>  
</thead>  
<tbody>  
   
   
{# Add our custom field to the dataset read page. #}  
{% if pkg.get('metadata_created') %}  
<tr>  
<th scope="row" class="dataset-label">Date Published</th>  
<td class="dataset-details" property="dct:issued">{{ pkg.metadata_created.split("T")[0] }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('metadata_updated') %}  
<tr>  
<th scope="row" class="dataset-label">Date Updated</th>  
<td class="dataset-details" property="dct:updated">{{ pkg.metadata_updated.split("T")[0] }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('agency_program') %}  
<tr>  
<th scope="row" class="dataset-label">Agency Program</th>  
<td class="dataset-details"> {{ pkg.agency_program }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('url') %}  
<tr>  
<th scope="row" class="dataset-label">{{ _('Source') }}</th>  
<td class="dataset-details" property="dct:source">{{ h.link_to(pkg.get('url'),  
pkg.get('url'), rel='dct:source', target='_blank') }}  
</td>  
</tr>  
{% endif %}  
   
{% if pkg.get('contact_point') %}  
<tr>  
<th scope="row" class="dataset-label">Contact Point</th>  
<td class="dataset-details" property="dcat:contactPoint"> {{ h.mail_to(email_address=pkg.contact_point,  
name=pkg.contact_point) }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('spatial_coverage') %}  
   
<tr>  
<th scope="row" class="dataset-label">Geospatial Coverage</th>  
<td class="dataset-details" property="dct:spatial"> {{ pkg.spatial_coverage }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('granularity') %}  
   
<tr>  
<th scope="row" class="dataset-label">Data Granularity</th>  
<td class="dataset-details"> {{ pkg.granularity }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('jurisdiction') %}  
<tr>  
<th scope="row" class="dataset-label">Government Jurisdiction</th>  
<td class="dataset-details" property="aglsterms:AglsJuri"> {{ pkg.jurisdiction }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('temporal_coverage') %}  
<tr>  
<th scope="row" class="dataset-label">Temporal Coverage</th>  
<td class="dataset-details" property="dct:temporal"> {{ pkg.temporal_coverage }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('data_state') %}  
<tr>  
<th scope="row" class="dataset-label">Data State</th>  
<td class="dataset-details"> {{ pkg.data_state }}</td>  
</tr>  
{% endif %}  
{% if pkg.get('update_freq') %}  
   
<tr>  
<th scope="row" class="dataset-label">Update Frequency</th>  
<td class="dataset-details"> {{ pkg.update_freq }}</td>  
</tr>  
{% endif %}  
   
{% set email =h.get_last_active_user(c.pkg_dict['id']).get('email','') %}  
<tr>  
<th scope="row" class="dataset-label">{{ _('Maintainer') }}</th>  
<td class="dataset-details" property="dc:contributor">{{  
h.mail_to(email_address=(email or ' '), name=h.get_last_active_user(c.pkg_dict['id']).get("display_name",'')) }}  
</td>  
</tr>  
<tr>  
<th scope="row" class="dataset-label">Publisher/Agency</th>  
<td class="dataset-details" property="dc:publisher">{{ c.pkg_dict['organization']['title']}}  
</td>  
</tr>  
<tr>  
<th scope="row" class="dataset-label">Type</th>  
<td class="dataset-details" property="dc:type">Dataset</td>  
</tr>  
<tr>  
<th scope="row" class="dataset-label">Language</th>  
<td class="dataset-details" property="dc:language">English</td>  
</tr>  
   
</tbody>  
</table>  
</section>  
   
   
{% endblock %} {% endblock %}
   
{% block secondary_content %} {% block secondary_content %}
{{ super() }} {{ super() }}
   
{% set dataset_extent = h.get_pkg_dict_extra(c.pkg_dict, 'spatial', '') %} {% set dataset_extent = h.get_pkg_dict_extra(c.pkg_dict, 'spatial', '') %}
{% if dataset_extent %} {% if dataset_extent %}
{% snippet "spatial/snippets/dataset_map_sidebar.html", extent=dataset_extent %} {% snippet "spatial/snippets/dataset_map_sidebar.html", extent=dataset_extent %}
{% endif %} {% endif %}
   
{% endblock %} {% endblock %}
   
@prefix : <http://www.w3.org/2000/01/rdf-schema#> .  
@prefix dcat: <http://www.w3.org/ns/dcat#> .  
@prefix dct: <http://purl.org/dc/terms/> .  
@prefix foaf: <http://xmlns.com/foaf/0.1/> .  
@prefix owl: <http://www.w3.org/2002/07/owl#> .  
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .  
 
<${ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}>  
a dcat:Dataset;  
dct:description "${c.pkg_dict['notes']}";  
dct:identifier "${c.pkg_dict['name']}";  
dct:relation [  
rdf:value "";  
:label "change_note" ],  
[  
rdf:value "";  
:label "definition_note" ],  
[  
rdf:value "";  
:label "editorial_note" ],  
[  
rdf:value "";  
:label "example_note" ],  
[  
rdf:value "";  
:label "history_note" ],  
[  
rdf:value "";  
:label "scope_note" ],  
[  
rdf:value "";  
:label "skos_note" ],  
[  
rdf:value "";  
:label "temporal_granularity" ],  
[  
rdf:value "";  
:label "type_of_dataset" ],  
[  
rdf:value "";  
:label "update_frequency" ];  
dct:title "${c.pkg_dict['title']}";  
:label "${c.pkg_dict['name']}";  
= <urn:uuid:${c.pkg_dict['id']}>;  
foaf:homepage <http://127.0.0.1:5000/dataset/testt> .  
<?xml version="1.0" encoding="utf-8"?>  
<rdf:RDF  
xmlns:py="http://genshi.edgewall.org/"  
xmlns:foaf="http://xmlns.com/foaf/0.1/"  
xmlns:owl="http://www.w3.org/2002/07/owl#"  
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"  
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
xmlns:dcat="http://www.w3.org/ns/dcat#"  
xmlns:dcam="http://purl.org/dc/dcam/"  
xmlns:aglsterms="http://www.agls.gov.au/agls/terms/"  
xmlns:agentterms="http://www.agls.gov.au/agls/agentterms/"  
xmlns:availterms="http://www.agls.gov.au/agls/availterms/"  
xmlns:adminterms="http://www.agls.gov.au/agls/adminterms/"  
xmlns:dct="http://purl.org/dc/terms/"  
>  
<dcat:Dataset rdf:about="${ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}">  
<dct:identifier>${c.pkg_dict['name']}</dct:identifier>  
<dct:title>${c.pkg_dict['title']}</dct:title>  
<dct:landingPage  
rdf:resource="${ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True) }"/>  
<owl:sameAs rdf:resource="urn:uuid:${c.pkg_dict['id']}"/>  
<dct:type>Dataset</dct:type>  
<dct:description>${c.pkg_dict['notes']}</dct:description>  
<dct:issued>${c.pkg_dict['metadata_created']}</dct:issued>  
<dct:modified>${c.pkg_dict['metadata_modified']}</dct:modified>  
 
<py:choose>  
<py:when test="c.pkg_dict.get('license_url',None)">  
<dct:license rdf:resource="${c.pkg_dict['license_url']}"/>  
<dct:rights rdf:resource="${c.pkg_dict['license_url']}"/>  
</py:when>  
<py:otherwise>  
<dct:license>${c.pkg_dict['license_id']}</dct:license>  
<dct:rights>"${c.pkg_dict['license_id']}"</dct:rights>  
</py:otherwise>  
</py:choose>  
<py:for each="tag_dict in c.pkg_dict.get('tags',[])">  
<dcat:keyword>${ tag_dict["name"] }</dcat:keyword>  
</py:for>  
 
 
<py:for each="rsc_dict in c.pkg_dict['resources']">  
<dcat:distribution>  
<dcat:Distribution>  
<dct:title>${rsc_dict.get('name')}</dct:title>  
<owl:sameAs rdf:resource="urn:uuid:${rsc_dict.get('id')}"/>  
<dct:description>${rsc_dict.get('description')}</dct:description>  
<dcat:accessURL rdf:resource="${ rsc_dict.get('url') }"/>  
<dct:created>${rsc_dict.get('created')}</dct:created>  
<dct:modified>${rsc_dict.get('revision_timestamp')}</dct:modified>  
<dcat:byteSize py:if="rsc_dict.get('size')">${rsc_dict.get('size')}</dcat:byteSize>  
<dcat:mediaType py:if="rsc_dict.get('mimetype')">${rsc_dict.get('mimetype')}</dcat:mediaType>  
<dct:extent py:if="rsc_dict.get('size')">${rsc_dict.get('size')} bytes</dct:extent>  
<dct:format py:if="rsc_dict.get('format')">  
<dct:IMT>  
<rdf:value>${rsc_dict.get('format')}</rdf:value>  
<rdfs:label>${rsc_dict.get('format')}</rdfs:label>  
</dct:IMT>  
</dct:format>  
<dct:title py:if="rsc_dict.get('name')">${rsc_dict.get('name')}</dct:title>  
</dcat:Distribution>  
</dcat:distribution>  
</py:for>  
 
 
<!-- data.gov.au specific stuff below this line -->  
<dct:publisher py:if="c.pkg_dict.get('organization', None)">  
<rdf:Description>  
<foaf:name>${ c.pkg_dict['organization']['title'] }</foaf:name>  
</rdf:Description>  
</dct:publisher>  
<dct:creator py:if="c.pkg_dict.get('organization', None)">  
<rdf:Description>  
<foaf:name>${ c.pkg_dict['organization']['title'] }</foaf:name>  
</rdf:Description>  
</dct:creator>  
<dct:contributor>  
<rdf:Description>  
<foaf:name>${h.get_last_active_user(c.pkg_dict['id'])["display_name"]}</foaf:name>  
<foaf:mbox py:if="h.get_last_active_user(c.pkg_dict['id']).get('email', None)"  
rdf:resource="mailto:${h.get_last_active_user(c.pkg_dict['id'])['email']}"/>  
</rdf:Description>  
</dct:contributor>  
 
<py:for each="extra_dict in c.pkg_dict.get('extras',[])">  
<dct:relation>  
<rdf:Description>  
<rdfs:label>${extra_dict.get('key','')}</rdfs:label>  
<rdf:value>${extra_dict.get('value','')}</rdf:value>  
</rdf:Description>  
</dct:relation>  
</py:for>  
<dct:language>en</dct:language>  
<foaf:homepage  
rdf:resource="${ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}"/>  
<dcat:contactPoint py:if="c.pkg_dict.get('contact_point')">${c.pkg_dict.contact_point }</dcat:contactPoint>  
<py:choose>  
<py:when test="c.pkg_dict.get('spatial',None)">  
<dct:spatial py:if="c.pkg_dict.get('spatial')">${ c.pkg_dict.spatial }</dct:spatial>  
</py:when>  
<py:otherwise>  
<dct:spatial py:if="c.pkg_dict.get('spatial_coverage')">${ c.pkg_dict.spatial_coverage }</dct:spatial>  
</py:otherwise>  
</py:choose>  
<aglsterms:AglsJuri py:if="c.pkg_dict.get('jurisdiction')">${ c.pkg_dict.jurisdiction }</aglsterms:AglsJuri>  
<dct:temporal py:if="c.pkg_dict.get('temporal_coverage')">${ c.pkg_dict.get('temporal_coverage') }</dct:temporal>  
<dct:relation py:if="c.pkg_dict.get('data_state')">  
<rdf:Description>  
<rdfs:label>Data State</rdfs:label>  
<rdf:value>${ c.pkg_dict.get('data_state') }</rdf:value>  
</rdf:Description>  
</dct:relation>  
<dct:relation py:if="c.pkg_dict.get('update_freq')">  
<rdf:Description>  
<rdfs:label>Update Frequency</rdfs:label>  
<rdf:value>${ c.pkg_dict.get('update_freq') }</rdf:value>  
</rdf:Description>  
</dct:relation>  
<dct:relation py:if="c.pkg_dict.get('agency_program')">  
<rdf:Description>  
<rdfs:label>Agency Program</rdfs:label>  
<rdf:value>${ c.pkg_dict.get('agency_program') }</rdf:value>  
</rdf:Description>  
</dct:relation>  
<dct:relation py:if="c.pkg_dict.get('granularity')">  
<rdf:Description>  
<rdfs:label>Data Granularity</rdfs:label>  
<rdf:value>${ c.pkg_dict.get('granularity') }</rdf:value>  
</rdf:Description>  
</dct:relation>  
</dcat:Dataset>  
</rdf:RDF>  
 
{% ckan_extends %}  
 
{% block links -%}  
{{ super() }}  
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" />  
<link rel="schema.AGLSTERMS" href="http://www.agls.gov.au/agls/terms/" />  
 
{% endblock -%}  
 
{% block head_extras -%}  
{{ super() }}  
<meta name="DCTERMS.Language" scheme="RFC3066" content="en" />  
<meta name="DCTERMS.Type" scheme="AGLSTERMS.Document" content="dataset" />  
<meta name="DCTERMS.Creator" scheme="AGLSTERMS.AglsAgent" content="{{ pkg['organization']['title'] }}" />  
<meta name="DCTERMS.Modified" scheme="DCTERMS.ISO8601" content="{{pkg['metadata_modified']}}" />  
<meta name="DCTERMS.Published" scheme="DCTERMS.ISO8601" content="{{pkg['metadata_created']}}" />  
<meta name="DCTERMS.Source.URI" content="{{pkg.url}}" />  
<meta name="DCTERMS.License" content="{{pkg['license_url']}}" />  
<meta name="DCTERMS.Coverage.Temporal" content="{{pkg.temporal_coverage}}" />  
<meta name="DCTERMS.Coverage.Spatial" content="{{pkg.spatial_coverage}}" />  
<meta name="AGLSTERMS.Jurisdiction" scheme="AGLSTERMS.AglsJuri" content="{{pkg.jurisdiction}}" />  
<meta name="DCAT.Theme" scheme="VO" content="{% for x in pkg.groups %}{{x['title']}},{% endfor %}" />  
<meta name="DCTERMS.Identifier" content="{{h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}}" />  
<meta name="DCTERMS.Title" content="{{pkg['title']}}" />  
<meta name="DCTERMS.Description" scheme="" content="{{pkg['notes']}}" />  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
 
{% endblock -%}  
 
{% block package_info %}  
<div class="module context-info">  
<div class="module-content">  
<h1 class="heading" property="dc:title">{{ pkg.title or pkg.name }}</h1>  
<div class="nums">  
<dl>  
<dt>{{ _('Followers') }}</dt>  
<dd>{{ h.SI_number_span(h.get_action('dataset_follower_count', {'id': pkg.id})) }}</dd>  
</dl>  
</div>  
<div class="follow_button">  
{{ h.follow_button('dataset', pkg.name) }}  
</div>  
</div>  
</div>  
{% endblock %}  
 
 
{% ckan_extends %}  
 
{% block links -%}  
{{ super() }}  
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" />  
<link rel="schema.AGLSTERMS" href="http://www.agls.gov.au/agls/terms/" />  
 
{% endblock -%}  
 
{% block head_extras -%}  
{{ super() }}  
<meta name="DCTERMS.Language" scheme="RFC3066" content="en" />  
<meta name="DCTERMS.Type" scheme="AGLSTERMS.Document" content="dataset" />  
<meta name="DCTERMS.Creator" scheme="AGLSTERMS.AglsAgent" content="{{ pkg['organization']['title'] }}" />  
<meta name="DCTERMS.Modified" scheme="DCTERMS.ISO8601" content="{{res['revision_timestamp']}}" />  
<meta name="DCTERMS.Published" scheme="DCTERMS.ISO8601" content="{{res['created']}}" />  
<meta name="DCTERMS.Source.URI" content="{{pkg.url}}" />  
<meta name="DCTERMS.License" content="{{pkg['license_url']}}" />  
<meta name="DCTERMS.Coverage.Temporal" content="{{pkg.temporal_coverage}}" />  
<meta name="DCTERMS.Coverage.Spatial" content="{{pkg.spatial_coverage}}" />  
<meta name="AGLSTERMS.Jurisdiction" scheme="AGLSTERMS.AglsJuri" content="{{pkg.jurisdiction}}" />  
<meta name="DCAT.Theme" scheme="VO" content="{% for x in pkg.groups %}{{x['title']}},{% endfor %}" />  
<meta name="DCAT.byteSize" content="{{res.get('size')}}" />  
<meta name="DCAT.mediaType" content="{{res.get('mimetype')}}" />  
<meta name="DCTERMS.Identifier" content="{{res.get('url')}}" />  
<meta name="DCTERMS.Title" content="{{res['name']}}" />  
<meta name="DCTERMS.Description" scheme="" content="{{res['description']}}" />  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
<meta name="DCTERMS.Format" content="{{res.format}}" />  
<meta name="DCTERMS.File.Size" content="{{res.size}}" />  
 
{% endblock -%}  
 
 
 
{% ckan_extends %} {% ckan_extends %}
   
{% block package_basic_fields_org %}  
   
{{ super() }}  
   
   
{{ form.input('agency_program', label=_('Agency Program'), id='field-agency_program',  
placeholder=_('Name of the Agency Program that generated the data if relevant'),  
value=data.agency_program, error=errors.agency_program, classes=['control-medium']) }}  
   
{{ form.input('contact_point', label=_('Contact Point'), id='field-contact_point',  
placeholder=_('Email address for questions about content of dataset'),  
value=data.contact_point, error=errors.contact_point, classes=['control-medium']) }}  
   
{{ form.input('spatial_coverage', label=_('Geospatial Coverage'), id='field-spatial_coverage',  
placeholder=_('The geographical area covered by the data. Eg: Whole of Australia, New South Wales, Canberra'),  
value=data.spatial_coverage, error=errors.spatial_coverage, classes=['control-medium']) }}  
   
{{ form.input('granularity', label=_('Data Granularity'), id='field-granularity',  
placeholder=_('Granularity in time, place etc. Eg: incidents reports on daily basis by location.'),  
value=data.granularity, error=errors.granularity, classes=['control-medium']) }}  
   
{{ form.input('jurisdiction', label=_('Government Jurisdiction'), id='field-jurisdiction',  
placeholder=_('New South Wales, Glenorchy City Council, Federal'),  
value=data.jurisdiction, error=errors.jurisdiction, classes=['control-medium']) }}  
   
{{ form.input('temporal_coverage', label=_('Temporal Coverage'), id='field-temporal_coverage',  
placeholder=_('The timespan the dataset relates to: Current, 2008, 2008-2012, Jan 2012'),  
value=data.temporal_coverage, error=errors.temporal_coverage, classes=['control-medium']) }}  
   
{{ form.select('data_state', label=_('Data State'), options= [{'value': 'active', 'text': 'Active'}, {'value': 'inactive', 'text': 'Inactive'}],  
selected='Active', error=errors.data_state) }}  
   
{{ form.input('update_freq', label=_('Update Frequency'), id='field-update_freq',  
placeholder=_('How often the dataset is updated. Eg: Daily, Weekly, Never'),  
value=data.update_freq, error=errors.update_freq, classes=['control-medium']) }}  
   
{% endblock %}  
   
   
{% block package_basic_fields_license %} {% block package_basic_fields_license %}
<div class="control-group"> <div class="control-group">
{% set error = errors.license_id %} {% set error = errors.license_id %}
<label class="control-label" for="field-license">{{ _("License") }}</label> <label class="control-label" for="field-license">{{ _("License") }}</label>
<div class="controls"> <div class="controls">
<select id="field-license" name="license_id" data-module="autocomplete"> <select id="field-license" name="license_id" data-module="autocomplete">
{% for license_desc, license_id in licenses|sort if license_desc %} {% for license_desc, license_id in licenses|sort if license_desc %}
{# Make cc-by the default value for data.gov.au #} {# Make cc-by the default value for data.gov.au #}
<option value="{{ license_id }}" {% if data.get('license_id', 'cc-by') == license_id %}selected="selected"{% endif %}>{{ license_desc }}</option> <option value="{{ license_id }}" {% if data.get('license_id', 'cc-by') == license_id %}selected="selected"{% endif %}>{{ license_desc }}</option>
{% endfor %} {% endfor %}
</select> </select>
{% if error %}<span class="error-block">{{ error }}</span>{% endif %} {% if error %}<span class="error-block">{{ error }}</span>{% endif %}
<span class="info-block info-inline"> <span class="info-block info-inline">
<i class="icon-info-sign"></i> <i class="icon-info-sign"></i>
{% trans %} {% trans %}
License definitions and additional information can be found License definitions and additional information can be found
at <a href="http://opendefinition.org/licenses/">opendefinition.org</a> at <a href="http://opendefinition.org/licenses/">opendefinition.org</a>
{% endtrans %} {% endtrans %}
</span> </span>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
   
{% ckan_extends %} {% ckan_extends %}
   
{# Remove 'free extras' from the package form. If you're using {# Remove 'free extras' from the package form. If you're using
convert_to/from_extras() as we are with our 'custom_text' field below then convert_to/from_extras() as we are with our 'custom_text' field below then
you need to remove free extras from the form, or editing your custom field you need to remove free extras from the form, or editing your custom field
won't work. #} won't work. #}
{% block custom_fields %} {% block custom_fields %}
{% endblock %} {% endblock %}
   
{# https://github.com/okfn/ckan/blob/master/ckan/templates/macros/form.html documents the macros for fields #} {# https://github.com/okfn/ckan/blob/master/ckan/templates/macros/form.html documents the macros for fields #}
   
{% block package_metadata_fields %}  
{{ form.input('url', label=_('Source URL'), id='field-url',  
placeholder=_('URL where dataset came from or more information can be obtained'),  
value=data.url, error=errors.url, classes=['control-medium']) }}  
{{ super() }}  
   
{% endblock %}  
   
{% block package_metadata_author %}  
{% endblock %}  
   
{% block package_metadata_fields_maintainer %}  
{% endblock %}  
   
{% block dataset_fields %} {% block dataset_fields %}
{% if data.groups %} {% if data.groups %}
<div class="control-group"> <div class="control-group">
<label class="control-label">Groups/Themes</label> <label class="control-label">Groups/Themes</label>
<div class="controls"> <div class="controls">
{% for group in data.groups %} {% for group in data.groups %}
<label class="checkbox" for="field-group-{{ loop.index0 }}"> <label class="checkbox" for="field-group-{{ loop.index0 }}">
<input id="field-group-{{ loop.index0 }}" type="checkbox" name="groups__{{ loop.index0 }}__id" value="{{ group.id }}" checked="checked" /> <input id="field-group-{{ loop.index0 }}" type="checkbox" name="groups__{{ loop.index0 }}__id" value="{{ group.id }}" checked="checked" />
{{ group.title }} {{ group.title }}
</label> </label>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% set group_name = 'groups__%s__id' % data.groups|length %} {% set group_name = 'groups__%s__id' % data.groups|length %}
{% set group_attrs = {'data-module': 'autocomplete', 'data-module-source': '/api/2/util/group/autocomplete?q=?', 'data-module-key': 'id', 'data-module-label': 'title'} %} {% set group_attrs = {'data-module': 'autocomplete', 'data-module-source': '/api/2/util/group/autocomplete?q=?', 'data-module-key': 'id', 'data-module-label': 'title'} %}
{{ form.input(group_name, label=_('Add Group/Theme'), id="field-group", value=data[group_name], classes=['control-medium'], attrs=group_attrs) }} {{ form.input(group_name, label=_('Add Group/Theme'), id="field-group", value=data[group_name], classes=['control-medium'], attrs=group_attrs) }}
{% endblock %} {% endblock %}
   
{% ckan_extends %}  
 
{% set url = h.url_for(controller='package', action='resource_read', id=pkg.name, resource_id=res.id) %}  
<li class="resource-item" vocab="http://www.w3.org/ns/dcat#"  
typeof="Distribution">  
{% block resource_item_title %}  
<a class="heading" href="{{ url }}" title="{{ res.name or res.description }}" property="title">  
{{ h.resource_display_name(res) | truncate(50) }}<span class="format-label" property="dc:format" data-format="{{ res.format.lower() or 'data' }}">{{ res.format }}</span>  
{{ h.popular('views', res.tracking_summary.total, min=10) }}  
</a>  
{% endblock %}  
<p class="description" property="description">  
{% if res.description %}  
{{ h.markdown_extract(res.description, extract_length=80) }}  
{% else %}  
<span class="empty">{{ _('No description for this resource') }}</span>  
{% endif %}  
</p>  
{% block resource_item_explore %}  
<div class="dropdown btn-group">  
<a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">  
<i class="icon-share-alt"></i>  
{{ _('Explore') }}  
<span class="caret"></span>  
</a>  
<ul class="dropdown-menu">  
{% block resource_item_explore_links %}  
<li>  
<a href="{{ url }}" property="accessURL">  
{% if res.can_be_previewed %}  
<i class="icon-bar-chart"></i>  
{{ _('Preview') }}  
{% else %}  
<i class="icon-info-sign"></i>  
{{ _('More information') }}  
{% endif %}  
</a>  
</li>  
<li>  
<a href="{{ res.url }}" class="resource-url-analytics" target="_blank" property="accessURL">  
{% if res.can_be_previewed %}  
<i class="icon-download"></i>  
{{ _('Download') }}  
{% else %}  
<i class="icon-external-link"></i>  
{{ _('Go to resource') }}  
{% endif %}  
</a>  
</li>  
{% endblock %}  
</ul>  
</div>  
{% endblock %}  
</li>