2019-11-05 14:14:41 +00:00
|
|
|
var pageComments, pageThreads, parsoidPromise, parsoidComments, parsoidDoc,
|
2019-10-30 16:12:27 +00:00
|
|
|
replyWidgetPromise = mw.loader.using( 'ext.discussionTools.ReplyWidget' ),
|
|
|
|
// eslint-disable-next-line no-jquery/no-global-selector
|
|
|
|
$pageContainer = $( '#mw-content-text' );
|
2019-10-10 20:17:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @class mw.discussionTools
|
|
|
|
* @singleton
|
|
|
|
*/
|
|
|
|
mw.dt = {
|
|
|
|
init: {},
|
|
|
|
ui: {},
|
2019-11-05 14:13:18 +00:00
|
|
|
parser: require( 'ext.discussionTools.parser' ),
|
|
|
|
modifier: require( 'ext.discussionTools.modifier' )
|
2019-10-10 20:17:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
function setupComment( comment ) {
|
2019-10-30 16:12:27 +00:00
|
|
|
var $replyLink, widgetPromise, newList, newListItem,
|
|
|
|
$tsNode = $( comment.range.endContainer );
|
2019-10-10 20:17:24 +00:00
|
|
|
|
|
|
|
// Is it possible to have a heading nested in a thread?
|
|
|
|
if ( comment.type !== 'comment' ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-30 16:12:27 +00:00
|
|
|
$replyLink = $( '<a>' )
|
|
|
|
.addClass( 'dt-init-replylink' )
|
2019-11-05 14:07:50 +00:00
|
|
|
// TODO: i18n
|
2019-10-30 16:12:27 +00:00
|
|
|
.text( 'Reply' )
|
|
|
|
.on( 'click', function () {
|
|
|
|
var $link = $( this );
|
2019-10-10 20:17:24 +00:00
|
|
|
|
|
|
|
$link.hide();
|
2019-10-30 16:12:27 +00:00
|
|
|
// TODO: Allow users to use multiple reply widgets simlutaneously
|
|
|
|
// Currently as all widgets share the same Parsoid doc, this could
|
|
|
|
// cause problems.
|
|
|
|
$pageContainer.addClass( 'dt-init-replylink-open' );
|
2019-10-10 20:17:24 +00:00
|
|
|
|
2019-10-30 16:12:27 +00:00
|
|
|
if ( !widgetPromise ) {
|
|
|
|
newList = mw.dt.modifier.addListAtComment( comment );
|
|
|
|
newListItem = mw.dt.modifier.addListItem( newList );
|
|
|
|
// TODO: i18n
|
|
|
|
$( newListItem ).text( 'Loading...' );
|
|
|
|
widgetPromise = replyWidgetPromise.then( function () {
|
|
|
|
var replyWidget = new mw.dt.ui.ReplyWidget(
|
|
|
|
comment,
|
|
|
|
parsoidDoc,
|
|
|
|
{
|
|
|
|
// TODO: Remove placeholder
|
|
|
|
doc: '<p>Reply to ' + comment.author + '</p>',
|
|
|
|
defaultMode: 'source'
|
|
|
|
}
|
|
|
|
);
|
2019-10-10 20:17:24 +00:00
|
|
|
|
2019-10-30 16:12:27 +00:00
|
|
|
replyWidget.on( 'cancel', function () {
|
|
|
|
$link.show();
|
|
|
|
$pageContainer.removeClass( 'dt-init-replylink-open' );
|
|
|
|
$( newListItem ).hide();
|
|
|
|
} );
|
2019-11-05 14:14:41 +00:00
|
|
|
|
2019-10-30 16:12:27 +00:00
|
|
|
$( newListItem ).empty().append( replyWidget.$element );
|
|
|
|
return replyWidget;
|
|
|
|
}, function () {
|
2019-11-05 14:07:50 +00:00
|
|
|
$link.show();
|
2019-10-30 16:12:27 +00:00
|
|
|
$pageContainer.removeClass( 'dt-init-replylink-open' );
|
2019-10-10 20:17:24 +00:00
|
|
|
} );
|
2019-10-30 16:12:27 +00:00
|
|
|
}
|
2019-11-05 14:14:41 +00:00
|
|
|
|
2019-10-30 16:12:27 +00:00
|
|
|
widgetPromise.then( function ( replyWidget ) {
|
|
|
|
$( newListItem ).show();
|
2019-10-10 20:17:24 +00:00
|
|
|
replyWidget.focus();
|
|
|
|
} );
|
2019-10-30 16:12:27 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
$tsNode.after( $replyLink );
|
2019-10-10 20:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function traverseNode( parent ) {
|
|
|
|
parent.replies.forEach( function ( comment ) {
|
|
|
|
setupComment( comment );
|
|
|
|
traverseNode( comment );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2019-10-24 14:38:31 +00:00
|
|
|
if ( new mw.Uri().query.dtdebug ) {
|
|
|
|
mw.loader.load( 'ext.discussionTools.debug' );
|
|
|
|
} else {
|
2019-10-30 16:12:27 +00:00
|
|
|
pageComments = mw.dt.parser.getComments( $pageContainer[ 0 ] );
|
2019-11-05 14:14:41 +00:00
|
|
|
pageThreads = mw.dt.parser.groupThreads( pageComments );
|
|
|
|
pageThreads.forEach( traverseNode );
|
|
|
|
|
|
|
|
// For debugging
|
|
|
|
mw.dt.pageThreads = pageThreads;
|
|
|
|
|
|
|
|
parsoidPromise = mw.loader.using( [
|
|
|
|
'ext.visualEditor.targetLoader',
|
|
|
|
// TODO: We are loading ext.visualEditor.base just for ve.createDocumentFromHTML
|
|
|
|
'ext.visualEditor.base',
|
|
|
|
// TODO: Loading mw.Target class for save testing
|
|
|
|
'ext.visualEditor.mediawiki'
|
|
|
|
] ).then( function () {
|
|
|
|
return mw.libs.ve.targetLoader.requestPageData(
|
|
|
|
'visual', mw.config.get( 'wgRelevantPageName' ), {
|
|
|
|
oldId: mw.config.get( 'wgRevisionId' )
|
|
|
|
}
|
|
|
|
).then( function ( response ) {
|
2019-11-05 14:07:50 +00:00
|
|
|
var data = response.visualeditor;
|
2019-11-05 14:14:41 +00:00
|
|
|
// TODO: error handling
|
2019-11-05 14:07:50 +00:00
|
|
|
parsoidDoc = ve.createDocumentFromHtml( data.content );
|
2019-11-05 14:14:41 +00:00
|
|
|
parsoidComments = mw.dt.parser.getComments( parsoidDoc.body );
|
|
|
|
|
|
|
|
// getThreads build the tree structure, currently only
|
|
|
|
// used to set 'replies'
|
|
|
|
mw.dt.parser.groupThreads( parsoidComments );
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Map PHP comments to Parsoid comments.
|
|
|
|
// TODO: Handle when these don't align
|
|
|
|
pageComments.forEach( function ( comment, i ) {
|
|
|
|
comment.parsoidCommentPromise = parsoidPromise.then( function () {
|
|
|
|
return parsoidComments[ i ];
|
|
|
|
} );
|
|
|
|
} );
|
2019-10-24 14:38:31 +00:00
|
|
|
}
|