<commit_before>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

// Start the main app logic.
requirejs(
  [ 'hft/gameclient',
    'hft/misc/misc',
    'hft/misc/strings',
    './semver',
  ], function(
    GameClient,
    Misc,
    Strings,
    semver) {

  var $ = document.getElementById.bind(document);
  var g = {
    elementToShowOnDisconnect: $("disconnected"),
    gamesById: {},
    hftData: {},
  };

  var handleCmdErrorMsg = function(data) {
    // TODO: change to html dialog.
    alert(data.msg);  // eslint-disable-line
  };

  var handleRedirectMsg = function(data) {
    window.location.href = data.url;
  };

  var handleDisconnect = function() {
    g.elementToShowOnDisconnect.style.display = "block";
  };

  var handleGameExited = function(data) {
    var runtimeInfo = g.gamesById[data.gameId];
    if (runtimeInfo && runtimeInfo.cleanupFn) {
      runtimeInfo.cleanupFn();
    }
  };

  var handleHFTInfo = function(data) {
    g.hftData = data;
    $("versionnum").innerHTML = "v" + data.version;
  };

  var params = Misc.parseUrlQuery();

  var client = new GameClient({
    gameId: "__hft__",
  });

  client.addEventListener('connect', function() {});
  client.addEventListener('errorMsg', handleCmdErrorMsg);
  client.addEventListener('redirect', handleRedirectMsg);
  client.addEventListener('disconnect', handleDisconnect);
  client.addEventListener('gameExited', handleGameExited);
  client.addEventListener('hftInfo', handleHFTInfo);

  $('quit').addEventListener('click', function() {
    g.elementToShowOnDisconnect = $("exited");
    client.sendCmd('quit');
  }, false);

  var gamemenu = $("gamemenu");

  var itemTemplateSuffix = "-item-template";
  var hiddenMsgSuffix = "-msg";
  var buttonIdSuffix = "-button";

  var templates = {};
  Array.prototype.forEach.call(document.querySelectorAll(".item-template"), function(elem) {
    templates[elem.id.toLowerCase().substr(0, elem.id.length - itemTemplateSuffix.length)] = elem.text;
  });

  var hiddenMsgs = {};
  Array.prototype.forEach.call(document.querySelectorAll(".hidden-msg"), function(elem) {
    hiddenMsgs[elem.id.toLowerCase().substr(0, elem.id.length - hiddenMsgSuffix.length)] = elem;
  });

  var quitGame = function(gameId) {
    console.log("sending quitGame: " + gameId);
    client.sendCmd('quitGame', {gameId: gameId});
  };

  var handleAvailableGames = function(obj) {
    var html = [];
    var gamesById = {};
    g.gamesById = gamesById;
    obj.forEach(function(runtimeInfo, ndx) {
      var gameInfo = runtimeInfo.info;
      var hftInfo = gameInfo.happyFunTimes;
      gameInfo.name = gameInfo.name.replace(/ /g, " ");
      gamesById[hftInfo.gameId] = runtimeInfo;
      runtimeInfo.dev = (runtimeInfo.originalGameId !== hftInfo.gameId) ? "(*)" : "";
      if (g.hftData.apiVersion) {
        if (semver.gt(hftInfo.apiVersion, g.hftData.apiVersion)) {
          runtimeInfo.needsUpgrade = true;
        }
      }
      runtimeInfo.count = ndx;
      var templateId = runtimeInfo.needsUpgrade ? "upgrade" : hftInfo.gameType.toLowerCase();
      var template = templates[templateId];
      if (!template) {
        console.error("missing template: " + templateId);
        return;
      }
      html.push(Strings.replaceParams(template, runtimeInfo));
    });

    gamemenu.innerHTML = html.join("");

    // change .msg-button elements to bring up message

    var forEachElementOnSelector = function(selector, fn) {
      Array.prototype.forEach.call(document.querySelectorAll(selector), function(elem) {
        var buttonId = elem.id;
        var count = parseInt(buttonId.substr(0, buttonId.length - buttonIdSuffix.length));
        var runtimeInfo = obj[count];
        fn(elem, runtimeInfo);
      });
    };

    var addOverlayMessgaeOnClickToSelector = function(selector, onDisplay, onHide) {
      forEachElementOnSelector(selector, function(elem, runtimeInfo) {
        var gameInfo = runtimeInfo.info;
        var hftInfo = gameInfo.happyFunTimes;
        var gameType = hftInfo.gameType;
        if (!gameType) {
          console.warn("missing happyFunTimes.gameType in package.json");
          return;
        }
        var msgId = (runtimeInfo.needsUpgrade ? "upgrade" : gameType.toLowerCase()) + hiddenMsgSuffix;
        var msgElement = $(msgId);
        if (!msgElement) {
          console.error("missing msg element: " + msgId);
          return;
        }
        elem.addEventListener('click', function(element, runtimeInfo) {
          return function(e) {
            e.preventDefault(true);
            element.style.display = "block";
            onDisplay(element, runtimeInfo);
          };
        }(msgElement, runtimeInfo), false);
        var cleanupFn = function(element) {
          return function() {
            element.style.display = "none";
          };
        }(msgElement);
        msgElement.addEventListener('click', function(fn, element, runtimeInfo) {
          return function(e) {
            e.preventDefault(true);
            fn();
            onHide(element, runtimeInfo);
          };
        }(cleanupFn, msgElement, runtimeInfo), false);
        gamesById[hftInfo.gameId].cleanupFn = cleanupFn;
      });
    };

    var noop = function() { };

    addOverlayMessgaeOnClickToSelector(".msg-button", noop, noop);

    var launch = function(element, runtimeInfo) {
      client.sendCmd('launch', {gameId: runtimeInfo.info.happyFunTimes.gameId});
    };
    var quit = function(element, runtimeInfo) {
      quitGame(runtimeInfo.info.happyFunTimes.gameId);
    };

    addOverlayMessgaeOnClickToSelector(".launch-button", launch, quit);

    forEachElementOnSelector(".upgrade-hft", function(elem/*, runtimeInfo*/) {
      elem.addEventListener('click', function() {
        window.location.href = "http://superhappyfuntimes.net/install";
      });
    });

    // If we started with a gameId param just launch it?
    // NOTE: this is kind of wonky. Seems like we should just go directly
    // instead of waiting
    if (params.gameId) {
      var runtimeInfo = gamesById[params.gameId];
      if (!runtimeInfo) {
        console.error("unknown gameId: " + params.gameId);
      } else {
        // LOL. If we don't replace the history then pressing back will just end up going forward again :P
        // Yet another reason maybe we should just go directly to the game?
        window.history.replaceState({}, "", window.location.origin + window.location.pathname);
        var event = new Event('click');
        var elem = $(runtimeInfo.count + "-button");
        elem.dispatchEvent(event);
      }
    }

    // If there's only one game just go to it.
    if (obj.length === 1 && obj[0].controllerUrl) {
      window.location.href = obj[0].controllerUrl;
      return;
    }
  };

  if (gamemenu) {
    client.addEventListener('availableGames', handleAvailableGames);
    client.sendCmd('getAvailableGames');
  }

  (function() {
    var elem = document.querySelector(".unhidden-msg");
    if (elem) {
      elem.addEventListener('click', function() {
        window.location.href = elem.getAttribute("target");
      }, false);
    }
  }());
});

<commit_msg>make showavailablegames go to installer page<commit_after>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

// Start the main app logic.
requirejs(
  [ 'hft/gameclient',
    'hft/misc/misc',
    'hft/misc/strings',
    './semver',
  ], function(
    GameClient,
    Misc,
    Strings,
    semver) {

  var $ = document.getElementById.bind(document);
  var g = {
    elementToShowOnDisconnect: $("disconnected"),
    gamesById: {},
    hftData: {},
  };

  var handleCmdErrorMsg = function(data) {
    // TODO: change to html dialog.
    alert(data.msg);  // eslint-disable-line
  };

  var handleRedirectMsg = function(data) {
    window.location.href = data.url;
  };

  var handleDisconnect = function() {
    g.elementToShowOnDisconnect.style.display = "block";
  };

  var handleGameExited = function(data) {
    var runtimeInfo = g.gamesById[data.gameId];
    if (runtimeInfo && runtimeInfo.cleanupFn) {
      runtimeInfo.cleanupFn();
    }
  };

  var handleHFTInfo = function(data) {
    g.hftData = data;
    $("versionnum").innerHTML = "v" + data.version;
  };

  var params = Misc.parseUrlQuery();

  var client = new GameClient({
    gameId: "__hft__",
  });

  client.addEventListener('connect', function() {});
  client.addEventListener('errorMsg', handleCmdErrorMsg);
  client.addEventListener('redirect', handleRedirectMsg);
  client.addEventListener('disconnect', handleDisconnect);
  client.addEventListener('gameExited', handleGameExited);
  client.addEventListener('hftInfo', handleHFTInfo);

  $('quit').addEventListener('click', function() {
    g.elementToShowOnDisconnect = $("exited");
    client.sendCmd('quit');
  }, false);

  var gamemenu = $("gamemenu");

  var itemTemplateSuffix = "-item-template";
  var hiddenMsgSuffix = "-msg";
  var buttonIdSuffix = "-button";

  var templates = {};
  Array.prototype.forEach.call(document.querySelectorAll(".item-template"), function(elem) {
    templates[elem.id.toLowerCase().substr(0, elem.id.length - itemTemplateSuffix.length)] = elem.text;
  });

  var hiddenMsgs = {};
  Array.prototype.forEach.call(document.querySelectorAll(".hidden-msg"), function(elem) {
    hiddenMsgs[elem.id.toLowerCase().substr(0, elem.id.length - hiddenMsgSuffix.length)] = elem;
  });

  var quitGame = function(gameId) {
    console.log("sending quitGame: " + gameId);
    client.sendCmd('quitGame', {gameId: gameId});
  };

  var handleAvailableGames = function(obj) {
    var html = [];
    var gamesById = {};
    g.gamesById = gamesById;
    obj.forEach(function(runtimeInfo, ndx) {
      var gameInfo = runtimeInfo.info;
      var hftInfo = gameInfo.happyFunTimes;
      gameInfo.name = gameInfo.name.replace(/ /g, " ");
      gamesById[hftInfo.gameId] = runtimeInfo;
      runtimeInfo.dev = (runtimeInfo.originalGameId !== hftInfo.gameId) ? "(*)" : "";
      if (g.hftData.apiVersion) {
        if (semver.gt(hftInfo.apiVersion, g.hftData.apiVersion)) {
          runtimeInfo.needsUpgrade = true;
        }
      }
      runtimeInfo.count = ndx;
      var templateId = runtimeInfo.needsUpgrade ? "upgrade" : hftInfo.gameType.toLowerCase();
      var template = templates[templateId];
      if (!template) {
        console.error("missing template: " + templateId);
        return;
      }
      html.push(Strings.replaceParams(template, runtimeInfo));
    });

    gamemenu.innerHTML = html.join("");

    // change .msg-button elements to bring up message

    var forEachElementOnSelector = function(selector, fn) {
      Array.prototype.forEach.call(document.querySelectorAll(selector), function(elem) {
        var buttonId = elem.id;
        var count = parseInt(buttonId.substr(0, buttonId.length - buttonIdSuffix.length));
        var runtimeInfo = obj[count];
        fn(elem, runtimeInfo);
      });
    };

    var addOverlayMessgaeOnClickToSelector = function(selector, onDisplay, onHide) {
      forEachElementOnSelector(selector, function(elem, runtimeInfo) {
        var gameInfo = runtimeInfo.info;
        var hftInfo = gameInfo.happyFunTimes;
        var gameType = hftInfo.gameType;
        if (!gameType) {
          console.warn("missing happyFunTimes.gameType in package.json");
          return;
        }
        var msgId = (runtimeInfo.needsUpgrade ? "upgrade" : gameType.toLowerCase()) + hiddenMsgSuffix;
        var msgElement = $(msgId);
        if (!msgElement) {
          console.error("missing msg element: " + msgId);
          return;
        }
        elem.addEventListener('click', function(element, runtimeInfo) {
          return function(e) {
            e.preventDefault(true);
            element.style.display = "block";
            onDisplay(element, runtimeInfo);
          };
        }(msgElement, runtimeInfo), false);
        var cleanupFn = function(element) {
          return function() {
            element.style.display = "none";
          };
        }(msgElement);
        msgElement.addEventListener('click', function(fn, element, runtimeInfo) {
          return function(e) {
            e.preventDefault(true);
            fn();
            onHide(element, runtimeInfo);
          };
        }(cleanupFn, msgElement, runtimeInfo), false);
        gamesById[hftInfo.gameId].cleanupFn = cleanupFn;
      });
    };

    var noop = function() { };

    addOverlayMessgaeOnClickToSelector(".msg-button", noop, noop);

    var launch = function(element, runtimeInfo) {
      client.sendCmd('launch', {gameId: runtimeInfo.info.happyFunTimes.gameId});
    };
    var quit = function(element, runtimeInfo) {
      quitGame(runtimeInfo.info.happyFunTimes.gameId);
    };

    addOverlayMessgaeOnClickToSelector(".launch-button", launch, quit);

    forEachElementOnSelector(".upgrade-hft", function(elem/*, runtimeInfo*/) {
      elem.addEventListener('click', function() {
        window.location.href = "http://docs.happyfuntimes.net/install.html";
      });
    });

    // If we started with a gameId param just launch it?
    // NOTE: this is kind of wonky. Seems like we should just go directly
    // instead of waiting
    if (params.gameId) {
      var runtimeInfo = gamesById[params.gameId];
      if (!runtimeInfo) {
        console.error("unknown gameId: " + params.gameId);
      } else {
        // LOL. If we don't replace the history then pressing back will just end up going forward again :P
        // Yet another reason maybe we should just go directly to the game?
        window.history.replaceState({}, "", window.location.origin + window.location.pathname);
        var event = new Event('click');
        var elem = $(runtimeInfo.count + "-button");
        elem.dispatchEvent(event);
      }
    }

    // If there's only one game just go to it.
    if (obj.length === 1 && obj[0].controllerUrl) {
      window.location.href = obj[0].controllerUrl;
      return;
    }
  };

  if (gamemenu) {
    client.addEventListener('availableGames', handleAvailableGames);
    client.sendCmd('getAvailableGames');
  }

  (function() {
    var elem = document.querySelector(".unhidden-msg");
    if (elem) {
      elem.addEventListener('click', function() {
        window.location.href = elem.getAttribute("target");
      }, false);
    }
  }());
});

<|endoftext|>


<commit_before>import React from 'react'
import {observer} from 'mobx-react'
import styles from './style.less'
import {UiState} from '~/src/business/UiState'
import {Modals} from '~/src/business/Modals'

import {ImageButton} from '~/src/ui/quark/ImageButton'

@observer
export class TextInputDialog extends React.Component {

  static contextTypes = {
    uiState: React.PropTypes.instanceOf(UiState).isRequired
  }

  render() {
    if (this.context.uiState.openedModal!=Modals.TEXT_MODAL) {
      return null;
    }

    return
this._onCancel(e)}>

        <ImageButton glyph="fa-times" huge={true} onClick={e=>this._onCancel(e)} />

        <input
          ref="input"
          autoFocus
          className={styles.input}
          defaultValue={this.context.uiState.openedModalParams.value}
          onClick={e=>e.stopPropagation()}
          onKeyPress={e=>this._onKeyPress(e)}
          onFocus={e=>this._onFocus(e)}
        />

        <ImageButton glyph="fa-check" huge={true} onClick={e=>this._onConfirm(e)} />

  }

  _onFocus(e) {
    e.target.select()
  }

  _onConfirm(e) {
    this.context.uiState.closeModal({confirmed: true, value: this.refs.input.value})
    e.stopPropagation()
  }

  _onCancel(e) {
    this.context.uiState.closeModal({confirmed: false})
    e.stopPropagation()
  }

  _onKeyPress(e) {
    if(e.key=='Enter') {
      this._onConfirm(e)
    }
  }
}
<commit_msg>Disabled capitalized input on mobile devices<commit_after>import React from 'react'
import {observer} from 'mobx-react'
import styles from './style.less'
import {UiState} from '~/src/business/UiState'
import {Modals} from '~/src/business/Modals'

import {ImageButton} from '~/src/ui/quark/ImageButton'

@observer
export class TextInputDialog extends React.Component {

  static contextTypes = {
    uiState: React.PropTypes.instanceOf(UiState).isRequired
  }

  render() {
    if (this.context.uiState.openedModal!=Modals.TEXT_MODAL) {
      return null;
    }

    return
this._onCancel(e)}>

        <ImageButton glyph="fa-times" huge={true} onClick={e=>this._onCancel(e)} />

        <input
          ref="input"
          autoFocus
          className={styles.input}
          defaultValue={this.context.uiState.openedModalParams.value}
          onClick={e=>e.stopPropagation()}
          onKeyPress={e=>this._onKeyPress(e)}
          onFocus={e=>this._onFocus(e)}
          autoCapitalize="off"
        />

        <ImageButton glyph="fa-check" huge={true} onClick={e=>this._onConfirm(e)} />

  }

  _onFocus(e) {
    e.target.select()
  }

  _onConfirm(e) {
    this.context.uiState.closeModal({confirmed: true, value: this.refs.input.value})
    e.stopPropagation()
  }

  _onCancel(e) {
    this.context.uiState.closeModal({confirmed: false})
    e.stopPropagation()
  }

  _onKeyPress(e) {
    if(e.key=='Enter') {
      this._onConfirm(e)
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('app').controller('queryCtrl', [
  '$scope',
  '$rootScope',
  'notificationService',
  'modalService',
  '$timeout', ($scope, $rootScope, notificationService, modalService, $timeout) => {
    const expression = require('lib/modules/expression');

    if (!$scope.database) throw new Error('database is required for database query directive');
    if (!$scope.database.collections || !$scope.database.collections.length) throw new Error('database must have collections for database query directive');

    $scope.loading = false;
    $scope.queryTime = null;

    $scope.serverName = `${$scope.database.host}:${$scope.database.port}`;
    $scope.databaseName = $scope.database.name;

    //editor
    $scope.editorHandle = {};
    $scope.codeEditorOptions = {};
    $scope.codeEditorCustomData = {
      collectionNames: _.pluck($scope.database.collections, 'name')
    };
    $scope.editorHasFocus = false;

    $scope.results = [];
    $scope.keyValueResults = [];

    $scope.deleteDocument = _deleteDocument;
    $scope.editDocument = _editDocument;

    let defaultCollection = $scope.defaultCollection ? _.findWhere($scope.database.collections, {
      name: $scope.defaultCollection
    }) : null;

    defaultCollection = defaultCollection || $scope.database.collections[0];

    let defaultExpression = `db.${defaultCollection.name}.find({\n  \n})`;

    $scope.changeTabName = (name) => {
      if (!name || !$scope.databaseTab) return;
      $scope.databaseTab.name = name.length > 20 ? `${name.substring(0, 20)}...` : name;
    };

    $scope.changeTabName(defaultExpression);

    $scope.form = {
      expression: defaultExpression
    };

    $scope.evaluateExpression = () => {
      _evalExpression($scope.form.expression);
    };

    $scope.VIEWS = {
      TEXT: 'TEXT',
      KEYVALUE: 'KEYVALUE',
      RAW: 'RAW'
    };
    $scope.currentView = $scope.VIEWS.KEYVALUE;

    _evalExpression(defaultExpression);

    $scope.autoformat = () => {
      if ($scope.editorHandle.autoformat) {
        $scope.editorHandle.autoformat();
      }
    };

    $scope.$watch('editorHasFocus', (val) => {
      if (val) {
        //make some functions available on the root scope when the editor gets focus,
        //used for keybindings
        $rootScope.currentQuery = {
          runQuery: $scope.evaluateExpression,
          autoformat: $scope.autoformat
        };
      } else {
        $rootScope.currentQuery = null;
      }
    });

    $scope.exportResults = () => {
      modalService.openQueryResultsExport($scope.form.expression);
    };

    $scope.collapseAll = () => {
      $scope.$broadcast('collapse');
    };

    function _evalExpression(rawExpression) {
      $scope.loading = true;
      $scope.error = null;

      $scope.changeTabName(rawExpression);

      let evalScope = _createEvalScopeFromCollections($scope.database.collections);

      expression.eval(rawExpression, evalScope)
        .then(expressionResult => {
          $scope.$apply(() => {
            $scope.result = expressionResult.result;
            $scope.resultMongoMethodName = expressionResult.mongoMethodName;
            $scope.queryTime = expressionResult.time;
            $scope.keyValueResults = expressionResult.keyValueResults;

            if (expressionResult.mongoCollectionName) {
              $scope.currentCollection = _.findWhere($scope.database.collections, {
                name: expressionResult.mongoCollectionName
              });

              if (_isModifyingMongoMethod(expressionResult.mongoMethodName)) {
                notificationService.success(`${expressionResult.mongoMethodName} was successful`);

                return _evalExpression(`db.${expressionResult.mongoCollectionName}.find()`, $scope.database.collections);
              }
            } else {
              $scope.currentView = $scope.VIEWS.RAW;
            }
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            $scope.error = error && error.message ? `Error : ${error.message}` : error;
            $scope.loading = false;
          });
        })
        .finally(() => {
          $timeout(() => {
            $scope.loading = false;
          });
        });
    }

    function _createEvalScopeFromCollections(collections) {
      let evalScope = {
        db: {}
      };

      collections.forEach(collection => {
        evalScope.db[collection.name] = collection;
      });

      return evalScope;
    }

    function _isModifyingMongoMethod(methodName) {
      return methodName && (methodName === 'updateMany' || methodName === 'updateById' || methodName === 'updateOne' || methodName === 'deleteMany' || methodName === 'deleteById' || methodName === 'deleteOne');
    }

    function _deleteDocument(doc) {
      if (!doc) return;

      modalService.openDeleteDocument(doc, $scope.currentCollection)
        .then(() => {
          $scope.$apply(() => {
            notificationService.success('Delete successful');

            _evalExpression(`db.${$scope.currentCollection.name}.find()`);
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            $scope.error = error && error.message ? error.message : error;
            $scope.loading = false;
          });
        });
    }

    function _editDocument(doc) {
      if (!doc) return;

      modalService.openEditDocument(doc, $scope.currentCollection)
        .then(() => {
          $scope.$apply(() => {
            notificationService.success('Update successful');

            _evalExpression(`db.${$scope.currentCollection.name}.find()`);
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            let errMsg = error && error.message ? error.message : error;
            if (errMsg !== 'backdrop click' && errMsg !== 'escape key press') {
              $scope.error = errMsg;
            }
            $scope.loading = false;
          });
        });
    }
  }
]);
<commit_msg>check for bracket notation<commit_after>'use strict';

angular.module('app').controller('queryCtrl', [
  '$scope',
  '$rootScope',
  'notificationService',
  'modalService',
  '$timeout', ($scope, $rootScope, notificationService, modalService, $timeout) => {
    const expression = require('lib/modules/expression');

    if (!$scope.database) throw new Error('database is required for database query directive');
    if (!$scope.database.collections || !$scope.database.collections.length) throw new Error('database must have collections for database query directive');

    $scope.loading = false;
    $scope.queryTime = null;

    $scope.serverName = `${$scope.database.host}:${$scope.database.port}`;
    $scope.databaseName = $scope.database.name;

    //editor
    $scope.editorHandle = {};
    $scope.codeEditorOptions = {};
    $scope.codeEditorCustomData = {
      collectionNames: _.pluck($scope.database.collections, 'name')
    };
    $scope.editorHasFocus = false;

    $scope.results = [];
    $scope.keyValueResults = [];

    $scope.deleteDocument = _deleteDocument;
    $scope.editDocument = _editDocument;

    let defaultCollection = $scope.defaultCollection ? _.findWhere($scope.database.collections, {
      name: $scope.defaultCollection
    }) : null;

    defaultCollection = defaultCollection || $scope.database.collections[0];

    //check for bracket notation
    let expressionCollectionName = defaultCollection.name.indexOf('.') > 0 ? `['${defaultCollection.name}']` : `.${defaultCollection.name}`;

    let defaultExpression = `db${expressionCollectionName}.find({\n  \n})`;

    $scope.changeTabName = (name) => {
      if (!name || !$scope.databaseTab) return;
      $scope.databaseTab.name = name.length > 20 ? `${name.substring(0, 20)}...` : name;
    };

    $scope.changeTabName(defaultExpression);

    $scope.form = {
      expression: defaultExpression
    };

    $scope.evaluateExpression = () => {
      _evalExpression($scope.form.expression);
    };

    $scope.VIEWS = {
      TEXT: 'TEXT',
      KEYVALUE: 'KEYVALUE',
      RAW: 'RAW'
    };
    $scope.currentView = $scope.VIEWS.KEYVALUE;

    _evalExpression(defaultExpression);

    $scope.autoformat = () => {
      if ($scope.editorHandle.autoformat) {
        $scope.editorHandle.autoformat();
      }
    };

    $scope.$watch('editorHasFocus', (val) => {
      if (val) {
        //make some functions available on the root scope when the editor gets focus,
        //used for keybindings
        $rootScope.currentQuery = {
          runQuery: $scope.evaluateExpression,
          autoformat: $scope.autoformat
        };
      } else {
        $rootScope.currentQuery = null;
      }
    });

    $scope.exportResults = () => {
      modalService.openQueryResultsExport($scope.form.expression);
    };

    $scope.collapseAll = () => {
      $scope.$broadcast('collapse');
    };

    function _evalExpression(rawExpression) {
      $scope.loading = true;
      $scope.error = null;

      $scope.changeTabName(rawExpression);

      let evalScope = _createEvalScopeFromCollections($scope.database.collections);

      expression.eval(rawExpression, evalScope)
        .then(expressionResult => {
          $scope.$apply(() => {
            $scope.result = expressionResult.result;
            $scope.resultMongoMethodName = expressionResult.mongoMethodName;
            $scope.queryTime = expressionResult.time;
            $scope.keyValueResults = expressionResult.keyValueResults;

            if (expressionResult.mongoCollectionName) {
              $scope.currentCollection = _.findWhere($scope.database.collections, {
                name: expressionResult.mongoCollectionName
              });

              if (_isModifyingMongoMethod(expressionResult.mongoMethodName)) {
                notificationService.success(`${expressionResult.mongoMethodName} was successful`);

                return _evalExpression(`db.${expressionResult.mongoCollectionName}.find()`, $scope.database.collections);
              }
            } else {
              $scope.currentView = $scope.VIEWS.RAW;
            }
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            $scope.error = error && error.message ? `Error : ${error.message}` : error;
            $scope.loading = false;
          });
        })
        .finally(() => {
          $timeout(() => {
            $scope.loading = false;
          });
        });
    }

    function _createEvalScopeFromCollections(collections) {
      let evalScope = {
        db: {}
      };

      collections.forEach(collection => {
        evalScope.db[collection.name] = collection;
      });

      return evalScope;
    }

    function _isModifyingMongoMethod(methodName) {
      return methodName && (methodName === 'updateMany' || methodName === 'updateById' || methodName === 'updateOne' || methodName === 'deleteMany' || methodName === 'deleteById' || methodName === 'deleteOne');
    }

    function _deleteDocument(doc) {
      if (!doc) return;

      modalService.openDeleteDocument(doc, $scope.currentCollection)
        .then(() => {
          $scope.$apply(() => {
            notificationService.success('Delete successful');

            _evalExpression(`db.${$scope.currentCollection.name}.find()`);
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            $scope.error = error && error.message ? error.message : error;
            $scope.loading = false;
          });
        });
    }

    function _editDocument(doc) {
      if (!doc) return;

      modalService.openEditDocument(doc, $scope.currentCollection)
        .then(() => {
          $scope.$apply(() => {
            notificationService.success('Update successful');

            _evalExpression(`db.${$scope.currentCollection.name}.find()`);
          });
        })
        .catch((error) => {
          $scope.$apply(() => {
            let errMsg = error && error.message ? error.message : error;
            if (errMsg !== 'backdrop click' && errMsg !== 'escape key press') {
              $scope.error = errMsg;
            }
            $scope.loading = false;
          });
        });
    }
  }
]);
<|endoftext|>


<commit_before>import DS from 'ember-data';
import filetypes from 'davros/lib/filetypes';

export default DS.Model.extend({
  mode: DS.attr('number'),
  path: DS.attr('string'),
  size: DS.attr('number'),
  name: DS.attr('string'),
  files: DS.hasMany('files', {async: true}),

  sortedFiles: function() {
    return this.get('files').sortBy('mode', 'name');
  }.property('files'),

  davBase: '/remote.php/webdav',

  parent: function() {
    return this.get('path').replace(/\/?[^\/]*\/?$/, '');
  }.property('path'),

  isDirectory: function() {
    return this.get('mode') === 16877;
  }.property('mode'),

  extension: function() {
    var pieces = this.get('name').split('.');
    return pieces[pieces.length - 1];
  }.property('name'),

  type: function() {
    return filetypes[this.get('extension')] || filetypes.defaultType;
  }.property('extension'),

  rawPath: function() {
    return [this.get('davBase'), this.get('path')].join('/');
  }.property('path', 'davBase')
});
<commit_msg>compute directory from file mode bitmask<commit_after>import DS from 'ember-data';
import filetypes from 'davros/lib/filetypes';

export default DS.Model.extend({
  mode: DS.attr('number'),
  path: DS.attr('string'),
  size: DS.attr('number'),
  name: DS.attr('string'),
  files: DS.hasMany('files', {async: true}),

  sortedFiles: function() {
    return this.get('files').sortBy('mode', 'name');
  }.property('files'),

  davBase: '/remote.php/webdav',

  parent: function() {
    return this.get('path').replace(/\/?[^\/]*\/?$/, '');
  }.property('path'),

  isDirectory: function() {
    // "0040000" in octal is the bitmask for a directory
    return (this.get('mode') & parseInt("0040000", 8)) > 0;
  }.property('mode'),

  extension: function() {
    var pieces = this.get('name').split('.');
    return pieces[pieces.length - 1];
  }.property('name'),

  type: function() {
    return filetypes[this.get('extension')] || filetypes.defaultType;
  }.property('extension'),

  rawPath: function() {
    return [this.get('davBase'), this.get('path')].join('/');
  }.property('path', 'davBase')
});
<|endoftext|>


<commit_before>/* ************************************ */
/* Define helper functions */
/* ************************************ */
function getDisplayElement() {
  $('

').appendTo('body')
  return $('

').appendTo('body')
}

function evalAttentionChecks() {
  var check_percent = 1
  if (run_attention_checks) {
    var attention_check_trials = jsPsych.data.getTrialsOfType('attention-check')
    var checks_passed = 0
    for (var i = 0; i < attention_check_trials.length; i++) {
      if (attention_check_trials[i].correct === true) {
        checks_passed += 1
      }
    }
    check_percent = checks_passed / attention_check_trials.length
  }
  return check_percent
}

function addID() {
  jsPsych.data.addDataToLastTrial({
    'exp_id': 'kirby'
  })
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = false
var attention_check_thresh = 0.45
var sumInstructTime = 0 //ms
var instructTimeThresh = 0 ///in seconds

// task specific variables
//hard coded options in the amounts and order specified in Kirby and Marakovic (1996)
var options = {
  small_amt: [54, 55, 19, 31, 14, 47, 15, 25, 78, 40, 11, 67, 34, 27, 69, 49, 80, 24, 33, 28, 34,
    25, 41, 54, 54, 22, 20
  ],
  large_amt: [55, 75, 25, 85, 25, 50, 35, 60, 80, 55, 30, 75, 35, 50, 85, 60, 85, 35, 80, 30, 50,
    30, 75, 60, 80, 25, 55
  ],
  later_del: [117, 61, 53, 7, 19, 160, 13, 14, 192, 62, 7, 119, 186, 21, 91, 89, 157, 29, 14, 179,
    30, 80, 20, 111, 30, 136, 7
  ]
}

var stim_html = []

//loop through each option to create html
for (var i = 0; i < options.small_amt.length; i++) {
  stim_html[i] =
    "

Please select the option that you would prefer pressing 'q' for left 'p' for right:

$" +
    options.small_amt[i] +
    "
today

$" + options.large_amt[
      i] + "
" + options.later_del[i] + " days

"
}

data_prop = []

for (var i = 0; i < options.small_amt.length; i++) {
  data_prop.push({
    small_amt: options.small_amt[i],
    large_amt: options.large_amt[i],
    later_del: options.later_del[i]
  });
}

trials = []

//used new features to include the stimulus properties in recorded data
for (var i = 0; i < 3; i++) { //stim_html.length
  trials.push({
    stimulus: stim_html[i],
    data: data_prop[i]
  });
}

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
// Set up attention check node
var attention_check_block = {
  type: 'attention-check',
  data: {
    trial_id: "attention_check"
  },
  timing_response: 180000,
  response_ends_trial: true,
  timing_post_trial: 200
}

var attention_node = {
  timeline: [attention_check_block],
  conditional_function: function() {
    return run_attention_checks
  }
}

/* define static blocks */
var feedback_instruct_text =
  'Welcome to the experiment. Press enter to begin.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  data: {
    trial_id: "instruction"
  },
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 180000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instruction_trials = []
var instructions_block = {
  type: 'poldrack-instructions',
  data: {
    trial_id: "instruction"
  },
  pages: [
    '

In this experiment you will be presented with two amounts of money to choose between. One of the amounts will be available now and the other will be available in the future. Your job is to indicate which option you would prefer by pressing "q" for the left option and "p" for the right option.

You should indicate your true preference because at the end of the experiment a random trial will be chosen and you will receive a bonus payment proportional to the option you selected at the time point you chose.

',
  ],
  allow_keys: false,
  show_clickable_nav: true
};

instruction_trials.push(feedback_instruct_block)
instruction_trials.push(instructions_block)

var instruction_node = {
  timeline: instruction_trials,
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (var i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var start_practice_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  data: {
    trial_id: "practice_intro"
  },
  text: '

Here is a sample trial. Your choice for this trial will not be included in your bonus payment.

Press enter to begin.

',
  cont_key: [13],
  //timing_post_trial: 1000
};

var practice_block = {
  type: 'poldrack-single-stim',
  data: {
    trial_id: "stim",
    exp_stage: "practice"
  },
  stimulus: "

Please select the option that you would prefer pressing 'q' for left 'p' for right:

$20
today

$25
5 days

",
  is_html: true,
  choices: [80,81],
  response_ends_trial: true,
};

var start_test_block = {
  type: 'poldrack-text',
  data: {
    trial_id: "test_intro"
  },
  timing_response: 180000,
  text: '

You are now ready to begin the survey.

Remember to indicate your true preferences.

Press enter to begin.

',
  cont_key: [13],
  //timing_post_trial: 1000
};

var test_block = {
  type: 'poldrack-single-stim',
  data: {
    trial_id: "stim",
    exp_stage: "test"
  },
  timeline: trials,
  is_html: true,
  choices: [80,81],
  response_ends_trial: true,
  //used new feature to include choice info in recorded data
  on_finish: function(data) {
    var choice = false;
    if (data.key_press == 80) {
      choice = 'larger_later';
    } else if (data.key_press == 81) {
      choice = 'smaller_sooner';
    }
    jsPsych.data.addDataToLastTrial({
      choice: choice
    });
  }
};

var end_block = {
  type: 'poldrack-text',
  data: {
    trial_id: "end"
  },
  timing_response: 180000,
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13],
  timing_post_trial: 0
};

//Set up experiment
var kirby_experiment = []
kirby_experiment.push(instruction_node);
kirby_experiment.push(start_practice_block);
kirby_experiment.push(practice_block);
kirby_experiment.push(attention_node);
kirby_experiment.push(start_test_block);
kirby_experiment.push(test_block);
kirby_experiment.push(attention_node);
kirby_experiment.push(end_block);<commit_msg>changed trial num for kirby<commit_after>/* ************************************ */
/* Define helper functions */
/* ************************************ */
function getDisplayElement() {
  $('

').appendTo('body')
  return $('

').appendTo('body')
}

function evalAttentionChecks() {
  var check_percent = 1
  if (run_attention_checks) {
    var attention_check_trials = jsPsych.data.getTrialsOfType('attention-check')
    var checks_passed = 0
    for (var i = 0; i < attention_check_trials.length; i++) {
      if (attention_check_trials[i].correct === true) {
        checks_passed += 1
      }
    }
    check_percent = checks_passed / attention_check_trials.length
  }
  return check_percent
}

function addID() {
  jsPsych.data.addDataToLastTrial({
    'exp_id': 'kirby'
  })
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = false
var attention_check_thresh = 0.45
var sumInstructTime = 0 //ms
var instructTimeThresh = 0 ///in seconds

// task specific variables
//hard coded options in the amounts and order specified in Kirby and Marakovic (1996)
var options = {
  small_amt: [54, 55, 19, 31, 14, 47, 15, 25, 78, 40, 11, 67, 34, 27, 69, 49, 80, 24, 33, 28, 34,
    25, 41, 54, 54, 22, 20
  ],
  large_amt: [55, 75, 25, 85, 25, 50, 35, 60, 80, 55, 30, 75, 35, 50, 85, 60, 85, 35, 80, 30, 50,
    30, 75, 60, 80, 25, 55
  ],
  later_del: [117, 61, 53, 7, 19, 160, 13, 14, 192, 62, 7, 119, 186, 21, 91, 89, 157, 29, 14, 179,
    30, 80, 20, 111, 30, 136, 7
  ]
}

var stim_html = []

//loop through each option to create html
for (var i = 0; i < options.small_amt.length; i++) {
  stim_html[i] =
    "

Please select the option that you would prefer pressing 'q' for left 'p' for right:

$" +
    options.small_amt[i] +
    "
today

$" + options.large_amt[
      i] + "
" + options.later_del[i] + " days

"
}

data_prop = []

for (var i = 0; i < options.small_amt.length; i++) {
  data_prop.push({
    small_amt: options.small_amt[i],
    large_amt: options.large_amt[i],
    later_del: options.later_del[i]
  });
}

trials = []

//used new features to include the stimulus properties in recorded data
for (var i = 0; i < stim_html.length; i++) {
  trials.push({
    stimulus: stim_html[i],
    data: data_prop[i]
  });
}

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
// Set up attention check node
var attention_check_block = {
  type: 'attention-check',
  data: {
    trial_id: "attention_check"
  },
  timing_response: 180000,
  response_ends_trial: true,
  timing_post_trial: 200
}

var attention_node = {
  timeline: [attention_check_block],
  conditional_function: function() {
    return run_attention_checks
  }
}

/* define static blocks */
var feedback_instruct_text =
  'Welcome to the experiment. Press enter to begin.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  data: {
    trial_id: "instruction"
  },
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 180000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instruction_trials = []
var instructions_block = {
  type: 'poldrack-instructions',
  data: {
    trial_id: "instruction"
  },
  pages: [
    '

In this experiment you will be presented with two amounts of money to choose between. One of the amounts will be available now and the other will be available in the future. Your job is to indicate which option you would prefer by pressing "q" for the left option and "p" for the right option.

You should indicate your true preference because at the end of the experiment a random trial will be chosen and you will receive a bonus payment proportional to the option you selected at the time point you chose.

',
  ],
  allow_keys: false,
  show_clickable_nav: true
};

instruction_trials.push(feedback_instruct_block)
instruction_trials.push(instructions_block)

var instruction_node = {
  timeline: instruction_trials,
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (var i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var start_practice_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  data: {
    trial_id: "practice_intro"
  },
  text: '

Here is a sample trial. Your choice for this trial will not be included in your bonus payment.

Press enter to begin.

',
  cont_key: [13],
  //timing_post_trial: 1000
};

var practice_block = {
  type: 'poldrack-single-stim',
  data: {
    trial_id: "stim",
    exp_stage: "practice"
  },
  stimulus: "

Please select the option that you would prefer pressing 'q' for left 'p' for right:

$20
today

$25
5 days

",
  is_html: true,
  choices: [80,81],
  response_ends_trial: true,
};

var start_test_block = {
  type: 'poldrack-text',
  data: {
    trial_id: "test_intro"
  },
  timing_response: 180000,
  text: '

You are now ready to begin the survey.

Remember to indicate your true preferences.

Press enter to begin.

',
  cont_key: [13],
  //timing_post_trial: 1000
};

var test_block = {
  type: 'poldrack-single-stim',
  data: {
    trial_id: "stim",
    exp_stage: "test"
  },
  timeline: trials,
  is_html: true,
  choices: [80,81],
  response_ends_trial: true,
  //used new feature to include choice info in recorded data
  on_finish: function(data) {
    var choice = false;
    if (data.key_press == 80) {
      choice = 'larger_later';
    } else if (data.key_press == 81) {
      choice = 'smaller_sooner';
    }
    jsPsych.data.addDataToLastTrial({
      choice: choice
    });
  }
};

var end_block = {
  type: 'poldrack-text',
  data: {
    trial_id: "end"
  },
  timing_response: 180000,
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13],
  timing_post_trial: 0
};

//Set up experiment
var kirby_experiment = []
kirby_experiment.push(instruction_node);
kirby_experiment.push(start_practice_block);
kirby_experiment.push(practice_block);
kirby_experiment.push(attention_node);
kirby_experiment.push(start_test_block);
kirby_experiment.push(test_block);
kirby_experiment.push(attention_node);
kirby_experiment.push(end_block);<|endoftext|>


<commit_before>const itemPattern = new RegExp([
  // rfiCode, rfiSubcode
  '-([A-Z]{1})/([A-Z0-9]{3})',
  // Fee description, passenger name, amount, currency
  '\\/([^\\/]+)/NM-1(.+?)\\/\\/((?:\\d+\\.)?\\d+)\\/([A-Z]{3})',
].join(''), 'i');

const parse = (string) => {
  const [
    _,
    rfiCode,
    rfiSubcode,
    feeDescription,
    name,
    amount,
    currency,
  ] = string.match(itemPattern);

  return {
    rfiCode,
    rfiSubcode,
    feeDescription,
    name,
    amount: Number(amount),
    currency,
  };
};

export default parse;
<commit_msg>Fixed parsing of service segments when issued<commit_after>const itemPattern = new RegExp([
  // rfiCode, rfiSubcode
  '-([A-Z]{1})/([A-Z0-9]{3})',
  // Fee description, passenger name, amount, currency
  '\\/([^\\/]+)/NM-1(.+?)\\/([^\\/]*)\\/((?:\\d+\\.)?\\d+)\\/([A-Z]{3})',
].join(''), 'i');

const parse = (string) => {
  const [
    _,
    rfiCode,
    rfiSubcode,
    feeDescription,
    name,
    documentNumber,
    amount,
    currency,
  ] = string.match(itemPattern);

  return Object.assign(
    {
      rfiCode,
      rfiSubcode,
      feeDescription,
      name,
      amount: Number(amount),
      currency,
    },
    documentNumber !== ''
      ? { ticketNumber: documentNumber.substr(0, 13) }
      : null
  );
};

export default parse;
<|endoftext|>


<commit_before>/**
 * Copyright 2015-2019 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {LitElement, html} from "lit";
import UtilsNew from "../../core/utilsNew.js";
import "../commons/opencga-browser.js";
import "../commons/opencb-facet-results.js";
import "../commons/facet-filter.js";
import "./job-timeline.js";
import "./job-grid.js";
import "./job-detail.js";
import "./job-detail-log.js";
import "./job-view.js";

export default class JobBrowser extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object,
            },
            query: {
                type: Object,
            },
            /* facetQuery: {
                type: Object
            },
            selectedFacet: {
                type: Object
            },*/
            settings: {
                type: Object,
            },
        };
    }

    _init() {
        this._config = this.getDefaultConfig();
    }

    // NOTE turn updated into update here reduces the number of remote requests from 2 to 1 as in the grid components propertyObserver()
    // is executed twice in case there is external settings
    update(changedProperties) {
        if (changedProperties.has("settings")) {
            this.settingsObserver();
        }

        super.update(changedProperties);
    }

    settingsObserver() {
        this._config = this.getDefaultConfig();
        // merge filter list, canned filters, detail tabs
        if (this.settings?.menu) {
            this._config.filter = UtilsNew.mergeFiltersAndDetails(this._config?.filter, this.settings);
        }
        if (this.settings?.table) {
            this._config.filter.result.grid = {...this._config.filter.result.grid, ...this.settings.table};
        }
        if (this.settings?.table?.toolbar) {
            this._config.filter.result.grid.toolbar = {...this._config.filter.result.grid.toolbar, ...this.settings.table.toolbar};
        }
    }

    render() {
        // No openCGA session available
        if (!this.opencgaSession) {
            return html`

No public projects available to browse. Please login to continue

            `;
        }

        return html`
            <opencga-browser
                resource="JOB"
                .opencgaSession="${this.opencgaSession}"
                .query="${this.query}"
                .config="${this._config}">
            </opencga-browser>
        `;
    }

    getDefaultConfig() {
        return {
            title: "Jobs Browser",
            icon: "fab fa-searchengin",
            description: "",
            views: [
                {
                    id: "table-tab",
                    name: "Table result",
                    icon: "fa fa-table",
                    active: true,
                    render: params => html`
                        <job-grid
                            .opencgaSession="${params.opencgaSession}"
                            .config="${params.config.filter.result.grid}"
                            .query="${params.executedQuery}"
                            .search="${params.executedQuery}"
                            .eventNotifyName="${params.eventNotifyName}"
                            .files="${params.files}"
                            @selectrow="${e => params.onClickRow(e, "job")}">
                        </job-grid>
                        <job-detail
                            .opencgaSession="${params.opencgaSession}"
                            .config="${params.config.filter.detail}"
                            .jobId="${params.detail.job?.id}">
                        </job-detail>
                    `,
                },
                {
                    id: "facet-tab",
                    name: "Aggregation stats",
                    icon: "fas fa-chart-bar",
                    render: params => html`
                        <opencb-facet-results
                            resource="${params.resource}"
                            .opencgaSession="${params.opencgaSession}"
                            .active="${params.active}"
                            .query="${params.facetQuery}"
                            .data="${params.facetResults}">
                        </opencb-facet-results>
                    `,
                },
                {
                    id: "visual-browser-tab",
                    name: "Visual browser",
                    render: params => html `
                        <jobs-timeline
                            .opencgaSession="${params.opencgaSession}"
                            .active="${params.active}"
                            .query="${params.executedQuery}">
                        </jobs-timeline>
                    `,
                },
            ],
            filter: {
                searchButton: false,
                sections: [
                    {
                        title: "Section title",
                        collapsed: false,
                        filters: [
                            {
                                id: "id",
                                name: "Job ID",
                                placeholder: "ID",
                                allowedValues: "",
                                defaultValue: "",
                                description: "Job ID. It must be a unique string within the study. An id will be autogenerated automatically if not provided.",
                                fileUpload: false,
                            },
                            {
                                id: "tool",
                                name: "Analysis Tool ID",
                                placeholder: "Tool",
                                allowedValues: "",
                                defaultValue: "",
                                description: "Tool executed by the job",
                            },
                            {
                                id: "input",
                                name: "Input File Name",
                                placeholder: "e.g.  NA12877.vcf.gz",
                                allowedValues: "",
                                defaultValue: "",
                                description: "File used by the Tool",
                                fileUpload: false,
                            },
                            {
                                id: "internalStatus",
                                name: "Status",
                                placeholder: "Status",
                                allowedValues: ["PENDING", "QUEUED", "RUNNING", "DONE", "ERROR", "UNKNOWN", "ABORTED", "DELETED"],
                                defaultValue: "",
                                description: "Job internal status",
                            },
                            {
                                id: "priority",
                                name: "Priority",
                                placeholder: "Priority",
                                allowedValues: ["URGENT", "HIGH", "MEDIUM", "LOW"],
                                defaultValue: "",
                                description: "Priority of the job",
                            },
                            {
                                id: "tags",
                                name: "Tags",
                                placeholder: "Tags",
                                allowedValues: "",
                                defaultValue: "",
                                description: "Job tags",
                            },
                            {
                                id: "creationDate",
                                name: "Creation Date",
                                placeholder: "Creation Date",
                                description: "Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805",
                            },
                            {
                                id: "visited",
                                name: "Visited",
                                placeholder: "Visited",
                                allowedValues: ["true", "false"],
                                defaultValue: "",
                                description: "Visited status of job",
                            },
                        ],
                    },
                ],
                examples: [
                    {
                        id: "Example 1 - Get VCF and BAM",
                        active: false,
                        query: {
                            format: "VCF,BAM",
                        },
                    },
                ],
                result: {
                    grid: {},
                },
                detail: {
                    title: "Job",
                    showTitle: true,
                    items: [
                        {
                            id: "job-view",
                            name: "Overview",
                            active: true,
                            render: (job, _active, opencgaSession) => html`
                                <job-view
                                    .opencgaSession="${opencgaSession}"
                                    mode="simple"
                                    .job="${job}">
                                </job-view>
                            `,
                        },
                        {
                            id: "job-log",
                            name: "Logs",
                            render: (job, active, opencgaSession) => html`
                                <job-detail-log
                                    .opencgaSession="${opencgaSession}"
                                    .active="${active}"
                                    .job="${job}">
                                </job-detail-log>
                            `,
                        },
                        {
                            id: "json-view",
                            name: "JSON Data",
                            mode: "development",
                            render: (job, active) => html`
                                <json-viewer
                                    .data="${job}"
                                    .active="${active}">
                                </json-viewer>
                            `,
                        },
                    ],
                },
            },
            aggregation: {
                default: ["creationYear>>creationMonth", "toolId>>executorId"],
                render: params => html `
                    <facet-filter
                        .config="${params.config.aggregation}"
                        .selectedFacet="${params.selectedFacet}"
                        @facetQueryChange="${params.onFacetQueryChange}">
                    </facet-filter>
                `,
                result: {
                    numColumns: 2,
                },
                sections: [
                    {
                        name: "Job attributes",
                        fields: [
                            {
                                id: "studyId",
                                name: "Study id",
                                type: "string",
                                description: "Study [[user@]project:]study where study and project can be either the ID or UUID",
                            },
                            {
                                id: "creationYear",
                                name: "Creation Year",
                                type: "string",
                                description: "Creation year",
                            },
                            {
                                id: "creationMonth",
                                name: "Creation Month",
                                type: "category",
                                allowedValues: ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"],
                                description: "Creation month (JANUARY, FEBRUARY...)",
                            },
                            {
                                id: "creationDay",
                                name: "Creation Day",
                                type: "category",
                                allowedValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"],
                                description: "Creation day",
                            },
                            {
                                id: "creationDayOfWeek",
                                name: "Creation Day Of Week",
                                type: "category",
                                allowedValues: ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
                                description: "Creation day of week (MONDAY, TUESDAY...)",
                            },
                            {
                                id: "status",
                                name: "Status",
                                type: "category",
                                allowedValues: ["PENDING", "QUEUED", "RUNNING", "DONE", "ERROR", "UNKNOWN", "ABORTED", "DELETED"],
                                description: "Status",
                            },
                            {
                                id: "release",
                                name: "Release",
                                type: "string",
                                description: "Release",
                            },
                            {
                                id: "toolId",
                                name: "Tool Id",
                                type: "string",
                                description: "Tool id",
                            },
                            {
                                id: "toolScope",
                                name: "Tool Scope",
                                type: "category",
                                allowedValues: ["GLOBAL", "PROJECT", "STUDY"],
                                description: "Tool scope",
                            },
                            {
                                id: "toolType",
                                name: "Tool Type",
                                type: "category",
                                allowedValues: ["OPERATION", "ANALYSIS"],
                                description: "Tool type",
                            },
                            {
                                id: "toolResource",
                                name: "Tool Resource",
                                type: "category",
                                allowedValues: ["USER", "PROJECT", "STUDY", "FILE", "SAMPLE", "JOB", "INDIVIDUAL", "COHORT", "DISEASE_PANEL",
                                    "FAMILY", "CLINICAL_ANALYSIS", "INTERPRETATION", "VARIANT", "ALIGNMENT", "CLINICAL", "EXPRESSION", "FUNCTIONAL"],
                                description: "Tool resource",
                            },
                            {
                                id: "userId",
                                name: "User Id",
                                type: "string",
                                description: "User id",
                            },
                            {
                                id: "priority",
                                name: "Priority",
                                type: "category",
                                allowedValues: ["URGENT", "HIGH", "MEDIUM", "LOW"],
                                description: "Priority",
                            },
                            {
                                id: "tags",
                                name: "Tags",
                                type: "string",
                                description: "Tags",
                            },
                            {
                                id: "executorId",
                                name: "Executor Id",
                                type: "string",
                                description: "Executor id",
                            },
                            {
                                id: "executorFramework",
                                name: "Executor Framework",
                                type: "string",
                                description: "Executor framework",
                            },
                        ],
                    },
                    {
                        name: "Advanced",
                        fields: [
                            {
                                id: "field",
                                name: "Field",
                                type: "string",
                                description: "List of fields separated by semicolons, e.g.: studies;type. For nested fields use >>, e.g.: studies>>biotype;type;numSamples[0..10]:1",
                            },
                        ],
                    },
                ],
            },
        };
    }

}

customElements.define("job-browser", JobBrowser);
<commit_msg>wc: sync filters<commit_after>/**
 * Copyright 2015-2019 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {LitElement, html} from "lit";
import UtilsNew from "../../core/utilsNew.js";
import "../commons/opencga-browser.js";
import "../commons/opencb-facet-results.js";
import "../commons/facet-filter.js";
import "./job-timeline.js";
import "./job-grid.js";
import "./job-detail.js";
import "./job-detail-log.js";
import "./job-view.js";

export default class JobBrowser extends LitElement {

    constructor() {
        super();

        // Set status and init private properties
        this._init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            opencgaSession: {
                type: Object,
            },
            query: {
                type: Object,
            },
            /* facetQuery: {
                type: Object
            },
            selectedFacet: {
                type: Object
            },*/
            settings: {
                type: Object,
            },
        };
    }

    _init() {
        this._config = this.getDefaultConfig();
    }

    // NOTE turn updated into update here reduces the number of remote requests from 2 to 1 as in the grid components propertyObserver()
    // is executed twice in case there is external settings
    update(changedProperties) {
        if (changedProperties.has("settings")) {
            this.settingsObserver();
        }

        super.update(changedProperties);
    }

    settingsObserver() {
        this._config = this.getDefaultConfig();
        // merge filter list, canned filters, detail tabs
        if (this.settings?.menu) {
            this._config.filter = UtilsNew.mergeFiltersAndDetails(this._config?.filter, this.settings);
        }
        if (this.settings?.table) {
            this._config.filter.result.grid = {...this._config.filter.result.grid, ...this.settings.table};
        }
        if (this.settings?.table?.toolbar) {
            this._config.filter.result.grid.toolbar = {...this._config.filter.result.grid.toolbar, ...this.settings.table.toolbar};
        }
    }

    render() {
        // No openCGA session available
        if (!this.opencgaSession) {
            return html`

No public projects available to browse. Please login to continue

            `;
        }

        return html`
            <opencga-browser
                resource="JOB"
                .opencgaSession="${this.opencgaSession}"
                .query="${this.query}"
                .config="${this._config}">
            </opencga-browser>
        `;
    }

    getDefaultConfig() {
        return {
            title: "Jobs Browser",
            icon: "fab fa-searchengin",
            description: "",
            views: [
                {
                    id: "table-tab",
                    name: "Table result",
                    icon: "fa fa-table",
                    active: true,
                    render: params => html`
                        <job-grid
                            .opencgaSession="${params.opencgaSession}"
                            .config="${params.config.filter.result.grid}"
                            .query="${params.executedQuery}"
                            .search="${params.executedQuery}"
                            .eventNotifyName="${params.eventNotifyName}"
                            .files="${params.files}"
                            @selectrow="${e => params.onClickRow(e, "job")}">
                        </job-grid>
                        <job-detail
                            .opencgaSession="${params.opencgaSession}"
                            .config="${params.config.filter.detail}"
                            .jobId="${params.detail.job?.id}">
                        </job-detail>
                    `,
                },
                {
                    id: "facet-tab",
                    name: "Aggregation stats",
                    icon: "fas fa-chart-bar",
                    render: params => html`
                        <opencb-facet-results
                            resource="${params.resource}"
                            .opencgaSession="${params.opencgaSession}"
                            .active="${params.active}"
                            .query="${params.facetQuery}"
                            .data="${params.facetResults}">
                        </opencb-facet-results>
                    `,
                },
                {
                    id: "visual-browser-tab",
                    name: "Visual browser",
                    render: params => html `
                        <jobs-timeline
                            .opencgaSession="${params.opencgaSession}"
                            .active="${params.active}"
                            .query="${params.executedQuery}">
                        </jobs-timeline>
                    `,
                },
            ],
            filter: {
                searchButton: false,
                sections: [
                    {
                        title: "Section title",
                        collapsed: false,
                        filters: [
                            {
                                id: "id",
                                name: "Job ID",
                                placeholder: "ID",
                                allowedValues: "",
                                defaultValue: "",
                                description: "",
                                fileUpload: false,
                            },
                            {
                                id: "tool",
                                name: "Analysis Tool ID",
                                placeholder: "Tool",
                                allowedValues: "",
                                defaultValue: "",
                                description: "",
                            },
                            {
                                id: "input",
                                name: "Input File Name",
                                placeholder: "e.g.  NA12877.vcf.gz",
                                allowedValues: "",
                                defaultValue: "",
                                description: "",
                                fileUpload: false,
                            },
                            {
                                id: "internalStatus",
                                name: "Status",
                                placeholder: "Status",
                                allowedValues: ["PENDING", "QUEUED", "RUNNING", "DONE", "ERROR", "UNKNOWN", "ABORTED", "DELETED"],
                                defaultValue: "",
                                description: "",
                            },
                            {
                                id: "priority",
                                name: "Priority",
                                placeholder: "Priority",
                                allowedValues: ["URGENT", "HIGH", "MEDIUM", "LOW"],
                                defaultValue: "",
                                description: "",
                            },
                            {
                                id: "tags",
                                name: "Tags",
                                placeholder: "Tags",
                                allowedValues: "",
                                defaultValue: "",
                                description: "",
                            },
                            {
                                id: "creationDate",
                                name: "Creation Date",
                                placeholder: "Creation Date",
                                description: "",
                            },
                            {
                                id: "visited",
                                name: "Visited",
                                placeholder: "Visited",
                                allowedValues: ["true", "false"],
                                defaultValue: "",
                                description: "",
                            },
                        ],
                    },
                ],
                examples: [
                    {
                        id: "Example 1 - Get VCF and BAM",
                        active: false,
                        query: {
                            format: "VCF,BAM",
                        },
                    },
                ],
                result: {
                    grid: {},
                },
                detail: {
                    title: "Job",
                    showTitle: true,
                    items: [
                        {
                            id: "job-view",
                            name: "Overview",
                            active: true,
                            render: (job, _active, opencgaSession) => html`
                                <job-view
                                    .opencgaSession="${opencgaSession}"
                                    mode="simple"
                                    .job="${job}">
                                </job-view>
                            `,
                        },
                        {
                            id: "job-log",
                            name: "Logs",
                            render: (job, active, opencgaSession) => html`
                                <job-detail-log
                                    .opencgaSession="${opencgaSession}"
                                    .active="${active}"
                                    .job="${job}">
                                </job-detail-log>
                            `,
                        },
                        {
                            id: "json-view",
                            name: "JSON Data",
                            mode: "development",
                            render: (job, active) => html`
                                <json-viewer
                                    .data="${job}"
                                    .active="${active}">
                                </json-viewer>
                            `,
                        },
                    ],
                },
            },
            aggregation: {
                default: ["creationYear>>creationMonth", "toolId>>executorId"],
                render: params => html `
                    <facet-filter
                        .config="${params.config.aggregation}"
                        .selectedFacet="${params.selectedFacet}"
                        @facetQueryChange="${params.onFacetQueryChange}">
                    </facet-filter>
                `,
                result: {
                    numColumns: 2,
                },
                sections: [
                    {
                        name: "Job attributes",
                        fields: [
                            {
                                id: "studyId",
                                name: "Study id",
                                type: "string",
                                description: "Study [[user@]project:]study where study and project can be either the ID or UUID",
                            },
                            {
                                id: "creationYear",
                                name: "Creation Year",
                                type: "string",
                                description: "Creation year",
                            },
                            {
                                id: "creationMonth",
                                name: "Creation Month",
                                type: "category",
                                allowedValues: ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"],
                                description: "Creation month (JANUARY, FEBRUARY...)",
                            },
                            {
                                id: "creationDay",
                                name: "Creation Day",
                                type: "category",
                                allowedValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"],
                                description: "Creation day",
                            },
                            {
                                id: "creationDayOfWeek",
                                name: "Creation Day Of Week",
                                type: "category",
                                allowedValues: ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
                                description: "Creation day of week (MONDAY, TUESDAY...)",
                            },
                            {
                                id: "status",
                                name: "Status",
                                type: "category",
                                allowedValues: ["PENDING", "QUEUED", "RUNNING", "DONE", "ERROR", "UNKNOWN", "ABORTED", "DELETED"],
                                description: "Status",
                            },
                            {
                                id: "release",
                                name: "Release",
                                type: "string",
                                description: "Release",
                            },
                            {
                                id: "toolId",
                                name: "Tool Id",
                                type: "string",
                                description: "Tool id",
                            },
                            {
                                id: "toolScope",
                                name: "Tool Scope",
                                type: "category",
                                allowedValues: ["GLOBAL", "PROJECT", "STUDY"],
                                description: "Tool scope",
                            },
                            {
                                id: "toolType",
                                name: "Tool Type",
                                type: "category",
                                allowedValues: ["OPERATION", "ANALYSIS"],
                                description: "Tool type",
                            },
                            {
                                id: "toolResource",
                                name: "Tool Resource",
                                type: "category",
                                allowedValues: ["USER", "PROJECT", "STUDY", "FILE", "SAMPLE", "JOB", "INDIVIDUAL", "COHORT", "DISEASE_PANEL",
                                    "FAMILY", "CLINICAL_ANALYSIS", "INTERPRETATION", "VARIANT", "ALIGNMENT", "CLINICAL", "EXPRESSION", "FUNCTIONAL"],
                                description: "Tool resource",
                            },
                            {
                                id: "userId",
                                name: "User Id",
                                type: "string",
                                description: "User id",
                            },
                            {
                                id: "priority",
                                name: "Priority",
                                type: "category",
                                allowedValues: ["URGENT", "HIGH", "MEDIUM", "LOW"],
                                description: "Priority",
                            },
                            {
                                id: "tags",
                                name: "Tags",
                                type: "string",
                                description: "Tags",
                            },
                            {
                                id: "executorId",
                                name: "Executor Id",
                                type: "string",
                                description: "Executor id",
                            },
                            {
                                id: "executorFramework",
                                name: "Executor Framework",
                                type: "string",
                                description: "Executor framework",
                            },
                        ],
                    },
                    {
                        name: "Advanced",
                        fields: [
                            {
                                id: "field",
                                name: "Field",
                                type: "string",
                                description: "List of fields separated by semicolons, e.g.: studies;type. For nested fields use >>, e.g.: studies>>biotype;type;numSamples[0..10]:1",
                            },
                        ],
                    },
                ],
            },
        };
    }

}

customElements.define("job-browser", JobBrowser);
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

var chalk = require('chalk');
var path = require('path');

function printRunInstructions(projectDir, projectName) {
  const absoluteProjectDir = path.resolve(projectDir);
  const relativeProjectDir = path.relative(process.cwd(), absoluteProjectDir);
  // If we're in the project directory already, no need to 'cd' into it
  const needToCd = !!relativeProjectDir;
  // iOS
  const xcodeProjectPath = path.resolve(projectDir, 'ios', projectName) + '.xcodeproj';
  const relativeXcodeProjectPath = path.relative(process.cwd(), xcodeProjectPath);
  console.log(chalk.white.bold('To run your app on iOS:'));
  if (needToCd) { console.log('   cd ' + relativeProjectDir); }
  console.log('   react-native run-ios');
  console.log('   - or -');
  console.log('   Open ' + relativeXcodeProjectPath + ' in Xcode');
  console.log('   Hit the Run button');
  // Android
  console.log(chalk.white.bold('To run your app on Android:'));
  console.log('   Have an Android emulator running (quickest way to get started), or a device connected');
  if (needToCd) { console.log('   cd ' + relativeProjectDir); }
  console.log('   react-native run-android');
}

module.exports = printRunInstructions;
<commit_msg>Fix instructions in 'react-native init'<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

var chalk = require('chalk');
var path = require('path');

function printRunInstructions(projectDir, projectName) {
  const absoluteProjectDir = path.resolve(projectDir);
  // iOS
  const xcodeProjectPath = path.resolve(projectDir, 'ios', projectName) + '.xcodeproj';
  const relativeXcodeProjectPath = path.relative(process.cwd(), xcodeProjectPath);
  console.log(chalk.white.bold('To run your app on iOS:'));
  console.log('   cd ' + absoluteProjectDir);
  console.log('   react-native run-ios');
  console.log('   - or -');
  console.log('   Open ' + relativeXcodeProjectPath + ' in Xcode');
  console.log('   Hit the Run button');
  // Android
  console.log(chalk.white.bold('To run your app on Android:'));
  console.log('   cd ' + absoluteProjectDir);
  console.log('   Have an Android emulator running (quickest way to get started), or a device connected');
  console.log('   react-native run-android');
}

module.exports = printRunInstructions;
<|endoftext|>