jenkins-bot has submitted this change and it was merged.

Change subject: Fix error handling
......................................................................


Fix error handling

There's a couple of changes here:
* added new findUpward method: use with caution as it can potentially seek a lot
  of DOM nodes (but I'm ok with it - it's limited: html will never be nested
  deep enough for it to cause problems)
* made error handling more generic; no need to pass container - just have error
  container somewhere near ;)
* a bunch of GET calls had no errors displaying (only removeError was called)
* switched a couple of flow_errors in templates (mostly to get them to show in
  processing GET stuff)

Bug: 68021
Change-Id: Id29473cabda78fa9ea5d9ca7d996e9485b0bdbf6
---
M Resources.php
M handlebars/compiled/flow_block_header.handlebars.php
M handlebars/compiled/flow_block_header_edit.handlebars.php
M handlebars/compiled/flow_block_topic.handlebars.php
M handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
M handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
M handlebars/compiled/flow_block_topiclist.handlebars.php
M handlebars/compiled/flow_post.handlebars.php
M handlebars/flow_block_header.handlebars
M handlebars/flow_block_header_edit.handlebars
M handlebars/flow_post.handlebars
M handlebars/flow_topic_titlebar_close.handlebars
M handlebars/flow_topic_titlebar_summary.handlebars
M i18n/en.json
M i18n/qqq.json
M modules/new/components/flow-board.js
16 files changed, 182 insertions(+), 109 deletions(-)

Approvals:
  EBernhardson: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Resources.php b/Resources.php
index 8fddb51..31bc10f 100644
--- a/Resources.php
+++ b/Resources.php
@@ -315,6 +315,7 @@
                ),
                'messages' => array(
                        'flow-error-http',
+                       'flow-error-fetch-after-open-close',
                )
        ),
        'ext.flow.vendor.storer' => $flowResourceTemplate + array(
diff --git a/handlebars/compiled/flow_block_header.handlebars.php 
b/handlebars/compiled/flow_block_header.handlebars.php
index ab12b30..fa1250b 100644
--- a/handlebars/compiled/flow_block_header.handlebars.php
+++ b/handlebars/compiled/flow_block_header.handlebars.php
@@ -9,7 +9,8 @@
             'mustlok' => false,
             'debug' => $debugopt,
         ),
-        'helpers' => Array(            'escapeContent' => 
'Flow\TemplateHelper::escapeContent',
+        'helpers' => Array(            'html' => 
'Flow\TemplateHelper::htmlHelper',
+            'escapeContent' => 'Flow\TemplateHelper::escapeContent',
 ),
         'blockhelpers' => Array(),
         'hbhelpers' => Array(),
@@ -18,6 +19,18 @@
 
     );
     return '<div class="flow-board-header">
+       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
        <div class="flow-board-header-detail-view">
                '.((LCRun3::ifvar($cx, ((is_array($in['revision']) && 
isset($in['revision']['content'])) ? $in['revision']['content'] : null))) ? '
                        '.LCRun3::ch($cx, 'escapeContent', 
Array(Array(((is_array($in['revision']['content']) && 
isset($in['revision']['content']['format'])) ? 
$in['revision']['content']['format'] : 
null),((is_array($in['revision']['content']) && 
isset($in['revision']['content']['content'])) ? 
$in['revision']['content']['content'] : null)),Array()), 'encq').'
diff --git a/handlebars/compiled/flow_block_header_edit.handlebars.php 
b/handlebars/compiled/flow_block_header_edit.handlebars.php
index a2a0608..63a85a7 100644
--- a/handlebars/compiled/flow_block_header_edit.handlebars.php
+++ b/handlebars/compiled/flow_block_header_edit.handlebars.php
@@ -21,7 +21,6 @@
     );
     return '<div class="flow-board-header">
        <div class="flow-board-header-edit-view">
-
                <form method="POST" 
action="'.htmlentities(((is_array($in['revision']['actions']['edit']) && 
isset($in['revision']['actions']['edit']['url'])) ? 
$in['revision']['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'" 
flow-api-action="edit-header">
                        <div class="flow-error-container">
 '.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
diff --git a/handlebars/compiled/flow_block_topic.handlebars.php 
b/handlebars/compiled/flow_block_topic.handlebars.php
index 13dbbcc..9ca1a9b 100644
--- a/handlebars/compiled/flow_block_topic.handlebars.php
+++ b/handlebars/compiled/flow_block_topic.handlebars.php
@@ -56,6 +56,18 @@
 <span class="flow-reply-count"><span class="wikiglyph 
wikiglyph-speech-bubble"></span><span 
class="flow-reply-count-number">'.htmlentities(((is_array($in) && 
isset($in['reply_count'])) ? $in['reply_count'] : null), ENT_QUOTES, 
'UTF-8').'</span></span>
 
 <div class="flow-topic-summary-container">
+       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
        '.((LCRun3::ifvar($cx, ((is_array($in) && isset($in['summary'])) ? 
$in['summary'] : null))) ? '
                <div class="flow-topic-summary">
                        '.LCRun3::ch($cx, 'escapeContent', 
Array(Array(((is_array($in['summary']) && isset($in['summary']['format'])) ? 
$in['summary']['format'] : null),((is_array($in['summary']) && 
isset($in['summary']['content'])) ? $in['summary']['content'] : 
null)),Array()), 'encq').'
diff --git a/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php 
b/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
index 8a100db..934b20b 100644
--- a/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
+++ b/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
@@ -61,6 +61,19 @@
                         data-flow-post-max-depth="1"
                         ' : '').'>
                <div class="flow-post-main">
+                       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
+
                        '.LCRun3::wi($cx, ((is_array($in) && 
isset($in['creator'])) ? $in['creator'] : null), $in, function($cx, $in) 
{return '
                                '.((LCRun3::ifvar($cx, ((is_array($in) && 
isset($in['isPreview'])) ? $in['isPreview'] : null))) ? '
        <span class="flow-author"><a href="#" class="mw-userlink">
diff --git a/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php 
b/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
index 0c387ed..4b5c896 100644
--- a/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
+++ b/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
@@ -63,6 +63,19 @@
                         data-flow-post-max-depth="1"
                         ' : '').'>
                <div class="flow-post-main">
+                       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
+
                        '.LCRun3::wi($cx, ((is_array($in) && 
isset($in['creator'])) ? $in['creator'] : null), $in, function($cx, $in) 
{return '
                                '.((LCRun3::ifvar($cx, ((is_array($in) && 
isset($in['isPreview'])) ? $in['isPreview'] : null))) ? '
        <span class="flow-author"><a href="#" class="mw-userlink">
diff --git a/handlebars/compiled/flow_block_topiclist.handlebars.php 
b/handlebars/compiled/flow_block_topiclist.handlebars.php
index cb363ac..72cf876 100644
--- a/handlebars/compiled/flow_block_topiclist.handlebars.php
+++ b/handlebars/compiled/flow_block_topiclist.handlebars.php
@@ -151,6 +151,18 @@
 <span class="flow-reply-count"><span class="wikiglyph 
wikiglyph-speech-bubble"></span><span 
class="flow-reply-count-number">'.htmlentities(((is_array($in) && 
isset($in['reply_count'])) ? $in['reply_count'] : null), ENT_QUOTES, 
'UTF-8').'</span></span>
 
 <div class="flow-topic-summary-container">
+       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
        '.((LCRun3::ifvar($cx, ((is_array($in) && isset($in['summary'])) ? 
$in['summary'] : null))) ? '
                <div class="flow-topic-summary">
                        '.LCRun3::ch($cx, 'escapeContent', 
Array(Array(((is_array($in['summary']) && isset($in['summary']['format'])) ? 
$in['summary']['format'] : null),((is_array($in['summary']) && 
isset($in['summary']['content'])) ? $in['summary']['content'] : 
null)),Array()), 'encq').'
diff --git a/handlebars/compiled/flow_post.handlebars.php 
b/handlebars/compiled/flow_post.handlebars.php
index 3242d02..022a149 100644
--- a/handlebars/compiled/flow_post.handlebars.php
+++ b/handlebars/compiled/flow_post.handlebars.php
@@ -11,6 +11,7 @@
         ),
         'helpers' => Array(            'l10n' => 'Flow\TemplateHelper::l10n',
             'uuidTimestamp' => 'Flow\TemplateHelper::uuidTimestamp',
+            'html' => 'Flow\TemplateHelper::htmlHelper',
             'post' => 'Flow\TemplateHelper::post',
             'escapeContent' => 'Flow\TemplateHelper::escapeContent',
 ),
@@ -29,6 +30,19 @@
                         data-flow-post-max-depth="1"
                         ' : '').'>
                <div class="flow-post-main">
+                       <div class="flow-error-container">
+'.((LCRun3::ifvar($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null))) ? '
+       <div class="flow-errors errorbox">
+               <ul>
+                       '.LCRun3::sec($cx, ((is_array($cx['scopes'][0]) && 
isset($cx['scopes'][0]['errors'])) ? $cx['scopes'][0]['errors'] : null), $in, 
true, function($cx, $in) {return '
+                               <li>'.LCRun3::ch($cx, 'html', 
Array(Array(((is_array($in) && isset($in['message'])) ? $in['message'] : 
null)),Array()), 'encq').'</li>
+                       ';}).'
+               </ul>
+       </div>
+' : '').'
+</div>
+
+
                        '.LCRun3::wi($cx, ((is_array($in) && 
isset($in['creator'])) ? $in['creator'] : null), $in, function($cx, $in) 
{return '
                                '.((LCRun3::ifvar($cx, ((is_array($in) && 
isset($in['isPreview'])) ? $in['isPreview'] : null))) ? '
        <span class="flow-author"><a href="#" class="mw-userlink">
@@ -238,4 +252,4 @@
 ';}).'
 ';
 }
-?>
+?>
\ No newline at end of file
diff --git a/handlebars/flow_block_header.handlebars 
b/handlebars/flow_block_header.handlebars
index a95a35c..19f01f2 100644
--- a/handlebars/flow_block_header.handlebars
+++ b/handlebars/flow_block_header.handlebars
@@ -1,4 +1,5 @@
 <div class="flow-board-header">
+       {{> flow_errors}}
        <div class="flow-board-header-detail-view">
                {{#if revision.content}}
                        {{escapeContent revision.content.format 
revision.content.content}}
diff --git a/handlebars/flow_block_header_edit.handlebars 
b/handlebars/flow_block_header_edit.handlebars
index 9b02600..8f37715 100644
--- a/handlebars/flow_block_header_edit.handlebars
+++ b/handlebars/flow_block_header_edit.handlebars
@@ -1,8 +1,7 @@
 <div class="flow-board-header">
        <div class="flow-board-header-edit-view">
-
                <form method="POST" action="{{revision.actions.edit.url}}" 
flow-api-action="edit-header">
-                       {{> flow_errors}}
+                       {{> flow_errors }}
                        <input type="hidden" name="wpEditToken" 
value="{{@root.editToken}}" />
                        {{#if revision.revisionId}}
                                <input type="hidden" 
name="header_prev_revision" value="{{revision.revisionId}}" />
diff --git a/handlebars/flow_post.handlebars b/handlebars/flow_post.handlebars
index 91bb06a..ba88cb2 100644
--- a/handlebars/flow_post.handlebars
+++ b/handlebars/flow_post.handlebars
@@ -6,6 +6,8 @@
                         data-flow-post-max-depth="1"
                         {{/if}}>
                <div class="flow-post-main">
+                       {{> flow_errors}}
+
                        {{#with creator}}
                                {{> flow_post_author}}
                        {{/with}}
diff --git a/handlebars/flow_topic_titlebar_close.handlebars 
b/handlebars/flow_topic_titlebar_close.handlebars
index c7d5123..64206e9 100644
--- a/handlebars/flow_topic_titlebar_close.handlebars
+++ b/handlebars/flow_topic_titlebar_close.handlebars
@@ -7,7 +7,7 @@
                                {{~else~}}
                                        {{~actions.close.url~}}
                                {{~/if~}}">
-                       {{> flow_errors}}
+                       {{> flow_errors }}
                        <input type="hidden" name="wpEditToken" 
value="{{@root.editToken}}" />
                        {{#if summary.revId}}
                                <input type="hidden" name="flow_prev_revision" 
value="{{summary.revId}}" />
diff --git a/handlebars/flow_topic_titlebar_summary.handlebars 
b/handlebars/flow_topic_titlebar_summary.handlebars
index a745d69..5dcc60d 100644
--- a/handlebars/flow_topic_titlebar_summary.handlebars
+++ b/handlebars/flow_topic_titlebar_summary.handlebars
@@ -1,4 +1,5 @@
 <div class="flow-topic-summary-container">
+       {{> flow_errors }}
        {{#if summary}}
                <div class="flow-topic-summary">
                        {{escapeContent summary.format summary.content}}
diff --git a/i18n/en.json b/i18n/en.json
index 92d93aa..a24bd22 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -137,6 +137,7 @@
     "flow-error-no-index": "Failed to find an index to perform data search.",
     "flow-error-no-render": "The specified action was not recognized.",
     "flow-error-no-commit": "The specified action could not be saved.",
+    "flow-error-fetch-after-open-close": "An error was encountered when 
requesting the new data. The open/close operation succeeded just fine, though. 
The error message was: $1",
     "flow-edit-header-placeholder": "Describe this Flow board",
     "flow-edit-header-submit": "Save header",
     "flow-edit-header-submit-overwrite": "Overwrite header",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 4404ff7..e16eca0 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -141,6 +141,7 @@
        "flow-error-no-index": "Error message when failing to find an index to 
perform data search.",
        "flow-error-no-render": "Error message when nothing was able to render 
the request (data was requested but it could not be processed).",
        "flow-error-no-commit": "Error message when nothing was able to commit 
the request (data was submitted but it could not be processed).",
+       "flow-error-fetch-after-open-close": "Error message to be displayed 
when failing to request the new data after successfully performing open/close 
topic. This is meant to indicate to the user that some error was encountered, 
but that the open/close actually succeeded just fine - we just failed to get 
the new data to display the new status. Parameters:\n* $1 - The error message 
received.",
        "flow-edit-header-placeholder": "Used as placeholder when editing the 
header of a Flow board",
        "flow-edit-header-submit": "Used as label for the Submit button.",
        "flow-edit-header-submit-overwrite": "Used as label for the Submit 
button, when submitting will overwrite a more recent change.",
diff --git a/modules/new/components/flow-board.js 
b/modules/new/components/flow-board.js
index 7011b32..0aa63c2 100644
--- a/modules/new/components/flow-board.js
+++ b/modules/new/components/flow-board.js
@@ -350,21 +350,10 @@
                 */
                FlowBoardComponent.UI.events.apiHandlers.board = function ( 
info, data, jqxhr ) {
                        var flowBoard = 
FlowBoardComponent.prototype.getInstanceByElement( $( this ) ),
-                               $errorTarget = flowBoard.$container.find( 
'.flow-board-navigation' ),
                                $rendered;
 
-                       // Generic error handling only works on forms; the 
interactive
-                       // element here is the header div that should be 
replaced, so let's
-                       // take care of displaying the error ourselves.
-                       // @todo: error handling should probably be made more 
generic
-                       // @todo: errorify me
-                       FlowBoardComponent.UI.removeError( $errorTarget );
                        if ( info.status !== 'done' ) {
-                               if ( jqxhr.error ) {
-                                       FlowBoardComponent.UI.showError( 
$errorTarget, jqxhr.error.info );
-                               } else {
-                                       FlowBoardComponent.UI.showError( 
$errorTarget, mw.msg( 'flow-error-http' ) );
-                               }
+                               // Error will be displayed by default, nothing 
else to wrap up
                                return;
                        }
 
@@ -388,20 +377,10 @@
                FlowBoardComponent.UI.events.apiHandlers.loadMore = function ( 
info, data, jqxhr ) {
                        var $this = $( this ),
                                flowBoard = 
FlowBoardComponent.prototype.getInstanceByElement( $this ),
-                               $errorTarget = $this.closest( '.flow-load-more' 
),
                                $tmp;
 
-                       // Generic error handling only works on forms; the 
interactive
-                       // element here is the header div that should be 
replaced, so let's
-                       // take care of displaying the error ourselves.
-                       // @todo: error handling should probably be made more 
generic
-                       FlowBoardComponent.UI.removeError( $errorTarget );
                        if ( info.status !== 'done' ) {
-                               if ( jqxhr.error ) {
-                                       FlowBoardComponent.UI.showError( 
$errorTarget, jqxhr.error.info );
-                               } else {
-                                       FlowBoardComponent.UI.showError( 
$errorTarget, mw.msg( 'flow-error-http' ) );
-                               }
+                               // Error will be displayed by default, nothing 
else to wrap up
                                return;
                        }
 
@@ -447,16 +426,11 @@
                 */
                FlowBoardComponent.UI.events.apiHandlers.activateEditHeader = 
function ( info, data, jqxhr ) {
                        var flowBoard = 
FlowBoardComponent.prototype.getInstanceByElement( $( this ) ),
-                               $target = info.$target,
                                $oldBoardNodes,
                                $rendered;
 
-                       // Generic error handling only works on forms; the 
interactive
-                       // element here is the header div that should be 
replaced, so let's
-                       // take care of displaying the error ourselves.
-                       // @todo: error handling should probably be made more 
generic
-                       FlowBoardComponent.UI.removeError( $target );
                        if ( info.status !== 'done' ) {
+                               // Error will be displayed by default & edit 
conflict handled, nothing else to wrap up
                                return;
                        }
 
@@ -520,11 +494,8 @@
 
                        $( this ).closest( '.flow-menu' ).removeClass( 'focus' 
);
 
-                       // Generic form error handling only works on forms; the 
interactive
-                       // element here is the summary div that should be 
replaced,
-                       // so lets take ore of displaying the error ourselves.
-                       FlowBoardComponent.UI.removeError( $old );
                        if ( info.status !== 'done' ) {
+                               // Error will be displayed by default & edit 
conflict handled, nothing else to wrap up
                                return;
                        }
 
@@ -568,51 +539,61 @@
                                flowBoard = 
FlowBoardComponent.prototype.getInstanceByElement( $( this ) ),
                                flowId = $( self ).closest( 
'.flow-topic-titlebar' ).parent().data( 'flow-id' );
 
-                       if ( info.status === 'done' ) {
-                               // We couldn't make close-open-topic to return 
topic data after a successful
-                               // post submission because close-open-topic is 
used for no-js support as well.
-                               // If we make it return topic data, that means 
it has to return wikitext format
-                               // for edit form in no-js mode.  This is a 
performance problem for wikitext
-                               // conversion since topic data returns all 
children data as well.  So we need to
-                               // make close-open-topic return a single post 
for topic then fire
-                               // another request to topic data in html format
-                               //
-                               // @todo the html could json encode the 
parameters including topics, the js
-                               // could then import that and continuously 
update it with new revisions from
-                               // api calls.  Rendering a topic would then 
just be pointing the template at
-                               // the right part of that data instead of 
requesting it.
-                               flowBoard.API.apiCall( {
-                                       action: 'flow',
-                                       submodule: 'view-topic',
-                                       workflow: flowId,
-                                       // Flow topic title, in Topic:<topicId> 
format (2600 is topic namespace id)
-                                       page: mw.Title.newFromText( flowId, 
2600 ).getPrefixedDb()
-                               } ).done( function( result ) {
-                                       // FIXME: Why doesn't the API return 
this?
-                                       result = 
result.flow['view-topic'].result.topic;
-                                       topicId = result.roots[0];
-                                       revisionId = result.posts[topicId];
-                                       revision = result.revisions[revisionId];
-
-                                       // FIXME: Api should be returning 
moderation state. Why not?
-                                       revision.isModerated = 
revision.moderateState === 'close';
-
-                                       // FIXME: Hackily remove the moderated 
class (avoids re-rendering entire post)
-                                       $target.parents( '.flow-topic' 
).removeClass( 'flow-topic-moderated' );
-
-                                       // Update view of the title bar
-                                       $topicTitleBar = $(
-                                               
flowBoard.TemplateEngine.processTemplateGetFragment(
-                                                       'flow_topic_titlebar',
-                                                       revision
-                                               )
-                                       ).children();
-                                       $target.replaceWith( $topicTitleBar );
-                                       
FlowBoardComponent.UI.makeContentInteractive( $topicTitleBar );
-                               } );
-                       } else {
+                       if ( info.status !== 'done' ) {
+                               // Error will be displayed by default & edit 
conflict handled, nothing else to wrap up
                                return;
                        }
+
+                       // We couldn't make close-open-topic to return topic 
data after a successful
+                       // post submission because close-open-topic is used for 
no-js support as well.
+                       // If we make it return topic data, that means it has 
to return wikitext format
+                       // for edit form in no-js mode.  This is a performance 
problem for wikitext
+                       // conversion since topic data returns all children 
data as well.  So we need to
+                       // make close-open-topic return a single post for topic 
then fire
+                       // another request to topic data in html format
+                       //
+                       // @todo the html could json encode the parameters 
including topics, the js
+                       // could then import that and continuously update it 
with new revisions from
+                       // api calls.  Rendering a topic would then just be 
pointing the template at
+                       // the right part of that data instead of requesting it.
+                       flowBoard.API.apiCall( {
+                               action: 'flow',
+                               submodule: 'view-topic',
+                               workflow: flowId,
+                               // Flow topic title, in Topic:<topicId> format 
(2600 is topic namespace id)
+                               page: mw.Title.newFromText( flowId, 2600 
).getPrefixedDb()
+                       } ).done( function( result ) {
+                               // FIXME: Why doesn't the API return this?
+                               result = result.flow['view-topic'].result.topic;
+                               topicId = result.roots[0];
+                               revisionId = result.posts[topicId];
+                               revision = result.revisions[revisionId];
+
+                               // FIXME: Api should be returning moderation 
state. Why not?
+                               revision.isModerated = revision.moderateState 
=== 'close';
+
+                               // FIXME: Hackily remove the moderated class 
(avoids re-rendering entire post)
+                               $target.parents( '.flow-topic' ).removeClass( 
'flow-topic-moderated' );
+
+                               // Update view of the title bar
+                               $topicTitleBar = $(
+                                       
flowBoard.TemplateEngine.processTemplateGetFragment(
+                                               'flow_topic_titlebar',
+                                               revision
+                                       )
+                               ).children();
+                               $target.replaceWith( $topicTitleBar );
+                               FlowBoardComponent.UI.makeContentInteractive( 
$topicTitleBar );
+                       } ).fail( function( code, result ) {
+                               /*
+                                * At this point, the open/close actually 
worked, but failed
+                                * fetching the new data to be displayed.
+                                */
+                               FlowBoardComponent.UI.removeError( $target );
+                               var errorMsg = result.error ? result.error.info 
: mw.msg( 'flow-error-http' );
+                               errorMsg = mw.msg( 
'flow-error-fetch-after-open-close', errorMsg );
+                               FlowBoardComponent.UI.showError( $target, 
errorMsg );
+                       } );
                };
 
                /**
@@ -889,12 +870,8 @@
                                $old = $target,
                                flowBoard = 
FlowBoardComponent.prototype.getInstanceByElement( $( this ) );
 
-                       // Generic error handling only works on forms; the 
interactive
-                       // element here is the summary div that should be 
replaced, so let's
-                       // take care of displaying the error ourselves.
-                       // @todo: error handling should probably be made more 
generic
-                       FlowBoardComponent.UI.removeError( $old );
                        if ( info.status !== 'done' ) {
+                               // Error will be displayed by default, nothing 
else to wrap up
                                return;
                        }
 
@@ -961,12 +938,8 @@
                                $post = info.$target,
                                $rendered;
 
-                       // Generic error handling only works on forms; the 
interactive
-                       // element here is the post div that should be 
replaced, so let's
-                       // take care of displaying the error ourselves.
-                       // @todo: error handling should probably be made more 
generic
-                       FlowBoardComponent.UI.removeError( $post );
                        if ( info.status !== 'done' ) {
+                               // Error will be displayed by default, nothing 
else to wrap up
                                return;
                        }
 
@@ -1438,7 +1411,7 @@
                        } );
 
                        // Remove existing errors from previous attempts
-                       FlowBoardComponent.UI.removeError( $this.closest( 
'form' ) );
+                       FlowBoardComponent.UI.removeError( $this );
 
                        // If this has a special api handler, bind it to the 
callback.
                        if ( FlowBoardComponent.UI.events.apiHandlers[ 
handlerName ] ) {
@@ -1454,7 +1427,6 @@
                                                        $form = $this.closest( 
'form' ),
                                                        errorMsg;
                                                info.status = 'fail';
-                                               info.$container = 
$this.closest( 'form' );
                                                args.unshift( info );
 
                                                /*
@@ -1468,18 +1440,14 @@
 
                                                /*
                                                 * Generic error handling: 
displays error message in the
-                                                * current form. If this is 
inappropriate for a
-                                                * specific action, the error 
can be removed again in
-                                                * the subsequent call to that 
specific api handler, by
-                                                * calling 
FlowBoardComponent.UI.removeError() with
-                                                * info.$container as argument.
+                                                * nearest error container.
                                                 *
                                                 * Errors returned by MW/Flow 
should always be in the
                                                 * same format. If the request 
failed without a specific
                                                 * error message, just fall 
back to some default error.
                                                 */
                                                errorMsg = result.error ? 
result.error.info : mw.msg( 'flow-error-http' );
-                                               
FlowBoardComponent.UI.showError( $form, errorMsg );
+                                               
FlowBoardComponent.UI.showError( info.$target, errorMsg );
 
                                                
FlowBoardComponent.UI.events.apiHandlers[ handlerName ].apply( _this, args );
                                        } );
@@ -1792,29 +1760,52 @@
                ////////////////////
 
                /**
-                * @param {FlowBoardComponent|jQuery} $container or entire 
FlowBoard
+                * @param {FlowBoardComponent|jQuery} $node or entire FlowBoard
                 * @param string msg The error that occurred. Currently 
hardcoded.
                 */
-               FlowBoardComponent.UI.showError = function ( $container, msg ) {
+               FlowBoardComponent.UI.showError = function ( $node, msg ) {
                        var html = mw.flow.TemplateEngine.processTemplate( 
'flow_errors', { errors: [ { message: msg } ] } );
 
-                       if ( !$container.jquery ) {
-                               $container = $container.$container;
+                       if ( !$node.jquery ) {
+                               $node = $node.$container;
                        }
 
-                       $container.find( '.flow-content-preview' ).hide();
-                       $container.find( '.flow-error-container' ).replaceWith( 
html );
+                       flowFindUpward( $node, '.flow-content-preview' ).hide();
+                       flowFindUpward( $node, '.flow-error-container' 
).filter( ':first' ).replaceWith( html );
+
                        mw.log.warn( msg );
                };
 
                /**
-                * @param {FlowBoardComponent|jQuery} $container or entire 
FlowBoard
+                * @param {FlowBoardComponent|jQuery} $node or entire FlowBoard
                 */
-               FlowBoardComponent.UI.removeError = function ( $container ) {
-                       $container.find( '.flow-error-container' ).empty();
+               FlowBoardComponent.UI.removeError = function ( $node ) {
+                       flowFindUpward( $node, '.flow-error-container' 
).filter( ':first' ).empty();
                };
 
                /**
+                * Given node & a selector, this will return the result closest 
to $node
+                * by first looking inside $node, then travelling up the DOM 
tree to
+                * locate the first result in a common ancestor.
+                *
+                * @param jQuery $node
+                * @param string selector
+                * @returns jQuery
+                */
+               function flowFindUpward( $node, selector ) {
+                       // first check if result can already be found inside 
$node
+                       var $result = $node.find( selector );
+
+                       // then keep looking up the tree until a result is found
+                       while ( $result.length === 0 && $node.length !== 0 ) {
+                               $node = $node.parent();
+                               $result = $node.children( selector );
+                       }
+
+                       return $result;
+               }
+
+               /**
                 *
                 * @param {FlowBoardComponent|jQuery} $container or entire 
FlowBoard
                 * @todo Move to FlowComponent somehow, perhaps use 
name="flow-load-handler" for performance in older browsers

-- 
To view, visit https://gerrit.wikimedia.org/r/146785
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id29473cabda78fa9ea5d9ca7d996e9485b0bdbf6
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
Gerrit-Reviewer: EBernhardson <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: SG <[email protected]>
Gerrit-Reviewer: Spage <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to