<commit_before>$.ajaxSetup({
    cache: false,
    dataType: "json"
});
//not used - the data should come sorted, but it does not
//left here in case all else fails
var sortJSON = function(data, key){
    return data.sort(function(a, b){
        var x = a[key];
        var y = b[key];
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
};

var iconDecider = function(itemType){
    var path = '/library/image/sakai/';
    switch (itemType) {
        case "application/mac-binhex40":
            return path + 'compressed.gif';
        case "application/msword":
            return path + 'word.gif';
        case "application/pdf":
            return path + 'pdf.gif';
        case "application/postscript":
            return path + 'postscript.gif';
        case "application/rtf":
            return path + 'word.gif';
        case "application/vnd.ms-excel":
            return path + 'excel.gif';
        case "application/vnd.ms-powerpoint":
            return path + 'ppt.gif';
        case "application/x-msaccess":
            return path + 'access.gif';
        case "application/x-shockwave-flash":
            return path + 'shockwave.gif';
        case "application/x-stuffit":
            return path + 'compressed.gif';
        case "application/x-tar":
            return path + 'compressed.gif';
        case "application/zip":
            return path + 'compressed.gif';
        case "audio/mpeg":
            return path + 'audio.gif';
        case "audio/x-pn-realaudio":
            return path + 'real.gif';
        case "image/gif":
            return path + 'image.gif';
        case "image/png":
            return path + 'image.gif';
        case "image/vnd.adobe.photoshop":
            return path + 'photoshop.gif';
        case "text/csv":
            return path + 'excel.gif';
        case "text/html":
            return path + 'html.gif';
        case "text/plain":
            return path + 'text.gif';
        case "text/x-java-source":
            return path + 'java.gif';
        case "video/mpeg":
            return path + 'movie.gif';
        case "video/quicktime":
            return path + 'movie.gif';
        default:
            return path + 'default.gif';
    }
};

var renderHierarchyWithJsonTree = function(data){

    var collId = $('#collectionId').val();
    var siteId = collId.split('/')[2];
    //massage the json so that we can use jsonTree
    $.each(data.content_collection, function(i, item){
        item.text = item.title;
        //get item.id field to turn into a jsTree happy item.id
        item.id = item.url.substr(item.url.indexOf('/content/group/' + siteId));

        //transforming item.container into item.parent
        if (item.type === 'collection'){
            item.id = item.id.substring(0,item.id.length -1);
        }
        var itemIdArr = item.id.split('/');
        var parentPath = item.id.split('/').slice(0,itemIdArr.length - 1).join('_');
        item.id = item.id.replace(/\//g, "_");
        //if this is site root, special parent value
        // since the site root title is null in /direct
        // give it the site title
        if (item.container === '/content/group/') {
            item.parent = '#';
            //TODO: some sites report 'null' for title, use the Id - need better handle
            if (item.title === null){
                item.text = siteId;
            }
            else {
                item.text = item.title;
            }

        }
        else {
            item.parent = parentPath;
        }
        var pathArr = item.url.split('/');
        var siteIdLoc = pathArr.indexOf(siteId);
        var pathToFolder = decodeURIComponent('/group/' + pathArr.slice(siteIdLoc).join('/'));
        var pathToFile = item.url;
        var itemType = '';
        var itemUrl = '';
        //depending on file or collection type, custom parameters
        if (item.type === 'collection') {
            var itemText ='';
            if(item.numChildren ===1){
                itemText = ' item';
            }
            if(item.numChildren ===0 || item.numChildren > 1){
                itemText = ' items';
            }
            itemType = 'folder';
            item.text = item.text + '   (' + item.numChildren + itemText + ')';
            itemUrl = pathToFolder;
        }
        else {
            itemType = 'file';
            item.icon = iconDecider(item.type);
            itemUrl = pathToFile;
        }
        //adding custom parameters for URL and TYPE
        item.li_attr = {
            'data_url': itemUrl,
            'data_type': itemType,
            'data_children': item.numChildren
        };
    });

    $(function(){
        $("#navigatePanelInner").on('changed.jstree', function(e, data){
            var selectedId = data.selected[0];
            //if the clicked link is a file - launch the /access link to it
            //TODO: will this trigger the copyright aggreement form?
            if (data.node.li_attr.data_type === 'file') {
                var launchURL = data.node.li_attr.data_url;
                window.open(launchURL);
            }
            else {
                var folderUrl = data.node.li_attr.data_url;
                // here we are populating the form associated with resources list
                $('#sakai_action').val('doNavigate');
                $('#collectionId').val(folderUrl);
                $('#navRoot').val('');
                // and after populating the values we submit the form to navigate
                // to the folder
                $('#showForm').submit();
            }
        }).jstree({
            'core': {
                'multiple': false,
                'data': data.content_collection,
                'themes': {
                    'stripes': true,
                    'theme': 'default',
                    'dots': true,
                    'icons': true
                }
            },
            "search": {
                "case_insensitive": true
            },
            "plugins": ["themes", "search"]
        });
    });
    $('#navigatePanelInner').jstree('open_node', '_content_group_' + siteId);
    $('#navigatePanel').fadeIn('slow');
};

$(document).ready(function(){
    var to = false;
    $('#navigatePanelSearch').keyup(function(){
        if (to) {
            clearTimeout(to);
        }
        to = setTimeout(function(){
            var v = $('#navigatePanelSearch').val();
            $("#navigatePanelInner").jstree("search", v);
        }, 250);
    });

    if ($('#content_print_result_url').length) {
        window.open($('#content_print_result_url').val(), $('#content_print_result_url_title'), "height=800,width=800");
    }
    $('.portletBody').click(function(e){
        if (e.target.className != 'menuOpen' && e.target.className != 'dropdn') {
            $('.makeMenuChild').hide();
        }
        else {
            if (e.target.className == 'dropdn') {
                $('.makeMenuChild').hide();
                $(e.target).parent('li').find('ul').show().find('li:first a').focus();

            }
            else {
                $('.makeMenuChild').hide();
                $(e.target).find('ul').show().find('li:first a').focus();
            }
        }
    });

    $('#navigatePanel p.close').on('click', function(){
        $('.keep-open').removeClass('open');
    });
    $('.toggleDescription').click(function(e){
        e.preventDefault();
        $('.descPanel').css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
        $(this).next('div').css({
            'top': e.pageY + 10,
            'left': e.pageX + 10,
            'cursor': 'pointer',
            'display': 'block'
        }).attr({
            'aria-hidden': 'false',
            'tabindex': '0'
        });
    });
    $('.descPanel').blur(function(){
        $(this).css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
    });
    $('.descPanel').click(function(){
        $(this).css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
    });

    $('#navigatePanelInnerCollapse').on('click', function(e){
        e.preventDefault();
        $('#navigatePanelInner').jstree('close_all');
    });
    $('#navigatePanelInnerExpand').on('click', function(e){
        e.preventDefault();
        $('#navigatePanelInner').jstree('open_all');
    });

    var collId = $('#collectionId').val();
    collId = collId.substring(0, collId.length - 1);
    // construct a url to /direct based on current site
    var url = '/direct/content' + collId.replace('/group/', '/site/').replace('/user/', '/site/') + '.json';
    $('#navigate').click(function(){
        if ($('#navigatePanelInner ul').length === 0) {
            var jqxhr = $.getJSON(url, function(data){
                if (data.content_collection.length) {
                    renderHierarchyWithJsonTree(data);
                }
                else {
                    $('#navigatePanelInner').html('
 Cannot do workspaces now, sorry!
');
                }
            }).done(function(){
            }).fail(function(){
            }).always(function(){
            });
        }
    });

    $('.dropdown.keep-open').on({
        "shown.bs.dropdown": function(){
            $(this).data('closable', true);
        },
        "click": function(){
            $(this).data('closable', false);

        },
        "hide.bs.dropdown": function(){
            return $(this).data('closable');
        }
    });

});
<commit_msg>SAK-25778 - add generic icon for unknowns<commit_after>$.ajaxSetup({
    cache: false,
    dataType: "json"
});
//not used - the data should come sorted, but it does not
//left here in case all else fails
var sortJSON = function(data, key){
    return data.sort(function(a, b){
        var x = a[key];
        var y = b[key];
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
};

var iconDecider = function(itemType){
    var path = '/library/image/sakai/';
    switch (itemType) {
        case "application/mac-binhex40":
            return path + 'compressed.gif';
        case "application/msword":
            return path + 'word.gif';
        case "application/pdf":
            return path + 'pdf.gif';
        case "application/postscript":
            return path + 'postscript.gif';
        case "application/rtf":
            return path + 'word.gif';
        case "application/vnd.ms-excel":
            return path + 'excel.gif';
        case "application/vnd.ms-powerpoint":
            return path + 'ppt.gif';
        case "application/x-msaccess":
            return path + 'access.gif';
        case "application/x-shockwave-flash":
            return path + 'shockwave.gif';
        case "application/x-stuffit":
            return path + 'compressed.gif';
        case "application/x-tar":
            return path + 'compressed.gif';
        case "application/zip":
            return path + 'compressed.gif';
        case "audio/mpeg":
            return path + 'audio.gif';
        case "audio/x-pn-realaudio":
            return path + 'real.gif';
        case "image/gif":
            return path + 'image.gif';
        case "image/png":
            return path + 'image.gif';
        case "image/vnd.adobe.photoshop":
            return path + 'photoshop.gif';
        case "text/csv":
            return path + 'excel.gif';
        case "text/html":
            return path + 'html.gif';
        case "text/plain":
            return path + 'text.gif';
        case "text/x-java-source":
            return path + 'java.gif';
        case "video/mpeg":
            return path + 'movie.gif';
        case "video/quicktime":
            return path + 'movie.gif';
        default:
            return path + 'generic.gif';
    }
};

var renderHierarchyWithJsonTree = function(data){

    var collId = $('#collectionId').val();
    var siteId = collId.split('/')[2];
    //massage the json so that we can use jsonTree
    $.each(data.content_collection, function(i, item){
        item.text = item.title;
        //get item.id field to turn into a jsTree happy item.id
        item.id = item.url.substr(item.url.indexOf('/content/group/' + siteId));

        //transforming item.container into item.parent
        if (item.type === 'collection'){
            item.id = item.id.substring(0,item.id.length -1);
        }
        var itemIdArr = item.id.split('/');
        var parentPath = item.id.split('/').slice(0,itemIdArr.length - 1).join('_');
        item.id = item.id.replace(/\//g, "_");
        //if this is site root, special parent value
        // since the site root title is null in /direct
        // give it the site title
        if (item.container === '/content/group/') {
            item.parent = '#';
            //TODO: some sites report 'null' for title, use the Id - need better handle
            if (item.title === null){
                item.text = siteId;
            }
            else {
                item.text = item.title;
            }

        }
        else {
            item.parent = parentPath;
        }
        var pathArr = item.url.split('/');
        var siteIdLoc = pathArr.indexOf(siteId);
        var pathToFolder = decodeURIComponent('/group/' + pathArr.slice(siteIdLoc).join('/'));
        var pathToFile = item.url;
        var itemType = '';
        var itemUrl = '';
        //depending on file or collection type, custom parameters
        if (item.type === 'collection') {
            var itemText ='';
            if(item.numChildren ===1){
                itemText = ' item';
            }
            if(item.numChildren ===0 || item.numChildren > 1){
                itemText = ' items';
            }
            itemType = 'folder';
            item.text = item.text + '   (' + item.numChildren + itemText + ')';
            itemUrl = pathToFolder;
        }
        else {
            itemType = 'file';
            item.icon = iconDecider(item.type);
            itemUrl = pathToFile;
        }
        //adding custom parameters for URL and TYPE
        item.li_attr = {
            'data_url': itemUrl,
            'data_type': itemType,
            'data_children': item.numChildren
        };
    });

    $(function(){
        $("#navigatePanelInner").on('changed.jstree', function(e, data){
            var selectedId = data.selected[0];
            //if the clicked link is a file - launch the /access link to it
            //TODO: will this trigger the copyright aggreement form?
            if (data.node.li_attr.data_type === 'file') {
                var launchURL = data.node.li_attr.data_url;
                window.open(launchURL);
            }
            else {
                var folderUrl = data.node.li_attr.data_url;
                // here we are populating the form associated with resources list
                $('#sakai_action').val('doNavigate');
                $('#collectionId').val(folderUrl);
                $('#navRoot').val('');
                // and after populating the values we submit the form to navigate
                // to the folder
                $('#showForm').submit();
            }
        }).jstree({
            'core': {
                'multiple': false,
                'data': data.content_collection,
                'themes': {
                    'stripes': true,
                    'theme': 'default',
                    'dots': true,
                    'icons': true
                }
            },
            "search": {
                "case_insensitive": true
            },
            "plugins": ["themes", "search"]
        });
    });
    $('#navigatePanelInner').jstree('open_node', '_content_group_' + siteId);
    $('#navigatePanel').fadeIn('slow');
};

$(document).ready(function(){
    var to = false;
    $('#navigatePanelSearch').keyup(function(){
        if (to) {
            clearTimeout(to);
        }
        to = setTimeout(function(){
            var v = $('#navigatePanelSearch').val();
            $("#navigatePanelInner").jstree("search", v);
        }, 250);
    });

    if ($('#content_print_result_url').length) {
        window.open($('#content_print_result_url').val(), $('#content_print_result_url_title'), "height=800,width=800");
    }
    $('.portletBody').click(function(e){
        if (e.target.className != 'menuOpen' && e.target.className != 'dropdn') {
            $('.makeMenuChild').hide();
        }
        else {
            if (e.target.className == 'dropdn') {
                $('.makeMenuChild').hide();
                $(e.target).parent('li').find('ul').show().find('li:first a').focus();

            }
            else {
                $('.makeMenuChild').hide();
                $(e.target).find('ul').show().find('li:first a').focus();
            }
        }
    });

    $('#navigatePanel p.close').on('click', function(){
        $('.keep-open').removeClass('open');
    });
    $('.toggleDescription').click(function(e){
        e.preventDefault();
        $('.descPanel').css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
        $(this).next('div').css({
            'top': e.pageY + 10,
            'left': e.pageX + 10,
            'cursor': 'pointer',
            'display': 'block'
        }).attr({
            'aria-hidden': 'false',
            'tabindex': '0'
        });
    });
    $('.descPanel').blur(function(){
        $(this).css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
    });
    $('.descPanel').click(function(){
        $(this).css({
            'top': '-1000px',
            'left': '-1000px',
            'display': 'none'
        }).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        });
    });

    $('#navigatePanelInnerCollapse').on('click', function(e){
        e.preventDefault();
        $('#navigatePanelInner').jstree('close_all');
    });
    $('#navigatePanelInnerExpand').on('click', function(e){
        e.preventDefault();
        $('#navigatePanelInner').jstree('open_all');
    });

    var collId = $('#collectionId').val();
    collId = collId.substring(0, collId.length - 1);
    // construct a url to /direct based on current site
    var url = '/direct/content' + collId.replace('/group/', '/site/').replace('/user/', '/site/') + '.json';
    $('#navigate').click(function(){
        if ($('#navigatePanelInner ul').length === 0) {
            var jqxhr = $.getJSON(url, function(data){
                if (data.content_collection.length) {
                    renderHierarchyWithJsonTree(data);
                }
                else {
                    $('#navigatePanelInner').html('
 Cannot do workspaces now, sorry!
');
                }
            }).done(function(){
            }).fail(function(){
            }).always(function(){
            });
        }
    });

    $('.dropdown.keep-open').on({
        "shown.bs.dropdown": function(){
            $(this).data('closable', true);
        },
        "click": function(){
            $(this).data('closable', false);

        },
        "hide.bs.dropdown": function(){
            return $(this).data('closable');
        }
    });

});
<|endoftext|>


<commit_before>/**
 * @file This file is the main (i.e. body) javascript file of web worker. It is not
 * an importable module.
 *
 * In module (non-classic) web worker, static import is available. But at the same
 * time, importScripts() will not be avbailable. For solving this problem, using
 * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
 * can be loaded by importScripts(). And use dynamic import() to load ourselves
 * modules because import() can be used in classic (non-module) script.
 */

//import( "./AsyncWorker_Body_tester.js" );

//!!! (2022/09/13 Remarked) use import() at global.
( async () => {
  await import( "./AsyncWorker_Body_tester.js" );
} )();

globalThis.onmessage = ( e ) => {
  console.log( "Hi2" );
  console.log( e );
};
<commit_msg>globalThis.onmessage<commit_after>/**
 * @file This file is the main (i.e. body) javascript file of web worker. It is not
 * an importable module.
 *
 * In module (non-classic) web worker, static import is available. But at the same
 * time, importScripts() will not be avbailable. For solving this problem, using
 * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
 * can be loaded by importScripts(). And use dynamic import() to load ourselves
 * modules because import() can be used in classic (non-module) script.
 */

import( "./AsyncWorker_Body_tester.js" );

//!!! (2022/09/13 Remarked) use import() at global.
// import( "./AsyncWorker_Body_tester.js" ).then( () => {
// });

//!!! (2022/09/13 Remarked) use import() at global.
// ( async () => {
//   await import( "./AsyncWorker_Body_tester.js" );
// } )();

globalThis.onmessage = ( e ) => {
  console.log( "Hi2" );
  console.log( e );
};
<|endoftext|>


<commit_before>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { processingId_Resulter_Map } from "./AsyncWorker_processingId_Resulter_Map.js";
import { Resulter } from "./AsyncWorker_Resulter.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {string} workerModuleURL
 *   The (absolute) javascript module URL which will be loaded (asynchronously) by
 * worker body (stub).
 *
 * @member {Worker} worker
 *   The worker.
 *
 * @member {number} processingId_next
 *   The next processing id. Zero means no command has been sent. Every
 * postCommand_and_expectResult() call will use a new id.
 *
 * @member {processingId_Resulter_Map} the_processingId_Resulter_Map
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a AsyncWorker.Resulter.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor( workerModuleURL ) {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerModuleURL );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerModuleURL );
    return this;
  }

  /** @override */
  static setAsConstructor_self( workerModuleURL ) {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_next = 0;

    if ( this.the_processingId_Resulter_Map )
      this.the_processingId_Resulter_Map.clear();
    else
      this.the_processingId_Resulter_Map = new processingId_Resulter_Map();

    AsyncWorker_Proxy.createWorker_byModuleURL.call( this, workerModuleURL );
  }

  /** @override */
  disposeResources() {

    if ( this.worker ) {
      // Note: No processingId, because this command needs not return value.
      this.postCommandArgs( "disposeResources" );
      this.worker = null;
    }

    this.workerOptions = undefined;
    this.workerURL = undefined;
    this.workerModuleURL = undefined;

    this.the_processingId_Resulter_Map.clear();

    this.processingId_next = undefined;

    super.disposeResources();
  }

  /**
   * @param {AsyncWorker_Proxy} this
   *   The worker proxy.
   */
  static createWorker_byModuleURL( workerModuleURL ) {
    this.workerModuleURL = workerModuleURL;

    let workerDataURI
      = AsyncWorker_Proxy.create_WorkerBodyStub_Codes_DataURI( workerModuleURL );

    this.workerURL = workerDataURI;

    // Q: Why not use "module" type worker?
    // A: A "module" type worker can not use importScripts() to load global library.
    //    (e.g. tensorflow.js)
    //
    // On the other hand, a "classic" type worker can use both importScripts() and
    // import() to load global library and module.
    //
    this.workerOptions = null;

    this.worker = new Worker( this.workerURL, this.workerOptions );

    // Register callback from the web worker.
    this.worker.onmessage
      = AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body.bind( this );
  }

  /**
   * Create a data URI representing the main (i.e. body) javascript file of web worker.
   * It is viewed as a classic javascript file (i.e. not an importable module). But
   * it will load specified workerModuleURL as a module.
   *
   * In module (non-classic) web worker, static import is available. But the function
   * importScripts() will not be avbailable. For solving this problem, using
   * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
   * can be loaded by importScripts(). And use dynamic import() to load ourselves
   * modules because import() can be used in classic (non-module) script.
   *
   * @param {string} workerModuleURL
   *   An (absolute) URL to a javascript module file. It will be imported
   * (asynchronously) by this generated classic javascript file (as a dataURI).
   */
  static create_WorkerBodyStub_Codes_DataURI( workerModuleURL ) {

    // The codes do the following:
    //
    //   - Import the specified module URL.
    //   - Create a temporary message queue.
    //   - Collect all messages before
    //       AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body() be registered
    //       as message handler.
    //
    let codes = ``
      + `import( "${workerModuleURL}" );\n`
      + `AsyncWorker_Body_temporaryMessageQueue = [];\n`
      + `onmessage = ( e ) => {\n`
        // + `console.log( "Hello" );\n`
        // + `console.log( e );\n`
        + `AsyncWorker_Body_temporaryMessageQueue.push( e );\n`
      + `};\n`
      ;

    let workerDataURI
      = AsyncWorker_Proxy.createDataURI_byStringASCII( "text/javascript", codes );

    return workerDataURI;
  }

  /**
   * @param {string} strMimeType  The result mime type of the data URI.
   * @param {string} strASCII     The ASCII text to be embedded in data URI.
   *
   * @return {string} Return the data URI string.
   */
  static createDataURI_byStringASCII( strMimeType, strASCII ) {
    // let textEncoder = new TextEncoder();
    // let str_utf8 = textEncoder.encode( str );
    // let str_base64 = btoa( str_utf8 );
    let str_base64 = btoa( strASCII );
    let dataURI = `data:${strMimeType};base64,${str_base64}`;
    return dataURI;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect the final result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {Promise}
   *   Return a promise resolved to the final value of the processing's resulter
   * from WorkerBody. (i.e. Only the Xxx of { done: true, value: Xxx } resolved.
   * All other intermediate result { done: false, value: Yyy } are discarded.)
   */
  createPromise_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let resulter = this.createResulter_by_postCommandArgs(
      commandArgs, transferableObjectArray );
    return resulter.untilDone();
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {AsyncWorker.Resulter}
   *   Return an async generator for receving result from WorkerBody of the processing.
   */
  createResulter_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let processingId = this.processingId_next;
    ++this.processingId_next;

    // Prepare the processing's result's receiving queue before sending it.
    let resulter = this.the_processingId_Resulter_Map.createResulter_by_processingId(
      processingId );

    this.worker.postMessage( commandArgs, transferableObjectArray );
    return resulter;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * without expecting result. (i.e. fire-and-forget)
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   */
  postCommandArgs( commandArgs, transferableObjectArray ) {
    this.worker.postMessage( commandArgs, transferableObjectArray );
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

    // ( e.data == [ processingId, done, value ] )
    let [ processingId, done, value ] = e.data;

    this.the_processingId_Resulter_Map.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<commit_msg>create_WorkerBodyStub_Codes_DataURI<commit_after>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { processingId_Resulter_Map } from "./AsyncWorker_processingId_Resulter_Map.js";
import { Resulter } from "./AsyncWorker_Resulter.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {string} workerModuleURL
 *   The (absolute) javascript module URL which will be loaded (asynchronously) by
 * worker body (stub).
 *
 * @member {Worker} worker
 *   The worker.
 *
 * @member {number} processingId_next
 *   The next processing id. Zero means no command has been sent. Every
 * postCommand_and_expectResult() call will use a new id.
 *
 * @member {processingId_Resulter_Map} the_processingId_Resulter_Map
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a AsyncWorker.Resulter.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor( workerModuleURL ) {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerModuleURL );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerModuleURL );
    return this;
  }

  /** @override */
  static setAsConstructor_self( workerModuleURL ) {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_next = 0;

    if ( this.the_processingId_Resulter_Map )
      this.the_processingId_Resulter_Map.clear();
    else
      this.the_processingId_Resulter_Map = new processingId_Resulter_Map();

    AsyncWorker_Proxy.createWorker_byModuleURL.call( this, workerModuleURL );
  }

  /** @override */
  disposeResources() {

    if ( this.worker ) {
      // Note: No processingId, because this command needs not return value.
      this.postCommandArgs( "disposeResources" );
      this.worker = null;
    }

    this.workerOptions = undefined;
    this.workerURL = undefined;
    this.workerModuleURL = undefined;

    this.the_processingId_Resulter_Map.clear();

    this.processingId_next = undefined;

    super.disposeResources();
  }

  /**
   * @param {AsyncWorker_Proxy} this
   *   The worker proxy.
   */
  static createWorker_byModuleURL( workerModuleURL ) {
    this.workerModuleURL = workerModuleURL;

    let workerDataURI
      = AsyncWorker_Proxy.create_WorkerBodyStub_Codes_DataURI( workerModuleURL );

    this.workerURL = workerDataURI;

    // Q: Why not use "module" type worker?
    // A: A "module" type worker can not use importScripts() to load global library.
    //    (e.g. tensorflow.js)
    //
    // On the other hand, a "classic" type worker can use both importScripts() and
    // import() to load global library and module.
    //
    this.workerOptions = null;

    this.worker = new Worker( this.workerURL, this.workerOptions );

    // Register callback from the web worker.
    this.worker.onmessage
      = AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body.bind( this );
  }

  /**
   * Create a data URI representing the main (i.e. body) javascript file of web worker.
   * It is viewed as a classic javascript file (i.e. not an importable module). But
   * it will load specified workerModuleURL as a module.
   *
   * In module (non-classic) web worker, static import is available. But the function
   * importScripts() will not be avbailable. For solving this problem, using
   * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
   * can be loaded by importScripts(). And use dynamic import() to load ourselves
   * modules because import() can be used in classic (non-module) script.
   *
   * @param {string} workerModuleURL
   *   An (absolute) URL to a javascript module file. It will be imported
   * (asynchronously) by this generated classic javascript file (as a dataURI).
   */
  static create_WorkerBodyStub_Codes_DataURI( workerModuleURL ) {

    // The codes do the following:
    //
    //   - Import the specified module URL.
    //   - Create a temporary message queue.
    //   - Collect all messages before
    //       AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body() be registered
    //       as message handler.
    //
    let codes = ``
      + `import( "${workerModuleURL}" );\n`
      + `AsyncWorker_Body_temporaryMessageQueue = [];\n`
      + `onmessage = ( e ) => {\n`
      // + `  console.log( "Hello" );\n`
      // + `  console.log( e );\n`
      + `  AsyncWorker_Body_temporaryMessageQueue.push( e );\n`
      + `};\n`
      ;

    let workerDataURI
      = AsyncWorker_Proxy.createDataURI_byStringASCII( "text/javascript", codes );

    return workerDataURI;
  }

  /**
   * @param {string} strMimeType  The result mime type of the data URI.
   * @param {string} strASCII     The ASCII text to be embedded in data URI.
   *
   * @return {string} Return the data URI string.
   */
  static createDataURI_byStringASCII( strMimeType, strASCII ) {
    // let textEncoder = new TextEncoder();
    // let str_utf8 = textEncoder.encode( str );
    // let str_base64 = btoa( str_utf8 );
    let str_base64 = btoa( strASCII );
    let dataURI = `data:${strMimeType};base64,${str_base64}`;
    return dataURI;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect the final result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {Promise}
   *   Return a promise resolved to the final value of the processing's resulter
   * from WorkerBody. (i.e. Only the Xxx of { done: true, value: Xxx } resolved.
   * All other intermediate result { done: false, value: Yyy } are discarded.)
   */
  createPromise_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let resulter = this.createResulter_by_postCommandArgs(
      commandArgs, transferableObjectArray );
    return resulter.untilDone();
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {AsyncWorker.Resulter}
   *   Return an async generator for receving result from WorkerBody of the processing.
   */
  createResulter_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let processingId = this.processingId_next;
    ++this.processingId_next;

    // Prepare the processing's result's receiving queue before sending it.
    let resulter = this.the_processingId_Resulter_Map.createResulter_by_processingId(
      processingId );

    this.worker.postMessage( commandArgs, transferableObjectArray );
    return resulter;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * without expecting result. (i.e. fire-and-forget)
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   */
  postCommandArgs( commandArgs, transferableObjectArray ) {
    this.worker.postMessage( commandArgs, transferableObjectArray );
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

    // ( e.data == [ processingId, done, value ] )
    let [ processingId, done, value ] = e.data;

    this.the_processingId_Resulter_Map.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<|endoftext|>


<commit_before>/**
 * @type import('next/dist/next-server/server/config-shared').NextConfig
 */
const config = {
  future: {
    strictPostcssConfiguration: true,
  },
  eslint: {
    // I have already run lint before this step...
    ignoreDuringBuilds: true,
  },
  poweredByHeader: false,
  webpack(config) {
    config.module.rules.unshift({
      test: /\.md$/,
      use: 'raw-loader',
      exclude: /node_modules/,
    });

    return config;
  },
  async redirects() {
    return [
      {
        source: '/v1/',
        destination: 'https://mlaursen.github.io/react-md-v1-docs/#/',
        permanent: false,
      },
      {
        source: '/v1/:paths*',
        destination: 'https://mlaursen.github.io/react-md-v1-docs/#/:paths*',
        permanent: false,
      },
    ];
  },
};

module.exports = config;
<commit_msg>chore(website): Enable React.StrictMode<commit_after>/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  eslint: {
    // I have already run lint before this step...
    ignoreDuringBuilds: true,
  },
  poweredByHeader: false,
  webpack(config) {
    config.module.rules.unshift({
      test: /\.md$/,
      use: 'raw-loader',
      exclude: /node_modules/,
    });

    return config;
  },
  async redirects() {
    return [
      {
        source: '/v1/',
        destination: 'https://mlaursen.github.io/react-md-v1-docs/#/',
        permanent: false,
      },
      {
        source: '/v1/:paths*',
        destination: 'https://mlaursen.github.io/react-md-v1-docs/#/:paths*',
        permanent: false,
      },
    ];
  },
};
<|endoftext|>


<commit_before>const path = require(`path`)
const resolveCwd = require(`resolve-cwd`)
const yargs = require(`yargs`)
const report = require(`./reporter`)
const didYouMean = require(`./did-you-mean`)
const envinfo = require(`envinfo`)
const existsSync = require(`fs-exists-cached`).sync
const clipboardy = require(`clipboardy`)
const {
  trackCli,
  setDefaultTags,
  setTelemetryEnabled,
} = require(`gatsby-telemetry`)

const handlerP = fn => (...args) => {
  Promise.resolve(fn(...args)).then(
    () => process.exit(0),
    err => report.panic(err)
  )
}

function buildLocalCommands(cli, isLocalSite) {
  const defaultHost = `localhost`
  const directory = path.resolve(`.`)

  // 'not dead' query not available in browserslist used in Gatsby v1
  const DEFAULT_BROWSERS =
    installedGatsbyVersion() === 1
      ? [`> 1%`, `last 2 versions`, `IE >= 9`]
      : [`>0.25%`, `not dead`]

  let siteInfo = { directory, browserslist: DEFAULT_BROWSERS }
  const useYarn = existsSync(path.join(directory, `yarn.lock`))
  if (isLocalSite) {
    const json = require(path.join(directory, `package.json`))
    siteInfo.sitePackageJson = json
    siteInfo.browserslist = json.browserslist || siteInfo.browserslist
  }

  function installedGatsbyVersion() {
    let majorVersion
    try {
      const packageInfo = require(path.join(
        process.cwd(),
        `node_modules`,
        `gatsby`,
        `package.json`
      ))
      try {
        setDefaultTags({ installedGatsbyVersion: packageInfo.version })
      } catch (e) {
        // ignore
      }
      majorVersion = parseInt(packageInfo.version.split(`.`)[0], 10)
    } catch (err) {
      /* ignore */
    }

    return majorVersion
  }

  function resolveLocalCommand(command) {
    if (!isLocalSite) {
      cli.showHelp()
      report.verbose(`current directory: ${directory}`)
      return report.panic(
        `gatsby <${command}> can only be run for a gatsby site. \n` +
          `Either the current working directory does not contain a valid package.json or ` +
          `'gatsby' is not specified as a dependency`
      )
    }

    try {
      const cmdPath =
        resolveCwd.silent(`gatsby/dist/commands/${command}`) ||
        // Old location of commands
        resolveCwd.silent(`gatsby/dist/utils/${command}`)
      if (!cmdPath)
        return report.panic(
          `There was a problem loading the local ${command} command. Gatsby may not be installed in your site's "node_modules" directory. Perhaps you need to run "npm install"? You might need to delete your "package-lock.json" as well.`
        )

      report.verbose(`loading local command from: ${cmdPath}`)
      return require(cmdPath)
    } catch (err) {
      cli.showHelp()
      return report.panic(
        `There was a problem loading the local ${command} command. Gatsby may not be installed. Perhaps you need to run "npm install"?`,
        err
      )
    }
  }

  function getCommandHandler(command, handler) {
    return argv => {
      report.setVerbose(!!argv.verbose)
      if (argv.noColor) {
        // disables colors in popular terminal output coloring packages
        //  - chalk: see https://www.npmjs.com/package/chalk#chalksupportscolor
        //  - ansi-colors: see https://github.com/doowb/ansi-colors/blob/8024126c7115a0efb25a9a0e87bc5e29fd66831f/index.js#L5-L7
        process.env.FORCE_COLOR = `0`
      }

      report.setNoColor(!!argv.noColor)

      process.env.gatsby_log_level = argv.verbose ? `verbose` : `normal`
      report.verbose(`set gatsby_log_level: "${process.env.gatsby_log_level}"`)

      process.env.gatsby_executing_command = command
      report.verbose(`set gatsby_executing_command: "${command}"`)

      let localCmd = resolveLocalCommand(command)
      let args = { ...argv, ...siteInfo, report, useYarn }

      report.verbose(`running command: ${command}`)
      return handler ? handler(args, localCmd) : localCmd(args)
    }
  }

  cli.command({
    command: `develop`,
    desc:
      `Start development server. Watches files, rebuilds, and hot reloads ` +
      `if something changes`,
    builder: _ =>
      _.option(`H`, {
        alias: `host`,
        type: `string`,
        default: defaultHost,
        describe: `Set host. Defaults to ${defaultHost}`,
      })
        .option(`p`, {
          alias: `port`,
          type: `string`,
          default: `8000`,
          describe: `Set port. Defaults to 8000`,
        })
        .option(`o`, {
          alias: `open`,
          type: `boolean`,
          describe: `Open the site in your (default) browser for you.`,
        })
        .option(`S`, {
          alias: `https`,
          type: `boolean`,
          describe: `Use HTTPS. See https://www.gatsbyjs.org/docs/local-https/ as a guide`,
        })
        .option(`c`, {
          alias: `cert-file`,
          type: `string`,
          default: ``,
          describe: `Custom HTTPS cert file (relative path; also required: --https, --key-file). See https://www.gatsbyjs.org/docs/local-https/`,
        })
        .option(`k`, {
          alias: `key-file`,
          type: `string`,
          default: ``,
          describe: `Custom HTTPS key file (relative path; also required: --https, --cert-file). See https://www.gatsbyjs.org/docs/local-https/`,
        })
        .option(`open-tracing-config-file`, {
          type: `string`,
          describe: `Tracer configuration file (OpenTracing compatible). See https://gatsby.dev/tracing`,
        }),
    handler: handlerP(
      getCommandHandler(`develop`, (args, cmd) => {
        process.env.NODE_ENV = process.env.NODE_ENV || `development`
        cmd(args)
        // Return an empty promise to prevent handlerP from exiting early.
        // The development server shouldn't ever exit until the user directly
        // kills it so this is fine.
        return new Promise(resolve => {})
      })
    ),
  })

  cli.command({
    command: `build`,
    desc: `Build a Gatsby project.`,
    builder: _ =>
      _.option(`prefix-paths`, {
        type: `boolean`,
        default: false,
        describe: `Build site with link paths prefixed (set pathPrefix in your gatsby-config.js).`,
      })
        .option(`no-uglify`, {
          type: `boolean`,
          default: false,
          describe: `Build site without uglifying JS bundles (for debugging).`,
        })
        .option(`open-tracing-config-file`, {
          type: `string`,
          describe: `Tracer configuration file (OpenTracing compatible). See https://gatsby.dev/tracing`,
        }),
    handler: handlerP(
      getCommandHandler(`build`, (args, cmd) => {
        process.env.NODE_ENV = `production`
        return cmd(args)
      })
    ),
  })

  cli.command({
    command: `serve`,
    desc: `Serve previously built Gatsby site.`,
    builder: _ =>
      _.option(`H`, {
        alias: `host`,
        type: `string`,
        default: defaultHost,
        describe: `Set host. Defaults to ${defaultHost}`,
      })
        .option(`p`, {
          alias: `port`,
          type: `string`,
          default: `9000`,
          describe: `Set port. Defaults to 9000`,
        })
        .option(`o`, {
          alias: `open`,
          type: `boolean`,
          describe: `Open the site in your (default) browser for you.`,
        })
        .option(`prefix-paths`, {
          type: `boolean`,
          default: false,
          describe: `Serve site with link paths prefixed (if built with pathPrefix in your gatsby-config.js).`,
        }),

    handler: getCommandHandler(`serve`),
  })

  cli.command({
    command: `info`,
    desc: `Get environment information for debugging and issue reporting`,
    builder: _ =>
      _.option(`C`, {
        alias: `clipboard`,
        type: `boolean`,
        default: false,
        describe: `Automagically copy environment information to clipboard`,
      }),
    handler: args => {
      try {
        const copyToClipboard =
          // Clipboard is not accessible when on a linux tty
          process.platform === `linux` && !process.env.DISPLAY
            ? false
            : args.clipboard

        envinfo
          .run({
            System: [`OS`, `CPU`, `Shell`],
            Binaries: [`Node`, `npm`, `Yarn`],
            Browsers: [`Chrome`, `Edge`, `Firefox`, `Safari`],
            Languages: [`Python`],
            npmPackages: `gatsby*`,
            npmGlobalPackages: `gatsby*`,
          })
          .then(envinfoOutput => {
            console.log(envinfoOutput)

            if (copyToClipboard) {
              clipboardy.writeSync(envinfoOutput)
            }
          })
      } catch (err) {
        console.log(`Error: Unable to print environment info`)
        console.log(err)
      }
    },
  })

  cli.command({
    command: `clean`,
    desc: `Wipe the local gatsby environment including built assets and cache`,
    handler: getCommandHandler(`clean`),
  })

  cli.command({
    command: `repl`,
    desc: `Get a node repl with context of Gatsby environment, see (add docs link here)`,
    handler: getCommandHandler(`repl`, (args, cmd) => {
      process.env.NODE_ENV = process.env.NODE_ENV || `development`
      return cmd(args)
    }),
  })
}

function isLocalGatsbySite() {
  let inGatsbySite = false
  try {
    let { dependencies, devDependencies } = require(path.resolve(
      `./package.json`
    ))
    inGatsbySite =
      (dependencies && dependencies.gatsby) ||
      (devDependencies && devDependencies.gatsby)
  } catch (err) {
    /* ignore */
  }
  return inGatsbySite
}

module.exports = argv => {
  let cli = yargs()
  let isLocalSite = isLocalGatsbySite()

  cli
    .scriptName(`gatsby`)
    .usage(`Usage: $0 <command> [options]`)
    .alias(`h`, `help`)
    .alias(`v`, `version`)
    .option(`verbose`, {
      default: false,
      type: `boolean`,
      describe: `Turn on verbose output`,
      global: true,
    })
    .option(`no-color`, {
      alias: `no-colors`,
      default: false,
      type: `boolean`,
      describe: `Turn off the color in output`,
      global: true,
    })

  buildLocalCommands(cli, isLocalSite)

  try {
    const { version } = require(`../package.json`)
    cli.version(`version`, version)
    setDefaultTags({ gatsbyCliVersion: version })
  } catch (e) {
    // ignore
  }

  trackCli(argv)

  return cli
    .command({
      command: `new [rootPath] [starter]`,
      desc: `Create new Gatsby project.`,
      handler: handlerP(({ rootPath, starter }) => {
        const initStarter = require(`./init-starter`)
        return initStarter(starter, { rootPath })
      }),
    })
    .command(`plugin`, `Useful commands relating to Gatsby plugins`, yargs =>
      yargs
        .command({
          command: `docs`,
          desc: `Helpful info about using and creating plugins`,
          handler: handlerP(() =>
            console.log(`
Using a plugin:
- What is a Plugin? (https://www.gatsbyjs.org/docs/what-is-a-plugin/)
- Using a Plugin in Your Site (https://www.gatsbyjs.org/docs/using-a-plugin-in-your-site/)
- What You Don't Need Plugins For (https://www.gatsbyjs.org/docs/what-you-dont-need-plugins-for/)
- Loading Plugins from Your Local Plugins Folder (https://www.gatsbyjs.org/docs/loading-plugins-from-your-local-plugins-folder/)
- Plugin Library (https://www.gatsbyjs.org/plugins/)

Creating a plugin:
- Naming a Plugin (https://www.gatsbyjs.org/docs/naming-a-plugin/)
- Files Gatsby Looks for in a Plugin (https://www.gatsbyjs.org/docs/files-gatsby-looks-for-in-a-plugin/)
- Creating a Local Plugin (https://www.gatsbyjs.org/docs/creating-a-local-plugin/)
- Creating a Source Plugin (https://www.gatsbyjs.org/docs/creating-a-source-plugin/)
- Creating a Transformer Plugin (https://www.gatsbyjs.org/docs/creating-a-transformer-plugin/)
- Submit to Plugin Library (https://www.gatsbyjs.org/contributing/submit-to-plugin-library/)
- Pixabay Source Plugin Tutorial (https://www.gatsbyjs.org/docs/pixabay-source-plugin-tutorial/)
- Maintaining a Plugin (https://www.gatsbyjs.org/docs/maintaining-a-plugin/)
- Join Discord #plugin-authoring channel to ask questions! (https://gatsby.dev/discord/)
          `)
          ),
        })
        .demandCommand(
          1,
          `Pass --help to see all available commands and options.`
        )
    )
    .command({
      command: `telemetry`,
      desc: `Enable or disable Gatsby anonymous analytics collection.`,
      builder: yargs =>
        yargs
          .option(`enable`, {
            type: `boolean`,
            description: `Enable telemetry (default)`,
          })
          .option(`disable`, {
            type: `boolean`,
            description: `Disable telemetry`,
          }),

      handler: handlerP(({ enable, disable }) => {
        const enabled = enable || !disable
        setTelemetryEnabled(enabled)
        report.log(`Telemetry collection ${enabled ? `enabled` : `disabled`}`)
      }),
    })
    .wrap(cli.terminalWidth())
    .demandCommand(1, `Pass --help to see all available commands and options.`)
    .strict()
    .fail((msg, err, yargs) => {
      const availableCommands = yargs.getCommands().map(commandDescription => {
        const [command] = commandDescription
        return command.split(` `)[0]
      })
      const arg = argv.slice(2)[0]
      const suggestion = arg ? didYouMean(arg, availableCommands) : ``

      cli.showHelp()
      report.log(suggestion)
      report.log(msg)
    })
    .parse(argv.slice(2))
}
<commit_msg>feat(gatsby-cli): improve version output (#14924)<commit_after>const path = require(`path`)
const resolveCwd = require(`resolve-cwd`)
const yargs = require(`yargs`)
const report = require(`./reporter`)
const didYouMean = require(`./did-you-mean`)
const envinfo = require(`envinfo`)
const existsSync = require(`fs-exists-cached`).sync
const clipboardy = require(`clipboardy`)
const {
  trackCli,
  setDefaultTags,
  setTelemetryEnabled,
} = require(`gatsby-telemetry`)

const handlerP = fn => (...args) => {
  Promise.resolve(fn(...args)).then(
    () => process.exit(0),
    err => report.panic(err)
  )
}

function buildLocalCommands(cli, isLocalSite) {
  const defaultHost = `localhost`
  const directory = path.resolve(`.`)

  // 'not dead' query not available in browserslist used in Gatsby v1
  const DEFAULT_BROWSERS =
    getLocalGatsbyMajorVersion() === 1
      ? [`> 1%`, `last 2 versions`, `IE >= 9`]
      : [`>0.25%`, `not dead`]

  let siteInfo = { directory, browserslist: DEFAULT_BROWSERS }
  const useYarn = existsSync(path.join(directory, `yarn.lock`))
  if (isLocalSite) {
    const json = require(path.join(directory, `package.json`))
    siteInfo.sitePackageJson = json
    siteInfo.browserslist = json.browserslist || siteInfo.browserslist
  }

  function getLocalGatsbyMajorVersion() {
    let version = getLocalGatsbyVersion()

    if (version) {
      version = Number(version.split(`.`)[0])
    }

    return version
  }

  function resolveLocalCommand(command) {
    if (!isLocalSite) {
      cli.showHelp()
      report.verbose(`current directory: ${directory}`)
      return report.panic(
        `gatsby <${command}> can only be run for a gatsby site. \n` +
          `Either the current working directory does not contain a valid package.json or ` +
          `'gatsby' is not specified as a dependency`
      )
    }

    try {
      const cmdPath =
        resolveCwd.silent(`gatsby/dist/commands/${command}`) ||
        // Old location of commands
        resolveCwd.silent(`gatsby/dist/utils/${command}`)
      if (!cmdPath)
        return report.panic(
          `There was a problem loading the local ${command} command. Gatsby may not be installed in your site's "node_modules" directory. Perhaps you need to run "npm install"? You might need to delete your "package-lock.json" as well.`
        )

      report.verbose(`loading local command from: ${cmdPath}`)
      return require(cmdPath)
    } catch (err) {
      cli.showHelp()
      return report.panic(
        `There was a problem loading the local ${command} command. Gatsby may not be installed. Perhaps you need to run "npm install"?`,
        err
      )
    }
  }

  function getCommandHandler(command, handler) {
    return argv => {
      report.setVerbose(!!argv.verbose)
      if (argv.noColor) {
        // disables colors in popular terminal output coloring packages
        //  - chalk: see https://www.npmjs.com/package/chalk#chalksupportscolor
        //  - ansi-colors: see https://github.com/doowb/ansi-colors/blob/8024126c7115a0efb25a9a0e87bc5e29fd66831f/index.js#L5-L7
        process.env.FORCE_COLOR = `0`
      }

      report.setNoColor(!!argv.noColor)

      process.env.gatsby_log_level = argv.verbose ? `verbose` : `normal`
      report.verbose(`set gatsby_log_level: "${process.env.gatsby_log_level}"`)

      process.env.gatsby_executing_command = command
      report.verbose(`set gatsby_executing_command: "${command}"`)

      let localCmd = resolveLocalCommand(command)
      let args = { ...argv, ...siteInfo, report, useYarn }

      report.verbose(`running command: ${command}`)
      return handler ? handler(args, localCmd) : localCmd(args)
    }
  }

  cli.command({
    command: `develop`,
    desc:
      `Start development server. Watches files, rebuilds, and hot reloads ` +
      `if something changes`,
    builder: _ =>
      _.option(`H`, {
        alias: `host`,
        type: `string`,
        default: defaultHost,
        describe: `Set host. Defaults to ${defaultHost}`,
      })
        .option(`p`, {
          alias: `port`,
          type: `string`,
          default: `8000`,
          describe: `Set port. Defaults to 8000`,
        })
        .option(`o`, {
          alias: `open`,
          type: `boolean`,
          describe: `Open the site in your (default) browser for you.`,
        })
        .option(`S`, {
          alias: `https`,
          type: `boolean`,
          describe: `Use HTTPS. See https://www.gatsbyjs.org/docs/local-https/ as a guide`,
        })
        .option(`c`, {
          alias: `cert-file`,
          type: `string`,
          default: ``,
          describe: `Custom HTTPS cert file (relative path; also required: --https, --key-file). See https://www.gatsbyjs.org/docs/local-https/`,
        })
        .option(`k`, {
          alias: `key-file`,
          type: `string`,
          default: ``,
          describe: `Custom HTTPS key file (relative path; also required: --https, --cert-file). See https://www.gatsbyjs.org/docs/local-https/`,
        })
        .option(`open-tracing-config-file`, {
          type: `string`,
          describe: `Tracer configuration file (OpenTracing compatible). See https://gatsby.dev/tracing`,
        }),
    handler: handlerP(
      getCommandHandler(`develop`, (args, cmd) => {
        process.env.NODE_ENV = process.env.NODE_ENV || `development`
        cmd(args)
        // Return an empty promise to prevent handlerP from exiting early.
        // The development server shouldn't ever exit until the user directly
        // kills it so this is fine.
        return new Promise(resolve => {})
      })
    ),
  })

  cli.command({
    command: `build`,
    desc: `Build a Gatsby project.`,
    builder: _ =>
      _.option(`prefix-paths`, {
        type: `boolean`,
        default: false,
        describe: `Build site with link paths prefixed (set pathPrefix in your gatsby-config.js).`,
      })
        .option(`no-uglify`, {
          type: `boolean`,
          default: false,
          describe: `Build site without uglifying JS bundles (for debugging).`,
        })
        .option(`open-tracing-config-file`, {
          type: `string`,
          describe: `Tracer configuration file (OpenTracing compatible). See https://gatsby.dev/tracing`,
        }),
    handler: handlerP(
      getCommandHandler(`build`, (args, cmd) => {
        process.env.NODE_ENV = `production`
        return cmd(args)
      })
    ),
  })

  cli.command({
    command: `serve`,
    desc: `Serve previously built Gatsby site.`,
    builder: _ =>
      _.option(`H`, {
        alias: `host`,
        type: `string`,
        default: defaultHost,
        describe: `Set host. Defaults to ${defaultHost}`,
      })
        .option(`p`, {
          alias: `port`,
          type: `string`,
          default: `9000`,
          describe: `Set port. Defaults to 9000`,
        })
        .option(`o`, {
          alias: `open`,
          type: `boolean`,
          describe: `Open the site in your (default) browser for you.`,
        })
        .option(`prefix-paths`, {
          type: `boolean`,
          default: false,
          describe: `Serve site with link paths prefixed (if built with pathPrefix in your gatsby-config.js).`,
        }),

    handler: getCommandHandler(`serve`),
  })

  cli.command({
    command: `info`,
    desc: `Get environment information for debugging and issue reporting`,
    builder: _ =>
      _.option(`C`, {
        alias: `clipboard`,
        type: `boolean`,
        default: false,
        describe: `Automagically copy environment information to clipboard`,
      }),
    handler: args => {
      try {
        const copyToClipboard =
          // Clipboard is not accessible when on a linux tty
          process.platform === `linux` && !process.env.DISPLAY
            ? false
            : args.clipboard

        envinfo
          .run({
            System: [`OS`, `CPU`, `Shell`],
            Binaries: [`Node`, `npm`, `Yarn`],
            Browsers: [`Chrome`, `Edge`, `Firefox`, `Safari`],
            Languages: [`Python`],
            npmPackages: `gatsby*`,
            npmGlobalPackages: `gatsby*`,
          })
          .then(envinfoOutput => {
            console.log(envinfoOutput)

            if (copyToClipboard) {
              clipboardy.writeSync(envinfoOutput)
            }
          })
      } catch (err) {
        console.log(`Error: Unable to print environment info`)
        console.log(err)
      }
    },
  })

  cli.command({
    command: `clean`,
    desc: `Wipe the local gatsby environment including built assets and cache`,
    handler: getCommandHandler(`clean`),
  })

  cli.command({
    command: `repl`,
    desc: `Get a node repl with context of Gatsby environment, see (add docs link here)`,
    handler: getCommandHandler(`repl`, (args, cmd) => {
      process.env.NODE_ENV = process.env.NODE_ENV || `development`
      return cmd(args)
    }),
  })
}

function isLocalGatsbySite() {
  let inGatsbySite = false
  try {
    let { dependencies, devDependencies } = require(path.resolve(
      `./package.json`
    ))
    inGatsbySite =
      (dependencies && dependencies.gatsby) ||
      (devDependencies && devDependencies.gatsby)
  } catch (err) {
    /* ignore */
  }
  return !!inGatsbySite
}

function getLocalGatsbyVersion() {
  let version
  try {
    const packageInfo = require(path.join(
      process.cwd(),
      `node_modules`,
      `gatsby`,
      `package.json`
    ))
    version = packageInfo.version

    try {
      setDefaultTags({ installedGatsbyVersion: version })
    } catch (e) {
      // ignore
    }
  } catch (err) {
    /* ignore */
  }

  return version
}

function getVersionInfo() {
  const { version } = require(`../package.json`)
  const isGatsbySite = isLocalGatsbySite()
  if (isGatsbySite) {
    // we need to get the version from node_modules
    let gatsbyVersion = getLocalGatsbyVersion()

    if (!gatsbyVersion) {
      gatsbyVersion = `unknown`
    }

    return `Gatsby CLI version: ${version}
Gatsby version: ${gatsbyVersion}
  Note: this is the Gatsby version for the site at: ${process.cwd()}`
  } else {
    return `Gatsby CLI version: ${version}`
  }
}

module.exports = argv => {
  let cli = yargs()
  let isLocalSite = isLocalGatsbySite()

  cli
    .scriptName(`gatsby`)
    .usage(`Usage: $0 <command> [options]`)
    .alias(`h`, `help`)
    .alias(`v`, `version`)
    .option(`verbose`, {
      default: false,
      type: `boolean`,
      describe: `Turn on verbose output`,
      global: true,
    })
    .option(`no-color`, {
      alias: `no-colors`,
      default: false,
      type: `boolean`,
      describe: `Turn off the color in output`,
      global: true,
    })

  buildLocalCommands(cli, isLocalSite)

  try {
    const { version } = require(`../package.json`)
    cli.version(
      `version`,
      `Show the version of the Gatsby CLI and the Gatsby package in the current project`,
      getVersionInfo()
    )
    setDefaultTags({ gatsbyCliVersion: version })
  } catch (e) {
    // ignore
  }

  trackCli(argv)

  return cli
    .command({
      command: `new [rootPath] [starter]`,
      desc: `Create new Gatsby project.`,
      handler: handlerP(({ rootPath, starter }) => {
        const initStarter = require(`./init-starter`)
        return initStarter(starter, { rootPath })
      }),
    })
    .command(`plugin`, `Useful commands relating to Gatsby plugins`, yargs =>
      yargs
        .command({
          command: `docs`,
          desc: `Helpful info about using and creating plugins`,
          handler: handlerP(() =>
            console.log(`
Using a plugin:
- What is a Plugin? (https://www.gatsbyjs.org/docs/what-is-a-plugin/)
- Using a Plugin in Your Site (https://www.gatsbyjs.org/docs/using-a-plugin-in-your-site/)
- What You Don't Need Plugins For (https://www.gatsbyjs.org/docs/what-you-dont-need-plugins-for/)
- Loading Plugins from Your Local Plugins Folder (https://www.gatsbyjs.org/docs/loading-plugins-from-your-local-plugins-folder/)
- Plugin Library (https://www.gatsbyjs.org/plugins/)

Creating a plugin:
- Naming a Plugin (https://www.gatsbyjs.org/docs/naming-a-plugin/)
- Files Gatsby Looks for in a Plugin (https://www.gatsbyjs.org/docs/files-gatsby-looks-for-in-a-plugin/)
- Creating a Local Plugin (https://www.gatsbyjs.org/docs/creating-a-local-plugin/)
- Creating a Source Plugin (https://www.gatsbyjs.org/docs/creating-a-source-plugin/)
- Creating a Transformer Plugin (https://www.gatsbyjs.org/docs/creating-a-transformer-plugin/)
- Submit to Plugin Library (https://www.gatsbyjs.org/contributing/submit-to-plugin-library/)
- Pixabay Source Plugin Tutorial (https://www.gatsbyjs.org/docs/pixabay-source-plugin-tutorial/)
- Maintaining a Plugin (https://www.gatsbyjs.org/docs/maintaining-a-plugin/)
- Join Discord #plugin-authoring channel to ask questions! (https://gatsby.dev/discord/)
          `)
          ),
        })
        .demandCommand(
          1,
          `Pass --help to see all available commands and options.`
        )
    )
    .command({
      command: `telemetry`,
      desc: `Enable or disable Gatsby anonymous analytics collection.`,
      builder: yargs =>
        yargs
          .option(`enable`, {
            type: `boolean`,
            description: `Enable telemetry (default)`,
          })
          .option(`disable`, {
            type: `boolean`,
            description: `Disable telemetry`,
          }),

      handler: handlerP(({ enable, disable }) => {
        const enabled = enable || !disable
        setTelemetryEnabled(enabled)
        report.log(`Telemetry collection ${enabled ? `enabled` : `disabled`}`)
      }),
    })
    .wrap(cli.terminalWidth())
    .demandCommand(1, `Pass --help to see all available commands and options.`)
    .strict()
    .fail((msg, err, yargs) => {
      const availableCommands = yargs.getCommands().map(commandDescription => {
        const [command] = commandDescription
        return command.split(` `)[0]
      })
      const arg = argv.slice(2)[0]
      const suggestion = arg ? didYouMean(arg, availableCommands) : ``

      cli.showHelp()
      report.log(suggestion)
      report.log(msg)
    })
    .parse(argv.slice(2))
}
<|endoftext|>


<commit_before><commit_msg>・フェイズ変更部分を関数化した。 ・それに伴い、フェイズごとに専用カウンタを追加した。<commit_after><|endoftext|>


<commit_before>/**
 * Created by ralemy on 2/21/16.
 * Node-Red node to run an Itemsense Job
 */
module.exports = function (RED) {
    "use strict";

    var lib = require("./lib/itemsense");
    lib.hookIntoApp(RED);

    function triageError(err) {
        if (err.response)
            if (err.response.body)
                if (err.response.body.message.indexOf("JobId=") !== -1)
                    return {jobId: err.response.body.message.match(/JobId=([^,]+)/)[1]};
                else
                    return {
                        jobId: null,
                        body: {message: err.response.body, statusCode: err.response.statusCode},
                        message: "Job Start Failed:" + err.response.statusCode + " " + JSON.stringify(err.response.body, null, " ")
                    };
            else
                return {
                    jobId: null,
                    body: {statusCode: err.response.statusCode},
                    message: "Job Start Failed: " + err.response.statusCode
                };
        return {jobId: null, body: {statusCode: 500, message: err.message}, message: err.message};
    }

    function RunJobNode(config) {
        RED.nodes.createNode(this, config);
        var node = this,
            LocalItemsense = RED.nodes.getNode(config.itemsense);
        this.on("input", function (msg) {
            var itemsense = lib.registerItemsense(node, msg, LocalItemsense),
                jobObject = {
                    "recipeName": config.recipe,
                    "durationSeconds": config.runLength,
                    "presenceLoggingEnabled": true,
                    "startDelay": config.startDelay,
                    "reportToDatabaseEnabled": true,
                    "reportToMessageQueueEnabled": true,
                    "reportToFileEnabled": false,
                    "facility": config.facility
                };
            Object.keys(jobObject).forEach(function (key) {
                if (msg.payload && msg.payload[key] !== undefined){
                    jobObject[key] = msg.payload[key];
                  }
            });
            lib.status("enter", "Running Job", node);
            if (itemsense)
                itemsense.jobs.start(jobObject).then(function (job) {
                    msg.topic = "Job";
                    msg.payload = job;
                    node.send([msg, null, {topic: "success", payload: "Job Starting: " + job.id}]);
                    lib.status("exit", "", node);
                }).catch(function (err) {
                    var triage = triageError(err);
                    console.log("error", triage);
                    lib.status("error", "Failed Running Job", node);
                    if (triage.jobId)
                        node.send([null,
                            lib.extend(msg, {topic: "jobId", payload: {id: triage.jobId}}),
                            {
                                topic: "failure",
                                payload: {statusCode: 400, message: "Another Job is Running " + triage.jobId}
                            }
                        ]);
                    else if (triage.body)
                        node.error(triage.message, lib.extend(msg, {
                            topic: "failure",
                            payload: triage.body,
                            statusCode: triage.body.statusCode
                        }));
                });
        });
    }

    RED.nodes.registerType("run-job", RunJobNode);
};
<commit_msg>added groups for jobs with 2017r1<commit_after>/**
 * Created by ralemy on 2/21/16.
 * Node-Red node to run an Itemsense Job
 */
module.exports = function (RED) {
    "use strict";

    var lib = require("./lib/itemsense");
    lib.hookIntoApp(RED);

    function triageError(err) {
        if (err.response)
            if (err.response.body)
                if (err.response.body.message.indexOf("JobId=") !== -1)
                    return {jobId: err.response.body.message.match(/JobId=([^,]+)/)[1]};
                else
                    return {
                        jobId: null,
                        body: {message: err.response.body, statusCode: err.response.statusCode},
                        message: "Job Start Failed:" + err.response.statusCode + " " + JSON.stringify(err.response.body, null, " ")
                    };
            else
                return {
                    jobId: null,
                    body: {statusCode: err.response.statusCode},
                    message: "Job Start Failed: " + err.response.statusCode
                };
        return {jobId: null, body: {statusCode: 500, message: err.message}, message: err.message};
    }

    function RunJobNode(config) {
        RED.nodes.createNode(this, config);
        var node = this,
            LocalItemsense = RED.nodes.getNode(config.itemsense);
        this.on("input", function (msg) {
            var itemsense = lib.registerItemsense(node, msg, LocalItemsense),
                jobObject = {
                    "readerGroups":null,
                    "recipeName": config.recipe,
                    "durationSeconds": config.runLength,
                    "presenceLoggingEnabled": true,
                    "startDelay": config.startDelay,
                    "reportToDatabaseEnabled": true,
                    "reportToHistoryEnabled": true,
                    "reportToMessageQueueEnabled": true,
                    "reportToFileEnabled": false,
                    "facility": config.facility
                };
            Object.keys(jobObject).forEach(function (key) {
                if (msg.payload && msg.payload[key] !== undefined){
                    jobObject[key] = msg.payload[key];
                  }
            });
            lib.status("enter", "Running Job", node);
            if (itemsense)
                itemsense.jobs.start(jobObject).then(function (job) {
                    msg.topic = "Job";
                    msg.payload = job;
                    node.send([msg, null, {topic: "success", payload: "Job Starting: " + job.id}]);
                    lib.status("exit", "", node);
                }).catch(function (err) {
                    var triage = triageError(err);
                    console.log("error", triage);
                    lib.status("error", "Failed Running Job", node);
                    if (triage.jobId)
                        node.send([null,
                            lib.extend(msg, {topic: "jobId", payload: {id: triage.jobId}}),
                            {
                                topic: "failure",
                                payload: {statusCode: 400, message: "Another Job is Running " + triage.jobId}
                            }
                        ]);
                    else if (triage.body)
                        node.error(triage.message, lib.extend(msg, {
                            topic: "failure",
                            payload: triage.body,
                            statusCode: triage.body.statusCode
                        }));
                });
        });
    }

    RED.nodes.registerType("run-job", RunJobNode);
};
<|endoftext|>


<commit_before><commit_msg>Only selectable if animations are done<commit_after><|endoftext|>


<commit_before><commit_msg>Do not autoopen base terms<commit_after><|endoftext|>


<commit_before><commit_msg>BEN-292 removed duplicated column in csv [legal_working_status]<commit_after><|endoftext|>


<commit_before><commit_msg>Improved checkbox<commit_after><|endoftext|>


<commit_before>/**
 * TeamsController
 *
 * @module      :: Controller
 * @description	:: A set of functions called `actions`.
 *
 *                 Actions contain code telling Sails how to respond to a certain type of request.
 *                 (i.e. do stuff, then send some JSON, show an HTML page, or redirect to another URL)
 *
 *                 You can configure the blueprint URLs which trigger these actions (`config/controllers.js`)
 *                 and/or override them with custom routes (`config/routes.js`)
 *
 *                 NOTE: The code you write here supports both HTTP and Socket.io automatically.
 *
 * @docs        :: http://sailsjs.org/#!documentation/controllers
 */

module.exports = {

	post: function (req, res, next) {
		return XEditable.handle(Team)(req, res, next);
	},

	/**
	* Overrides for the settings in `config/controllers.js`
	* (specific to TeamsController)
	*/
	_config: {
		menus: [
			{name: 'Teams', path: '/teams'}
		]
	}

};
<commit_msg>added index action<commit_after>/**
 * TeamsController
 *
 * @module      :: Controller
 * @description	:: A set of functions called `actions`.
 *
 *                 Actions contain code telling Sails how to respond to a certain type of request.
 *                 (i.e. do stuff, then send some JSON, show an HTML page, or redirect to another URL)
 *
 *                 You can configure the blueprint URLs which trigger these actions (`config/controllers.js`)
 *                 and/or override them with custom routes (`config/routes.js`)
 *
 *                 NOTE: The code you write here supports both HTTP and Socket.io automatically.
 *
 * @docs        :: http://sailsjs.org/#!documentation/controllers
 */

module.exports = {

    index: function(req, res){
    	return res.view({

		});
    },

	post: function (req, res, next) {
		return XEditable.handle(Team)(req, res, next);
	},

	/**
	* Overrides for the settings in `config/controllers.js`
	* (specific to TeamsController)
	*/
	_config: {
		menus: [
			{name: 'Teams', path: '/teams'}
		]
	}

};
<|endoftext|>


<commit_before>import { User } from '../models/user';
import imgur from 'imgur';
imgur.setClientId('665e91941704f23');

export default function addEditedPhoto(req, res) {
  console.log(req.params);
  console.log(req.body);

  return User.find({ _id: req.params.id })
  .then(([u]) => {
    u.memory = req.body.memory;

    if (req.body.bigScreen) {
      u.state = 'APPROVED';
    }
    else {
      u.state = 'FINISHED';
    }

    return imgur.uploadBase64(req.body.imageData.split(',')[1])
    .then((res) => {
      u.editedPhoto = res.data.link;
      return u.save();
    });
  })
  .then((u) => res.status(200).json(u));
}

<commit_msg>Add email to model<commit_after>import { User } from '../models/user';
import imgur from 'imgur';
imgur.setClientId('665e91941704f23');

export default function addEditedPhoto(req, res) {
  console.log(req.params);
  console.log(req.body.bigScreen, req.body.bigScreen === true);

  return User.find({ _id: req.params.id })
  .then(([u]) => {
    u.memory = req.body.memory;
    u.email = req.body.email;

    if (req.body.bigScreen) {
      u.state = 'APPROVED';
    }
    else {
      u.state = 'FINISHED';
    }

    return imgur.uploadBase64(req.body.imageData.split(',')[1])
    .then((res) => {
      u.editedPhoto = res.data.link;
      return u.save();
    });
  })
  .then((u) => res.status(200).json(u));
}

<|endoftext|>


<commit_before>var fabmo = new FabMoDashboard();

function refreshApps() {
    // Load the list of apps available on the tool
    fabmo.getApps(function(err, apps) {
        apps.reverse();
        if (err) {
            return console.error(err);
        }
        $(".app-listing").empty();

        html = [
            '
',
            '

',
            '	',
            'Click here to install an app	',
            '
'].join('');
            $(".app-listing").append(html);

            $.each(apps, function(key, val) {
                var appid = 'app_' + val.id;
                var appiconid = 'appicon_' + val.id;
                var id = val.id;
                var delete_button = '';
                if (val.icon_display !== 'none') {
                    delete_button = '

';
                }
                html = [
                    '
',
                    '',
                    '',
                    '',
                    '	',
                    '',
                    val.name,
                    '',
                    '	',
                    val.version || '',
                    '	',
                    val.description || 'No description.',
                    '		' + delete_button + '
'
                ].join('');
                $(".app-listing").append(html);

                $('#delete_' + appid).click(function() {
                    fabmo.showModal({
                        title : 'Delete app',
                        message : 'Are you sure you want to delete this app?',
                        okText : 'Yes',
                        cancelText : 'No',
                        ok : function() {
                            fabmo.deleteApp(id, function(err, result) {
                                if (err) {
                                    fabmo.notify('error', err);
                                }
                                refreshApps();
                            });
                        },
                        cancel : function() {}
                    })
                });

                $('#' + appid).click(function() {
                    fabmo.launchApp(id);
                });
                $('#' + appiconid).click(function() {
                    fabmo.launchApp(id);
                });

            }); // each
            $('.app-install-row').click(function(evt) {
                jQuery('#file').trigger('click');
            });

        });
    };
    fabmo.on('change', function(topic) {
        if (topic === 'apps') {
            refreshApps();
        }
    });

    function setupAppManager() {
        refreshApps();

        $('#file').change(function(evt) {
            fabmo.submitApp($('#file'), {}, function(err, data) {
                if (err) {
                    fabmo.notify('error', "Could not install app:
" + (err.message || err));
                } else {
                    fabmo.notify('success', data.length + " app" + ((data.length > 1) ? 's' : '') + " installed successfully.");
                }
                refreshApps();
            });
        });

        $('#dropzone').dragster({
            enter: function(devt, evt) {
                $('#dropzone').addClass('hover');
                return false;
            },

            leave: function(devt, evt) {
                $('#dropzone').removeClass('hover');
                return false;
            },
            drop: function(devt, evt) {
                evt.preventDefault();
                try {
                    files = evt.originalEvent.dataTransfer.files;
                    fabmo.submitApp(files, {}, function(err, data) {
                        if (err) {
                            fabmo.notify('error', err.message || err);
                        } else {
                            fabmo.notify('success', "App installed successfully.");
                        }
                        refreshApps();
                    });
                } catch (e) {
                    console.error(e);
                } finally {
                    $('#dropzone').removeClass('hover');
                    return false;
                }
            }
        });
    }
<commit_msg>Close #428<commit_after>var fabmo = new FabMoDashboard();

function refreshApps() {
    // Load the list of apps available on the tool
    fabmo.getApps(function(err, apps) {
        apps.reverse();
        if (err) {
            return console.error(err);
        }
        $(".app-listing").empty();

        html = [
            '
',
            '

',
            '	',
            'Click here to install an app	',
            '
'].join('');
            $(".app-listing").append(html);

            $.each(apps, function(key, val) {
                var appid = 'app_' + val.id;
                var appiconid = 'appicon_' + val.id;
                var id = val.id;
                var delete_button = '';
                if (val.icon_display !== 'none') {
                    delete_button = '

';
                }
                html = [
                    '
',
                    '',
                    '',
                    '',
                    '	',
                    '',
                    val.name,
                    '',
                    '	',
                    val.version || '',
                    '	',
                    val.description || 'No description.',
                    '		' + delete_button + '
'
                ].join('');
                $(".app-listing").append(html);

                $('#delete_' + appid).click(function() {
                    fabmo.showModal({
                        title : 'Delete app',
                        message : 'Are you sure you want to delete this app?',
                        okText : 'Yes',
                        cancelText : 'No',
                        ok : function() {
                            fabmo.deleteApp(id, function(err, result) {
                                if (err) {
                                    fabmo.notify('error', err);
                                }
                                refreshApps();
                            });
                        },
                        cancel : function() {}
                    })
                });

                $('#' + appid).click(function() {
                    fabmo.launchApp(id);
                });
                $('#' + appiconid).click(function() {
                    fabmo.launchApp(id);
                });

            }); // each
            $('.app-install-row').click(function(evt) {
                jQuery('#file').trigger('click');
            });

        });
    };
    fabmo.on('change', function(topic) {
        if (topic === 'apps') {
            refreshApps();
        }
    });

    function setupAppManager() {
        refreshApps();

        $('#file').change(function(evt) {
            startBusy();
            fabmo.submitApp($('#file'), {}, function(err, data) {
                stopBusy();
                if (err) {
                    fabmo.notify('error', "Could not install app:
" + (err.message || err));
                } else {
                    fabmo.notify('success', data.length + " app" + ((data.length > 1) ? 's' : '') + " installed successfully.");
                }
                refreshApps();
            });
        });

        $('#dropzone').dragster({
            enter: function(devt, evt) {
                $('#dropzone').addClass('hover');
                return false;
            },

            leave: function(devt, evt) {
                $('#dropzone').removeClass('hover');
                return false;
            },
            drop: function(devt, evt) {
                evt.preventDefault();
                try {
                    files = evt.originalEvent.dataTransfer.files;
                    startBusy();
                    fabmo.submitApp(files, {}, function(err, data) {
                      stopBusy();
                        if (err) {
                            fabmo.notify('error', err.message || err);
                        } else {
                            fabmo.notify('success', "App installed successfully.");
                        }
                        refreshApps();
                    });
                } catch (e) {
                    console.error(e);
                } finally {
                    $('#dropzone').removeClass('hover');
                    return false;
                }
            }
        });
    }

function startBusy() {
  $(".app-ghost-icon").removeClass('fa-plus').addClass('fa-cog fa-spin');
}

function stopBusy() {
  $(".app-ghost-icon").removeClass('fa-cog fa-spin').addClass('fa-plus');
}
<|endoftext|>