Initial commit
--- /dev/null
+++ b/.gitignore
@@ -1,1 +1,10 @@
-
+*.egg-info
+*.pyc
+*.swp
+*.swo
+*~
+#*
+.#*
+build/
+dist/
+distribute-*
--- /dev/null
+++ b/README.rst
@@ -1,1 +1,17 @@
+This CKAN Extension customises a CKAN instance for the hosting of data.gov.au.
+It comprises:
+
+ * A path to local customisations of the core templates to include AGLS/Dublin Core minimum metadata
+ * A custom n3/rdf output format
+
+Installation
+============
+
+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
+
+Then activate it by setting ``ckan.plugins = datagovau`` in your main ``ini``-file.
+
+
--- /dev/null
+++ b/ckanext/__init__.py
@@ -1,1 +1,8 @@
+# this is a namespace package
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
--- /dev/null
+++ b/ckanext/agls/__init__.py
--- /dev/null
+++ b/ckanext/agls/plugin.py
@@ -1,1 +1,128 @@
+import logging
+import ckan.plugins as plugins
+import ckan.lib as lib
+import ckan.lib.dictization.model_dictize as model_dictize
+import ckan.plugins.toolkit as tk
+import ckan.model as model
+from pylons import config
+
+from sqlalchemy import orm
+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})
+
+class AGLSPlugin(plugins.SingletonPlugin,
+ tk.DefaultDatasetForm):
+ '''An example IDatasetForm CKAN plugin.
+
+ Uses a tag vocabulary to add a custom metadata field to datasets.
+
+ '''
+ plugins.implements(plugins.IConfigurer, inherit=False)
+ plugins.implements(plugins.IDatasetForm, inherit=False)
+ plugins.implements(plugins.ITemplateHelpers, inherit=False)
+
+ def update_config(self, config):
+ # Add this plugin's templates dir to CKAN's extra_template_paths, so
+ # that CKAN will use this plugin's custom templates.
+ # here = os.path.dirname(__file__)
+ # rootdir = os.path.dirname(os.path.dirname(here))
+
+ tk.add_template_directory(config, 'templates')
+ tk.add_public_directory(config, 'theme/public')
+ tk.add_resource('theme/public', 'ckanext-agls')
+ # config['licenses_group_url'] = 'http://%(ckan.site_url)/licenses.json'
+
+ def get_helpers(self):
+ return {'get_last_active_user': get_last_active_user}
+
+ 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(AGLSPlugin, self).create_package_schema()
+ schema = self._modify_package_schema(schema)
+ return schema
+
+ def update_package_schema(self):
+ schema = super(AGLSPlugin, self).update_package_schema()
+ schema = self._modify_package_schema(schema)
+ return schema
+
+ def show_package_schema(self):
+ schema = super(AGLSPlugin, 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
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/read.html
@@ -1,1 +1,124 @@
+{% ckan_extends %}
+{% 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 %}
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/read.rdf
@@ -1,1 +1,133 @@
+<?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>
+
--- /dev/null
+++ b/ckanext/agls/templates/package/read_base.html
@@ -1,1 +1,47 @@
+{% 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 %}
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/resource_read.html
@@ -1,1 +1,35 @@
+{% 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 -%}
+
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/snippets/package_basic_fields.html
@@ -1,1 +1,42 @@
+{% 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 %}
+
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/snippets/package_metadata_fields.html
@@ -1,1 +1,27 @@
+{% ckan_extends %}
+{# 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
+you need to remove free extras from the form, or editing your custom field
+won't work. #}
+{% block custom_fields %}
+{% endblock %}
+
+{# 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 %}
+
+{# hide author/maintainer fields #}
+{% block package_metadata_author %}
+{% endblock %}
+
+{% block package_metadata_fields_maintainer %}
+{% endblock %}
+
+
--- /dev/null
+++ b/ckanext/agls/templates/package/snippets/resource_item.html
@@ -1,1 +1,54 @@
+{% 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">
+