Skip to content

Commit

Permalink
Merge pull request #1200 from okfn/1200-datastore-read-only
Browse files Browse the repository at this point in the history
Datapusher Core Extension
  • Loading branch information
johnglover committed Oct 25, 2013
2 parents f67fe41 + 8cf3fec commit e4fc2fa
Show file tree
Hide file tree
Showing 43 changed files with 880 additions and 395 deletions.
5 changes: 3 additions & 2 deletions ckan/config/deployment.ini_tmpl
Expand Up @@ -79,6 +79,7 @@ ckan.site_id = default
## Plugins Settings

# Note: Add ``datastore`` to enable the CKAN DataStore
# Add ``datapusher`` to enable DataPusher
# Add ``pdf_preview`` to enable the resource preview for PDFs
# Add ``resource_proxy`` to enable resorce proxying and get around the
# same origin policy
Expand Down Expand Up @@ -146,8 +147,8 @@ ckan.feeds.author_link =

# Make sure you have set up the DataStore

datapusher.formats = csv
datapusher.url = http://datapusher.ckan.org/
ckan.datapusher.formats = csv
ckan.datapusher.url = http://datapusher.ckan.org/

## Activity Streams Settings

Expand Down
4 changes: 2 additions & 2 deletions ckan/logic/action/get.py
Expand Up @@ -1868,11 +1868,11 @@ def task_status_show(context, data_dict):

context['task_status'] = task_status

_check_access('task_status_show', context, data_dict)

if task_status is None:
raise NotFound

_check_access('task_status_show', context, data_dict)

task_status_dict = model_dictize.task_status_dictize(task_status, context)
return task_status_dict

Expand Down
1 change: 1 addition & 0 deletions ckan/logic/schema.py
Expand Up @@ -85,6 +85,7 @@ def default_resource_schema():
'cache_last_updated': [ignore_missing, isodate],
'webstore_last_updated': [ignore_missing, isodate],
'tracking_summary': [ignore_missing],
'datastore_active': [ignore],
'__extras': [ignore_missing, extras_unicode_convert, keep_extras],
}

Expand Down
4 changes: 2 additions & 2 deletions ckan/model/meta.py
Expand Up @@ -162,5 +162,5 @@ def engine_is_sqlite(sa_engine=None):
def engine_is_pg(sa_engine=None):
# Returns true iff the engine is connected to a postgresql database.
# According to http://docs.sqlalchemy.org/en/latest/core/engines.html#postgresql
# all Postgres driver names start with `postgresql`
return (sa_engine or engine).url.drivername.startswith('postgresql')
# all Postgres driver names start with `postgres`
return (sa_engine or engine).url.drivername.startswith('postgres')
11 changes: 10 additions & 1 deletion ckan/plugins/core.py
Expand Up @@ -18,7 +18,7 @@
'PluginNotFoundException', 'Plugin', 'SingletonPlugin',
'load', 'load_all', 'unload', 'unload_all',
'get_plugin', 'plugins_update',
'use_plugin',
'use_plugin', 'plugin_loaded',
]

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -210,6 +210,15 @@ def unload(*plugins):
plugins_update()


def plugin_loaded(name):
'''
See if a particular plugin is loaded.
'''
if name in _PLUGINS:
return True
return False


def find_system_plugins():
'''
Return all plugins in the ckan.system_plugins entry point group.
Expand Down
1 change: 0 additions & 1 deletion ckan/plugins/interfaces.py
Expand Up @@ -443,7 +443,6 @@ def before_view(self, pkg_dict):
class IResourceController(Interface):
"""
Hook into the resource controller.
(see IGroupController)
"""

def before_show(self, resource_dict):
Expand Down
1 change: 1 addition & 0 deletions ckan/public/base/javascript/main.js
Expand Up @@ -36,6 +36,7 @@ this.ckan = this.ckan || {};
ckan.i18n.load(data);
ckan.module.initialize();
});
jQuery('[data-target="popover"]').popover();
};

/* Returns a full url for the current site with the provided path appended.
Expand Down
18 changes: 18 additions & 0 deletions ckan/public/base/less/activity.less
Expand Up @@ -56,6 +56,9 @@
.border-radius(100px);
.box-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
}
&.no-avatar p {
margin-left: 40px;
}
}
.load-less {
margin-bottom: 15px;
Expand All @@ -76,11 +79,26 @@
float: right;
text-decoration: none;
}
.popover-content {
font-size: @baseFontSize;
line-height: @baseLineHeight;
color: @layoutTextColor;
word-break: break-all;
dl {
margin: 0;
dd {
margin-left: 0;
margin-bottom: 10px;
}
}
}
}

// colors
.activity .item {
& .icon { background-color: @activityColorBlank; } // Non defined
&.failure .icon { background-color: @activityColorDelete; }
&.success .icon { background-color: @activityColorNew; }
&.added-tag .icon { background-color: spin(@activityColorNew, 60); }
&.changed-group .icon { background-color: @activityColorModify; }
&.changed-package .icon { background-color: spin(@activityColorModify, 20); }
Expand Down
1 change: 1 addition & 0 deletions ckan/public/base/less/ckan.less
Expand Up @@ -20,6 +20,7 @@
@import "activity.less";
@import "dropdown.less";
@import "dashboard.less";
@import "datapusher.less";

body {
// Using the masthead/footer gradient prevents the color from changing
Expand Down
18 changes: 18 additions & 0 deletions ckan/public/base/less/datapusher.less
@@ -0,0 +1,18 @@
.datapusher-status-link:hover {
text-decoration: none;
}

.datapusher-status {
&.status-unknown {
color: #bbb;
}
&.status-pending {
color: #FFCC00;
}
&.status-error {
color: red;
}
&.status-complete {
color: #009900;
}
}
5 changes: 4 additions & 1 deletion ckan/templates/package/base_form_page.html
Expand Up @@ -2,8 +2,11 @@

{% block primary_content %}
<section class="module">
{% block page_header %}{% endblock %}
<div class="module-content">
{% block form %}{{ c.form | safe }}{% endblock %}
{% block primary_content_inner %}
{% block form %}{{ c.form | safe }}{% endblock %}
{% endblock %}
</div>
</section>
{% endblock %}
Expand Down
4 changes: 1 addition & 3 deletions ckan/templates/package/edit.html
@@ -1,7 +1,5 @@
{% extends 'package/edit_base.html' %}

{% block subtitle %}{{ _('Edit') }} - {{ h.dataset_display_name(pkg) }}{% endblock %}

{% block primary_content_inner %}
{% block form %}{{ c.form | safe }}{% endblock %}
{% block form %}{{ c.form | safe }}{% endblock %}
{% endblock %}
1 change: 1 addition & 0 deletions ckan/templates/package/edit_base.html
@@ -1,6 +1,7 @@
{% extends 'package/base.html' %}

{% set pkg = c.pkg_dict %}
{% set pkg_dict = c.pkg_dict %}

{% block breadcrumb_content_selected %}{% endblock %}

Expand Down
7 changes: 1 addition & 6 deletions ckan/templates/package/new_resource.html
Expand Up @@ -13,12 +13,7 @@
{% block form %}{% snippet 'package/snippets/resource_form.html', data=data, errors=errors, error_summary=error_summary, include_metadata=false, pkg_name=pkg_name, stage=stage, allow_upload=g.ofs_impl and logged_in %}{% endblock %}

{% block secondary_content %}
<section class="module module-narrow module-shallow">
<h2 class="module-heading"><i class="icon-info-sign"></i> {{ _('What\'s a resource?') }}</h2>
<div class="module-content">
<p>{{ _('A resource can be any file or link to a file containing useful data.') }}</p>
</div>
</section>
{% snippet 'package/snippets/resource_help.html' %}
{% endblock %}

{% block scripts %}
Expand Down
12 changes: 12 additions & 0 deletions ckan/templates/package/new_resource_not_draft.html
Expand Up @@ -3,6 +3,18 @@
{% block subtitle %}{{ _('Add resource') }} - {{ h.dataset_display_name(pkg) }}{% endblock %}
{% block form_title %}{{ _('Add resource') }}{% endblock %}

{% block breadcrumb_content %}
<li class="active"><a href="#">{{ _('Add New Resource') }}</a></li>
{% endblock %}

{% block form %}
{% snippet 'package/snippets/resource_form.html', data=data, errors=errors, error_summary=error_summary, include_metadata=false, pkg_name=pkg_name, stage=stage, allow_upload=g.ofs_impl and logged_in %}
{% endblock %}

{% block content_primary_nav %}
<li class="active"><a href="#"><i class="icon-edit"></i> {{ _('New resource') }}</a></li>
{% endblock %}

{% block secondary_content %}
{% snippet 'package/snippets/resource_help.html' %}
{% endblock %}
68 changes: 68 additions & 0 deletions ckan/templates/package/resource_data.html
@@ -0,0 +1,68 @@
{% extends "package/resource_edit_base.html" %}

{% block subtitle %}{{ h.dataset_display_name(pkg) }} - {{ h.resource_display_name(res) }}{% endblock %}

{% block primary_content_inner %}

{% set action = h.url_for(controller='ckanext.datapusher.plugin:ResourceDataController', action='resource_data', id=pkg.name, resource_id=res.id) %}
{% set show_table = true %}

<form method="post" action="{{ action }}" >
<button class="btn btn-primary" name="save" type="submit">
<i class="icon-cloud-upload"></i> {{ _('Upload Data') }}
</button>
</form>

{% if status.error and status.error.message %}
{% set show_table = false %}
<div class="alert alert-error">
<strong>{{ _('Upload error:') }}</strong> {{ status.error.message }}
</div>
{% elif status.task_info and status.task_info.error %}
{% set show_table = false %}
<div class="alert alert-error">
<strong>{{ _('Error:') }}</strong> {{ status.task_info.error }}
</div>
{% endif %}

<table class="table table-bordered">
<colgroup>
<col width="150">
<col>
</colgroup>
<tr>
<th>{{ _('Status') }}</th>
<td>{{ status.status.capitalize() if status.status else _('Not Uploaded Yet') }}</td>
</tr>
<tr>
<th>{{ _('Last updated') }}</th>
<td>{{ h.time_ago_from_timestamp(status.last_updated) if status.status else _('Never') }}</td>
</tr>
</table>

{% if status.status and status.task_info and show_table %}
<h3>{{ _('Upload Log') }}</h3>
<ul class="activity">
{% for item in status.task_info.logs %}
{% set icon = 'ok' if item.level == 'INFO' else 'exclamation' %}
{% set class = ' failure' if icon == 'exclamation' else ' success' %}
{% set popover_content = 'test' %}
<li class="item no-avatar{{ class }}">
<i class="icon icon-{{ icon }}"></i>
<p>
{{ item.message | urlize }}<br>
<span class="date">
{{ h.time_ago_from_timestamp(item.timestamp) }}
<a href="#" data-target="popover" data-content="<dl>{% for key, value in item.iteritems() %}<dt>{{ key }}</dt><dd>{{ value }}</dd>{% endfor %}</dl>" data-html="true">more info</a>
</span>
</p>
</li>
{% endfor %}
<li class="item no-avatar">
<i class="icon icon-info"></i>
<p class="muted">{{ _('End of log') }}</p>
</li>
</ul>
{% endif %}

{% endblock %}
4 changes: 1 addition & 3 deletions ckan/templates/package/resource_edit.html
@@ -1,9 +1,7 @@
{% extends "package/resource_edit_base.html" %}

{% set res = c.resource %}

{% block subtitle %}{{ _('Edit') }} - {{ h.resource_display_name(res) }} - {{ h.dataset_display_name(pkg) }}{% endblock %}

{% block form %}
{{ h.snippet('package/snippets/resource_edit_form.html', data=data, errors=errors, error_summary=error_summary, pkg_name=pkg.name, form_action=c.form_action, allow_upload=g.ofs_impl and logged_in) }}
{% snippet 'package/snippets/resource_edit_form.html', data=data, errors=errors, error_summary=error_summary, pkg_name=pkg.name, form_action=c.form_action, allow_upload=g.ofs_impl and logged_in %}
{% endblock %}
18 changes: 12 additions & 6 deletions ckan/templates/package/resource_edit_base.html
@@ -1,33 +1,39 @@
{% extends "package/base.html" %}

{% set logged_in = true if c.userobj else false %}
{% set res = c.resource %}

{% block breadcrumb_content_selected %}{% endblock %}

{% block breadcrumb_content %}
{{ super() }}
<li>{% link_for h.resource_display_name(res)|truncate(30), controller='package', action='resource_read', id=pkg.name, resource_id=res.id %}</li>
<li class="active"><a href="">Edit</a></li>
<li class="active"><a href="">{{ _('Edit') }}</a></li>
{% endblock %}

{% block content_action %}
{% link_for _('All resources'), controller='package', action='resources', id=pkg.name, class_='btn', icon='arrow-left' %}
{% link_for _('View resource'), controller='package', action='resource_read', id=pkg.name, resource_id=res.id, class_='btn', icon='eye-open' %}
{% if res %}
{% link_for _('View resource'), controller='package', action='resource_read', id=pkg.name, resource_id=res.id, class_='btn', icon='eye-open' %}
{% endif %}
{% endblock %}

{% block content_primary_nav %}
{{ h.build_nav_icon('resource_edit', _('Edit resource'), id=pkg.name, resource_id=res.id) }}
{% endblock %}

{% block secondary_content %}
{% snippet 'package/snippets/resource_info.html', res=res %}
{% if 'datapusher' in g.plugins %}
{{ h.build_nav_icon('resource_data', _('Resource Data'), id=pkg.name, resource_id=res.id) }}
{% endif %}
{% endblock %}

{% block primary_content_inner %}
<h1 class="hide-heading">{% block form_title %}{{ _('Edit resource') }}{% endblock %}</h1>
{% block form %}{% endblock %}
{% endblock %}

{% block secondary_content %}
{% snippet 'package/snippets/resource_info.html', res=res %}
{% endblock %}

{% block scripts %}
{{ super() }}
{% resource 'vendor/fileupload' %}
Expand Down
34 changes: 19 additions & 15 deletions ckan/templates/package/snippets/info.html
Expand Up @@ -8,19 +8,23 @@
{% snippet "package/snippets/info.html", pkg=pkg %}

#}
<div class="module context-info">
<div class="module-content">
<h1 class="heading">{{ 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>
{% if not hide_follow_button %}
<div class="follow_button">
{{ h.follow_button('dataset', pkg.name) }}
{% if pkg %}
<section class="module module-narrow">
<div class="module context-info">
<div class="module-content">
<h1 class="heading">{{ 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>
{% if not hide_follow_button %}
<div class="follow_button">
{{ h.follow_button('dataset', pkg.name) }}
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
</section>
{% endif %}
6 changes: 6 additions & 0 deletions ckan/templates/package/snippets/resource_help.html
@@ -0,0 +1,6 @@
<section class="module module-narrow module-shallow">
<h2 class="module-heading"><i class="icon-info-sign"></i> {{ _('What\'s a resource?') }}</h2>
<div class="module-content">
<p>{{ _('A resource can be any file or link to a file containing useful data.') }}</p>
</div>
</section>

0 comments on commit e4fc2fa

Please sign in to comment.