Initial commit
Initial commit

file:b/.gitignore (new)
--- /dev/null
+++ b/.gitignore
@@ -1,1 +1,10 @@
-
+*.egg-info
+*.pyc
+*.swp
+*.swo
+*~
+#*
+.#*
+build/
+dist/
+distribute-*

file:b/README.rst (new)
--- /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">
+