2017-05-26 17:35:07 +00:00
|
|
|
/**
|
|
|
|
* @module actions
|
|
|
|
*/
|
|
|
|
|
2017-07-28 17:32:46 +00:00
|
|
|
import types from './actionTypes';
|
|
|
|
import wait from './wait';
|
2018-03-07 11:10:53 +00:00
|
|
|
import { createNullModel, previewTypes } from './preview/model';
|
2017-07-28 17:32:46 +00:00
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
var $ = jQuery,
|
|
|
|
mw = window.mediaWiki,
|
2017-03-24 05:33:50 +00:00
|
|
|
|
|
|
|
// See the following for context around this value.
|
|
|
|
//
|
|
|
|
// * https://phabricator.wikimedia.org/T161284
|
|
|
|
// * https://phabricator.wikimedia.org/T70861#3129780
|
|
|
|
FETCH_START_DELAY = 150, // ms.
|
2017-02-14 19:19:06 +00:00
|
|
|
|
2018-02-08 22:11:44 +00:00
|
|
|
// The minimum time a preview must be open before we judge it
|
|
|
|
// has been seen.
|
|
|
|
// See https://phabricator.wikimedia.org/T184793
|
|
|
|
PREVIEW_SEEN_DURATION = 1000, // ms
|
|
|
|
|
2017-03-26 18:19:24 +00:00
|
|
|
// The delay after which a FETCH_COMPLETE action should be dispatched.
|
2017-02-14 19:19:06 +00:00
|
|
|
//
|
|
|
|
// If the API endpoint responds faster than 500 ms (or, say, the API
|
|
|
|
// response is served from the UA's cache), then we introduce a delay of
|
2017-03-26 18:19:24 +00:00
|
|
|
// 500 - t to make the preview delay consistent to the user.
|
|
|
|
FETCH_COMPLETE_TARGET_DELAY = 500, // ms.
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
ABANDON_END_DELAY = 300; // ms.
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mixes in timing information to an action.
|
|
|
|
*
|
|
|
|
* Warning: the `baseAction` parameter is modified and returned.
|
|
|
|
*
|
|
|
|
* @param {Object} baseAction
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
function timedAction( baseAction ) {
|
|
|
|
baseAction.timestamp = mw.now();
|
|
|
|
|
|
|
|
return baseAction;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents Page Previews booting.
|
|
|
|
*
|
|
|
|
* When a Redux store is created, the `@@INIT` action is immediately
|
|
|
|
* dispatched to it. To avoid overriding the term, we refer to booting rather
|
|
|
|
* than initializing.
|
|
|
|
*
|
|
|
|
* Page Previews persists critical pieces of information to local storage.
|
|
|
|
* Since reading from and writing to local storage are synchronous, Page
|
|
|
|
* Previews is booted when the browser is idle (using
|
|
|
|
* [`mw.requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback))
|
|
|
|
* so as not to impact latency-critical events.
|
|
|
|
*
|
2017-03-03 11:19:46 +00:00
|
|
|
* @param {Boolean} isEnabled See `isEnabled.js`
|
2017-02-14 19:19:06 +00:00
|
|
|
* @param {mw.user} user
|
|
|
|
* @param {ext.popups.UserSettings} userSettings
|
|
|
|
* @param {Function} generateToken
|
|
|
|
* @param {mw.Map} config The config of the MediaWiki client-side application,
|
|
|
|
* i.e. `mw.config`
|
2018-02-15 20:15:23 +00:00
|
|
|
* @param {String} url url
|
2017-10-09 14:56:15 +00:00
|
|
|
* @return {Object}
|
2017-02-14 19:19:06 +00:00
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function boot(
|
2017-02-14 19:19:06 +00:00
|
|
|
isEnabled,
|
|
|
|
user,
|
|
|
|
userSettings,
|
|
|
|
generateToken,
|
2018-02-15 20:15:23 +00:00
|
|
|
config,
|
|
|
|
url
|
2017-02-14 19:19:06 +00:00
|
|
|
) {
|
|
|
|
var editCount = config.get( 'wgUserEditCount' ),
|
|
|
|
previewCount = userSettings.getPreviewCount();
|
|
|
|
|
|
|
|
return {
|
|
|
|
type: types.BOOT,
|
|
|
|
isEnabled: isEnabled,
|
|
|
|
isNavPopupsEnabled: config.get( 'wgPopupsConflictsWithNavPopupGadget' ),
|
|
|
|
sessionToken: user.sessionId(),
|
|
|
|
pageToken: generateToken(),
|
|
|
|
page: {
|
2018-02-15 20:15:23 +00:00
|
|
|
url: url,
|
2017-02-14 19:19:06 +00:00
|
|
|
title: config.get( 'wgTitle' ),
|
2018-02-26 18:23:38 +00:00
|
|
|
namespaceId: config.get( 'wgNamespaceNumber' ),
|
2017-02-14 19:19:06 +00:00
|
|
|
id: config.get( 'wgArticleId' )
|
|
|
|
},
|
|
|
|
user: {
|
|
|
|
isAnon: user.isAnon(),
|
|
|
|
editCount: editCount,
|
|
|
|
previewCount: previewCount
|
|
|
|
}
|
2016-11-08 19:42:21 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents Page Previews fetching data via the gateway.
|
|
|
|
*
|
2017-06-15 11:35:19 +00:00
|
|
|
* @param {Gateway} gateway
|
2017-06-08 15:23:44 +00:00
|
|
|
* @param {mw.Title} title
|
2017-02-14 19:19:06 +00:00
|
|
|
* @param {Element} el
|
2017-04-07 11:34:21 +00:00
|
|
|
* @param {String} token The unique token representing the link interaction that
|
|
|
|
* triggered the fetch
|
2017-02-14 19:19:06 +00:00
|
|
|
* @return {Redux.Thunk}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function fetch( gateway, title, el, token ) {
|
2017-06-12 10:13:32 +00:00
|
|
|
var titleText = title.getPrefixedDb(),
|
2018-02-26 18:23:38 +00:00
|
|
|
namespaceId = title.namespace;
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
return function ( dispatch ) {
|
2017-03-26 23:18:29 +00:00
|
|
|
var request;
|
|
|
|
|
2017-03-07 00:27:38 +00:00
|
|
|
dispatch( timedAction( {
|
2017-02-14 19:19:06 +00:00
|
|
|
type: types.FETCH_START,
|
|
|
|
el: el,
|
2017-05-09 18:41:23 +00:00
|
|
|
title: titleText,
|
2018-02-26 18:23:38 +00:00
|
|
|
namespaceId: namespaceId
|
2017-03-07 00:27:38 +00:00
|
|
|
} ) );
|
Add reading depth
Use schema revision 16163887.
Add the 'checkin' action, which is accompanied by the 'checkin'
property. The action is logged at the following seconds
(Fibonacci numbers) after the page loads: 1, 2, 3, 5, 8, 13, 21,
34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765.
The `checkin` property contains the values listed above.
Bug: T147314
Change-Id: Ib9ec7bd0e60aa34a04e32222b025347f6ee31794
2016-12-13 22:52:20 +00:00
|
|
|
|
2017-05-09 18:41:23 +00:00
|
|
|
request = gateway.getPageSummary( titleText )
|
2017-03-26 23:18:29 +00:00
|
|
|
.then( function ( result ) {
|
|
|
|
dispatch( timedAction( {
|
|
|
|
type: types.FETCH_END,
|
|
|
|
el: el
|
|
|
|
} ) );
|
|
|
|
|
|
|
|
return result;
|
|
|
|
} )
|
2018-02-13 11:57:31 +00:00
|
|
|
.catch( function ( err ) {
|
2017-02-14 19:19:06 +00:00
|
|
|
dispatch( {
|
|
|
|
type: types.FETCH_FAILED,
|
|
|
|
el: el
|
2016-11-16 19:45:10 +00:00
|
|
|
} );
|
2018-02-13 11:57:31 +00:00
|
|
|
// Keep the request promise in a rejected status since it failed.
|
|
|
|
throw err;
|
2017-03-26 23:18:29 +00:00
|
|
|
} );
|
2017-02-14 19:19:06 +00:00
|
|
|
|
2018-01-18 18:48:16 +00:00
|
|
|
return $.when(
|
|
|
|
request,
|
|
|
|
wait( FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY )
|
|
|
|
)
|
2017-03-26 23:18:29 +00:00
|
|
|
.then( function ( result ) {
|
2018-01-11 18:56:56 +00:00
|
|
|
dispatch( {
|
2017-03-26 23:18:29 +00:00
|
|
|
type: types.FETCH_COMPLETE,
|
|
|
|
el: el,
|
2017-04-07 11:34:21 +00:00
|
|
|
result: result,
|
|
|
|
token: token
|
2018-01-11 18:56:56 +00:00
|
|
|
} );
|
|
|
|
} )
|
2018-02-16 12:52:56 +00:00
|
|
|
.catch( function ( data, result ) {
|
2018-01-18 18:48:16 +00:00
|
|
|
// All failures, except those due to being offline or network error,
|
|
|
|
// should present "There was an issue displaying this preview".
|
|
|
|
// e.g.:
|
|
|
|
// - Show (timeout): data="http" {xhr: {…}, textStatus: "timeout",
|
|
|
|
// exception: "timeout"}
|
2018-01-11 18:56:56 +00:00
|
|
|
// - Show (bad MW request): data="unknown_action" {error: {…}}
|
2018-01-18 18:48:16 +00:00
|
|
|
// - Show (RB 4xx): data="http" {xhr: {…}, textStatus: "error",
|
|
|
|
// exception: "Bad Request"}
|
|
|
|
// - Show (RB 5xx): data="http" {xhr: {…}, textStatus: "error",
|
|
|
|
// exception: "Service Unavailable"}
|
|
|
|
// - Suppress (offline or network error): data="http"
|
|
|
|
// result={xhr: {…}, textStatus: "error", exception: ""}
|
|
|
|
var networkError = result && result.xhr &&
|
|
|
|
result.xhr.readyState === 0 && result.textStatus === 'error' &&
|
|
|
|
result.exception === '';
|
2018-01-11 18:56:56 +00:00
|
|
|
if ( !networkError ) {
|
|
|
|
dispatch( {
|
|
|
|
// Both FETCH_FAILED and FETCH_END conclude with FETCH_COMPLETE.
|
|
|
|
type: types.FETCH_COMPLETE,
|
|
|
|
el: el,
|
|
|
|
result: createNullModel( titleText, title.getUrl() ),
|
|
|
|
token: token
|
|
|
|
} );
|
|
|
|
}
|
2016-12-19 12:53:11 +00:00
|
|
|
} );
|
2017-02-14 19:19:06 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user dwelling on a link, either by hovering over it with
|
|
|
|
* their mouse or by focussing it using their keyboard or an assistive device.
|
|
|
|
*
|
2017-06-08 15:23:44 +00:00
|
|
|
* @param {mw.Title} title
|
2017-02-14 19:19:06 +00:00
|
|
|
* @param {Element} el
|
|
|
|
* @param {Event} event
|
2017-06-15 11:35:19 +00:00
|
|
|
* @param {Gateway} gateway
|
2017-02-14 19:19:06 +00:00
|
|
|
* @param {Function} generateToken
|
|
|
|
* @return {Redux.Thunk}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function linkDwell( title, el, event, gateway, generateToken ) {
|
2017-05-15 18:02:27 +00:00
|
|
|
var token = generateToken(),
|
2017-06-12 10:13:32 +00:00
|
|
|
titleText = title.getPrefixedDb(),
|
2018-02-26 18:23:38 +00:00
|
|
|
namespaceId = title.namespace;
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
return function ( dispatch, getState ) {
|
|
|
|
var action = timedAction( {
|
|
|
|
type: types.LINK_DWELL,
|
|
|
|
el: el,
|
|
|
|
event: event,
|
2017-05-15 18:02:27 +00:00
|
|
|
token: token,
|
|
|
|
title: titleText,
|
2018-02-26 18:23:38 +00:00
|
|
|
namespaceId: namespaceId
|
2017-02-14 19:19:06 +00:00
|
|
|
} );
|
2016-12-19 12:53:11 +00:00
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
// Has the new generated token been accepted?
|
|
|
|
function isNewInteraction() {
|
|
|
|
return getState().preview.activeToken === token;
|
|
|
|
}
|
2017-01-10 23:23:40 +00:00
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
dispatch( action );
|
2016-11-16 19:45:10 +00:00
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
if ( !isNewInteraction() ) {
|
2018-02-15 14:01:36 +00:00
|
|
|
return $.Deferred().resolve().promise();
|
2017-02-14 19:19:06 +00:00
|
|
|
}
|
2017-01-10 23:23:40 +00:00
|
|
|
|
2018-02-13 11:57:31 +00:00
|
|
|
return wait( FETCH_START_DELAY )
|
2017-02-14 19:19:06 +00:00
|
|
|
.then( function () {
|
|
|
|
var previewState = getState().preview;
|
2016-11-25 21:22:09 +00:00
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
if ( previewState.enabled && isNewInteraction() ) {
|
2018-02-16 12:52:56 +00:00
|
|
|
return dispatch( fetch( gateway, title, el, token ) );
|
2017-02-14 19:19:06 +00:00
|
|
|
}
|
|
|
|
} );
|
2016-11-09 11:57:24 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user abandoning a link, either by moving their mouse away
|
|
|
|
* from it or by shifting focus to another UI element using their keyboard or
|
|
|
|
* an assistive device, or abandoning a preview by moving their mouse away
|
|
|
|
* from it.
|
|
|
|
*
|
|
|
|
* @return {Redux.Thunk}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function abandon() {
|
2017-02-14 19:19:06 +00:00
|
|
|
return function ( dispatch, getState ) {
|
|
|
|
var token = getState().preview.activeToken;
|
|
|
|
|
2017-04-18 18:43:16 +00:00
|
|
|
if ( !token ) {
|
2018-02-15 14:01:36 +00:00
|
|
|
return $.Deferred().resolve().promise();
|
2017-04-18 18:43:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-14 19:19:06 +00:00
|
|
|
dispatch( timedAction( {
|
|
|
|
type: types.ABANDON_START,
|
|
|
|
token: token
|
|
|
|
} ) );
|
|
|
|
|
2018-02-13 11:57:31 +00:00
|
|
|
return wait( ABANDON_END_DELAY )
|
2017-02-14 19:19:06 +00:00
|
|
|
.then( function () {
|
|
|
|
dispatch( {
|
|
|
|
type: types.ABANDON_END,
|
|
|
|
token: token
|
2016-11-28 12:00:07 +00:00
|
|
|
} );
|
2017-02-14 19:19:06 +00:00
|
|
|
} );
|
2016-11-28 12:00:07 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user clicking on a link with their mouse, keyboard, or an
|
|
|
|
* assistive device.
|
|
|
|
*
|
|
|
|
* @param {Element} el
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function linkClick( el ) {
|
2017-02-14 19:19:06 +00:00
|
|
|
return timedAction( {
|
|
|
|
type: types.LINK_CLICK,
|
|
|
|
el: el
|
|
|
|
} );
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user dwelling on a preview with their mouse.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function previewDwell() {
|
2017-02-14 19:19:06 +00:00
|
|
|
return {
|
|
|
|
type: types.PREVIEW_DWELL
|
2016-12-05 11:56:51 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a preview being shown to the user.
|
|
|
|
*
|
2017-03-03 11:19:46 +00:00
|
|
|
* This action is dispatched by the `./changeListeners/render.js` change
|
2017-02-14 19:19:06 +00:00
|
|
|
* listener.
|
|
|
|
*
|
2017-04-10 17:28:24 +00:00
|
|
|
* @param {String} token
|
2017-02-14 19:19:06 +00:00
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function previewShow( token ) {
|
2018-02-08 22:11:44 +00:00
|
|
|
return function ( dispatch, getState ) {
|
|
|
|
dispatch(
|
|
|
|
timedAction( {
|
|
|
|
type: types.PREVIEW_SHOW,
|
|
|
|
token: token
|
|
|
|
} )
|
|
|
|
);
|
|
|
|
|
|
|
|
return wait( PREVIEW_SEEN_DURATION )
|
|
|
|
.then( function () {
|
|
|
|
var state = getState(),
|
|
|
|
preview = state.preview,
|
|
|
|
fetchResponse = preview && preview.fetchResponse,
|
2018-03-07 11:10:53 +00:00
|
|
|
currentToken = preview && preview.activeToken,
|
|
|
|
validType = fetchResponse && [
|
|
|
|
previewTypes.TYPE_PAGE,
|
|
|
|
previewTypes.TYPE_DISAMBIGUATION
|
|
|
|
].indexOf( fetchResponse.type ) > -1;
|
2018-02-08 22:11:44 +00:00
|
|
|
|
|
|
|
if (
|
2018-02-21 18:28:56 +00:00
|
|
|
// Check the pageview can still be associated with original event
|
2018-02-08 22:11:44 +00:00
|
|
|
currentToken && currentToken === token &&
|
|
|
|
// and the preview is still active and of type `page`
|
2018-03-07 11:10:53 +00:00
|
|
|
fetchResponse && validType
|
2018-02-08 22:11:44 +00:00
|
|
|
) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.PREVIEW_SEEN,
|
|
|
|
title: fetchResponse.title,
|
2018-02-15 20:15:23 +00:00
|
|
|
pageId: fetchResponse.pageId,
|
2018-02-08 22:11:44 +00:00
|
|
|
// The existing version of summary endpoint does not
|
|
|
|
// provide namespace information, but new version
|
2018-02-21 18:28:56 +00:00
|
|
|
// will. Given we only show pageviews for main namespace
|
2018-02-08 22:11:44 +00:00
|
|
|
// this is hardcoded until the newer version is available.
|
|
|
|
namespace: 0
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-21 18:28:56 +00:00
|
|
|
* Represents the situation when a pageview has been logged
|
2018-02-08 22:11:44 +00:00
|
|
|
* (see previewShow and PREVIEW_SEEN action type)
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2018-02-21 18:28:56 +00:00
|
|
|
export function pageviewLogged() {
|
2018-02-08 22:11:44 +00:00
|
|
|
return {
|
|
|
|
type: types.PAGEVIEW_LOGGED
|
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user clicking either the "Enable previews" footer menu link,
|
|
|
|
* or the "cog" icon that's present on each preview.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function showSettings() {
|
2017-02-14 19:19:06 +00:00
|
|
|
return {
|
|
|
|
type: types.SETTINGS_SHOW
|
2016-12-12 17:17:41 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user closing the settings dialog and saving their settings.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function hideSettings() {
|
2017-02-14 19:19:06 +00:00
|
|
|
return {
|
|
|
|
type: types.SETTINGS_HIDE
|
2016-11-15 18:18:13 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user saving their settings.
|
|
|
|
*
|
|
|
|
* N.B. This action returns a Redux.Thunk not because it needs to perform
|
|
|
|
* asynchronous work, but because it needs to query the global state for the
|
|
|
|
* current enabled state. In order to keep the enabled state in a single
|
|
|
|
* place (the preview reducer), we query it and dispatch it as `wasEnabled`
|
|
|
|
* so that other reducers (like settings) can act on it without having to
|
|
|
|
* duplicate the `enabled` state locally.
|
|
|
|
* See doc/adr/0003-keep-enabled-state-only-in-preview-reducer.md for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* @param {Boolean} enabled if previews are enabled or not
|
|
|
|
* @return {Redux.Thunk}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function saveSettings( enabled ) {
|
2017-02-14 19:19:06 +00:00
|
|
|
return function ( dispatch, getState ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.SETTINGS_CHANGE,
|
|
|
|
wasEnabled: getState().preview.enabled,
|
|
|
|
enabled: enabled
|
|
|
|
} );
|
2016-12-12 19:26:55 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2017-02-14 19:19:06 +00:00
|
|
|
|
|
|
|
/**
|
2017-03-03 11:19:46 +00:00
|
|
|
* Represents the queued event being logged `changeListeners/eventLogging.js`
|
|
|
|
* change listener.
|
2017-02-14 19:19:06 +00:00
|
|
|
*
|
2017-05-10 11:38:41 +00:00
|
|
|
* @param {Object} event
|
2017-02-14 19:19:06 +00:00
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function eventLogged( event ) {
|
2017-02-14 19:19:06 +00:00
|
|
|
return {
|
2017-05-10 11:38:41 +00:00
|
|
|
type: types.EVENT_LOGGED,
|
|
|
|
event: event
|
2016-11-30 13:40:08 +00:00
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|
2016-11-30 13:40:08 +00:00
|
|
|
|
2017-03-07 00:27:38 +00:00
|
|
|
/**
|
|
|
|
* Represents the queued statsv event being logged.
|
|
|
|
* See `mw.popups.changeListeners.statsv` change listener.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2017-07-28 17:32:46 +00:00
|
|
|
export function statsvLogged() {
|
2017-03-07 00:27:38 +00:00
|
|
|
return {
|
|
|
|
type: types.STATSV_LOGGED
|
|
|
|
};
|
2017-07-28 17:32:46 +00:00
|
|
|
}
|