Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

A support for comments on data requests #6

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 68 additions & 36 deletions ckanext/ytp/comments/controller.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import helpers
import logging

from ckan.lib.base import h, BaseController, render, abort, request
Expand All @@ -11,44 +12,54 @@


class CommentController(BaseController):
def add(self, dataset_id):
return self._add_or_reply(dataset_id)
def add(self, dataset_id, content_type='dataset'):
return self._add_or_reply('new', dataset_id, content_type)

def edit(self, dataset_id, comment_id):
def edit(self, content_type, content_item_id, comment_id):

context = {'model': model, 'user': c.user}
data_dict = {'id': content_item_id}

# Auth check to make sure the user can see this package

data_dict = {'id': dataset_id}
check_access('package_show', context, data_dict)
# Auth check to make sure the user can see this content item
helpers.check_content_access(content_type, context, data_dict)

try:
c.pkg_dict = get_action('package_show')(context, {'id': dataset_id})
c.pkg = context['package']
# Load the content item
helpers.get_content_item(content_type, context, data_dict)
except:
abort(403)

if request.method == 'POST':
data_dict = clean_dict(unflatten(
tuplize_dict(parse_params(request.POST))))
data_dict['id'] = comment_id
data_dict['content_type'] = content_type
data_dict['content_item_id'] = content_item_id
success = False
try:
res = get_action('comment_update')(context, data_dict)
get_action('comment_update')(context, data_dict)
success = True
except ValidationError, ve:
log.debug(ve)
if ve.error_dict and ve.error_dict.get('message'):
msg = ve.error_dict['message']
else:
msg = str(ve)
h.flash_error(msg)
except Exception, e:
log.debug(e)
abort(403)

if success:
h.redirect_to(str('/dataset/%s#comment_%s' % (c.pkg.name, res['id'])))
h.redirect_to(
helpers.get_redirect_url(
content_type,
content_item_id if content_type == 'datarequest' else c.pkg.name,
'comment_' + str(comment_id) if success else 'edit_' + str(comment_id)
))

return render("package/read.html")
return helpers.render_content_template(content_type)

def reply(self, dataset_id, parent_id):
def reply(self, content_type, dataset_id, parent_id):
c.action = 'reply'

try:
Expand All @@ -59,66 +70,87 @@ def reply(self, dataset_id, parent_id):
except:
abort(404)

return self._add_or_reply(dataset_id)
return self._add_or_reply('reply', dataset_id, content_type, parent_id)

def _add_or_reply(self, dataset_id):
def _add_or_reply(self, comment_type, content_item_id, content_type, parent_id=None):
"""
Allows the user to add a comment to an existing dataset
"""
content_type = 'dataset' if 'content_type' not in vars() else content_type

context = {'model': model, 'user': c.user}

# Auth check to make sure the user can see this package
data_dict = {'id': content_item_id}

data_dict = {'id': dataset_id}
check_access('package_show', context, data_dict)
# Auth check to make sure the user can see this content item
helpers.check_content_access(content_type, context, data_dict)

try:
c.pkg_dict = get_action('package_show')(context, {'id': dataset_id})
c.pkg = context['package']
# Load the content item
helpers.get_content_item(content_type, context, data_dict)
except:
abort(403)

if request.method == 'POST':
data_dict = clean_dict(unflatten(
tuplize_dict(parse_params(request.POST))))
data_dict['parent_id'] = c.parent.id if c.parent else None
data_dict['url'] = '/dataset/%s' % c.pkg.name
data_dict['url'] = '/%s/%s' % (content_type, content_item_id if content_type == 'datarequest' else c.pkg.name)
success = False
try:
res = get_action('comment_create')(context, data_dict)
success = True
except ValidationError, ve:
log.debug(ve)
if ve.error_dict and ve.error_dict.get('message'):
msg = ve.error_dict['message']
else:
msg = str(ve)
h.flash_error(msg)
except Exception, e:
log.debug(e)
abort(403)

if success:
h.redirect_to(str('/dataset/%s#comment_%s' % (c.pkg.name, res['id'])))
h.redirect_to(
helpers.get_redirect_url(
content_type,
content_item_id if content_type == 'datarequest' else c.pkg.name,
'comment_' + str(res['id']) if success else ('comment_form' if comment_type == 'new' else 'reply_' + str(parent_id))
))

return render("package/read.html")
return helpers.render_content_template(content_type)

def delete(self, dataset_id, comment_id):
def delete(self, content_type, content_item_id, comment_id):

context = {'model': model, 'user': c.user}

# Auth check to make sure the user can see this package
data_dict = {'id': content_item_id}

data_dict = {'id': dataset_id}
check_access('package_show', context, data_dict)
# Auth check to make sure the user can see this content item
helpers.check_content_access(content_type, context, data_dict)

try:
c.pkg_dict = get_action('package_show')(context, {'id': dataset_id})
c.pkg = context['package']
# Load the content item
helpers.get_content_item(content_type, context, data_dict)
except:
abort(403)

try:
data_dict = {'id': comment_id}
data_dict = {'id': comment_id, 'content_type': content_type, 'content_item_id': content_item_id}
get_action('comment_delete')(context, data_dict)
except Exception, e:
log.debug(e)

h.redirect_to(str('/dataset/%s' % c.pkg.name))

return render("package/read.html")
if e.error_dict and e.error_dict.get('message'):
msg = e.error_dict['message']
else:
msg = str(e)
h.flash_error(msg)

h.redirect_to(
helpers.get_redirect_url(
content_type,
content_item_id if content_type == 'datarequest' else c.pkg.name,
'comment_' + str(comment_id)
))

return helpers.render_content_template(content_type)
47 changes: 47 additions & 0 deletions ckanext/ytp/comments/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import ckan.plugins.toolkit as toolkit

from ckan.common import c, config
from ckan.lib.base import render
from ckan.logic import check_access, get_action
from ckanext.datarequests import actions


def get_content_item(content_type, context, data_dict):
if content_type == 'datarequest':
c.datarequest = actions.show_datarequest(context, data_dict)
else:
data_dict['include_tracking'] = True
c.pkg_dict = get_action('package_show')(context, data_dict)
c.pkg = context['package']


def check_content_access(content_type, context, data_dict):
check_access('show_datarequest' if content_type == 'datarequest' else 'package_show', context, data_dict)


def get_redirect_url(content_type, content_item_id, anchor):
return '/%s/%s#%s' % (
'datarequest/comment' if content_type == 'datarequest' else 'dataset',
content_item_id,
anchor
)


def render_content_template(content_type):
return render(
'datarequests/comment.html' if content_type == 'datarequest' else "package/read.html"
)


def get_org_id(content_type):
return c.datarequest['organization_id'] if content_type == 'datarequest' else c.pkg.owner_org


def ytp_comments_enabled():
return "ytp_comments" in config.get('ckan.plugins', False)


def get_datarequest_comments_badge(datarequest_id):
return toolkit.render_snippet('datarequests/snippets/badge.html',
{'comments_count': toolkit.h.get_comment_count_for_dataset(datarequest_id,
'datarequest')})
28 changes: 15 additions & 13 deletions ckanext/ytp/comments/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import ckan.plugins as plugins
import ckan.model as model
import helpers
from ckan.logic import get_action
from ckan.plugins import implements, toolkit

import logging
Expand Down Expand Up @@ -27,7 +30,10 @@ def update_config(self, config):
def get_helpers(self):
return {
'get_comment_thread': self._get_comment_thread,
'get_comment_count_for_dataset': self._get_comment_count_for_dataset
'get_comment_count_for_dataset': self._get_comment_count_for_dataset,
'get_org_id': helpers.get_org_id,
'ytp_comments_enabled': helpers.ytp_comments_enabled,
'get_datarequest_comments_badge': helpers.get_datarequest_comments_badge,
}

def get_actions(self):
Expand Down Expand Up @@ -66,21 +72,17 @@ def before_map(self, map):
/dataset/NAME/comments/add
"""
controller = 'ckanext.ytp.comments.controller:CommentController'
map.connect('/dataset/{dataset_id}/comments/add', controller=controller, action='add')
map.connect('/dataset/{dataset_id}/comments/{comment_id}/edit', controller=controller, action='edit')
map.connect('/dataset/{dataset_id}/comments/{parent_id}/reply', controller=controller, action='reply')
map.connect('/dataset/{dataset_id}/comments/{comment_id}/delete', controller=controller, action='delete')
map.connect('/{content_type}/{dataset_id}/comments/add', controller=controller, action='add')
map.connect('/{content_type}/{content_item_id}/comments/{comment_id}/edit', controller=controller, action='edit')
map.connect('/{content_type}/{dataset_id}/comments/{parent_id}/reply', controller=controller, action='reply')
map.connect('/{content_type}/{content_item_id}/comments/{comment_id}/delete', controller=controller, action='delete')
return map

def _get_comment_thread(self, dataset_name):
import ckan.model as model
from ckan.logic import get_action
url = '/dataset/%s' % dataset_name
def _get_comment_thread(self, dataset_name, content_type='dataset'):
url = '/%s/%s' % (content_type, dataset_name)
return get_action('thread_show')({'model': model, 'with_deleted': True}, {'url': url})

def _get_comment_count_for_dataset(self, dataset_name):
import ckan.model as model
from ckan.logic import get_action
url = '/dataset/%s' % dataset_name
def _get_comment_count_for_dataset(self, dataset_name, content_type='dataset'):
url = '/%s/%s' % (content_type, dataset_name)
count = get_action('comment_count')({'model': model}, {'url': url})
return count
7 changes: 7 additions & 0 deletions ckanext/ytp/comments/templates/datarequests/comment.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% ckan_extends %}

{% block primary_content_inner %}

{% snippet "package/comment_list.html", content_type='datarequest', pkg_id=c.datarequest.id, pkg_name=c.datarequest.id, userobj=c.userobj %}

{% endblock %}
9 changes: 9 additions & 0 deletions ckanext/ytp/comments/templates/datarequests/show.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% ckan_extends %}

{% block content_primary_nav %}
{{ h.build_nav_icon('show_datarequest', _('Data request'), id=datarequest_id) }}

{% if h.show_comments_tab() and h.ytp_comments_enabled() %}
{{ h.build_nav_icon('comment_datarequest', _('Comments') + ' ' + h.get_datarequest_comments_badge(datarequest_id), id=datarequest_id) }}
{% endif %}
{% endblock %}
42 changes: 22 additions & 20 deletions ckanext/ytp/comments/templates/package/comment_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
{% resource "comments_js/comments.js" %}
{% resource "comments_js/comment_validation.js" %}

{% set content_type = content_type or 'dataset' %}

{% macro comment_form(values={}, empty=False, hidden=True, prefix="", action="add") %}
<form id="{{ prefix + values.id }}" class="form {% if hidden %}hidden{% endif %}" action="{{ pkg_id }}/comments/{% if values.id %}{{ values.id }}/{% endif %}{{ action }}" method="POST">
<form id="{{ prefix + values.id }}" class="form {% if hidden %}hidden{% endif %}" action="/{{ content_type or 'dataset' }}/{{ pkg_id }}/comments/{% if values.id %}{{ values.id }}/{% endif %}{{ action }}" method="POST">
<div class="{{ action }}_form_errors form-errors alert alert-error hidden">
<div class="hidden error-comment">{{ _('Please enter a Comment.') }}</div>
</div>
Expand All @@ -24,9 +26,9 @@



{% set thread = h.get_comment_thread(pkg_name) %}
{% set thread = h.get_comment_thread(pkg_name, content_type) %}

{% macro comment_thread(thread) %}
{% macro comment_thread(thread, content_type) %}

<div class="comment-wrapper">
{% for comment in thread.comments %}
Expand Down Expand Up @@ -69,35 +71,35 @@ <h3>{{ _('This comment was deleted.') }}</h3>
</div>
</div>
{% if comment.comments | length != 0 %}
{{ comment_thread(comment) }}
{{ comment_thread(comment, content_type) }}
{% endif %}
{% endfor %}
</div>

{% endmacro %}
<h3 id="comments">{{ _('Comments') }}</h3>
<div class="comment-container">
{{ comment_thread(thread) }}
{{ comment_thread(thread, content_type) }}
</div>

{% if userobj %}

<form class="form" action="{{ pkg_id }}/comments/add" method="POST">
<div id="comment_form_errors" class="alert alert-error form-errors hidden">
<div class="hidden error-comment">{{ _('Please enter a Comment.') }}</div>
</div>
<div class="form-controls">
<label for="subject">{{ _('Subject') }}</label>
<input type="text" class="form-control" name="subject"/>
<form id="comment_form" class="form" action="/{{ content_type }}/{{ pkg_id }}/comments/add" method="POST">
<div id="comment_form_errors" class="alert alert-error form-errors hidden">
<div class="hidden error-comment">{{ _('Please enter a Comment.') }}</div>
</div>
<div class="form-controls">
<label for="subject">{{ _('Subject') }}</label>
<input type="text" class="form-control" name="subject"/>

<label for="comment">{{ _('Comment') }}</label>
<textarea name="comment" class="form-control" rows="10"></textarea>
</div>
<div class="form-actions">
<input type="submit" class="btn btn-primary" value="{{ _('Save') }}"/>
<input type="reset" class="btn" value="{{ _('Clear') }}"/>
</div>
</form>
<label for="comment">{{ _('Comment') }}</label>
<textarea name="comment" class="form-control" rows="10"></textarea>
</div>
<div class="form-actions">
<input type="submit" class="btn btn-primary" value="{{ _('Save') }}"/>
<input type="reset" class="btn" value="{{ _('Clear') }}"/>
</div>
</form>

{% else %}
{{ _('Login to comment.') }}
Expand Down