[FIX] website_forum links which should not be, post-install crawler
authorXavier Morel <xmo@openerp.com>
Mon, 12 May 2014 16:34:55 +0000 (18:34 +0200)
committerXavier Morel <xmo@openerp.com>
Mon, 12 May 2014 16:34:55 +0000 (18:34 +0200)
* move URLs of purely-JS-hook <a> to data-href so the crawler does not try to
  access them (they're JSON-RPC endpoints...)
* replace side-effecting links (...) by styled buttons
* fix crawler to not take fragments in account when deduplicating and
  navigating URLs

addons/website/tests/test_requests.py
addons/website_forum/static/src/css/website_forum.css
addons/website_forum/static/src/css/website_forum.sass
addons/website_forum/static/src/js/website_forum.js
addons/website_forum/views/website_forum.xml

index 127aea2..e0309c9 100644 (file)
@@ -41,6 +41,9 @@ class CrawlSuite(unittest2.TestSuite):
     starting the crawl
     """
 
+    at_install = False
+    post_install = True
+
     def __init__(self, user=None, password=None):
         super(CrawlSuite, self).__init__()
 
@@ -108,14 +111,23 @@ class CrawlSuite(unittest2.TestSuite):
                 for link in doc.xpath('//a[@href]'):
                     href = link.get('href')
 
+                    parts = urlparse.urlsplit(href)
+                    # href with any fragment removed
+                    href = urlparse.urlunsplit((
+                        parts.scheme,
+                        parts.netloc,
+                        parts.path,
+                        parts.query,
+                        ''
+                    ))
+
                     # avoid repeats, even for links we won't crawl no need to
                     # bother splitting them if we've already ignored them
                     # previously
                     if href in seen: continue
                     seen.add(href)
 
-                    parts = urlparse.urlsplit(href)
-
+                    # FIXME: handle relative link (not parts.path.startswith /)
                     if parts.netloc or \
                         not parts.path.startswith('/') or \
                         parts.path == '/web' or\
index b90c178..75befd6 100644 (file)
@@ -94,3 +94,7 @@ a.no-decoration {
   font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important;
   height: 1.2em !important;
 }
+
+button.btn-link.text-muted {
+  color: #999999;
+}
index f8e46f0..d800d29 100644 (file)
@@ -74,3 +74,6 @@ a.no-decoration
   .text-tags .text-tag .text-button
     font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important
     height: 1.2em !important
+
+button.btn-link.text-muted
+  color: #999
index e84e76e..0b45d43 100644 (file)
@@ -3,7 +3,7 @@ $(document).ready(function () {
     $('.vote_up ,.vote_down').on('click', function (ev) {
         ev.preventDefault();
         var $link = $(ev.currentTarget);
-        openerp.jsonRpc($link.attr('href'), 'call', {})
+        openerp.jsonRpc($link.data('href'), 'call', {})
             .then(function (data) {
                 if (data['error']){
                     if (data['error'] == 'own_post'){
@@ -47,7 +47,7 @@ $(document).ready(function () {
     $('.accept_answer').on('click', function (ev) {
         ev.preventDefault();
         var $link = $(ev.currentTarget);
-        openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
+        openerp.jsonRpc($link.data('href'), 'call', {}).then(function (data) {
             if (data['error']) {
                 if (data['error'] == 'anonymous_user'){
                     var $warning = $('<div class="alert alert-danger alert-dismissable" id="correct_answer_alert" style="position:absolute; margin-top: -30px; margin-left: 90px;">'+
@@ -83,7 +83,7 @@ $(document).ready(function () {
     $('.favourite_question').on('click', function (ev) {
         ev.preventDefault();
         var $link = $(ev.currentTarget);
-        openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
+        openerp.jsonRpc($link.data('href'), 'call', {}).then(function (data) {
             if (data) {
                 $link.addClass("forum_favourite_question")
             } else {
@@ -96,7 +96,7 @@ $(document).ready(function () {
     $('.comment_delete').on('click', function (ev) {
         ev.preventDefault();
         var $link = $(ev.currentTarget);
-        openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
+        openerp.jsonRpc($link.data('href'), 'call', {}).then(function (data) {
             $link.parents('.comment').first().remove();
         });
         return true;
index c73486d..fbda6a4 100644 (file)
     </xpath>
 </template>
 
+<!-- helper -->
+<template id="muted_button">
+    <form method="POST" t-att-action="url">
+        <button t-attf-class="text-muted fa btn-link #{classes}">
+            <t t-esc="label"/></button>
+    </form>
+</template>
+
 <!-- Page Index -->
 <template id="header" name="Forum Index">
     <t t-call="website.layout">
 <template id="vote">
     <div t-attf-class="box oe_grey">
         <a t-attf-class="vote_up fa fa-thumbs-up no-decoration #{post.user_vote == 1 and 'text-success' or ''}" 
-            t-attf-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/upvote"/>
+            t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/upvote"/>
         <span id="vote_count" t-esc="post.vote_count"/>
         <a t-attf-class="vote_down fa fa-thumbs-down no-decoration #{post.user_vote == -1 and 'text-warning' or ''}" 
-            t-attf-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/downvote"/>
+            t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/downvote"/>
         <div t-if="vote_count &gt; 1" class="subtitle">
             votes
         </div>
                     <span t-field="question.views"/> Views
                 </div>
                 <div class="mt4">
-                    <a t-attf-href="/forum/#{slug(question.forum_id)}/question/#{slug(question)}/toggle_favourite"
+                    <a t-attf-data-href="/forum/#{slug(question.forum_id)}/question/#{slug(question)}/toggle_favourite"
                         t-attf-class="favourite_question no-decoration fa fa-2x fa-star #{question.user_favourite and 'forum_favourite_question' or ''}"/>
                 </div>
             </div>
                     </t>
                     <div class="text-muted mt8">
                         <a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'}"
-                            t-attf-href="/forum/#{slug(question.forum_id)}/post/#{slug(answer)}/toggle_correct"/>
+                            t-attf-data-href="/forum/#{slug(question.forum_id)}/post/#{slug(answer)}/toggle_correct"/>
                     </div>
                 </div>
                 <div style="margin-left: 95px;" class="clearfix">
                                 <a class="text-muted fa fa-edit" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/edit"> Edit</a>
                             </li>
                             <li t-if="(user.id == answer.create_uid.id and can_unlink_own) or can_unlink_all">
-                                <a class="text-muted fa fa-trash-o" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/delete"> Delete</a>
+                                <t t-call="website_forum.muted_button">
+                                    <t t-set="url"><t t-escf="/forum/#{slug(forum)}/post/#{slug(answer)}/delete"/></t>
+                                    <t t-set="label"> Delete</t>
+                                    <t t-set="classes">fa-trash-o</t>
+                                </t>
                             </li>
                             <li t-if="user.id == answer.create_uid.id">
-                                <a class="text-muted fa fa-magic" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/convert_to_comment"> Convert as a comment</a>
+                                <t t-call="website_forum.muted_button">
+                                    <t t-set="url"><t t-escf="/forum/#{slug(forum)}/post/#{slug(answer)}/convert_to_comment"/></t>
+                                    <t t-set="label">Convert as a comment</t>
+                                    <t t-set="classes">fa-magic</t>
+                                </t>
                             </li>
                         </ul>
                         <span t-field="answer.create_uid.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
             <div t-foreach="reversed(object.website_message_ids)" t-as="message" class="comment oe_comment_grey">
                 <small class="text-muted">
                     <button type="button" t-if="user.partner_id.id == message.author_id.id and user.karma&gt;=750"
-                        t-attf-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/delete" 
+                        t-attf-data-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/delete"
                         class="close comment_delete">&amp;times;</button>
                     <span t-field="message.body"/>
                     <a t-attf-href="/forum/#{slug(forum)}/partner/#{message.author_id.id}"
                         t-field="message.author_id" t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
                         style="display: inline-block;"/>
                     on <span t-field="message.date" t-field-options='{"format":"short"}'/>
-                    <a class="fa fa-magic text-muted pull-right"
-                        t-attf-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/convert_to_answer">Convert as an answer</a>
+
+                    <t t-call="website_forum.muted_button">
+                        <t t-set="url"><t t-escf="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/convert_to_answer"/></t>
+                        <t t-set="label"> Convert as an answer</t>
+                        <t t-set="classes">fa-magic pull-right</t>
+                    </t>
                 </small>
             </div>
             <div class="css_editable_mode_hidden">