diff --git a/resources/skins.minerva.scripts/PageIssuesOverlay.js b/resources/skins.minerva.scripts/PageIssuesOverlay.js index 4143a15..f4d6dbb 100644 --- a/resources/skins.minerva.scripts/PageIssuesOverlay.js +++ b/resources/skins.minerva.scripts/PageIssuesOverlay.js @@ -1,39 +1,40 @@ -( function ( M ) { - var Overlay = M.require( 'mobile.startup/Overlay' ), - util = M.require( 'mobile.startup/util' ); - - /** - * @typedef {Object} PageIssue - * @property {string} icon html associated with Icon component - * @property {string} text html explaining the details of the issue - * @property {string} severity associated with the issue - */ - - /** - * Obtain severity associated with a given $target node - * by looking at associated parent node (defined by template) - * - * @param {jQuery.Object} $target - * @return {string} severity as defined in associated PageIssue - */ - function parseSeverity( $target ) { - return $target.parents( '.issue-notice' ).data( 'severity' ); - } +( function ( M, mwMsg ) { + var + Overlay = M.require( 'mobile.startup/Overlay' ), + util = M.require( 'mobile.startup/util' ), + KEYWORD_ALL_SECTIONS = 'all', + NS_MAIN = 0, + NS_TALK = 1, + NS_CATEGORY = 14; /** * Overlay for displaying page issues * @class PageIssuesOverlay * @extends Overlay * - * @param {Object} options Configuration options - * @param {string} options.headingText - * @param {PageIssue[]} options.issues list of page issues for display - * @fires PageIssuesOverlay#link-edit-click - * @fires PageIssuesOverlay#link-internal-click + * @param {IssueSummary[]} issues list of page issue summaries for display. + * @param {PageIssuesLogger} logger E.g., { log: console.log }. + * @param {string} section + * @param {number} namespaceID */ - function PageIssuesOverlay( options ) { - options.heading = '' + options.headingText + ''; + function PageIssuesOverlay( issues, logger, section, namespaceID ) { + var + options, + // 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 ? + getNamespaceHeadingText( namespaceID ) : + mwMsg( 'minerva-meta-data-issues-section-header' ); + + this.issues = issues; + this.logger = logger; + + options = {}; + options.issues = issues; + options.heading = '' + headingText + ''; Overlay.call( this, options ); + + this.on( Overlay.EVENT_EXIT, this.onExit.bind( this ) ); } OO.mfExtend( PageIssuesOverlay, Overlay, { @@ -42,6 +43,7 @@ * @instance */ className: 'overlay overlay-issues', + /** * @memberof PageIssuesOverlay * @instance @@ -50,6 +52,7 @@ 'click a:not(.external):not([href*=edit])': 'onInternalClick', 'click a[href*="edit"]': 'onEditClick' } ), + /** * @memberof PageIssuesOverlay * @instance @@ -57,38 +60,87 @@ templatePartials: util.extend( {}, Overlay.prototype.templatePartials, { content: mw.template.get( 'skins.minerva.scripts', 'PageIssuesOverlayContent.hogan' ) } ), + /** - * Event that is triggered when an internal link inside the overlay is clicked - * This event will not be triggered if the link contains the edit keyword, in which - * case onEditClick will be fired - * This is primarily used for instrumenting page issues - * (see https://meta.wikimedia.org/wiki/Schema:PageIssues) - * @param {jQuery.Event} ev + * Note: an "on enter" state is tracked by the issueClicked log event. + * @return {void} + */ + onExit: function () { + this.logger.log( { + action: 'modalClose', + issuesSeverity: this.issues.map( issueSummaryToSeverity ) + } ); + }, + + /** + * Event that is triggered when an internal link inside the overlay is clicked. This event will + * not be triggered if the link contains the edit keyword, in which case onEditClick will be + * fired. This is primarily used for instrumenting page issues (see + * https://meta.wikimedia.org/wiki/Schema:PageIssues). + * @param {JQuery.Event} ev * @memberof PageIssuesOverlay * @instance */ onInternalClick: function ( ev ) { - /** - * @event PageIssuesOverlay#link-internal-click - * @param {string} severity - */ - this.emit( 'link-internal-click', parseSeverity( this.$( ev.target ) ) ); + var severity = parseSeverity( this.$( ev.target ) ); + this.logger.log( { + action: 'modalInternalClicked', + issuesSeverity: [ severity ] + } ); }, + /** - * Event that is triggered when an edit link inside the overlay is clicked - * This is primarily used for instrumenting page issues - * (see https://meta.wikimedia.org/wiki/Schema:PageIssues) - * @param {jQuery.Event} ev + * Event that is triggered when an edit link inside the overlay is clicked. This is primarily + * used for instrumenting page issues (see https://meta.wikimedia.org/wiki/Schema:PageIssues). + * @param {JQuery.Event} ev * @memberof PageIssuesOverlay * @instance */ onEditClick: function ( ev ) { - /** - * @event PageIssuesOverlay#link-edit-click - * @param {string} severity - */ - this.emit( 'link-edit-click', parseSeverity( this.$( ev.target ) ) ); + var severity = parseSeverity( this.$( ev.target ) ); + this.logger.log( { + action: 'modalEditClicked', + issuesSeverity: [ severity ] + } ); } } ); + + /** + * Obtain severity associated with a given $target node by looking at associated parent node + * (defined by templatePartials, PageIssuesOverlayContent.hogan). + * + * @param {JQuery.Object} $target + * @return {string[]} severity as defined in associated PageIssue + */ + function parseSeverity( $target ) { + return $target.parents( '.issue-notice' ).data( 'severity' ); + } + + /** + * @param {IssueSummary} issue + * @return {string} A PageIssue.severity. + */ + function issueSummaryToSeverity( issue ) { + return issue.severity; + } + + /** + * Obtain a suitable heading for the issues overlay based on the namespace + * @param {number} namespaceID is the namespace to generate heading for + * @return {string} heading for overlay + */ + function getNamespaceHeadingText( namespaceID ) { + switch ( namespaceID ) { + 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 ''; + } + } + M.define( 'skins.minerva.scripts/PageIssuesOverlay', PageIssuesOverlay ); -}( mw.mobileFrontend ) ); +}( mw.mobileFrontend, mw.msg ) ); diff --git a/resources/skins.minerva.scripts/pageIssues.js b/resources/skins.minerva.scripts/pageIssues.js index 8999bab..60f03e4 100644 --- a/resources/skins.minerva.scripts/pageIssues.js +++ b/resources/skins.minerva.scripts/pageIssues.js @@ -9,7 +9,6 @@ NS_TALK = 1, NS_CATEGORY = 14, CURRENT_NS = config.get( 'wgNamespaceNumber' ), - allPageIssuesSeverity, Icon = M.require( 'mobile.startup/Icon' ), pageIssuesLogger = M.require( 'skins.minerva.scripts/pageIssuesLogger' ), pageIssuesParser = M.require( 'skins.minerva.scripts/pageIssuesParser' ), @@ -24,27 +23,30 @@ } ), newTreatmentEnabled = abTest.isB(); + /** + * @typedef {Object} IssueSummary + * @prop {string} severity A PageIssue.severity. + * @prop {string} icon HTML string. + * @prop {string} text HTML string. + */ + function isLoggingRequired( pageIssues ) { // No logging necessary when the A/B test is disabled (control group). return abTest.isEnabled() && pageIssues.length; } /** - * @param {PageIssue} issue + * @param {IssueSummary} summary * @return {string} */ - function formatPageIssuesSeverity( issue ) { - return issue.severity; + function formatPageIssuesSeverity( summary ) { + return summary.severity; } + /** * 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 {string} severity - * @prop {string} icon HTML string. - * @prop {string} text HTML string. * @return {IssueSummary} */ function extractMessage( $box ) { @@ -206,24 +208,6 @@ } } - /** - * 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 ''; - } - } - /** * Scan an element for any known cleanup templates and replace them with a button * that opens them in a mobile friendly overlay. @@ -233,7 +217,6 @@ */ function initPageIssues( overlayManager, page ) { var label, - headingText = getNamespaceHeadingText( CURRENT_NS ), $lead = page.getLeadSectionElement(), issueOverlayShowAll = CURRENT_NS === NS_CATEGORY || CURRENT_NS === NS_TALK || !$lead, inline = newTreatmentEnabled && CURRENT_NS === 0; @@ -275,43 +258,17 @@ getIssues( KEYWORD_ALL_SECTIONS ).map( formatPageIssuesSeverity ) ) ); + + // Report that the page has been loaded. + pageIssuesLogger.log( { + action: 'pageLoaded', + issuesSeverity: getIssues( KEYWORD_ALL_SECTIONS ).map( formatPageIssuesSeverity ) + } ); } // Setup the overlay route. overlayManager.add( new RegExp( '^/issues/(\\d+|' + KEYWORD_ALL_SECTIONS + ')$' ), function ( section ) { - var overlay = new PageIssuesOverlay( { - 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' ) - } ); - // Tracking overlay close event. - overlay.on( 'Overlay-exit', function () { - pageIssuesLogger.log( { - action: 'modalClose', - issuesSeverity: getIssues( section ).map( formatPageIssuesSeverity ) - } ); - } ); - overlay.on( 'link-edit-click', function ( severity ) { - pageIssuesLogger.log( { - action: 'modalEditClicked', - issuesSeverity: [ severity ] - } ); - } ); - overlay.on( 'link-internal-click', function ( severity ) { - pageIssuesLogger.log( { - action: 'modalInternalClicked', - issuesSeverity: [ severity ] - } ); - } ); - return overlay; - } ); - - // Tracking pageLoaded event (technically, "issues" loaded). - pageIssuesLogger.log( { - action: 'pageLoaded', - issuesSeverity: allPageIssuesSeverity + return new PageIssuesOverlay( getIssues( section ), pageIssuesLogger, section, CURRENT_NS ); } ); }