User:SBisson (WMF)/story.js

var verbose = true; var log = verbose ? console.log : function {};

function isReadingArticle { var action = mw.config.get( 'wgAction' ); if ( action !== 'view' ) { log( 'Article action should be view but it is', action ); return false; }

var ns = mw.config.get( 'wgNamespaceNumber' ); if ( ns !== 0 ) { log( 'Not the article ns:', ns ); return false; }

// todo: check that the article exists: articleId !== 0

return true; }

function makeStoryFromMediaList( title ) { var url = 'https://en.wikipedia.org/api/rest_v1/page/media-list/' + title; return fetch( url ).then( function( resp ) {   return resp.json;  }).then( function ( json ) {    var frames = json && json.items && json.items      .filter( function( item ) { return item.type === 'image' && item.showInGallery && item.caption && item.caption.text; } )      .map( function( item ) { return { src: item.srcset[0].src, text: item.caption.text } } );    if ( frames && frames.length >= 4 ) {      return frames;    }  }); }

function getStory( title ) { return makeStoryFromMediaList( title ); }

function addStoryButton( onClick ) { var span = $( ' ' ).text( 'WikiStory' ); var button = $( '' ).append( span ).on( 'click', onClick ); var listItem = $( '' ).addClass( 'mw-list-item' ).attr( 'id', 'ca-story' ).append( button ); $( '#left-navigation .vector-menu-content-list' ).append( listItem ); }

function createStoryViewer { return mw.loader.using( 'vue' ).done( function ( require ) {   var Vue = require( 'vue' );

Vue.component( 'frame', {     template: '  ',      props: [ 'src', 'text', 'click' ],      computed: {        style: function  { return { backgroundImage: 'url(' + this.src + ')', position: 'relative', backgroundSize: 'cover', backgroundPosition: 'center', width: '80vw', height: '80vh' }; },        pStyle: function  { return { position: 'absolute', bottom: '10px', left: '10px', right: '10px', maxHeight: '80%', backgroundColor: 'white', borderRadius: '10px', textAlign: 'center', margin: 0, padding: '10px' }; },      }    } );

Vue.component( 'story-viewer', {     template: ' ',      props: [ 'story', 'visible', 'eventSubmit' ],      data: function {        return {          show: this.visible,          index: 0,          style: { backgroundColor: 'black', position: 'absolute', top: 0, bottom: 0, right: 0, left: 0, zIndex: 101, display: 'flex', alignItems: 'center', justifyContent: 'center' }        };      },      computed: { frame: function { return this.story[ this.index ]; } },      methods: {        overlayClick: function( e ) { if ( e.target.classList.contains('story-viewer') ) { this.close; } },        nextFrame: function { if ( this.index < this.story.length - 1 ) { this.index++; } else { this.close; } },        logEvent: function {          this.eventSubmit('test.instrumentation', { "$schema": "/analytics/test/2.0.0", "test_string": "Inuka-WSRE-test1", "test_map": { "title": mw.config.get( 'wgPageName' ), "story_frame_count": this.story.length, "story_frame_read": this.index }         });        },        close: function { this.logEvent; this.show = false; }      }    } );

log('StoryViewer initialized' ); }); }

function launchStoryViewer( Vue, story ) { $( 'body' ).append ( $( ' ' ).addClass( 'story-container' ) ); new Vue( { 	render: function ( h ) { return h( 'story-viewer', { props: { story: story, visible: true, eventSubmit: mw.eventLog.submit } } ) }  } ).$mount( '.story-container' ); }

if ( isReadingArticle ) { var title = mw.config.get( 'wgPageName' ); getStory( title ).then( function( story ) {   if ( story ) {      var p = createStoryViewer;      addStoryButton( function { p.done( function( require ) { launchStoryViewer( require( 'vue' ), story ); } ) } );    } else {      log( 'No story available for article', title );    }  }); }