Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql |
— | — | @@ -24,11 +24,13 @@ |
25 | 25 | af_user_anon_token varbinary(32) NOT NULL DEFAULT '', |
26 | 26 | -- Foreign key to revision.rev_id |
27 | 27 | af_revision_id integer unsigned NOT NULL, |
28 | | - -- Which rating widget the user was given. Default of 0 is the "old" design |
29 | | - af_bucket_id int unsigned NOT NULL DEFAULT 0, |
30 | | - -- Which CTA widget was displayed to the user. 0 is "none" |
| 28 | + -- Which feedback widget the user was given. Default of 0 is "none". |
| 29 | + af_bucket_id integer unsigned NOT NULL DEFAULT 0, |
| 30 | + -- Which CTA widget was displayed to the user. 0 is "none", |
31 | 31 | -- Which would come up if they got the edit page CTA, and couldn't edit. |
32 | | - af_cta_id int unsigned NOT NULL DEFAULT 0, |
| 32 | + af_cta_id integer unsigned NOT NULL DEFAULT 0, |
| 33 | + -- Which link the user clicked on to get to the widget. Default of 0 is "none". |
| 34 | + af_link_id integer unsigned NOT NULL DEFAULT 0, |
33 | 35 | af_created timestamp NULL DEFAULT CURRENT_TIMESTAMP, |
34 | 36 | af_modified timestamp NULL |
35 | 37 | ) /*$wgDBTableOptions*/; |
Index: trunk/extensions/ArticleFeedbackv5/sql/alter.sql |
— | — | @@ -20,4 +20,5 @@ |
21 | 21 | INSERT INTO aft_article_field_option (afo_field_id, afo_name) |
22 | 22 | SELECT afi_id, 'praise' FROM aft_article_field WHERE afi_name = 'tag' AND afi_bucket_id = 2; |
23 | 23 | |
| 24 | +ALTER TABLE aft_article_feedback ADD COLUMN af_link_id integer unsigned NOT NULL DEFAULT 0; |
24 | 25 | |
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php |
— | — | @@ -78,6 +78,8 @@ |
79 | 79 | 'articlefeedbackv5-transparency-terms' => 'By posting, you agree to transparency under these $1.', |
80 | 80 | 'articlefeedbackv5-transparency-terms-linktext' => 'terms', |
81 | 81 | 'articlefeedbackv5-transparency-terms-url' => 'Project:Privacy_policy', // TODO: Confirm correct link |
| 82 | + 'articlefeedbackv5-section-linktext' => 'feedback', |
| 83 | + 'articlefeedbackv5-toolbox-linktext' => 'Feedback', |
82 | 84 | /* END Messages needing translation */ |
83 | 85 | 'articlefeedbackv5-error' => 'An error has occured. Please try again later.', |
84 | 86 | 'articlefeedbackv5-bucket5-form-switch-label' => 'Rate this page', |
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js |
— | — | @@ -68,7 +68,7 @@ |
69 | 69 | * |
70 | 70 | * @see http://www.mediawiki.org/wiki/Article_feedback/Version_5/Feature_Requirements#Feedback_form_interface |
71 | 71 | */ |
72 | | - $.articleFeedbackv5.bucketId = 0; |
| 72 | + $.articleFeedbackv5.bucketId = '0'; |
73 | 73 | |
74 | 74 | /** |
75 | 75 | * The CTA is the view presented to a user who has successfully submitted |
— | — | @@ -76,9 +76,22 @@ |
77 | 77 | * |
78 | 78 | * @see http://www.mediawiki.org/wiki/Article_feedback/Version_5/Feature_Requirements#Calls_to_Action |
79 | 79 | */ |
80 | | - $.articleFeedbackv5.ctaId = 1; |
| 80 | + $.articleFeedbackv5.ctaId = '1'; |
81 | 81 | |
82 | 82 | /** |
| 83 | + * The link ID indicates where the user clicked (or not) to get to the |
| 84 | + * feedback form. Options are: |
| 85 | + * 0: No link; user scrolled to the bottom of the page |
| 86 | + * 1: Section bars |
| 87 | + * 2: Title bar |
| 88 | + * 3: Vertical button |
| 89 | + * 4: Toolbox (bottom of left nav) |
| 90 | + * |
| 91 | + * @see http://www.mediawiki.org/wiki/Article_feedback/Version_5/Feature_Requirements#Placement |
| 92 | + */ |
| 93 | + $.articleFeedbackv5.linkId = '0'; |
| 94 | + |
| 95 | + /** |
83 | 96 | * Use the mediawiki util resource's config method to find the correct url to |
84 | 97 | * call for all ajax requests. |
85 | 98 | */ |
— | — | @@ -2041,19 +2054,23 @@ |
2042 | 2055 | // Lock the form |
2043 | 2056 | $.articleFeedbackv5.lockForm(); |
2044 | 2057 | |
| 2058 | + // Request data |
| 2059 | + var data = $.extend( formdata, { |
| 2060 | + 'action': 'articlefeedbackv5', |
| 2061 | + 'format': 'json', |
| 2062 | + 'anontoken': $.articleFeedbackv5.userId, |
| 2063 | + 'pageid': $.articleFeedbackv5.pageId, |
| 2064 | + 'revid': $.articleFeedbackv5.revisionId, |
| 2065 | + 'bucket': $.articleFeedbackv5.bucketId, |
| 2066 | + 'link': $.articleFeedbackv5.linkId |
| 2067 | + } ); |
| 2068 | + |
2045 | 2069 | // Send off the ajax request |
2046 | 2070 | $.ajax( { |
2047 | 2071 | 'url': $.articleFeedbackv5.apiUrl, |
2048 | 2072 | 'type': 'POST', |
2049 | 2073 | 'dataType': 'json', |
2050 | | - 'data': $.extend( formdata, { |
2051 | | - 'action': 'articlefeedbackv5', |
2052 | | - 'format': 'json', |
2053 | | - 'anontoken': $.articleFeedbackv5.userId, |
2054 | | - 'pageid': $.articleFeedbackv5.pageId, |
2055 | | - 'revid': $.articleFeedbackv5.revisionId, |
2056 | | - 'bucket': $.articleFeedbackv5.bucketId |
2057 | | - } ), |
| 2074 | + 'data': data, |
2058 | 2075 | 'success': function( data ) { |
2059 | 2076 | if ( 'articlefeedbackv5' in data |
2060 | 2077 | && 'feedback_id' in data.articlefeedbackv5 |
— | — | @@ -2095,6 +2112,21 @@ |
2096 | 2113 | }; |
2097 | 2114 | |
2098 | 2115 | // }}} |
| 2116 | + // {{{ Outside interaction methods |
| 2117 | + |
| 2118 | + /** |
| 2119 | + * Sets the link ID |
| 2120 | + * |
| 2121 | + * @param int linkId the link ID |
| 2122 | + */ |
| 2123 | + $.articleFeedbackv5.setLinkId = function ( linkId ) { |
| 2124 | + var knownLinks = { '0': true, '1': true, '2': true, '3': true, '4': true }; |
| 2125 | + if ( linkId in knownLinks ) { |
| 2126 | + $.articleFeedbackv5.linkId = linkId + ''; |
| 2127 | + } |
| 2128 | + }; |
| 2129 | + |
| 2130 | + // }}} |
2099 | 2131 | // {{{ UI methods |
2100 | 2132 | |
2101 | 2133 | /** |
— | — | @@ -2161,24 +2193,16 @@ |
2162 | 2194 | // {{{ articleFeedbackv5 plugin |
2163 | 2195 | |
2164 | 2196 | /** |
2165 | | - * Can be called with an options object like... |
| 2197 | + * Right now there are no options for this plugin, but there will be in the |
| 2198 | + * future, so allow them to be passed in. |
2166 | 2199 | * |
2167 | | - * $( ... ).articleFeedbackv5( { |
2168 | | - * 'ratings': { |
2169 | | - * 'rating-name': { |
2170 | | - * 'id': 1, // Numeric identifier of the rating, same as the rating_id value in the db |
2171 | | - * 'label': 'msg-key-for-label', // String of message key for label |
2172 | | - * 'tip': 'msg-key-for-tip', // String of message key for tip |
2173 | | - * }, |
2174 | | - * // More ratings here... |
2175 | | - * } |
2176 | | - * } ); |
2177 | | - * |
2178 | | - * Rating IDs need to be included in $wgArticleFeedbackv5RatingTypes, which is an array mapping allowed IDs to rating names. |
| 2200 | + * If a string is passed in, it's considered a public function |
2179 | 2201 | */ |
2180 | | -$.fn.articleFeedbackv5 = function ( opts ) { |
2181 | | - if ( typeof( opts ) == 'object' ) { |
| 2202 | +$.fn.articleFeedbackv5 = function ( opts, arg ) { |
| 2203 | + if ( typeof ( opts ) == 'undefined' || typeof ( opts ) == 'object' ) { |
2182 | 2204 | $.articleFeedbackv5.init( $( this ), opts ); |
| 2205 | + } else if ( 'setLinkId' === opts ) { |
| 2206 | + $.articleFeedbackv5.setLinkId( arg ); |
2183 | 2207 | } |
2184 | 2208 | return $( this ); |
2185 | 2209 | }; |
Index: trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedbackv5/ext.articleFeedbackv5.js |
— | — | @@ -3,22 +3,46 @@ |
4 | 4 | */ |
5 | 5 | ( function( $ ) { |
6 | 6 | |
| 7 | +/* Setup for feedback links */ |
| 8 | + |
7 | 9 | // Only track users who have been assigned to the tracking group |
8 | | -var tracked = 'track' === mw.user.bucket( |
| 10 | +var useClickTracking = 'track' === mw.user.bucket( |
9 | 11 | 'ext.articleFeedbackv5-tracking', mw.config.get( 'wgArticleFeedbackv5Tracking' ) |
10 | 12 | ); |
11 | 13 | |
12 | | -function trackClick( id ) { |
13 | | - // Track the click so we can figure out how useful this is |
14 | | - if ( tracked && $.isFunction( $.trackActionWithInfo ) ) { |
15 | | - $.trackActionWithInfo( $.articleFeedbackv5.prefix( id ), mw.config.get( 'wgTitle' ) ); |
| 14 | +// Info about each of the links |
| 15 | +var linkInfo = { |
| 16 | + '4': { |
| 17 | + clickTracking: $.articleFeedbackv5.prefix( 'toolbox-link' ) |
16 | 18 | } |
| 19 | +}; |
| 20 | + |
| 21 | +// Click event |
| 22 | +var clickFeedbackLink = function ( linkId ) { |
| 23 | + // Click tracking |
| 24 | + if ( useClickTracking && $.isFunction( $.trackActionWithInfo ) ) { |
| 25 | + $.trackActionWithInfo( linkInfo[linkId].clickTracking, mw.config.get( 'wgTitle' ) ); |
| 26 | + } |
| 27 | + // Set the link id |
| 28 | + $( '#mw-articlefeedbackv5' ).articleFeedbackv5( 'setLinkId', linkId ); |
| 29 | + // Go to the box and flash it |
| 30 | + var $box = $( '#mw-articlefeedbackv5' ); |
| 31 | + var count = 0; |
| 32 | + var interval = setInterval( function() { |
| 33 | + // Animate the opacity over .2 seconds |
| 34 | + $box.animate( { 'opacity': 0.5 }, 100, function() { |
| 35 | + // When finished, animate it back to solid. |
| 36 | + $box.animate( { 'opacity': 1.0 }, 100 ); |
| 37 | + } ); |
| 38 | + // Clear the interval once we've reached 3. |
| 39 | + if ( ++count >= 3 ) { |
| 40 | + clearInterval( interval ); |
| 41 | + } |
| 42 | + }, 200 ); |
17 | 43 | } |
18 | 44 | |
19 | | -var config = { }; |
20 | | - |
21 | 45 | /* Load at the bottom of the article */ |
22 | | -var $aftDiv = $( '<div id="mw-articlefeedbackv5"></div>' ).articleFeedbackv5( config ); |
| 46 | +var $aftDiv = $( '<div id="mw-articlefeedbackv5"></div>' ).articleFeedbackv5(); |
23 | 47 | |
24 | 48 | // Put on bottom of article before #catlinks (if it exists) |
25 | 49 | // Except in legacy skins, which have #catlinks above the article but inside content-div. |
— | — | @@ -30,32 +54,23 @@ |
31 | 55 | mw.util.$content.append( $aftDiv ); |
32 | 56 | } |
33 | 57 | |
34 | | -/* Add link so users can navigate to the feedback tool from the toolbox */ |
35 | | -var $tbAft = $( '<li id="t-articlefeedbackv5"><a href="#mw-articlefeedbackv5"></a></li>' ) |
| 58 | +/* Add section links */ |
| 59 | +$( 'span.editsection' ).append( |
| 60 | + ' [' + |
| 61 | + '<a href="#mw-articlefeedbackv5" class="articleFeedbackv5-sectionlink">' + |
| 62 | + mw.msg( 'articlefeedbackv5-section-linktext' ) + '</a>' + |
| 63 | + ']' |
| 64 | +); |
| 65 | +$( 'span.editsection a.articleFeedbackv5-sectionlink' ).click( function () { |
| 66 | + clickFeedbackLink( '1' ); |
| 67 | +} ); |
| 68 | + |
| 69 | +/* Add toolbox link */ |
| 70 | +var $aftLink4 = $( '<li id="t-articlefeedbackv5"><a href="#mw-articlefeedbackv5"></a></li>' ) |
36 | 71 | .find( 'a' ) |
37 | | - // TODO: Find out whether this needs to change per bucket. Bucketing |
38 | | - // logic may need to move out of the jquery component into here. |
39 | | - .text( mw.msg( 'articlefeedbackv5-bucket5-form-switch-label' ) ) |
40 | | - .click( function() { |
41 | | - // Click tracking |
42 | | - trackClick( 'toolbox-link' ); |
43 | | - // Get the image, set the count and an interval. |
44 | | - var $box = $( '#mw-articlefeedbackv5' ); |
45 | | - var count = 0; |
46 | | - var interval = setInterval( function() { |
47 | | - // Animate the opacity over .2 seconds |
48 | | - $box.animate( { 'opacity': 0.5 }, 100, function() { |
49 | | - // When finished, animate it back to solid. |
50 | | - $box.animate( { 'opacity': 1.0 }, 100 ); |
51 | | - } ); |
52 | | - // Clear the interval once we've reached 3. |
53 | | - if ( ++count >= 3 ) { |
54 | | - clearInterval( interval ); |
55 | | - } |
56 | | - }, 200 ); |
57 | | - return true; |
58 | | - } ) |
59 | | - .end(); |
60 | | -$( '#p-tb' ).find( 'ul' ).append( $tbAft ); |
| 72 | + .text( mw.msg( 'articlefeedbackv5-toolbox-linktext' ) ) |
| 73 | + .click( function () { clickFeedbackLink( '4' ) } ) |
| 74 | + .end(); |
| 75 | +$( '#p-tb' ).find( 'ul' ).append( $aftLink4 ); |
61 | 76 | |
62 | 77 | } )( jQuery ); |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php |
— | — | @@ -288,6 +288,7 @@ |
289 | 289 | $dbw = wfGetDB( DB_MASTER ); |
290 | 290 | $revId = $params['revid']; |
291 | 291 | $bucket = $params['bucket']; |
| 292 | + $link = $params['link']; |
292 | 293 | $token = ApiArticleFeedbackv5Utils::getAnonToken( $params ); |
293 | 294 | $timestamp = $dbw->timestamp(); |
294 | 295 | |
— | — | @@ -309,6 +310,7 @@ |
310 | 311 | 'af_user_text' => $wgUser->getName(), |
311 | 312 | 'af_user_anon_token' => $token, |
312 | 313 | 'af_bucket_id' => $bucket, |
| 314 | + 'af_link_id' => $link, |
313 | 315 | ) ); |
314 | 316 | |
315 | 317 | return $dbw->insertID(); |
— | — | @@ -372,8 +374,14 @@ |
373 | 375 | ApiBase::PARAM_TYPE => 'integer', |
374 | 376 | ApiBase::PARAM_REQUIRED => true, |
375 | 377 | ApiBase::PARAM_ISMULTI => false, |
376 | | - ApiBase::PARAM_MIN => 1 |
| 378 | + ApiBase::PARAM_MIN => 0 |
377 | 379 | ), |
| 380 | + 'link' => array( |
| 381 | + ApiBase::PARAM_TYPE => 'integer', |
| 382 | + ApiBase::PARAM_REQUIRED => true, |
| 383 | + ApiBase::PARAM_ISMULTI => false, |
| 384 | + ApiBase::PARAM_MIN => 0 |
| 385 | + ), |
378 | 386 | ); |
379 | 387 | |
380 | 388 | $fields = ApiArticleFeedbackv5Utils::getFields(); |
— | — | @@ -398,7 +406,8 @@ |
399 | 407 | 'pageid' => 'Page ID to submit feedback for', |
400 | 408 | 'revid' => 'Revision ID to submit feedback for', |
401 | 409 | 'anontoken' => 'Token for anonymous users', |
402 | | - 'bucket' => 'Which rating widget was shown to the user', |
| 410 | + 'bucket' => 'Which feedback widget was shown to the user', |
| 411 | + 'link' => 'Which link the user clicked on to get to the widget', |
403 | 412 | ); |
404 | 413 | $fields = ApiArticleFeedbackv5Utils::getFields(); |
405 | 414 | foreach ( $fields as $f ) { |
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php |
— | — | @@ -13,32 +13,14 @@ |
14 | 14 | 'scripts' => 'ext.articleFeedbackv5/ext.articleFeedbackv5.startup.js', |
15 | 15 | 'dependencies' => array( |
16 | 16 | 'mediawiki.util', |
17 | | - 'ext.articleFeedbackv5', |
18 | 17 | ), |
19 | 18 | ), |
20 | 19 | 'ext.articleFeedbackv5' => array( |
21 | 20 | 'scripts' => 'ext.articleFeedbackv5/ext.articleFeedbackv5.js', |
22 | 21 | 'styles' => 'ext.articleFeedbackv5/ext.articleFeedbackv5.css', |
23 | 22 | 'messages' => array( |
24 | | - 'articlefeedbackv5-pitch-reject', |
25 | | - 'articlefeedbackv5-pitch-or', |
26 | | - 'articlefeedbackv5-pitch-thanks', |
27 | | - 'articlefeedbackv5-pitch-survey-message', |
28 | | - 'articlefeedbackv5-pitch-survey-body', |
29 | | - 'articlefeedbackv5-pitch-survey-accept', |
30 | | - 'articlefeedbackv5-pitch-join-message', |
31 | | - 'articlefeedbackv5-pitch-join-body', |
32 | | - 'articlefeedbackv5-pitch-join-accept', |
33 | | - 'articlefeedbackv5-pitch-join-login', |
34 | | - 'articlefeedbackv5-pitch-edit-message', |
35 | | - 'articlefeedbackv5-pitch-edit-body', |
36 | | - 'articlefeedbackv5-pitch-edit-accept', |
37 | | - 'articlefeedbackv5-survey-title', |
38 | | - 'articlefeedbackv5-survey-message-success', |
39 | | - 'articlefeedbackv5-survey-message-error', |
40 | | - 'articlefeedbackv5-survey-disclaimer', |
41 | | - 'articlefeedbackv5-survey-disclaimerlink', |
42 | | - 'articlefeedbackv5-privacyurl', |
| 23 | + 'articlefeedbackv5-section-linktext', |
| 24 | + 'articlefeedbackv5-toolbox-linktext', |
43 | 25 | ), |
44 | 26 | 'dependencies' => array( |
45 | 27 | 'jquery.ui.dialog', |