Source code for assembl.views.api2.ideas

from io import BytesIO

from pyramid.response import Response
from pyramid.view import view_config
from pyramid.httpexceptions import (
    HTTPUnauthorized, HTTPBadRequest, HTTPFound)
from pyramid.security import authenticated_userid, Everyone
from sqlalchemy.orm import aliased

from ..traversal import (InstanceContext, CollectionContext)
from . import instance_view
from assembl.auth import (CrudPermissions, P_READ, P_EDIT_IDEA)
from assembl.lib.text_search import add_text_search
from assembl.models import (
    Idea, LangString, LangStringEntry, LanguagePreferenceCollection, Discussion)
from .discussion import request_to_graph_mimetype, pygraphviz_formats

@view_config(context=InstanceContext, request_method='DELETE', renderer='json',
             ctx_instance_class=Idea, permission=P_EDIT_IDEA)
def instance_del(request):
    ctx = request.context
    user_id = authenticated_userid(request) or Everyone
    idea = ctx._instance
    if not idea.user_can(
            user_id, CrudPermissions.DELETE, ctx.get_permissions()):
        raise HTTPUnauthorized()
    for link in idea.source_links:
        link.is_tombstone = True
    idea.is_tombstone = True

    return {}


@view_config(context=InstanceContext, request_method='GET', renderer='json',
             ctx_instance_class=Idea, accept="text/html")
def redirect_idea_html(request):
    if (request.accept.quality('text/html') or 0) > max(
            request.accept.quality('application/json') or 0,
            request.accept.quality('application/ld+json') or 0):
        idea = request.context._instance
        return HTTPFound(request.route_url(
            'purl_idea', discussion_slug=idea.discussion.slug,
            remainder='/'+str(idea.id)))
    return instance_view(request)


@view_config(context=InstanceContext, request_method='POST', renderer='json',
             ctx_instance_class=Idea, name="do_transition")
def pub_state_transition(request):
    ctx = request.context
    user_id = authenticated_userid(request) or Everyone
    idea = ctx._instance
    discussion = idea.discussion
    flow = discussion.idea_publication_flow
    if not flow:
        raise HTTPBadRequest("discussion has no flow set")
    transition = flow.transition_by_label(request.json['transition'])
    if not transition:
        raise HTTPBadRequest("Cannot find this transition")
    if transition.source_id != idea.pub_state_id:
        raise HTTPBadRequest("Idea is not in source state")
    if transition.requires_permission.name not in request.permissions:
        raise HTTPUnauthorized()
    idea.pub_state_id = transition.target_id
    return {"pub_state_name": transition.target.label}


[docs]@view_config(context=InstanceContext, name="mindmap", ctx_instance_class=Idea, request_method='GET', permission=P_READ) def as_mind_map(request): """Provide a mind-map like representation of the table of ideas""" mimetype = request_to_graph_mimetype(request) idea = request.context._instance G = idea.local_mind_map() io = BytesIO() G.draw(io, format=pygraphviz_formats[mimetype]) io.seek(0) return Response(body_file=io, content_type=mimetype)
@view_config(context=CollectionContext, renderer='json', ctx_collection_class=Idea, name='autocomplete', permission=P_READ) def autocomplete(request): discussion = request.context.get_instance_of_class(Discussion) keywords = request.GET.get('q') if not keywords: raise HTTPBadRequest("please specify search terms (q)") locales = request.GET.getall('locale') user_prefs = LanguagePreferenceCollection.getCurrent() if not locales: locales = user_prefs.known_languages() if not set(locales).intersection(discussion.discussion_locales): locales.extend(discussion.discussion_locales) include_description = bool(request.GET.get('description')) match_lse = aliased(LangStringEntry) title_ls = aliased(LangString) query = Idea.default_db.query( Idea.id, title_ls, match_lse.langstring_id, match_lse.locale ).join(title_ls, title_ls.id == Idea.title_id ).filter( Idea.discussion_id == discussion.id) limit = int(request.GET.get('limit') or 5) columns = [Idea.title_id] if include_description: columns.append(Idea.description_id) query, rank = add_text_search( query, columns, keywords.split(), locales, True, match_lse) query = query.order_by(rank.desc()).limit(limit).all() results = [] if not query: return results for (idea_id, title, ls_id, lse_locale, rank) in query: title_entry = title.best_lang(user_prefs, False) r = {'id': Idea.uri_generic(idea_id), 'title_locale': title_entry.locale, 'match_locale': lse_locale, 'text': title_entry.value } if include_description: r['match_field'] = 'shortTitle' if ls_id == title.id else 'definition' results.append(r) return {'results': results}