Matthias Mullie has uploaded a new change for review.

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

Change subject: [WIP] Log Flow topic and post actions (FlowReplies)
......................................................................

[WIP] Log Flow topic and post actions (FlowReplies)

Todo:
* preview & keep-editing actions
* make sure cancels aren't executed on after-save (I assume cancel callbacks 
are used to destruct form)
* add more properties than just 'action' (share them somewhere so we don't have 
to repeat)
* not sure how to do 'entrypoints' yet
* no-JS cases
* probably lots more

Change-Id: Ic011a6130184aadae539eced307bf982f84c990d
---
M Resources.php
M modules/engine/components/board/base/flow-board-api-events.js
M modules/engine/components/board/base/flow-board-interactive-events.js
M modules/engine/components/board/base/flow-boardandhistory-base.js
M modules/engine/components/common/flow-component-engines.js
M modules/engine/components/common/flow-component-events.js
A modules/engine/misc/flow-eventlog.js
7 files changed, 115 insertions(+), 25 deletions(-)


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

diff --git a/Resources.php b/Resources.php
index bfd7f89..038f878 100644
--- a/Resources.php
+++ b/Resources.php
@@ -324,6 +324,8 @@
                        'engine/misc/mw-ui.modal.js',
                        // FlowApi
                        'engine/misc/flow-api.js',
+                       // FlowEventLog
+                       'engine/misc/flow-eventlog.js',
                        // Component registry
                        'engine/components/flow-registry.js',
                        // FlowComponent must come before actual components
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 cfd6c78..8192066 100644
--- a/modules/engine/components/board/base/flow-board-api-events.js
+++ b/modules/engine/components/board/base/flow-board-api-events.js
@@ -712,13 +712,16 @@
         */
        FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.submitReply = 
function ( info, data, jqxhr ) {
                var $form = $( this ).closest( 'form' ),
-                       flowBoard = mw.flow.getPrototypeMethod( 'board', 
'getInstanceByElement' )( $form );
+                       flowBoard = mw.flow.getPrototypeMethod( 'board', 
'getInstanceByElement' )( $form ),
+                       eventLog = new mw.flow.EventLog( 'FlowReplies' ); // 
@todo: create a shared object somewhere with the shared properties for 
FlowReplies schema
 
                if ( info.status !== 'done' ) {
                        // Error will be displayed by default, nothing else to 
wrap up
                        return;
                }
 
+               eventLog.logEvent( { action: 'save' } );
+
                flowBoard.emitWithReturn( 'cancelForm', $form );
 
                // Target should be flow-topic
diff --git 
a/modules/engine/components/board/base/flow-board-interactive-events.js 
b/modules/engine/components/board/base/flow-board-interactive-events.js
index b0e87ca..6299242 100644
--- a/modules/engine/components/board/base/flow-board-interactive-events.js
+++ b/modules/engine/components/board/base/flow-board-interactive-events.js
@@ -164,7 +164,8 @@
                        postId = $targetPost.data( 'flow-id' ),
                        topicTitle = $post.closest( '.flow-topic' ).find( 
'.flow-topic-title' ).text(),
                        replyToContent = $post.find( '.flow-post-content' 
).filter( ':first' ).text() || topicTitle,
-                       author = $.trim( $post.find( '.flow-author' ).filter( 
':first' ).find( '.mw-userlink' ).text() );
+                       author = $.trim( $post.find( '.flow-author' ).filter( 
':first' ).find( '.mw-userlink' ).text() ),
+                       eventLog = new mw.flow.EventLog( 'FlowReplies' ); // 
@todo: create a shared object somewhere with the shared properties for 
FlowReplies schema
 
                // Check if reply form has already been opened
                if ( $post.data( 'flow-replying' ) ) {
@@ -197,14 +198,27 @@
                // We have to make sure the data attribute is added to the 
form; the
                // addBack is failsafe for when form is actually the root node 
in $form
                // already (there may or may not be parent containers)
-               flowBoard.emitWithReturn( 'addFormCancelCallback', $form.find( 
'form' ).addBack( 'form' ), function () {
-                       $post.removeData( 'flow-replying' );
-                       $form.remove();
-               } );
+               flowBoard.emitWithReturn(
+                       'addFormCancelCallback',
+                       $form.find( 'form' ).addBack( 'form' ),
+                       function () {
+                               $post.removeData( 'flow-replying' );
+                               $form.remove();
+                       }
+               );
+
+               // Assign event log object to log cancel event
+               flowBoard.emitWithReturn(
+                       'setFormCancelEventLog',
+                       $form.find( 'form' ).addBack( 'form' ),
+                       eventLog
+               );
 
                // Add reply form below the post being replied to (WRT max 
depth)
                $targetPost.children( '.flow-replies' ).append( $form );
                $form.conditionalScrollIntoView();
+
+               eventLog.logEvent( { action: 'initiate' } );
        };
 
        /**
diff --git a/modules/engine/components/board/base/flow-boardandhistory-base.js 
b/modules/engine/components/board/base/flow-boardandhistory-base.js
index 1d4297b..1f4c814 100644
--- a/modules/engine/components/board/base/flow-boardandhistory-base.js
+++ b/modules/engine/components/board/base/flow-boardandhistory-base.js
@@ -110,9 +110,13 @@
                        $form = $( this ).closest( 'form' ),
                        flowComponent = mw.flow.getPrototypeMethod( 
'boardAndHistoryBase', 'getInstanceByElement' )( $form ),
                        $fields = $form.find( 'textarea, :text' ),
-                       changedFieldCount = 0;
+                       changedFieldCount = 0,
+                       callbacks = $form.data( 'flow-cancel-callback' ) || [],
+                       eventLog = $form.data( 'flow-cancel-eventlog' ) || { 
logEvent: function() {} };
 
                event.preventDefault();
+
+               eventLog.logEvent( { action: 'cancel-attempt' } );
 
                // Check for non-empty fields of text
                $fields.each( function () {
@@ -121,27 +125,36 @@
                                return false;
                        }
                } );
-               // If all the text fields are empty, OR if the user confirms to 
close this with text already entered, do it.
-               if ( !changedFieldCount || confirm( 
flowComponent.constructor.static.TemplateEngine.l10n( 'flow-cancel-warning' ) ) 
) {
-                       // Reset the form content
-                       $form[0].reset();
 
-                       // Trigger for flow-actions-disabler
-                       $form.find( 'textarea, :text' ).trigger( 'keyup' );
+               // If fields are not empty, AND the user confirms to close this 
with text already entered, log it as abort.
+               if ( changedFieldCount && !confirm( 
flowComponent.constructor.static.TemplateEngine.l10n( 'flow-cancel-warning' ) ) 
) {
+                       eventLog.logEvent( { action: 'cancel-abort' } );
 
-                       // Hide the form
-                       flowComponent.emitWithReturn( 'hideForm', $form );
-
-                       // Get rid of existing error messages
-                       flowComponent.emitWithReturn( 'removeError', $form );
-
-                       // Trigger the cancel callback
-                       if ( $form.data( 'flow-cancel-callback' ) ) {
-                               $.each( $form.data( 'flow-cancel-callback' ), 
function ( idx, fn ) {
-                                       fn.call( target, event );
-                               } );
-                       }
+                       // Don't cancel!
+                       return;
                }
+
+               // Only log if user had already entered text (= confirmed to 
close)
+               if ( changedFieldCount ) {
+                       eventLog.logEvent( { action: 'cancel' } );
+               }
+
+               // Reset the form content
+               $form[0].reset();
+
+               // Trigger for flow-actions-disabler
+               $form.find( 'textarea, :text' ).trigger( 'keyup' );
+
+               // Hide the form
+               flowComponent.emitWithReturn( 'hideForm', $form );
+
+               // Get rid of existing error messages
+               flowComponent.emitWithReturn( 'removeError', $form );
+
+               // Trigger the cancel callback
+               $.each( callbacks, function ( idx, fn ) {
+                       fn.call( target, event );
+               } );
        };
 
        //
diff --git a/modules/engine/components/common/flow-component-engines.js 
b/modules/engine/components/common/flow-component-engines.js
index 2769efd..3d8a928 100644
--- a/modules/engine/components/common/flow-component-engines.js
+++ b/modules/engine/components/common/flow-component-engines.js
@@ -28,6 +28,12 @@
         */
        mw.flow.Api = new mw.flow.FlowApi( 
FlowComponentEnginesMixin.static.StorageEngine );
 
+       /**
+        * EventLogging wrapper
+        * @type {FlowEventLog}
+        */
+       mw.flow.EventLog = mw.flow.FlowEventLog;
+
        // Copy static and prototype from mixin to main class
        mw.flow.mixinComponent( 'component', FlowComponentEnginesMixin );
 }( jQuery, mediaWiki, mediaWiki.flow.vendor.initStorer ) );
diff --git a/modules/engine/components/common/flow-component-events.js 
b/modules/engine/components/common/flow-component-events.js
index 9a81c89..ddc7864 100644
--- a/modules/engine/components/common/flow-component-events.js
+++ b/modules/engine/components/common/flow-component-events.js
@@ -666,6 +666,16 @@
        FlowComponentEventsMixin.eventHandlers.addFormCancelCallback = 
flowEventsMixinAddFormCancelCallback;
 
        /**
+        * Adds a flow-cancel-eventlog to a given form, to be triggered on 
click of the "cancel" button.
+        * @param {jQuery} $form
+        * @param {FlowEventLog} eventLog
+        */
+       function flowEventsMixinSetFormCancelCallback( $form, eventLog ) {
+               $form.data( 'flow-cancel-eventlog', eventLog );
+       }
+       FlowComponentEventsMixin.eventHandlers.setFormCancelEventLog = 
flowEventsMixinSetFormCancelCallback;
+
+       /**
         * @param {FlowBoardComponent|jQuery} $node or entire FlowBoard
         */
        function flowEventsMixinRemoveError( $node ) {
diff --git a/modules/engine/misc/flow-eventlog.js 
b/modules/engine/misc/flow-eventlog.js
new file mode 100644
index 0000000..a2291aa
--- /dev/null
+++ b/modules/engine/misc/flow-eventlog.js
@@ -0,0 +1,42 @@
+/*!
+ *
+ */
+
+window.mw = window.mw || {}; // mw-less testing
+
+( function ( mw, $ ) {
+       mw.flow = mw.flow || {}; // create mw.flow globally
+
+       /**
+        * @param {String} schemaName Canonical schema name.
+        * @param {Object} [eventInstance] Shared event instance data.
+        * @returns {FlowEventLog}
+        * @constructor
+        */
+       function FlowEventLog( schemaName, eventInstance ) {
+               this.schemaName = schemaName;
+               this.eventInstance = eventInstance || {};
+
+               /**
+                * @param {Object} eventInstance Additional event instance data 
for this
+                *   particular event.
+                * @returns {$.Deferred}
+                */
+               function logEvent( eventInstance ) {
+                       if ( mw.eventLog ) {
+                               return mw.eventLog.logEvent(
+                                       this.schema,
+                                       $.extend( this.eventInstance, 
eventInstance )
+                               );
+                       } else {
+                               // for compatibility: a deferred that never 
resolves
+                               return $.Deferred().promise();
+                       }
+               }
+
+               this.logEvent = logEvent;
+       }
+
+       // Export
+       mw.flow.FlowEventLog = FlowEventLog;
+}( mw, jQuery ) );

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

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

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

Reply via email to