r63763 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63762‎ | r63763 | r63764 >
Date:03:08, 15 March 2010
Author:jeroendedauw
Status:ok (Comments)
Tags:
Comment:
* Made Special:StoryReview use it's API class for actions
* Moved css for stories to a new file, to be used by everything that shows stories (<storyboard>, Special:Storyreview and Special:Story)
Modified paths:
  • /trunk/extensions/Storyboard/Storyboard.i18n.php (modified) (history)
  • /trunk/extensions/Storyboard/api/ApiStoryReview.php (modified) (history)
  • /trunk/extensions/Storyboard/specials/StoryReview/StoryReview_body.php (modified) (history)
  • /trunk/extensions/Storyboard/specials/StoryReview/storyreview.js (added) (history)
  • /trunk/extensions/Storyboard/story.css (added) (history)
  • /trunk/extensions/Storyboard/storyboard.sql (modified) (history)
  • /trunk/extensions/Storyboard/tags/Storyboard/Storyboard_body.php (modified) (history)
  • /trunk/extensions/Storyboard/tags/Storyboard/storyboard.css (modified) (history)
  • /trunk/extensions/Storyboard/tags/Storyboard/storyboard.js (modified) (history)

Diff [purge]

Index: trunk/extensions/Storyboard/storyboard.sql
@@ -13,7 +13,8 @@
1414 story_modified CHAR(14) binary NOT NULL default '',
1515 story_created CHAR(14) binary NOT NULL default '',
1616 story_is_published TINYINT NOT NULL default '0',
17 - story_is_hidden TINYINT NOT NULL default '0'
 17+ story_is_hidden TINYINT NOT NULL default '0',
 18+ story_image_hidden TINYINT NOT NULL default '0'
1819 ) /*$wgDBTableOptions*/;
1920
2021 CREATE INDEX story_published_modified ON /*$wgDBprefix*/storyboard (story_is_published, story_modified);
Index: trunk/extensions/Storyboard/Storyboard.i18n.php
@@ -31,6 +31,9 @@
3232 'storyboard-unpublish' => 'Unpublish',
3333 'storyboard-reviewed' => 'Reviewed',
3434 'storyboard-unreviewed' => 'Unreviewed',
 35+ 'storyboard-hideimage' => 'Hide image',
 36+ 'storyboard-unhideimage' => 'Show image',
 37+ 'storyboard-deleteimage' => 'Delete image',
3538
3639 // Story submission
3740 'storyboard-yourname' => 'Your name',
Index: trunk/extensions/Storyboard/tags/Storyboard/storyboard.css
@@ -1,7 +1,7 @@
22 /**
33 * Css for <storyboard> tags of the Storyboard extension.
44 *
5 - * @file Storyboard.css
 5+ * @file storyboard.css
66 * @ingroup Storyboard
77 *
88 * @author Jeroen De Dauw
@@ -24,32 +24,4 @@
2525 .storyboard .storyboard-empty .storyboard-box {
2626 border: 1px solid #ddd;
2727 background: #FCFCFC url(../../images/storyboard-loader.gif) no-repeat scroll center center;
28 -}
29 -.storyboard-sharing {
30 - height: 30px;
31 - width: 110px;
32 - float: right;
33 -}
34 -.storyboard-sharing-item {
35 - float: left;
36 - padding-right: 5px;
37 -}
38 -.storyboard-header {
39 - margin: 10px 0px 10px 15px;
40 - height: 21px;
41 -}
42 -.storyboard-title {
43 - font: 16px "Lucida Sans", Verdana;
44 - font-weight: bold;
45 - float: left;
46 - overflow: hidden;
47 -}
48 -.storyboard-text {
49 - margin-left: 15px;
50 - float: left;
51 - overflow: hidden;
52 -}
53 -.storyboard-image {
54 - margin: 5px 15px 0px 15px;
55 - float: right;
5628 }
\ No newline at end of file
Index: trunk/extensions/Storyboard/tags/Storyboard/storyboard.js
@@ -29,13 +29,15 @@
3030 var story = data.query.stories[i];
3131 var $storyBody = $( "<div />" ).addClass( "storyboard-box" );
3232
33 - var $header = $( "<div />" ).addClass( "storyboard-header" ).appendTo( $storyBody );
34 - $( "<div />" ).addClass( "storyboard-title" ).text( story.title ).appendTo( $header );
 33+ var $header = $( "<div />" ).addClass( "story-header" ).appendTo( $storyBody );
 34+ $( "<div />" ).addClass( "story-title" ).text( story.title ).appendTo( $header );
3535
 36+ // TODO: move social sharing to a pop-up that's triggered by a link above each storyboard-box
 37+
3638 $( "<div />" )
37 - .addClass( "storyboard-sharing" )
 39+ .addClass( "story-sharing" )
3840 .append(
39 - $( "<div />" ).addClass( "storyboard-sharing-item" ).append(
 41+ $( "<div />" ).addClass( "story-sharing-item" ).append(
4042 $( "<a />" ).attr( {
4143 "target": "_blank",
4244 "href": "http://delicious.com/save?jump=yes&url=" + ""
@@ -46,7 +48,7 @@
4749 )
4850 ) //TODO
4951 .append(
50 - $( "<div />" ).addClass( "storyboard-sharing-item" ).append(
 52+ $( "<div />" ).addClass( "story-sharing-item" ).append(
5153 $( "<a />" ).attr( {
5254 "target": "_blank",
5355 "href": "http://www.facebook.com/sharer.php?u=" + "" + "&t=" + story.title
@@ -57,7 +59,7 @@
5860 )
5961 ) //TODO
6062 .append(
61 - $( "<div />" ).addClass( "storyboard-sharing-item" ).append(
 63+ $( "<div />" ).addClass( "story-sharing-item" ).append(
6264 $( "<a />" ).attr( {
6365 "target": "_blank",
6466 "href": "http://twitter.com/home?status=" + ""
@@ -69,15 +71,17 @@
7072 ) //TODO
7173 .appendTo( $header );
7274
73 - $storyBody.append( $( "<div />" ).addClass( "storyboard-text" )
 75+ $storyBody.append( $( "<div />" ).addClass( "story-text" )
7476 .text( story["*"] )
7577 .prepend( $( "<img />" )
7678 // TODO: replace by wgScriptPath + path/to/scropped/img
7779 .attr( "src", "http://upload.wikimedia.org/wikipedia/mediawiki/9/99/SemanticMaps.png" )
78 - .addClass( "storyboard-image" )
 80+ .addClass( "story-image" )
7981 )
8082 );
8183
 84+ // TODO: add delete button that hides the story from the storyboard (=unpublish+hide?)
 85+
8286 $div.append( $storyBody );
8387 }
8488 $storyboard.html( $div );
Index: trunk/extensions/Storyboard/tags/Storyboard/Storyboard_body.php
@@ -19,6 +19,7 @@
2020 public static function render( $input, $args, $parser, $frame ) {
2121 global $wgOut, $wgJsMimeType, $wgScriptPath, $egStoryboardScriptPath, $egStoryboardWidth, $egStoryboardHeight;
2222
 23+ $wgOut->addStyle( $egStoryboardScriptPath . '/story.css' );
2324 $wgOut->addStyle( $egStoryboardScriptPath . '/tags/Storyboard/storyboard.css' );
2425 $wgOut->includeJQuery();
2526 // TODO: Combine+minfiy JS files, add switch to use combined+minified version
Index: trunk/extensions/Storyboard/specials/StoryReview/StoryReview_body.php
@@ -35,11 +35,13 @@
3636 }
3737
3838 private function addOutput() {
39 - global $wgOut;
 39+ global $wgOut, $egStoryboardScriptPath;
4040
4141 $wgOut->setPageTitle( wfMsg( 'storyboard-storyreview' ) );
4242
 43+ $wgOut->addStyle( $egStoryboardScriptPath . '/story.css' );
4344 $wgOut->includeJQuery();
 45+ $wgOut->addScriptFile( $egStoryboardScriptPath . '/specials/StoryReview/storyreview.js' );
4446
4547 // Get a slave db object to do read operations against.
4648 $dbr = wfGetDB( DB_SLAVE );
@@ -52,7 +54,8 @@
5355 'story_author_name',
5456 'story_title',
5557 'story_text',
56 - 'story_is_published'
 58+ 'story_is_published',
 59+ 'story_image_hidden'
5760 ),
5861 array( 'story_is_hidden' => 0 )
5962 );
@@ -64,10 +67,10 @@
6568 // Loop through all stories, get their html, and add it to the appropriate string.
6669 while ( $story = $dbr->fetchObject( $stories ) ) {
6770 if ( $story->story_is_published ) {
68 - $reviewed .= $this->getStorySegments( $story, $story->story_is_published );
 71+ $reviewed .= $this->getStorySegments( $story );
6972 }
7073 else {
71 - $unreviewed .= $this->getStorySegments( $story, $story->story_is_published );
 74+ $unreviewed .= $this->getStorySegments( $story );
7275 }
7376 }
7477
@@ -77,13 +80,9 @@
7881 // Output the html for the stories.
7982 $wgOut->addHTML( <<<EOT
8083 <h2>$unrevMsg</h2>
81 - <table width="100%">
8284 $unreviewed
83 - </table>
8485 <h2>$revMsg</h2>
85 - <table width="100%">
86 - $reviewed
87 - </table>
 86+ $reviewed
8887 EOT
8988 );
9089 }
@@ -95,37 +94,43 @@
9695 *
9796 * @return string
9897 */
99 - private function getStorySegments( $story, $published ) {
 98+ private function getStorySegments( $story ) {
10099 $imageSrc = 'http://upload.wikimedia.org/wikipedia/mediawiki/9/99/SemanticMaps.png'; // TODO: get cropped image here
 100+
101101 $title = htmlspecialchars( $story->story_title );
102102 $text = htmlspecialchars( $story->story_text );
103 - $publish = $published ? wfMsg( 'storyboard-unpublish' ) : wfMsg( 'storyboard-publish' );
104 - $edit = wfMsg( 'edit' );
105 - $hide = wfMsg( 'hide' );
106103
 104+ $publishAction = $story->story_is_published ? 'unpublish' : 'publish';
 105+ $publishMsg = wfMsg( "storyboard-$publishAction" );
 106+
 107+ $imageAction = $story->story_image_hidden ? 'unhideimage' : 'hideimage';
 108+ $imageMsg = wfMsg( "storyboard-$imageAction" );
 109+
 110+ $editMsg = wfMsg( 'edit' );
 111+ $hideMsg = wfMsg( 'hide' );
 112+ $deleteImageMsg = wfMsg( 'storyboard-deleteimage' );
 113+
107114 return <<<EOT
108 - <tr>
109 - <td>
110 - <table width="100%" border="1">
111 - <tr>
112 - <td rowspan="2" width="200px">
113 - <img src="$imageSrc" />
114 - </td>
115 - <td>
116 - <b>$title</b>
117 - <br />$text
118 - </td>
119 - </tr>
120 - <tr>
121 - <td align="center" height="35">
122 - <button type="button">$publish</button>&nbsp;&nbsp;&nbsp;
123 - <button type="button">$edit</button>&nbsp;&nbsp;&nbsp;
124 - <button type="button">$hide</button>
125 - </td>
126 - </tr>
127 - </table>
128 - </td>
129 - </tr>
 115+ <table width="100%" border="1" id="story_$story->story_id">
 116+ <tr>
 117+ <td>
 118+ <div class="story">
 119+ <img src="http://upload.wikimedia.org/wikipedia/mediawiki/9/99/SemanticMaps.png" class="story-image">
 120+ <div class="story-title">$title</div><br />
 121+ $text
 122+ </div>
 123+ </td>
 124+ </tr>
 125+ <tr>
 126+ <td align="center" height="35">
 127+ <button type="button" onclick="doStoryAction( this, $story->story_id, '$publishAction' )">$publishMsg</button>&nbsp;&nbsp;&nbsp;
 128+ <button type="button" onclick="">$editMsg</button>&nbsp;&nbsp;&nbsp;
 129+ <button type="button" onclick="doStoryAction( this, $story->story_id, 'hide' )">$hideMsg</button>&nbsp;&nbsp;&nbsp;
 130+ <button type="button" onclick="doStoryAction( this, $story->story_id, '$imageAction' )">$imageMsg</button>&nbsp;&nbsp;&nbsp;
 131+ <button type="button" onclick="deleteStoryImage( this, $story->story_id )">$deleteImageMsg</button>
 132+ </td>
 133+ </tr>
 134+ </table>
130135 EOT;
131136 }
132137 }
\ No newline at end of file
Index: trunk/extensions/Storyboard/specials/StoryReview/storyreview.js
@@ -0,0 +1,37 @@
 2+//(function($) {
 3+
 4+ function doStoryAction( sender, storyid, action ) {
 5+ sender.disabled = true;
 6+
 7+ jQuery.getJSON( wgScriptPath + '/api.php',
 8+ {
 9+ 'action': 'storyreview',
 10+ 'format': 'json',
 11+ 'storyid': storyid,
 12+ 'storyaction': action
 13+ },
 14+ function( data ) {
 15+ if ( data.result ) {
 16+ switch( data.result.action ) {
 17+ case 'publish' : case 'unpublish' : case 'hide' :
 18+ jQuery( '#story_' + data.result.id ).slideUp( 'slow', function () {
 19+ jQuery( this ).remove();
 20+ } );
 21+ // TODO: would be neat to update the other list when doing an (un)publish here
 22+ break;
 23+ // TODO: add handling for the other actions
 24+ }
 25+ } else {
 26+ alert( 'An error occured:\n' + data.error.info ); // TODO: i18n
 27+ }
 28+ }
 29+ );
 30+ }
 31+
 32+ function deleteStoryImage( sender, storyid ) {
 33+ if ( confirm( 'Are you sure you want to permanently delete this stories image?' ) ) { // TODO: i18n
 34+ doStoryAction( sender, storyid, 'deleteimage' )
 35+ }
 36+ }
 37+
 38+//})(jQuery);
\ No newline at end of file
Property changes on: trunk/extensions/Storyboard/specials/StoryReview/storyreview.js
___________________________________________________________________
Name: svn:eol-style
139 + native
Index: trunk/extensions/Storyboard/story.css
@@ -0,0 +1,35 @@
 2+/**
 3+ * Css for stories, used at variouse places in the Storyboard extension.
 4+ *
 5+ * @file story.css
 6+ * @ingroup Storyboard
 7+ *
 8+ * @author Jeroen De Dauw
 9+ */
 10+
 11+.story {
 12+ margin-left: 15px;
 13+ margin-top: 5px;
 14+ float: left;
 15+ overflow: hidden;
 16+}
 17+.story-title {
 18+ font: 16px "Lucida Sans", Verdana;
 19+ font-weight: bold;
 20+ float: left;
 21+ overflow: hidden;
 22+}
 23+.story-image {
 24+ margin: 5px 15px 0px 15px;
 25+ float: right;
 26+}
 27+
 28+.story-sharing {
 29+ height: 30px;
 30+ width: 110px;
 31+ float: right;
 32+}
 33+.story-sharing-item {
 34+ float: left;
 35+ padding-right: 5px;
 36+}
\ No newline at end of file
Property changes on: trunk/extensions/Storyboard/story.css
___________________________________________________________________
Name: svn:eol-style
137 + native
Index: trunk/extensions/Storyboard/api/ApiStoryReview.php
@@ -49,16 +49,15 @@
5050 $params = $this->extractRequestParams();
5151
5252 // Check required parameters
53 - if ( !array_key_exists( 'storyid', $params ) ) {
 53+ if ( !isset( $params['storyid'] ) ) {
5454 $this->dieUsageMsg( array( 'missingparam', 'storyid' ) );
5555 }
56 - if ( !array_key_exists( 'storyaction', $params ) ) {
 56+ if ( !isset( $params['storyaction'] ) ) {
5757 $this->dieUsageMsg( array( 'missingparam', 'storyaction' ) );
5858 }
5959
60 - // TODO: test the actions after using them in the storyreview special page
6160 $dbw = wfGetDB( DB_MASTER );
62 -
 61+
6362 if ( $params['storyaction'] == 'delete' ) {
6463 $dbw->delete( 'storyboard', array( 'story_id' => $dbw->escape( $params['storyid'] ) ) );
6564 } else {
@@ -92,7 +91,7 @@
9392 'story_image_hidden' => 1
9493 );
9594 break;
96 - case 'showimage' :
 95+ case 'unhideimage' :
9796 $values = array(
9897 'story_image_hidden' => 0
9998 );
@@ -100,12 +99,20 @@
101100 case 'deleteimage' :
102101 $values = array(
103102 'story_author_image' => ''
104 - );
 103+ ); // TODO: should image file also be removed?
105104 break;
106105 }
107106
108107 $dbw->update( 'storyboard', $values, $conds );
109108 }
 109+
 110+ $result = array(
 111+ 'action' => $params['storyaction'],
 112+ 'id' => $params['storyid'],
 113+ );
 114+
 115+ $this->getResult()->setIndexedTagName( $result, 'story' );
 116+ $this->getResult()->addValue( null, 'result', $result );
110117 }
111118
112119 public function getAllowedParams() {
@@ -120,7 +127,7 @@
121128 'publish',
122129 'unpublish',
123130 'hideimage',
124 - 'showimage',
 131+ 'unhideimage',
125132 'deleteimage',
126133 )
127134 ),

Follow-up revisions

RevisionCommit summaryAuthorDate
r63775Follow up to r63758 and r63763.jeroendedauw16:35, 15 March 2010

Comments

#Comment by Catrope (talk | contribs)   15:30, 15 March 2010
+		$publishAction = $story->story_is_published ? 'unpublish' : 'publish';
+		$publishMsg = wfMsg( "storyboard-$publishAction" );

When doing stuff like this (variable message keys), include a comment mentioning the possible message keys verbatim, so it'll show up when grepping. Something like:

// Uses storyboard-publish or storyboard-unpublish (comment for easy grepping)

It'd also be nice to escape wfMsg()'s return value with htmlspecialchars() so as to avoid creating more messages whose contents are directly injected into HTML, but at least part of that is probably my personal opinion. I'll ask Nikerabbit about this.

+//(function($) {
...
+		jQuery.getJSON( wgScriptPath + '/api.php',
...
+//})(jQuery);

You can use the (function($) { trick even when not adding a jQuery plugin, so you can uncomment the first and last lines and replace jQuery with $.

+		$this->getResult()->addValue( null, 'result', $result );

For consistency with other API modules, you should use the name of the module (i.e. $this->getModuleName()) instead of 'result'.

#Comment by Jeroen De Dauw (talk | contribs)   16:25, 15 March 2010

When I use the

(function($) {

stuff, I'll get an error saying function doStoryAction is not found.

#Comment by Catrope (talk | contribs)   16:28, 15 March 2010

D'oh, I should've seen that. Forget about it then.

Status & tagging log