Sbisson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/260006

Change subject: [WIP] Various fixes to edit-title
......................................................................

[WIP] Various fixes to edit-title

* Introduced TopicTitleWidget for editing
  - standardize cancel button
  - add anon warning
  - update browser tests

* Fixed no-js editing

Bug: T100851
Bug: T118427
Bug: T104252
Change-Id: I24eafe0a2dbdad7a133d81c089deae0d0feb8589
---
M Resources.php
M handlebars/compiled/flow_block_topic.handlebars.php
M handlebars/compiled/flow_block_topic_edit_title.handlebars.php
M handlebars/compiled/flow_block_topiclist.handlebars.php
M handlebars/compiled/flow_post.handlebars.php
M handlebars/flow_edit_topic_title.partial.handlebars
M handlebars/flow_moderation_actions_list.partial.handlebars
M includes/Block/Topic.php
M includes/UrlGenerator.php
M modules/engine/components/board/base/flow-board-api-events.js
M modules/flow/dm/api/mw.flow.dm.APIHandler.js
A modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js
M modules/mw.flow.Initializer.js
A modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less
M tests/browser/features/step_definitions/edit_existing_steps.rb
M tests/browser/features/support/pages/abstract_flow_page.rb
16 files changed, 231 insertions(+), 126 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/06/260006/1

diff --git a/Resources.php b/Resources.php
index 2432f64..9aa9c86 100644
--- a/Resources.php
+++ b/Resources.php
@@ -398,6 +398,7 @@
                        'flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js',
                        'flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js',
                        'flow/ui/widgets/mw.flow.ui.NewTopicWidget.js',
+                       'flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js',
 
                        
'flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js',
                        
'flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js',
@@ -427,6 +428,7 @@
                        
'styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less',
                        
'styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less',
                        'styles/flow/widgets/mw.flow.ui.CategoriesWidget.less',
+                       'styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less',
                ),
                'messages' => array(
                        'flow-error-parsoid-failure',
diff --git a/handlebars/compiled/flow_block_topic.handlebars.php 
b/handlebars/compiled/flow_block_topic.handlebars.php
index 87420ac..149634c 100644
--- a/handlebars/compiled/flow_block_topic.handlebars.php
+++ b/handlebars/compiled/flow_block_topic.handlebars.php
@@ -89,12 +89,8 @@
 '.$sp.'           data-flow-api-target="< .flow-topic-watchlist"
 '.$sp.'           
data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && 
is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span 
class="flow-unwatch mw-ui-icon mw-ui-icon-before 
mw-ui-icon-unStar-constructive" title="'.LCRun3::ch($cx, 'l10n', 
array(array('flow-topic-action-watchlist-remove'),array()), 
'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 
'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon 
mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-constructive-hover" 
title="'.LCRun3::ch($cx, 'l10n', 
array(array('flow-topic-action-watchlist-add'),array()), 
'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
 '.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'"
-'.$sp.'                                   
data-flow-interactive-handler="apiRequest"
-'.$sp.'                                   
data-flow-api-handler="activateEditTitle"
-'.$sp.'                                   data-flow-api-target="< 
.flow-topic-titlebar"
-'.$sp.'                                >'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit 
mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' 
: '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && 
is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] 
: null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> 
' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-history'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic']) && is_array($in['links'])) ? 
$in['links']['topic'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic']['url']) && 
is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-view'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['actions']['summarize']) && is_array($in['actions'])) ? 
$in['actions']['summarize'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && 
is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : 
null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC 
mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, 
((isset($in['summary']['revision']['content']['content']) && 
is_array($in['summary']['revision']['content'])) ? 
$in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 
'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 
'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 
'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : 
'').'';}).''.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','history'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['lock']) && is_array($in['actions'])) ? 
$in['actions']['lock'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
diff --git a/handlebars/compiled/flow_block_topic_edit_title.handlebars.php 
b/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
index f2ca4aa..cca136c 100644
--- a/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
+++ b/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
@@ -13,11 +13,9 @@
         'constants' => array(),
         'helpers' => array(            'l10n' => 'Flow\TemplateHelper::l10n',
             'html' => 'Flow\TemplateHelper::htmlHelper',
-            'l10nParse' => 'Flow\TemplateHelper::l10nParse',
 ),
         'blockhelpers' => array(),
         'hbhelpers' => array(            'eachPost' => 
'Flow\TemplateHelper::eachPost',
-            'progressiveEnhancement' => 
'Flow\TemplateHelper::progressiveEnhancement',
 ),
         'partials' => array('flow_errors' => function ($cx, $in, $sp) {return 
''.$sp.'<div class="flow-error-container">
 '.$sp.''.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['errors']) && 
is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null))) 
? '  <div class="flow-errors errorbox">
@@ -32,16 +30,8 @@
 '.$sp.'        <input name="topic_content" class="mw-ui-input" 
value="'.((LCRun3::ifvar($cx, 
((isset($cx['sp_vars']['root']['submitted']['content']) && 
is_array($cx['sp_vars']['root']['submitted'])) ? 
$cx['sp_vars']['root']['submitted']['content'] : null))) ? 
''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) 
&& is_array($cx['sp_vars']['root']['submitted'])) ? 
$cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'' 
: ''.htmlentities((string)((isset($in['content']['content']) && 
is_array($in['content'])) ? $in['content']['content'] : null), ENT_QUOTES, 
'UTF-8').'').'" />
 '.$sp.'        <div class="flow-form-actions">
 '.$sp.'                <button data-role="submit"
-'.$sp.'                        data-flow-api-handler="submitTopicTitle"
-'.$sp.'                        data-flow-api-target="< .flow-topic"
 '.$sp.'                        class="mw-ui-button 
mw-ui-constructive">'.LCRun3::ch($cx, 'l10n', 
array(array('flow-edit-title-submit'),array()), 'encq').'</button>
-'.$sp.'
-'.$sp.''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array()), 
$in, false, function($cx, $in)use($sp){return '                   <button 
data-role="cancel"
-'.$sp.'                                type="reset"
-'.$sp.'                                
data-flow-interactive-handler="cancelForm"
-'.$sp.'                                class="mw-ui-button mw-ui-destructive 
mw-ui-quiet">'.LCRun3::ch($cx, 'l10n', array(array('flow-cancel'),array()), 
'encq').'</button>
-'.$sp.'                        <small class="flow-terms-of-use 
plainlinks">'.LCRun3::ch($cx, 'l10nParse', 
array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
-'.$sp.'';}).'  </div>
+'.$sp.'        </div>
 '.$sp.'</form>
 ';},),
         'scopes' => array(),
diff --git a/handlebars/compiled/flow_block_topiclist.handlebars.php 
b/handlebars/compiled/flow_block_topiclist.handlebars.php
index bf1c557..fe9fc6f 100644
--- a/handlebars/compiled/flow_block_topiclist.handlebars.php
+++ b/handlebars/compiled/flow_block_topiclist.handlebars.php
@@ -134,12 +134,8 @@
 '.$sp.'           data-flow-api-target="< .flow-topic-watchlist"
 '.$sp.'           
data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && 
is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span 
class="flow-unwatch mw-ui-icon mw-ui-icon-before 
mw-ui-icon-unStar-constructive" title="'.LCRun3::ch($cx, 'l10n', 
array(array('flow-topic-action-watchlist-remove'),array()), 
'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 
'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon 
mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-constructive-hover" 
title="'.LCRun3::ch($cx, 'l10n', 
array(array('flow-topic-action-watchlist-add'),array()), 
'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
 '.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'"
-'.$sp.'                                   
data-flow-interactive-handler="apiRequest"
-'.$sp.'                                   
data-flow-api-handler="activateEditTitle"
-'.$sp.'                                   data-flow-api-target="< 
.flow-topic-titlebar"
-'.$sp.'                                >'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit 
mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' 
: '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && 
is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] 
: null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> 
' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-history'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic']) && is_array($in['links'])) ? 
$in['links']['topic'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic']['url']) && 
is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-view'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['actions']['summarize']) && is_array($in['actions'])) ? 
$in['actions']['summarize'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && 
is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : 
null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC 
mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, 
((isset($in['summary']['revision']['content']['content']) && 
is_array($in['summary']['revision']['content'])) ? 
$in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 
'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 
'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 
'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : 
'').'';}).''.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','history'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['lock']) && is_array($in['actions'])) ? 
$in['actions']['lock'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
diff --git a/handlebars/compiled/flow_post.handlebars.php 
b/handlebars/compiled/flow_post.handlebars.php
index b9f6791..d8fd37f 100644
--- a/handlebars/compiled/flow_post.handlebars.php
+++ b/handlebars/compiled/flow_post.handlebars.php
@@ -76,12 +76,8 @@
 '.$sp.'                        <a 
href="'.htmlentities((string)((isset($in['links']['diff-prev']['url']) && 
is_array($in['links']['diff-prev'])) ? $in['links']['diff-prev']['url'] : 
null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 
'uuidTimestamp', array(array(((isset($in['lastEditId']) && is_array($in)) ? 
$in['lastEditId'] : null)),array()), 'encq').'</a>
 '.$sp.'').'    </span>
 '.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'"
-'.$sp.'                                   
data-flow-interactive-handler="apiRequest"
-'.$sp.'                                   
data-flow-api-handler="activateEditTitle"
-'.$sp.'                                   data-flow-api-target="< 
.flow-topic-titlebar"
-'.$sp.'                                >'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit 
mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return 
''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','topic'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['edit']) && is_array($in['actions'])) ? 
$in['actions']['edit'] : null))) ? '<li 
class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && 
is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' 
: '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic-history']) && is_array($in['links'])) ? 
$in['links']['topic-history'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && 
is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] 
: null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> 
' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-history'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['links']['topic']) && is_array($in['links'])) ? 
$in['links']['topic'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-quiet"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['links']['topic']['url']) && 
is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), 
ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) 
&& is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon 
mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', 
array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-view'),array()), 'raw')),array()), 
'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, 
((isset($in['actions']['summarize']) && is_array($in['actions'])) ? 
$in['actions']['summarize'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
 '.$sp.'                                   
href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && 
is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : 
null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, 
((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : 
null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC 
mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, 
((isset($in['summary']['revision']['content']['content']) && 
is_array($in['summary']['revision']['content'])) ? 
$in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 
'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 
'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', 
array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 
'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) 
? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : 
'').'';}).''.LCRun3::hbch($cx, 'ifCond', 
array(array(((isset($in['moderationType']) && is_array($in)) ? 
$in['moderationType'] : null),'===','history'),array()), $in, false, 
function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, 
((isset($in['actions']['lock']) && is_array($in['actions'])) ? 
$in['actions']['lock'] : null))) ? 
'<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? 
$in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a 
class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && 
is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
diff --git a/handlebars/flow_edit_topic_title.partial.handlebars 
b/handlebars/flow_edit_topic_title.partial.handlebars
index 836501e..ba3ed92 100644
--- a/handlebars/flow_edit_topic_title.partial.handlebars
+++ b/handlebars/flow_edit_topic_title.partial.handlebars
@@ -12,16 +12,6 @@
                " />
        <div class="flow-form-actions">
                <button data-role="submit"
-                       data-flow-api-handler="submitTopicTitle"
-                       data-flow-api-target="< .flow-topic"
                        class="mw-ui-button mw-ui-constructive">{{l10n 
"flow-edit-title-submit"}}</button>
-
-               {{#progressiveEnhancement}}
-                       <button data-role="cancel"
-                               type="reset"
-                               data-flow-interactive-handler="cancelForm"
-                               class="mw-ui-button mw-ui-destructive 
mw-ui-quiet">{{l10n "flow-cancel"}}</button>
-                       <small class="flow-terms-of-use plainlinks">{{l10nParse 
"flow-terms-of-use-edit"}}</small>
-               {{/progressiveEnhancement}}
        </div>
 </form>
diff --git a/handlebars/flow_moderation_actions_list.partial.handlebars 
b/handlebars/flow_moderation_actions_list.partial.handlebars
index 656e468..1ecd240 100644
--- a/handlebars/flow_moderation_actions_list.partial.handlebars
+++ b/handlebars/flow_moderation_actions_list.partial.handlebars
@@ -4,12 +4,8 @@
                {{~#if actions.edit~}}
                        <li class="flow-js">
                                {{~noop~}}
-                               <a class="{{moderationMwUiClass}} 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-                                  href="{{actions.edit.url}}"
-                                  data-flow-interactive-handler="apiRequest"
-                                  data-flow-api-handler="activateEditTitle"
-                                  data-flow-api-target="< .flow-topic-titlebar"
-                               >
+                               <a class="{{moderationMwUiClass}} 
mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+                                  href="{{actions.edit.url}}">
                                        {{~#if moderationIcons}}<span 
class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit 
mw-ui-icon-edit-progressive-hover"></span> {{/if~}}
                                        {{~l10n (concat 
"flow-topic-action-edit-title")~}}
                                </a>
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index dea8a7b..2f07433 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -535,11 +535,11 @@
                                $output += $this->renderTopicApi( $options );
                                break;
 
+                       case 'edit-title':
                        case 'view-post':
                        case 'view':
                        default:
                                // view single post, possibly specific revision
-                               // @todo this isn't valid for the topic title
                                $output += $this->renderPostApi( $options );
                                break;
                }
@@ -649,6 +649,8 @@
                                // known when the reply is submitted) so we'll 
grab it from the
                                // newly added revision
                                $postId = $this->newRevision->getPostId();
+                       } else {
+                               throw new FlowException('No post id specified');
                        }
                } else {
                        // $postId is only set for lock-topic, which should 
default to
diff --git a/includes/UrlGenerator.php b/includes/UrlGenerator.php
index 3c58f1a..8bb1d08 100644
--- a/includes/UrlGenerator.php
+++ b/includes/UrlGenerator.php
@@ -665,8 +665,8 @@
                        $this->resolveTitle( $title, $workflowId ),
                        array(
                                'action' => 'edit-title',
-                               // @todo not necessary?
-                               'topic_revId' => $revId->getAlphadecimal(),
+                               'topic_postId' => $postId,
+                               'topic_format' => 'topic-title-wikitext',
                        )
                );
        }
diff --git a/modules/engine/components/board/base/flow-board-api-events.js 
b/modules/engine/components/board/base/flow-board-api-events.js
index e7a83f0..53a9720 100644
--- a/modules/engine/components/board/base/flow-board-api-events.js
+++ b/modules/engine/components/board/base/flow-board-api-events.js
@@ -100,24 +100,6 @@
        };
 
        /**
-        * Before activating topic, sends an overrideObject to the API to 
modify the request params.
-        *
-        * @param {Event} event
-        * @param {Object} info
-        * @param {Object} queryMap
-        * @return {Object}
-        */
-       
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditTitle = 
function ( event, info, queryMap ) {
-               // Use view-post API for topic as well; we only want this on
-               // particular (title) post revision, not the full topic
-               return $.extend( {}, queryMap, {
-                       submodule: 'view-post',
-                       vppostId: $( this ).closest( '.flow-topic' ).data( 
'flow-id' ),
-                       vpformat: mw.flow.editor.getFormat()
-               } );
-       };
-
-       /**
         * Adjusts query params to use global watch action, and specifies it 
should use a watch token.
         * @param {Event} event
         * @param {Object} info
@@ -260,63 +242,6 @@
                        // Successful watch: show tooltip
                        flowBoard.emitWithReturn( 'showSubscribedTooltip', 
$newLink.find( '.mw-ui-icon' ), watchType );
                }
-
-               return $.Deferred().resolve().promise();
-       };
-
-       /**
-        * Shows the form for editing a topic title, it's not already showing.
-        *
-        * @param {Object} info (status:done|fail, $target: jQuery)
-        * @param {Object} data
-        * @param {jqXHR} jqxhr
-        * @return {jQuery.Promise}
-        */
-       
FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.activateEditTitle = 
function ( info, data, jqxhr ) {
-               var flowBoard, $form, cancelCallback,
-                       $link = $( this ),
-                       activeClass = 'flow-topic-title-activate-edit',
-                       rootBlock = data.flow[ 'view-post' ].result.topic,
-                       revision = rootBlock.revisions[ rootBlock.posts[ 
rootBlock.roots[ 0 ] ] ];
-
-               if ( info.status !== 'done' ) {
-                       // Error will be displayed by default, nothing else to 
wrap up
-                       return $.Deferred().resolve().promise();
-               }
-
-               $form = info.$target.find( 'form' );
-
-               if ( $form.length === 0 ) {
-                       // Add class to identify title is being edited (so we 
can hide the
-                       // current title in CSS)
-                       info.$target.addClass( activeClass );
-
-                       cancelCallback = function () {
-                               $form.remove();
-                               info.$target.removeClass( activeClass );
-                       };
-
-                       flowBoard = mw.flow.getPrototypeMethod( 'board', 
'getInstanceByElement' )( $link );
-                       $form = $( 
flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
-                               'flow_edit_topic_title.partial',
-                               {
-                                       actions: {
-                                               edit: {
-                                                       url: $link.attr( 'href' 
)
-                                               }
-                                       },
-                                       content: {
-                                               content: 
revision.content.content
-                                       },
-                                       revisionId: revision.revisionId
-                               }
-                       ) ).children();
-
-                       flowBoard.emitWithReturn( 'addFormCancelCallback', 
$form, cancelCallback );
-                       $form.prependTo( info.$target );
-               }
-
-               $form.find( '.mw-ui-input' ).focus();
 
                return $.Deferred().resolve().promise();
        };
diff --git a/modules/flow/dm/api/mw.flow.dm.APIHandler.js 
b/modules/flow/dm/api/mw.flow.dm.APIHandler.js
index c9783ff..ebbe20b 100644
--- a/modules/flow/dm/api/mw.flow.dm.APIHandler.js
+++ b/modules/flow/dm/api/mw.flow.dm.APIHandler.js
@@ -352,6 +352,30 @@
        };
 
        /**
+        * Save a topic title.
+        *
+        * @param {string} topicId
+        * @param {string} content
+        * @param {string} format
+        * @param {Object} captcha
+        * @return {jQuery.Promise} Promise that is resolved with workflow id
+        */
+       mw.flow.dm.APIHandler.prototype.saveTopicTitle = function ( topicId, 
content, captcha ) {
+               var params = {
+                               page: this.getTopicTitle( topicId ),
+                               etcontent: content,
+                               etprev_revision: this.currentRevision
+                       };
+
+               this.addCaptcha( params, captcha );
+
+               return this.postEdit( 'edit-title', params )
+                       .then( function ( data ) {
+                               return OO.getProp( data.flow, 'edit-title', 
'workflow' );
+                       } );
+       };
+
+       /**
         * Execute the 'lock-topic' moderation action against a topic. Can be 
used to resolve or reopen a topic.
         *
         * @param {string} topicId Id of the topic to moderate
diff --git a/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js 
b/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js
new file mode 100644
index 0000000..37ec7c8
--- /dev/null
+++ b/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js
@@ -0,0 +1,126 @@
+( function ( $ ) {
+       /**
+        * Topic title widget
+        *
+        * @class
+        * @extends OO.ui.Widget
+        *
+        * @constructor
+        * @param {string} topicId
+        * @param {Object} [config]
+        */
+       mw.flow.ui.TopicTitleWidget = function mwFlowUiTopicTitleWidget( 
topicId, config ) {
+               mw.flow.ui.TopicTitleWidget.parent.call( this, config );
+
+               this.topicId = topicId;
+               this.api = new mw.flow.dm.APIHandler(
+                       'Topic:' + topicId
+               );
+
+               this.anonWarning = new mw.flow.ui.AnonWarningWidget();
+               this.anonWarning.toggle( true );
+
+               this.error = new OO.ui.LabelWidget( {
+                       classes: [ 'flow-ui-topicTitleWidget-error flow-errors 
errorbox' ]
+               } );
+               this.error.toggle( false );
+
+               this.captcha = new mw.flow.dm.Captcha();
+               this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha 
);
+
+               this.input = new OO.ui.TextInputWidget( {
+                       classes: [ 'flow-ui-topicTitleWidget-titleInput' ],
+                       autofocus: true
+               } );
+
+               this.termsLabel = new OO.ui.LabelWidget( {
+                       classes: [ 'flow-ui-topicTitleWidget-termsLabel' ],
+                       label: $( $.parseHTML( mw.message( 
'flow-terms-of-use-edit' ).parse() ) )
+               } );
+
+               this.controls = $( '<div>' ).addClass( 
'flow-ui-topicTitleWidget-controls' );
+               this.buttons = $( '<div>' ).addClass( 
'flow-ui-topicTitleWidget-buttons' );
+               this.saveButton = new OO.ui.ButtonWidget( {
+                       flags: [ 'primary', 'constructive' ],
+                       label: mw.msg( 'flow-edit-title-submit' ),
+                       classes: [ 'flow-ui-topicTitleWidget-saveButton' ]
+               } );
+
+               this.cancelButton = new OO.ui.ButtonWidget( {
+                       flags: 'destructive',
+                       framed: false,
+                       label: mw.msg( 'flow-cancel' ),
+                       classes: [ 'flow-ui-topicTitleWidget-cancelButton' ]
+               } );
+               this.buttons.append(
+                       this.cancelButton.$element,
+                       this.saveButton.$element
+               );
+               this.controls.append(
+                       this.termsLabel.$element,
+                       this.buttons,
+                       $( '<div>' ).css( 'clear', 'both' )
+               );
+
+               // Events
+               this.saveButton.connect( this, { click: [ 'onSaveButtonClick' ] 
} );
+               this.cancelButton.connect( this, { click: [ 'emit', 'cancel' ] 
} );
+
+               this.$element
+                       .addClass( 'flow-ui-topicTitleWidget' )
+                       .append(
+                               this.anonWarning.$element,
+                               this.error.$element,
+                               this.captchaWidget.$element,
+                               this.input.$element,
+                               this.controls
+                       );
+
+               this.input.pushPending();
+               var widget = this;
+               this.api.getPost( topicId, topicId, 'wikitext' ).then(
+                       function ( topic ) {
+                               var content = OO.getProp( topic, 'content', 
'content' ),
+                                       currentRevisionId = topic.revisionId;
+
+                               widget.api.setCurrentRevision( 
currentRevisionId );
+                               widget.input.setValue( content );
+                       },
+                       function ( error ) {
+                               widget.error.setLabel( mw.msg( 
'flow-error-external', error ) );
+                               widget.error.toggle( true );
+                       }
+               ).always(
+                       function () {
+                               widget.input.popPending();
+                       }
+               );
+
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.flow.ui.TopicTitleWidget, OO.ui.Widget );
+
+       /* Methods */
+
+       mw.flow.ui.TopicTitleWidget.prototype.onSaveButtonClick = function () {
+               var content = this.input.getValue(),
+                       captcha = this.captchaWidget.getResponse(),
+                       widget = this;
+               this.api.saveTopicTitle( this.topicId, content, captcha ).then(
+                       function ( workflowId ) {
+                               widget.emit( 'saveContent', workflowId );
+                       },
+                       function ( errorCode, errorObj ) {
+                               widget.captcha.update( errorCode, errorObj );
+                               if ( !widget.captcha.isRequired() ) {
+                                       widget.error.setLabel( errorObj.error 
&& errorObj.error.info || errorObj.exception );
+                                       widget.error.toggle( true );
+                               }
+                       }
+               );
+       };
+
+
+}( jQuery ) );
diff --git a/modules/mw.flow.Initializer.js b/modules/mw.flow.Initializer.js
index 6ee50a9..8cd24aa 100644
--- a/modules/mw.flow.Initializer.js
+++ b/modules/mw.flow.Initializer.js
@@ -157,6 +157,7 @@
                this.setupReplyLinkActions();
                this.setupEditPostAction();
                this.setupEditTopicSummaryAction();
+               this.setupEditTopicTitleAction();
        };
 
        /**
@@ -513,6 +514,49 @@
        };
 
        /**
+        * Take over the action of the 'edit topic title' links
+        * This is delegated, so it applies to all future links as well.
+        */
+       mw.flow.Initializer.prototype.setupEditTopicTitleAction = function () {
+               var self = this;
+
+               this.$component
+                       .on( 'click', 'a.flow-ui-edit-title-link', function ( 
event ) {
+                               var $topic = $( this ).closest( '.flow-topic' ),
+                                       topicId = $topic.data( 'flow-id' ),
+                                       $container = $topic.find( 
'.flow-topic-titlebar-container' ),
+                                       $topicTitleViewMode = $container.find( 
'h2.flow-topic-title' ),
+                                       $editForm = $topic.find( 
'.flow-ui-topicTitleWidget' ),
+                                       widget;
+
+                               if ( $editForm.length ) {
+                                       event.preventDefault();
+                                       return false;
+                               }
+
+                               widget = new mw.flow.ui.TopicTitleWidget( 
topicId, { mode: 'edit' } );
+                               widget
+                                       .on( 'saveContent', function ( workflow 
) {
+                                               widget.$element.remove();
+
+                                               return 
self.flowBoard.flowBoardComponentRefreshTopic(
+                                                       $topic,
+                                                       workflow
+                                               );
+                                       } )
+                                       .on( 'cancel', function () {
+                                               widget.$element.remove();
+                                               $container.prepend( 
$topicTitleViewMode );
+                                       } );
+
+                               $topicTitleViewMode.remove();
+                               $container.prepend( widget.$element );
+
+                               event.preventDefault();
+                       } );
+       };
+
+       /**
         * Take over the action of the 'reply' links.  This is delegated,
         * so it applies to current and future links.
         */
diff --git a/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less 
b/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less
new file mode 100644
index 0000000..d91fbf4
--- /dev/null
+++ b/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less
@@ -0,0 +1,18 @@
+.flow-ui-topicTitleWidget {
+       &-controls {
+               margin-top: 8px;
+       }
+
+       &-buttons {
+               float: right;
+       }
+
+       &-termsLabel {
+               color: #666;
+               font-size: 0.75em;
+       }
+
+       &-titleInput {
+               max-width: none;
+       }
+}
diff --git a/tests/browser/features/step_definitions/edit_existing_steps.rb 
b/tests/browser/features/step_definitions/edit_existing_steps.rb
index a9d9bc8..b7fac37 100644
--- a/tests/browser/features/step_definitions/edit_existing_steps.rb
+++ b/tests/browser/features/step_definitions/edit_existing_steps.rb
@@ -27,7 +27,7 @@
     @edited_topic_string = edited_title + @random_string
     # Take focus away from menu
     page.title_edit_element.when_present.click
-    page.title_edit_element.when_present.send_keys(@edited_topic_string)
+    page.title_edit = @edited_topic_string
   end
 end
 
diff --git a/tests/browser/features/support/pages/abstract_flow_page.rb 
b/tests/browser/features/support/pages/abstract_flow_page.rb
index b001bc9..dbf84b1 100644
--- a/tests/browser/features/support/pages/abstract_flow_page.rb
+++ b/tests/browser/features/support/pages/abstract_flow_page.rb
@@ -139,8 +139,8 @@
   end
 
   ### Editing title of first topic
-  text_field(:title_edit, css: ".flow-topic-titlebar form .mw-ui-input", 
index: 0)
-  button(:change_title_save, css: ".flow-topic-titlebar form 
.mw-ui-constructive")
+  text_field(:title_edit, css: ".flow-ui-topicTitleWidget-titleInput input", 
index: 0)
+  a(:change_title_save, css: ".flow-ui-topicTitleWidget-saveButton a")
 
   ### Post meta actions
   span(:post_meta_actions, css: ".flow-post .flow-post-meta-actions", index: 0)

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I24eafe0a2dbdad7a133d81c089deae0d0feb8589
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Sbisson <[email protected]>

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

Reply via email to