summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CheckUser/modules/ext.checkUser.investigate/tables.js')
-rw-r--r--CheckUser/modules/ext.checkUser.investigate/tables.js283
1 files changed, 283 insertions, 0 deletions
diff --git a/CheckUser/modules/ext.checkUser.investigate/tables.js b/CheckUser/modules/ext.checkUser.investigate/tables.js
new file mode 100644
index 00000000..6f7fa464
--- /dev/null
+++ b/CheckUser/modules/ext.checkUser.investigate/tables.js
@@ -0,0 +1,283 @@
+/**
+ * Add highlight pinning capability and tool links to tables.
+ */
+module.exports = function setupTables() {
+ // Attributes used for pinnable highlighting
+ var highlightData = mw.storage.session.get( 'checkuser-investigate-highlight' ),
+ toggleButtons = {};
+
+ // The message 'checkuser-toollinks' was parsed in PHP, since translations
+ // may contain wikitext that is too complex for the JS parser:
+ // https://www.mediawiki.org/wiki/Manual:Messages_API#Feature_support_in_JavaScript
+ mw.messages.set( require( './message.json' ) );
+
+ function logEvent( data ) {
+ mw.track( 'event.SpecialInvestigate', data );
+ }
+
+ function getDataKey( $element ) {
+ return JSON.stringify( [
+ $element.data( 'field' ),
+ $element.data( 'value' )
+ ] );
+ }
+
+ function updateMatchingElements( $target, value, classSuffix ) {
+ var $matches,
+ dataField = $target.data( 'field' ),
+ dataValue = $target.data( 'value' ),
+ cellClass = 'ext-checkuser-investigate-table-cell-' + classSuffix,
+ rowClass = 'ext-checkuser-investigate-table-row-' + classSuffix;
+
+ $matches = $( 'td[data-field="' + dataField + '"][data-value="' + dataValue + '"]' );
+ // The following messages can be passed here:
+ // * ext-checkuser-investigate-table-cell-hover-data-match
+ // * ext-checkuser-investigate-table-cell-pinned-data-match
+ $matches.toggleClass( cellClass, value );
+
+ // Rows should be highlighted iff they contain highlighted cells
+ $matches.closest( 'tr' ).each( function () {
+ // The following messages can be passed here:
+ // * ext-checkuser-investigate-table-row-hover-data-match
+ // * ext-checkuser-investigate-table-row-pinned-data-match
+ $( this ).toggleClass(
+ rowClass,
+ value
+ );
+ } );
+ }
+
+ function onPinnableCellHover( event ) {
+ // Toggle on for mouseover, off for mouseout
+ updateMatchingElements( $( this ), event.type === 'mouseover' || event.type === 'focusin', 'hover-data-match' );
+ }
+
+ function onToggleButtonChange( $tableCell, value ) {
+ $( '.ext-checkuser-investigate-table' ).toggleClass( 'ext-checkuser-investigate-table-pinned', value );
+ $tableCell.toggleClass( 'ext-checkuser-investigate-table-cell-pinned', value );
+
+ toggleButtons[ getDataKey( $tableCell ) ].forEach( function ( button ) {
+ button.setValue( value );
+ button.setFlags( { progressive: value } );
+ } );
+ updateMatchingElements( $tableCell, value, 'pinned-data-match' );
+
+ if ( value ) {
+ mw.storage.session.set( 'checkuser-investigate-highlight', getDataKey( $tableCell ) );
+ } else {
+ mw.storage.session.remove( 'checkuser-investigate-highlight' );
+ }
+ }
+
+ function filterValue( $tableCell ) {
+ $( 'textarea[name=exclude-targets]' ).val( function () {
+ return this.value + '\n' + $tableCell.data( 'value' );
+ } );
+ $( '.mw-htmlform' ).trigger( 'submit' );
+ }
+
+ function addTargets( $tableCell ) {
+ $( 'input[name=targets]' ).val( $tableCell.data( 'value' ) );
+ $( '.mw-htmlform' ).trigger( 'submit' );
+ }
+
+ function appendButtons( $tableCell, buttonTypes ) {
+ // eslint-disable-next-line no-jquery/no-class-state
+ var isTarget = $tableCell.hasClass( 'ext-checkuser-compare-table-cell-target' ),
+ $optionsContainer = $( '<div>' ).addClass( 'ext-checkuser-investigate-table-options-container' ),
+ key = getDataKey( $tableCell ),
+ options = [],
+ selectWidget,
+ toggleButton,
+ message,
+ $links;
+
+ $tableCell.prepend( $optionsContainer );
+
+ if ( buttonTypes.filter ) {
+ options.push( new OO.ui.MenuOptionWidget( {
+ icon: 'funnel',
+ classes: [
+ 'ext-checkuser-investigate-button-filter-ip'
+ ],
+ label: mw.msg( 'checkuser-investigate-compare-table-button-filter-label' ),
+ data: { type: 'filter' }
+ } ) );
+ }
+
+ if ( buttonTypes.addUsers ) {
+ options.push( new OO.ui.MenuOptionWidget( {
+ disabled: isTarget,
+ icon: 'add',
+ classes: [
+ 'ext-checkuser-investigate-button-add-user-targets'
+ ],
+ label: $tableCell.data( 'edits' ) === $tableCell.data( 'all-edits' ) ?
+ mw.msg( 'checkuser-investigate-compare-table-button-add-user-targets-log-label' ) :
+ mw.msg( 'checkuser-investigate-compare-table-button-add-user-targets-label' ),
+ data: { type: 'addUsers' }
+ } ) );
+ }
+
+ if ( buttonTypes.addIps ) {
+ options.push( new OO.ui.MenuOptionWidget( {
+ disabled: isTarget,
+ icon: 'add',
+ label: mw.msg( 'checkuser-investigate-compare-table-button-add-ip-targets-label' ),
+ data: { type: 'addIps' }
+ } ) );
+ }
+
+ if ( buttonTypes.contribs ) {
+ options.push( new OO.ui.MenuOptionWidget( {
+ icon: 'userContributions',
+ label: mw.msg( 'checkuser-investigate-compare-table-button-contribs-label' ),
+ data: {
+ type: 'toolLinks',
+ href: new mw.Title( 'Special:Contributions' ).getUrl( {
+ target: $tableCell.data( 'value' )
+ } ),
+ tool: 'Special:Contributions'
+ }
+ } ) );
+ }
+
+ if ( buttonTypes.checks ) {
+ options.push( new OO.ui.MenuOptionWidget( {
+ icon: 'check',
+ label: mw.msg( 'checkuser-investigate-compare-table-button-checks-label' ),
+ data: {
+ type: 'toolLinks',
+ // TODO: Filter the log by the target, after T259791
+ href: new mw.Title( 'Special:InvestigateLog' ).getUrl(),
+ tool: 'Special:InvestigateLog'
+ }
+ } ) );
+ }
+
+ if ( buttonTypes.toolLinks ) {
+ message = mw.msg( 'checkuser-investigate-compare-toollinks', $tableCell.data( 'value' ) );
+ $links = $( '<div>' ).html( message ).find( 'a' );
+ $links.each( function ( i, $link ) {
+ var label = $link.text,
+ href = $link.getAttribute( 'href' );
+ options.push( new OO.ui.MenuOptionWidget( {
+ icon: 'linkExternal',
+ label: label,
+ data: {
+ type: 'toolLinks',
+ href: href,
+ tool: new mw.Uri( href ).host
+ }
+ } ) );
+ } );
+ }
+
+ if ( options.length > 0 ) {
+ selectWidget = new OO.ui.ButtonMenuSelectWidget( {
+ icon: 'ellipsis',
+ framed: false,
+ classes: [ 'ext-checkuser-investigate-table-select' ],
+ menu: {
+ horizontalPosition: 'end',
+ items: options
+ }
+ } );
+
+ selectWidget.getMenu().on( 'choose', function ( item ) {
+ var data = item.getData();
+ switch ( data.type ) {
+ case 'filter':
+ filterValue( $tableCell );
+ break;
+ case 'addIps':
+ addTargets( $tableCell );
+ break;
+ case 'addUsers':
+ addTargets( $tableCell );
+ break;
+ case 'toolLinks':
+ logEvent( {
+ action: 'tool',
+ tool: data.tool
+ } );
+ window.open( data.href, '_blank' );
+ break;
+ }
+ } );
+
+ $optionsContainer.append( selectWidget.$element );
+ }
+
+ if ( buttonTypes.toggle ) {
+ toggleButton = new OO.ui.ToggleButtonWidget( {
+ icon: 'pushPin',
+ framed: false,
+ classes: [ 'ext-checkuser-investigate-table-button-pin' ]
+ } );
+ toggleButtons[ key ] = toggleButtons[ key ] || [];
+ toggleButtons[ key ].push( toggleButton );
+ toggleButton.on( 'change', onToggleButtonChange.bind( null, $tableCell ) );
+ // Log the click not the change, since clicking on one button
+ // can lead to several other buttons changing
+ toggleButton.on( 'click', function () {
+ if ( toggleButton.getValue() ) {
+ logEvent( { action: 'pin' } );
+ }
+ } );
+ $optionsContainer.append( toggleButton.$element );
+ }
+ }
+
+ $( 'td.ext-checkuser-investigate-table-cell-pinnable' ).on( 'mouseover mouseout focusin focusout', onPinnableCellHover );
+
+ // Prevent the user from putting a table cell into focus.
+ $( '.ext-checkuser-investigate-table td' ).on( 'mousedown', function ( e ) {
+ e.preventDefault();
+ } );
+
+ $( '.ext-checkuser-investigate-table-preliminary-check td.ext-checkuser-investigate-table-cell-pinnable' )
+ .each( function () {
+ appendButtons( $( this ), {
+ toggle: true
+ } );
+ } );
+
+ $( '.ext-checkuser-investigate-table-compare .ext-checkuser-compare-table-cell-user-agent' )
+ .each( function () {
+ appendButtons( $( this ), {
+ toggle: true
+ } );
+ } );
+
+ $( '.ext-checkuser-investigate-table-compare .ext-checkuser-compare-table-cell-ip-target' )
+ .each( function () {
+ appendButtons( $( this ), {
+ toggle: true,
+ filter: true,
+ addUsers: true,
+ contribs: true,
+ checks: true,
+ toolLinks: true
+ } );
+ } );
+
+ $( 'td.ext-checkuser-compare-table-cell-user-target' )
+ .each( function () {
+ appendButtons( $( this ), {
+ filter: true,
+ addIps: true,
+ contribs: true,
+ checks: true
+ } );
+ } );
+
+ // Persist highlights across paginated tabs
+ if (
+ highlightData !== null &&
+ toggleButtons[ highlightData ] &&
+ toggleButtons[ highlightData ].length > 0
+ ) {
+ toggleButtons[ highlightData ][ 0 ].setValue( true );
+ }
+};