2017-07-12 15:12:40 +00:00
|
|
|
( function ( M, $ ) {
|
2018-05-08 22:03:52 +00:00
|
|
|
var AB = M.require( 'skins.minerva.scripts/AB' ),
|
2018-07-02 22:12:37 +00:00
|
|
|
allIssues = {},
|
|
|
|
KEYWORD_ALL_SECTIONS = 'all',
|
|
|
|
ACTION_EDIT = mw.config.get( 'wgAction' ) === 'edit',
|
|
|
|
NS_MAIN = 0,
|
|
|
|
NS_TALK = 1,
|
|
|
|
NS_CATEGORY = 14,
|
2018-07-02 13:15:04 +00:00
|
|
|
isInGroupB = new AB( {
|
|
|
|
testName: 'WME.PageIssuesAB',
|
|
|
|
samplingRate: mw.config.get( 'wgMinervaABSamplingRate', 0 ),
|
|
|
|
sessionId: mw.user.sessionId(),
|
|
|
|
onABStart: function ( bucket ) {
|
|
|
|
// See: https://gerrit.wikimedia.org/r/#/c/mediawiki/extensions/WikimediaEvents/+/437686/
|
|
|
|
var READING_DEPTH_BUCKET_KEYS = {
|
|
|
|
A: 'page-issues-a_sample',
|
|
|
|
B: 'page-issues-b_sample'
|
|
|
|
},
|
|
|
|
readingDepthBucket = READING_DEPTH_BUCKET_KEYS[ bucket ];
|
|
|
|
mw.track( 'wikimedia.event.ReadingDepthSchema.enable', readingDepthBucket );
|
|
|
|
}
|
|
|
|
} ).getBucket() === 'B',
|
2018-07-30 11:33:34 +00:00
|
|
|
Icon = M.require( 'mobile.startup/Icon' ),
|
|
|
|
pageIssueParser = M.require( 'skins.minerva.scripts/pageIssueParser' ),
|
|
|
|
CleanupOverlay = M.require( 'mobile.issues/CleanupOverlay' );
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Extract a summary message from a cleanup template generated element that is
|
|
|
|
* friendly for mobile display.
|
|
|
|
* @param {Object} $box element to extract the message from
|
|
|
|
* @ignore
|
|
|
|
* @typedef {Object} IssueSummary
|
|
|
|
* @prop {PageIssue} pageIssue
|
|
|
|
* @prop {string} icon HTML string.
|
|
|
|
* @prop {string} text HTML string.
|
|
|
|
* @return {IssueSummary}
|
|
|
|
*/
|
|
|
|
function extractMessage( $box ) {
|
|
|
|
var selector = '.mbox-text, .ambox-text',
|
|
|
|
$container = $( '<div>' ),
|
|
|
|
pageIssue;
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
$box.find( selector ).each( function () {
|
|
|
|
var contents,
|
|
|
|
$this = $( this );
|
|
|
|
// Clean up talk page boxes
|
|
|
|
$this.find( 'table, .noprint' ).remove();
|
|
|
|
contents = $this.html();
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
if ( contents ) {
|
|
|
|
$( '<p>' ).html( contents ).appendTo( $container );
|
|
|
|
}
|
|
|
|
} );
|
2018-07-10 20:06:51 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
pageIssue = pageIssueParser.parse( $box.get( 0 ) );
|
|
|
|
return {
|
|
|
|
pageIssue: pageIssue,
|
|
|
|
icon: pageIssue.icon.toHtmlString(),
|
|
|
|
text: $container.html()
|
|
|
|
};
|
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Create a link element that opens the issues overlay.
|
|
|
|
*
|
|
|
|
* @ignore
|
|
|
|
*
|
|
|
|
* @param {string} labelText The text value of the element
|
|
|
|
* @return {JQuery}
|
|
|
|
*/
|
|
|
|
function createLinkElement( labelText ) {
|
|
|
|
return $( '<a class="cleanup mw-mf-cleanup"></a>' )
|
|
|
|
.text( labelText );
|
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Render a banner in a containing element.
|
|
|
|
* if in group B, a learn more link will be append to any amboxes inside $container
|
|
|
|
* if in group A or control, any amboxes in container will be removed and a link "page issues"
|
|
|
|
* will be rendered above the heading.
|
|
|
|
* This function comes with side effects. It will populate a global "allIssues" object which
|
|
|
|
* will link section numbers to issues.
|
|
|
|
* @param {JQuery.Object} $container to render the page issues banner inside.
|
|
|
|
* @param {string} labelText what the label of the page issues banner should say
|
|
|
|
* @param {number|string} section that the banner and its issues belong to.
|
|
|
|
* If string KEYWORD_ALL_SECTIONS banner should apply to entire page.
|
|
|
|
* @param {boolean} inline - if true the first ambox in the section will become the entry point for the issues overlay
|
|
|
|
* and if false, a link will be rendered under the heading.
|
2018-07-30 14:45:44 +00:00
|
|
|
* @param {OverlayManager} overlayManager
|
2018-07-30 11:33:34 +00:00
|
|
|
* @ignore
|
2018-07-30 14:35:54 +00:00
|
|
|
*
|
|
|
|
* @return {JQuery.Object}
|
2018-07-30 11:33:34 +00:00
|
|
|
*/
|
2018-07-30 14:45:44 +00:00
|
|
|
function createBanner( $container, labelText, section, inline, overlayManager ) {
|
2018-07-30 11:33:34 +00:00
|
|
|
var $learnMore,
|
|
|
|
issueUrl = section === KEYWORD_ALL_SECTIONS ? '#/issues/' + KEYWORD_ALL_SECTIONS : '#/issues/' + section,
|
|
|
|
selector = 'table.ambox, table.tmbox, table.cmbox, table.fmbox',
|
|
|
|
$metadata = $container.find( selector ),
|
|
|
|
issues = [],
|
|
|
|
$link,
|
|
|
|
severity;
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
// clean it up a little
|
|
|
|
$metadata.find( '.NavFrame' ).remove();
|
|
|
|
$metadata.each( function () {
|
|
|
|
var issue,
|
|
|
|
$this = $( this );
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
if ( $this.find( selector ).length === 0 ) {
|
|
|
|
issue = extractMessage( $this );
|
|
|
|
// Some issues after "extractMessage" has been run will have no text.
|
|
|
|
// For example in Template:Talk header the table will be removed and no issue found.
|
|
|
|
// These should not be rendered.
|
|
|
|
if ( issue.text ) {
|
|
|
|
issues.push( issue );
|
2017-07-12 15:12:40 +00:00
|
|
|
}
|
2018-07-30 11:33:34 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
// store it for late
|
|
|
|
allIssues[section] = issues;
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
if ( inline ) {
|
|
|
|
severity = pageIssueParser.maxSeverity(
|
|
|
|
issues.map( function ( issue ) { return issue.pageIssue; } )
|
|
|
|
);
|
|
|
|
new Icon( {
|
|
|
|
glyphPrefix: 'minerva',
|
|
|
|
name: pageIssueParser.iconName( $metadata, severity )
|
|
|
|
} ).prependTo( $metadata.find( '.mbox-text' ) );
|
|
|
|
$learnMore = $( '<span>' )
|
|
|
|
.addClass( 'ambox-learn-more' )
|
|
|
|
.text( mw.msg( 'skin-minerva-issue-learn-more' ) );
|
|
|
|
if ( $( '.mw-collapsible-content' ).length ) {
|
|
|
|
// e.g. Template:Multiple issues
|
|
|
|
$learnMore.insertAfter( $metadata.find( '.mbox-text-span' ) );
|
2018-05-08 22:03:52 +00:00
|
|
|
} else {
|
2018-07-30 11:33:34 +00:00
|
|
|
// e.g. Template:merge from
|
|
|
|
$learnMore.appendTo( $metadata.find( '.mbox-text' ) );
|
|
|
|
}
|
|
|
|
$metadata.click( function () {
|
|
|
|
overlayManager.router.navigate( issueUrl );
|
|
|
|
return false;
|
|
|
|
} );
|
|
|
|
} else {
|
|
|
|
$link = createLinkElement( labelText );
|
|
|
|
// In group B, we link to all issues no matter where the banner is.
|
|
|
|
$link.attr( 'href', '#/issues/' + KEYWORD_ALL_SECTIONS );
|
|
|
|
if ( $metadata.length ) {
|
|
|
|
$link.insertAfter( $( 'h1#section_0' ) );
|
|
|
|
$metadata.remove();
|
2018-05-08 22:03:52 +00:00
|
|
|
}
|
2018-07-02 22:12:37 +00:00
|
|
|
}
|
2018-07-30 14:35:54 +00:00
|
|
|
|
|
|
|
return $metadata;
|
2018-07-30 11:33:34 +00:00
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Obtains the list of issues for the current page and provided section
|
|
|
|
* @param {number|string} section either KEYWORD_ALL_SECTIONS or a number relating to the section
|
|
|
|
* the issues belong to
|
|
|
|
* @return {jQuery.Object[]} array of all issues.
|
|
|
|
*/
|
|
|
|
function getIssues( section ) {
|
|
|
|
if ( section === KEYWORD_ALL_SECTIONS ) {
|
|
|
|
// Note section.all may not exist, depending on the structure of the HTML page.
|
|
|
|
// It will only exist when Minerva has been run in desktop mode.
|
|
|
|
// If it's absent, we'll reduce all the other lists into one.
|
|
|
|
return allIssues.all || Object.keys( allIssues ).reduce(
|
|
|
|
function ( all, key ) {
|
|
|
|
return all.concat( allIssues[key] );
|
|
|
|
},
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return allIssues[section] || [];
|
2018-07-02 22:12:37 +00:00
|
|
|
}
|
2018-07-30 11:33:34 +00:00
|
|
|
}
|
2018-07-02 22:12:37 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Obtain a suitable heading for the issues overlay based on the namespace
|
|
|
|
* @param {number} ns is the namespace to generate heading for
|
|
|
|
* @return {string} heading for overlay
|
|
|
|
*/
|
|
|
|
function getNamespaceHeadingText( ns ) {
|
|
|
|
switch ( ns ) {
|
|
|
|
case NS_CATEGORY:
|
|
|
|
return mw.msg( 'mobile-frontend-meta-data-issues-categories' );
|
|
|
|
case NS_TALK:
|
|
|
|
return mw.msg( 'mobile-frontend-meta-data-issues-talk' );
|
|
|
|
case NS_MAIN:
|
|
|
|
return mw.msg( 'mobile-frontend-meta-data-issues' );
|
|
|
|
default:
|
|
|
|
return '';
|
2017-07-12 15:12:40 +00:00
|
|
|
}
|
2018-07-30 11:33:34 +00:00
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
/**
|
|
|
|
* Scan an element for any known cleanup templates and replace them with a button
|
|
|
|
* that opens them in a mobile friendly overlay.
|
|
|
|
* @ignore
|
2018-07-30 14:45:44 +00:00
|
|
|
* @param {OverlayManager} overlayManager
|
|
|
|
* @param {Page} page
|
2018-07-30 11:33:34 +00:00
|
|
|
*/
|
2018-07-30 14:45:44 +00:00
|
|
|
function initPageIssues( overlayManager, page ) {
|
2018-07-30 11:33:34 +00:00
|
|
|
var ns = mw.config.get( 'wgNamespaceNumber' ),
|
|
|
|
label,
|
|
|
|
headingText = ACTION_EDIT ? mw.msg( 'edithelp' ) : getNamespaceHeadingText( ns ),
|
|
|
|
$lead = page.getLeadSectionElement(),
|
|
|
|
issueOverlayShowAll = ns === NS_CATEGORY || ns === NS_TALK || ACTION_EDIT || !$lead,
|
|
|
|
inline = isInGroupB && ns === 0,
|
|
|
|
$container = $( '#bodyContent' );
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
// set A-B test class.
|
|
|
|
$( 'html' ).addClass( isInGroupB ? 'issues-group-B' : 'issues-group-A' );
|
2018-07-02 22:12:37 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
if ( ACTION_EDIT ) {
|
|
|
|
// Editor uses different parent element
|
|
|
|
$container = $( '#mw-content-text' );
|
2018-07-30 14:45:44 +00:00
|
|
|
createBanner( $container, mw.msg( 'edithelp' ), KEYWORD_ALL_SECTIONS, inline, overlayManager );
|
2018-07-30 11:33:34 +00:00
|
|
|
} else if ( ns === NS_TALK || ns === NS_CATEGORY ) {
|
|
|
|
// e.g. Template:English variant category; Template:WikiProject
|
2018-07-30 14:45:44 +00:00
|
|
|
createBanner( $container, mw.msg( 'mobile-frontend-meta-data-issues-header-talk' ),
|
|
|
|
KEYWORD_ALL_SECTIONS, inline, overlayManager );
|
2018-07-30 11:33:34 +00:00
|
|
|
} else if ( ns === NS_MAIN ) {
|
|
|
|
label = mw.msg( 'mobile-frontend-meta-data-issues-header' );
|
|
|
|
if ( issueOverlayShowAll ) {
|
2018-07-30 14:45:44 +00:00
|
|
|
createBanner( $container, label, KEYWORD_ALL_SECTIONS, inline, overlayManager );
|
2018-07-30 11:33:34 +00:00
|
|
|
} else {
|
|
|
|
// parse lead
|
2018-07-30 14:45:44 +00:00
|
|
|
createBanner( $lead, label, 0, inline, overlayManager );
|
2018-07-30 11:33:34 +00:00
|
|
|
if ( isInGroupB ) {
|
|
|
|
// parse other sections but only in group B. In treatment A no issues are shown for sections.
|
|
|
|
$lead.nextAll( 'h1,h2,h3,h4,h5,h6' ).each( function ( i, headingEl ) {
|
|
|
|
var $headingEl = $( headingEl ),
|
|
|
|
$section = $headingEl.next(),
|
|
|
|
sectionNum = $headingEl.find( '.edit-page' ).data( 'section' );
|
2018-07-13 20:23:55 +00:00
|
|
|
|
2018-07-30 14:45:44 +00:00
|
|
|
createBanner( $section, label, sectionNum, inline, overlayManager );
|
2018-07-30 11:33:34 +00:00
|
|
|
} );
|
2018-07-02 22:12:37 +00:00
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
}
|
2018-07-30 11:33:34 +00:00
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 11:33:34 +00:00
|
|
|
// Setup the overlay route.
|
|
|
|
overlayManager.add( new RegExp( '^/issues/(\\d+|' + KEYWORD_ALL_SECTIONS + ')$' ), function ( section ) {
|
|
|
|
return new CleanupOverlay( {
|
|
|
|
issues: getIssues( section ),
|
|
|
|
// Note only the main namespace is expected to make use of section issues, so the heading will always be
|
|
|
|
// minerva-meta-data-issues-section-header regardless of namespace
|
|
|
|
headingText: section === '0' || section === KEYWORD_ALL_SECTIONS ? headingText :
|
|
|
|
mw.msg( 'minerva-meta-data-issues-section-header' )
|
2018-07-02 22:12:37 +00:00
|
|
|
} );
|
2018-07-30 11:33:34 +00:00
|
|
|
} );
|
|
|
|
}
|
2017-07-12 15:12:40 +00:00
|
|
|
|
2018-07-30 14:45:44 +00:00
|
|
|
M.define( 'skins.minerva.scripts/cleanuptemplates', {
|
2018-07-30 14:35:54 +00:00
|
|
|
init: initPageIssues,
|
|
|
|
test: {
|
|
|
|
createBanner: createBanner
|
|
|
|
}
|
2018-07-30 14:45:44 +00:00
|
|
|
} );
|
2017-07-12 15:12:40 +00:00
|
|
|
|
|
|
|
}( mw.mobileFrontend, jQuery ) );
|