<commit_before>/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you 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.
 */

var exec      = require('cordova/exec'),
    ua        = navigator.userAgent.toLowerCase(),
    isAndroid = !window.Windows && ua.indexOf('android') > -1,
    mailto    = 'mailto:';

/**
 * List of all registered mail app aliases.
 */
exports.aliases = {
    gmail:   isAndroid ? 'com.google.android.gm' : 'googlegmail://co',
    outlook: isAndroid ? 'com.microsoft.office.outlook' : 'ms-outlook://compose'
};

/**
 * List of all available options with their default value.
 *
 * @return [ Object ]
 */
exports.getDefaults = function () {
    return {
        app:           mailto,
        subject:       '',
        body:          '',
        to:            [],
        cc:            [],
        bcc:           [],
        attachments:   [],
        isHtml:        true,
        chooserHeader: 'Open with'
    };
};

/**
 * Informs if the app has the needed permission.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.hasPermission = function(callback, scope) {
    var fn = this.createCallbackFn(callback, scope);

    if (!isAndroid) {
        if (fn) fn(true);
        return;
    }

    exec(fn, null, 'EmailComposer','hasPermission', []);
 };

/**
 * Request permission if not already granted.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.requestPermission = function(callback, scope) {
    var fn = this.createCallbackFn(callback, scope);

    if (!isAndroid) {
        if (fn) fn(true);
        return;
    }

    exec(fn, null, 'EmailComposer','requestPermission', []);
};

/**
 * Verifies if sending emails is supported on the device.
 *
 * @param [ String ]   app      An optional app id or uri scheme.
 *                              Defaults to mailto.
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.isAvailable = function (app, callback, scope) {

    if (typeof callback != 'function') {
        scope    = null;
        callback = app;
        app      = mailto;
    }

    var fn  = this.createCallbackFn(callback, scope);
        app = app || mailto;

    if (this.aliases.hasOwnProperty(app)) {
        app = this.aliases[app];
    }

    exec(fn, null, 'EmailComposer', 'isAvailable', [app]);
};

/**
 * Verifies if sending emails is supported on the device.
 *
 * @param [ String ]   app      An optional app id or uri scheme.
 *                              Defaults to mailto.
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.isAvailable2 = function (app, callback, scope) {

    if (typeof callback != 'function') {
        scope    = null;
        callback = app;
        app      = mailto;
    }

    var fn  = this.createCallbackFn(callback, scope), fn2;
        app = app || mailto;

    if (this.aliases.hasOwnProperty(app)) {
        app = this.aliases[app];
    }

    if (fn) {
        fn2 = function (a, b) { fn(b, a); };
    }

    exec(fn2, null, 'EmailComposer', 'isAvailable', [app]);
};

/**
 * Displays the email composer pre-filled with data.
 *
 * @param [ Object ]   options  The email properties like the body,...
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.open = function (options, callback, scope) {

    if (typeof options == 'function') {
        scope    = callback;
        callback = options;
        options  = {};
    }

    var fn      = this.createCallbackFn(callback, scope);
        options = this.mergeWithDefaults(options || {});

    if (!isAndroid && options.app != mailto && fn) {
        this.registerCallbackForScheme(fn);
    }

    exec(fn, null, 'EmailComposer', 'open', [options]);
};

/**
 * Adds a new mail app alias.
 *
 * @param [ String ] alias   The alias name.
 * @param [ String ] package The package name.
 *
 * @return [ Void ]
 */
exports.addAlias = function (alias, package) {
    this.aliases[alias] = package;
};

/**
 * Alias für `open()`.
 */
exports.openDraft = function () {
    this.open.apply(this, arguments);
};

/**
 * @private
 *
 * Merge settings with default values.
 *
 * @param [ Object ] options The custom options
 *
 * @retrun [ Object ] Default values merged with custom values.
 */
exports.mergeWithDefaults = function (options) {
    var defaults = this.getDefaults();

    if (options.hasOwnProperty('isHTML')) {
        options.isHtml = options.isHTML;
    }

    if (options.hasOwnProperty('app')) {
        var package = this.aliases[options.app];
        options.app = package || options.app;
    }

    for (var key in defaults) {

        if (!options.hasOwnProperty(key)) {
            options[key] = defaults[key];
            continue;
        }

        var custom_  = options[key],
            default_ = defaults[key];

        if (custom_ === null || custom_ === undefined) {
            options[key] = default_;
            continue;
        }

        if (typeof default_ == typeof custom_)
            continue;

        if (typeof default_ == 'string') {
            options[key] = custom_.join('');
        } else
        if (typeof default_ == 'object') {
            options[key] = [custom_.toString()];
        }
    }

    return options;
};

/**
 * @private
 *
 * Creates a callback, which will be executed
 * within a specific scope.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope for the function.
 *
 * @return [ Function ] The new callback function
 */
exports.createCallbackFn = function (callback, scope) {

    if (typeof callback != 'function')
        return;

    return function () {
        callback.apply(scope || this, arguments);
    };
};

/**
 * @private
 *
 * Register an Eventlistener on resume-Event to
 * execute callback after open a draft.
 *
 * @return [ Void ]
 */
exports.registerCallbackForScheme = function (fn) {

    var callback = function () {
        fn();
        document.removeEventListener('resume',callback);
    };

    document.addEventListener('resume', callback, false);
};
<commit_msg>Refactored mergeWithDefaults()<commit_after>/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you 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.
 */

var exec      = require('cordova/exec'),
    ua        = navigator.userAgent.toLowerCase(),
    isAndroid = !window.Windows && ua.indexOf('android') > -1,
    mailto    = 'mailto:';

/**
 * List of all registered mail app aliases.
 */
exports.aliases = {
    gmail:   isAndroid ? 'com.google.android.gm' : 'googlegmail://co',
    outlook: isAndroid ? 'com.microsoft.office.outlook' : 'ms-outlook://compose'
};

/**
 * List of all available options with their default value.
 *
 * @return [ Object ]
 */
exports.getDefaults = function () {
    return {
        app:           mailto,
        subject:       '',
        body:          '',
        to:            [],
        cc:            [],
        bcc:           [],
        attachments:   [],
        isHtml:        true,
        chooserHeader: 'Open with'
    };
};

/**
 * Informs if the app has the needed permission.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.hasPermission = function(callback, scope) {
    var fn = this.createCallbackFn(callback, scope);

    if (!isAndroid) {
        if (fn) fn(true);
        return;
    }

    exec(fn, null, 'EmailComposer','hasPermission', []);
 };

/**
 * Request permission if not already granted.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.requestPermission = function(callback, scope) {
    var fn = this.createCallbackFn(callback, scope);

    if (!isAndroid) {
        if (fn) fn(true);
        return;
    }

    exec(fn, null, 'EmailComposer','requestPermission', []);
};

/**
 * Verifies if sending emails is supported on the device.
 *
 * @param [ String ]   app      An optional app id or uri scheme.
 *                              Defaults to mailto.
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.isAvailable = function (app, callback, scope) {

    if (typeof callback != 'function') {
        scope    = null;
        callback = app;
        app      = mailto;
    }

    var fn  = this.createCallbackFn(callback, scope);
        app = app || mailto;

    if (this.aliases.hasOwnProperty(app)) {
        app = this.aliases[app];
    }

    exec(fn, null, 'EmailComposer', 'isAvailable', [app]);
};

/**
 * Verifies if sending emails is supported on the device.
 *
 * @param [ String ]   app      An optional app id or uri scheme.
 *                              Defaults to mailto.
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.isAvailable2 = function (app, callback, scope) {

    if (typeof callback != 'function') {
        scope    = null;
        callback = app;
        app      = mailto;
    }

    var fn  = this.createCallbackFn(callback, scope), fn2;
        app = app || mailto;

    if (this.aliases.hasOwnProperty(app)) {
        app = this.aliases[app];
    }

    if (fn) {
        fn2 = function (a, b) { fn(b, a); };
    }

    exec(fn2, null, 'EmailComposer', 'isAvailable', [app]);
};

/**
 * Displays the email composer pre-filled with data.
 *
 * @param [ Object ]   options  The email properties like the body,...
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope of the callback.
 *
 * @return [ Void ]
 */
exports.open = function (options, callback, scope) {

    if (typeof options == 'function') {
        scope    = callback;
        callback = options;
        options  = {};
    }

    var fn      = this.createCallbackFn(callback, scope);
        options = this.mergeWithDefaults(options || {});

    if (!isAndroid && options.app != mailto && fn) {
        this.registerCallbackForScheme(fn);
    }

    exec(fn, null, 'EmailComposer', 'open', [options]);
};

/**
 * Adds a new mail app alias.
 *
 * @param [ String ] alias   The alias name.
 * @param [ String ] package The package name.
 *
 * @return [ Void ]
 */
exports.addAlias = function (alias, package) {
    this.aliases[alias] = package;
};

/**
 * Alias für `open()`.
 */
exports.openDraft = function () {
    this.open.apply(this, arguments);
};

/**
 * @private
 *
 * Merge settings with default values.
 *
 * @param [ Object ] options The custom options
 *
 * @retrun [ Object ] Default values merged with custom values.
 */
exports.mergeWithDefaults = function (options) {
    var defaults = this.getDefaults();

    if (options.hasOwnProperty('isHTML')) {
        options.isHtml = options.isHTML;
    }

    if (!options.hasOwnProperty('isHtml')) {
        options.isHtml = defaults.isHtml;
    }

    if (options.hasOwnProperty('app')) {
        var package = this.aliases[options.app];
        options.app = package || options.app;
    }

    options.subject       = String(options.subject || defaults.subject);
    options.body          = String(options.body || defaults.body);
    options.chooserHeader = String(options.chooserHeader || defaults.chooserHeader);
    options.to            = options.to || defaults.to;
    options.cc            = options.cc || defaults.cc;
    options.bcc           = options.bcc || defaults.bcc;
    options.isHtml        = !!options.isHtml;

    if (!Array.isArray(options.to)) {
        options.to = [options.to];
    }

    if (!Array.isArray(options.cc)) {
        options.cc = [options.cc];
    }

    if (!Array.isArray(options.bcc)) {
        options.bcc = [options.bcc];
    }

    return options;
};

/**
 * @private
 *
 * Creates a callback, which will be executed
 * within a specific scope.
 *
 * @param [ Function ] callback The callback function.
 * @param [ Object ]   scope    The scope for the function.
 *
 * @return [ Function ] The new callback function
 */
exports.createCallbackFn = function (callback, scope) {

    if (typeof callback !== 'function')
        return;

    return function () {
        callback.apply(scope || this, arguments);
    };
};

/**
 * @private
 *
 * Register an Eventlistener on resume-Event to
 * execute callback after open a draft.
 *
 * @return [ Void ]
 */
exports.registerCallbackForScheme = function (fn) {

    var callback = function () {
        fn();
        document.removeEventListener('resume',callback);
    };

    document.addEventListener('resume', callback, false);
};
<|endoftext|>


<commit_before>#!/usr/bin/env node
// Alters the 'node_modules' to remove a C++ dependency of the API Blueprint
// parser before the 'npm pack' creates the package

const fs = require('fs');
const path = require('path');
const rimraf = require('rimraf');

const PACKAGE_DIR = path.resolve(path.dirname(__filename), '..');
const SYMLINKS_LOG = path.join(PACKAGE_DIR, 'prepack-symlinks.log');
const DRAFTER_PATH = path.join(PACKAGE_DIR, 'node_modules', 'drafter');

function readPackageJson(packageDir) {
  return JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')));
}

function writePackageJson(packageDir, packageData) {
  fs.writeFileSync(path.join(packageDir, 'package.json'), JSON.stringify(packageData, null, 2));
}

/**
 * Goes through the whole dependency tree of a given top-level dependency
 * and makes sure all packages involved are accessible in the local
 * 'node_modules' directory at least in form of symlinks.
 *
 * This is useful if the project uses yarn workspaces, but wants to publish
 * the package with npm and uses 'bundledDependencies'. 'npm pack' is not able
 * to find packages if they're put into the root 'node_modules' by yarn and
 * wouldn't be able to bundle them.
 *
 * @param {string} dependencyName Dependency tree root
 */
function symlinkDependencyTreeToLocalNodeModules(dependencyName) {
  const localDependencyPath = path.join(PACKAGE_DIR, 'node_modules', dependencyName);
  if (!fs.existsSync(localDependencyPath)) {
    fs.symlinkSync(`../../../node_modules/${dependencyName}`, localDependencyPath);
    fs.appendFileSync(SYMLINKS_LOG, `${dependencyName}\n`);
  }
  const packageData = readPackageJson(localDependencyPath);
  const dependencies = Object.keys(packageData.dependencies || {});
  dependencies.forEach(symlinkDependencyTreeToLocalNodeModules);
}

// make sure all bundled deps are accessible in the local 'node_modules' dir
const packageData = readPackageJson(PACKAGE_DIR, 'package.json');
const { bundledDependencies } = packageData;
bundledDependencies.forEach(symlinkDependencyTreeToLocalNodeModules);

// alter drafter's package.json so it doesn't depend on protagonist
const drafterPackageData = readPackageJson(DRAFTER_PATH);
delete drafterPackageData.dependencies.protagonist;
delete drafterPackageData.optionalDependencies.protagonist;
writePackageJson(DRAFTER_PATH, drafterPackageData);

// get rid of protagonist everywhere
[
  path.join(PACKAGE_DIR, 'node_modules', 'protagonist'),
  path.join(PACKAGE_DIR, '..', '..', 'node_modules', 'protagonist'),
]
  .filter(protagonistPath => fs.existsSync(protagonistPath))
  .forEach(protagonistPath => rimraf.sync(protagonistPath));
<commit_msg>fix: adjusts "readPackageJson" function call<commit_after>#!/usr/bin/env node
// Alters the 'node_modules' to remove a C++ dependency of the API Blueprint
// parser before the 'npm pack' creates the package

const fs = require('fs');
const path = require('path');
const rimraf = require('rimraf');

const PACKAGE_DIR = path.resolve(__dirname, '..');
const SYMLINKS_LOG = path.join(PACKAGE_DIR, 'prepack-symlinks.log');
const DRAFTER_PATH = path.join(PACKAGE_DIR, 'node_modules', 'drafter');

function readPackageJson(packageDir) {
  return JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json')));
}

function writePackageJson(packageDir, packageData) {
  fs.writeFileSync(path.join(packageDir, 'package.json'), JSON.stringify(packageData, null, 2));
}

/**
 * Goes through the whole dependency tree of a given top-level dependency
 * and makes sure all packages involved are accessible in the local
 * 'node_modules' directory at least in form of symlinks.
 *
 * This is useful if the project uses yarn workspaces, but wants to publish
 * the package with npm and uses 'bundledDependencies'. 'npm pack' is not able
 * to find packages if they're put into the root 'node_modules' by yarn and
 * wouldn't be able to bundle them.
 *
 * @param {string} dependencyName Dependency tree root
 */
function symlinkDependencyTreeToLocalNodeModules(dependencyName) {
  const localDependencyPath = path.join(PACKAGE_DIR, 'node_modules', dependencyName);
  if (!fs.existsSync(localDependencyPath)) {
    fs.symlinkSync(`../../../node_modules/${dependencyName}`, localDependencyPath);
    fs.appendFileSync(SYMLINKS_LOG, `${dependencyName}\n`);
  }
  const packageData = readPackageJson(localDependencyPath);
  const dependencies = Object.keys(packageData.dependencies || {});
  dependencies.forEach(symlinkDependencyTreeToLocalNodeModules);
}

// make sure all bundled deps are accessible in the local 'node_modules' dir
const packageData = readPackageJson(PACKAGE_DIR);
const { bundledDependencies } = packageData;
bundledDependencies.forEach(symlinkDependencyTreeToLocalNodeModules);

// alter drafter's package.json so it doesn't depend on protagonist
const drafterPackageData = readPackageJson(DRAFTER_PATH);
delete drafterPackageData.dependencies.protagonist;
delete drafterPackageData.optionalDependencies.protagonist;
writePackageJson(DRAFTER_PATH, drafterPackageData);

// get rid of protagonist everywhere
[
  path.join(PACKAGE_DIR, 'node_modules', 'protagonist'),
  path.join(PACKAGE_DIR, '..', '..', 'node_modules', 'protagonist'),
]
  .filter(protagonistPath => fs.existsSync(protagonistPath))
  .forEach(protagonistPath => rimraf.sync(protagonistPath));
<|endoftext|>


<commit_before>const qs = require('query-string');
const url = require('url');
const QuickLRU = require('quick-lru');
const _ = require('lodash');

const { fetch } = require('../../util');
const logger = require('../logger');
const config = require('../../config');
const { validatorGconvert } = require('./gprofiler');

const pcCache = new QuickLRU({ maxSize: config.PC_CACHE_MAX_SIZE });

const fetchOptions = {
  method: 'GET',
  headers: {
    'Accept': 'application/json'
  }
};

//Pathway Commons HTTP GET request; options.cmd = 'pc2/get', 'pc2/search', 'pc2/traverse', 'pc2/graph', etc.
let query = opts => {
  let queryOpts = _.assign( { user: 'app-ui', cmd: 'pc2/get' }, opts);
  let { cmd } = queryOpts;
  let url = config.PC_URL + cmd + '?' + qs.stringify( queryOpts );

  return fetch(url, fetchOptions)
    .then(res => ( cmd === 'pc2/get' || cmd === 'pc2/graph' ? res.text() : res.json() ) )
    .catch((e) => {
      logger.error('query ' + queryOpts + ' failed - ' + e);
      return null;
    });
};

let sanitize = s => {
  // Escape (with '\'), to treat them literally, symbols, such as '*', ':', or space,
  // which otherwise play special roles in a Lucene query string.
  return s.replace(/([!*+\-&|()[\]{}^~?:/\\"\s])/g, '\\$1');
};

// recognize biological entities from an input string
let extractEntityIds = inputString => {
  let tokens = inputString.split(' ');

  return validatorGconvert( tokens ).then( result => {
    let { unrecognized, alias  } = result;
    let entities = _.keys( alias ).map( initialAlias => 'xrefid:' + sanitize( initialAlias.toUpperCase() ) );

    let otherIds = unrecognized.map( id => {
      id = id.toUpperCase();
      let isChebiId = /^CHEBI:\d+$/.test( id );
      let isSmpdbId = /^SMP\d{5}$/.test( id );
      let recognized = isSmpdbId || isChebiId && ( id.length <= ("CHEBI:".length + 6) );
      let sanitized = sanitize(id);

      return recognized ? ( 'xrefid:' + sanitized ) : ( 'name:' + '*' + sanitized + '*' );
    });

    return entities.concat(otherIds);
  })
  .catch( e => {
    logger.error('unable to get response from gconvert with the following inputstring: ' + inputString);
    logger.error(e);
    return [];
  });
};

// generate three search query candidates: the first one is the fastest, the last - slowest
let generateSearchQueries = async inputString => {
  let phrase = sanitize( inputString );
  let entities = await extractEntityIds( inputString );
  return [
    '(name:' + phrase + ') OR (' + 'name:*' + phrase + '*) OR (' + entities.join(' AND ') + ')',
    '(' + entities.join(' OR ') + ')',
    inputString //"as is" (won't additionally escape Lucene query syntax, spaces, etc.)
  ];
};

// A fine-tuned PC search to improve relevance of full-text search and filter out unwanted hits.
// The argument (query object) has the following fields:
//  - q: user input - search query string
//  - type: BioPAX type to match/filter by
//  - lt: max graph size result returned
//  - gt: min graph size result returned
let search = async opts => {
  let { gt:minSize = 0, lt:maxSize = 250, q } = opts;
  let queryStrings = await generateSearchQueries( q.trim() );

  for( let queryString of queryStrings ) {
    let queryOpts = _.assign( opts, { cmd: 'pc2/search', q: queryString } );
    let searchResult = await query( queryOpts );
    let searchResults = _.get( searchResult, 'searchHit', []).filter( result => {
      let size = _.get( result, 'numParticipants', 0);

      return minSize < size && size < maxSize;
    });

    if ( searchResults.length > 0 ){
      return searchResults;
    }

  }

  return [];
};

const sifGraph = opts => {
  let hasMultipleSources = _.get(opts, 'source', []).length > 1;
  let sifGraphType = hasMultipleSources ? 'pathsbetween' : 'neighborhood';
  let queryOpts = Object.assign( {}, opts, {
    limit: 1,
    pattern: ['CONTROLS_STATE_CHANGE_OF','CONTROLS_TRANSPORT_OF','CONTROLS_EXPRESSION_OF','CATALYSIS_PRECEDES','INTERACTS_WITH'],
    directed: hasMultipleSources ? 'false' : undefined,
    direction: hasMultipleSources ? undefined : 'UNDIRECTED'
  });
  let url = config.PC_URL + 'sifgraph/v1/' + sifGraphType + '?' + qs.stringify( queryOpts );

  return fetch( url, { method: 'GET', headers: { 'Accept': 'text/plain' } } )
  .then( res => res.text() )
  .catch( e => {
    logger.error( 'sifGraph ' + opts + ' failed - ' + e );
    throw e;
  });
};

const handleEntityUriResponse = text => {
  const uri = new url.URL( text ); // Throws TypeError
  const pathParts = _.compact( uri.pathname.split('/') );
  if( _.isEmpty( pathParts ) || pathParts.length !== 2 ) throw new Error( 'Unrecognized URI' );
  const namespace = _.head( pathParts );
  return {
    origin: uri.origin,
    namespace
  };
};

const constructQueryPath = ( name, localId ) => {
  // Edge case - localId has periods e.g. 'enzyme nomenclature/6.1.1.5' gotta add a trailing slash
  const suffix = /\./.test( localId ) ? '/' : '';
  return name + '/' + localId + suffix;
};

/* fetchEntityUriBase
 * Light wrapper around the pc2 service to get the uri given a collection name and local ID for entity
 * http://www.pathwaycommons.org/pc2/swagger-ui.html#!/metadata45controller/identifierOrgUriUsingGET
 * NB: pc2 service returns 200 and empty body if collection name and/or local ID are unrecognized.
 *   If the local ID is empty, throws a 404
 * @return { object } the URL origin and namespace
 */
const fetchEntityUriBase = ( name, localId ) => {
  const url = config.PC_URL + 'pc2/miriam/uri/' + constructQueryPath( name, localId ) ;
  return fetch( url , { method: 'GET', headers: { 'Accept': 'text/plain' } })
    .then( res => res.text() )
    .then( handleEntityUriResponse );
};

const getEntityUriParts = ( name, localId ) => {
  if( pcCache.has( name ) ){
    return pcCache.get( name );
  } else {
    let res = fetchEntityUriBase( name, localId );
    pcCache.set( name, res );
    res.catch( err => {
      pcCache.del( name );
      logger.error(`Failed to fill cache with ${name} and ${localId} - ${err}`);
    });
    return res;
  }
};

/*
 * xref2Uri: Obtain the URI for an xref
 * @param {string} name -  MIRIAM 'name', 'synonym' ?OR MI CV database citation (MI:0444) 'label'
 * @param {string} localId - Entity local entity identifier, should be valid
 * @return {Object} return the origin and 'namespace' in path
 */
const xref2Uri =  ( name, localId ) => {
  return getEntityUriParts( name, localId )
    .then( uriParts => ({
      uri: uriParts.origin + '/' + uriParts.namespace + '/' + localId,
      namespace: uriParts.namespace
    }) );
};

module.exports = { query, search: _.memoize( search, query => JSON.stringify( query ) ), sifGraph, xref2Uri };<commit_msg>return luncene tokens instead of empty array for failed gconvert requests<commit_after>const qs = require('query-string');
const url = require('url');
const QuickLRU = require('quick-lru');
const _ = require('lodash');

const { fetch } = require('../../util');
const logger = require('../logger');
const config = require('../../config');
const { validatorGconvert } = require('./gprofiler');

const pcCache = new QuickLRU({ maxSize: config.PC_CACHE_MAX_SIZE });

const fetchOptions = {
  method: 'GET',
  headers: {
    'Accept': 'application/json'
  }
};

//Pathway Commons HTTP GET request; options.cmd = 'pc2/get', 'pc2/search', 'pc2/traverse', 'pc2/graph', etc.
let query = opts => {
  let queryOpts = _.assign( { user: 'app-ui', cmd: 'pc2/get' }, opts);
  let { cmd } = queryOpts;
  let url = config.PC_URL + cmd + '?' + qs.stringify( queryOpts );

  return fetch(url, fetchOptions)
    .then(res => ( cmd === 'pc2/get' || cmd === 'pc2/graph' ? res.text() : res.json() ) )
    .catch((e) => {
      logger.error('query ' + queryOpts + ' failed - ' + e);
      return null;
    });
};

let sanitize = s => {
  // Escape (with '\'), to treat them literally, symbols, such as '*', ':', or space,
  // which otherwise play special roles in a Lucene query string.
  return s.replace(/([!*+\-&|()[\]{}^~?:/\\"\s])/g, '\\$1');
};

// recognize biological entities from an input string
let extractEntityIds = inputString => {
  let tokens = inputString.split(' ');

  return validatorGconvert( tokens ).then( result => {
    let { unrecognized, alias  } = result;
    let entities = _.keys( alias ).map( initialAlias => 'xrefid:' + sanitize( initialAlias.toUpperCase() ) );

    let otherIds = unrecognized.map( id => {
      id = id.toUpperCase();
      let isChebiId = /^CHEBI:\d+$/.test( id );
      let isSmpdbId = /^SMP\d{5}$/.test( id );
      let recognized = isSmpdbId || isChebiId && ( id.length <= ("CHEBI:".length + 6) );
      let sanitized = sanitize(id);

      return recognized ? ( 'xrefid:' + sanitized ) : ( 'name:' + '*' + sanitized + '*' );
    });

    return entities.concat(otherIds);
  })
  .catch( e => {
    logger.error('unable to get response from gconvert with the following inputstring: ' + inputString);
    logger.error(e);
    // luncene each token in place of recognized entities
    return tokens.map( token => 'name:' + '*' + sanitize(token) + '*');
  });
};

// generate three search query candidates: the first one is the fastest, the last - slowest
let generateSearchQueries = async inputString => {
  let phrase = sanitize( inputString );
  let entities = await extractEntityIds( inputString );
  return [
    '(name:' + phrase + ') OR (' + 'name:*' + phrase + '*) OR (' + entities.join(' AND ') + ')',
    '(' + entities.join(' OR ') + ')',
    inputString //"as is" (won't additionally escape Lucene query syntax, spaces, etc.)
  ];
};

// A fine-tuned PC search to improve relevance of full-text search and filter out unwanted hits.
// The argument (query object) has the following fields:
//  - q: user input - search query string
//  - type: BioPAX type to match/filter by
//  - lt: max graph size result returned
//  - gt: min graph size result returned
let search = async opts => {
  let { gt:minSize = 0, lt:maxSize = 250, q } = opts;
  let queryStrings = await generateSearchQueries( q.trim() );

  for( let queryString of queryStrings ) {
    let queryOpts = _.assign( opts, { cmd: 'pc2/search', q: queryString } );
    let searchResult = await query( queryOpts );
    let searchResults = _.get( searchResult, 'searchHit', []).filter( result => {
      let size = _.get( result, 'numParticipants', 0);

      return minSize < size && size < maxSize;
    });

    if ( searchResults.length > 0 ){
      return searchResults;
    }

  }

  return [];
};

const sifGraph = opts => {
  let hasMultipleSources = _.get(opts, 'source', []).length > 1;
  let sifGraphType = hasMultipleSources ? 'pathsbetween' : 'neighborhood';
  let queryOpts = Object.assign( {}, opts, {
    limit: 1,
    pattern: ['CONTROLS_STATE_CHANGE_OF','CONTROLS_TRANSPORT_OF','CONTROLS_EXPRESSION_OF','CATALYSIS_PRECEDES','INTERACTS_WITH'],
    directed: hasMultipleSources ? 'false' : undefined,
    direction: hasMultipleSources ? undefined : 'UNDIRECTED'
  });
  let url = config.PC_URL + 'sifgraph/v1/' + sifGraphType + '?' + qs.stringify( queryOpts );

  return fetch( url, { method: 'GET', headers: { 'Accept': 'text/plain' } } )
  .then( res => res.text() )
  .catch( e => {
    logger.error( 'sifGraph ' + opts + ' failed - ' + e );
    throw e;
  });
};

const handleEntityUriResponse = text => {
  const uri = new url.URL( text ); // Throws TypeError
  const pathParts = _.compact( uri.pathname.split('/') );
  if( _.isEmpty( pathParts ) || pathParts.length !== 2 ) throw new Error( 'Unrecognized URI' );
  const namespace = _.head( pathParts );
  return {
    origin: uri.origin,
    namespace
  };
};

const constructQueryPath = ( name, localId ) => {
  // Edge case - localId has periods e.g. 'enzyme nomenclature/6.1.1.5' gotta add a trailing slash
  const suffix = /\./.test( localId ) ? '/' : '';
  return name + '/' + localId + suffix;
};

/* fetchEntityUriBase
 * Light wrapper around the pc2 service to get the uri given a collection name and local ID for entity
 * http://www.pathwaycommons.org/pc2/swagger-ui.html#!/metadata45controller/identifierOrgUriUsingGET
 * NB: pc2 service returns 200 and empty body if collection name and/or local ID are unrecognized.
 *   If the local ID is empty, throws a 404
 * @return { object } the URL origin and namespace
 */
const fetchEntityUriBase = ( name, localId ) => {
  const url = config.PC_URL + 'pc2/miriam/uri/' + constructQueryPath( name, localId ) ;
  return fetch( url , { method: 'GET', headers: { 'Accept': 'text/plain' } })
    .then( res => res.text() )
    .then( handleEntityUriResponse );
};

const getEntityUriParts = ( name, localId ) => {
  if( pcCache.has( name ) ){
    return pcCache.get( name );
  } else {
    let res = fetchEntityUriBase( name, localId );
    pcCache.set( name, res );
    res.catch( err => {
      pcCache.del( name );
      logger.error(`Failed to fill cache with ${name} and ${localId} - ${err}`);
    });
    return res;
  }
};

/*
 * xref2Uri: Obtain the URI for an xref
 * @param {string} name -  MIRIAM 'name', 'synonym' ?OR MI CV database citation (MI:0444) 'label'
 * @param {string} localId - Entity local entity identifier, should be valid
 * @return {Object} return the origin and 'namespace' in path
 */
const xref2Uri =  ( name, localId ) => {
  return getEntityUriParts( name, localId )
    .then( uriParts => ({
      uri: uriParts.origin + '/' + uriParts.namespace + '/' + localId,
      namespace: uriParts.namespace
    }) );
};

module.exports = { query, search: _.memoize( search, query => JSON.stringify( query ) ), sifGraph, xref2Uri };<|endoftext|>


<commit_before>var app = angular.module('project_questions', ['formgroup']);

// customizations for Django integration
app.config(['$httpProvider', '$interpolateProvider', '$locationProvider', function($httpProvider, $interpolateProvider, $locationProvider) {
    // use {$ and $} as tags for angular
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');

    // set Django's CSRF Cookie and Header
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

    // set the $location to not use #
    $locationProvider.html5Mode(true);
}]);

app.directive('input', function() {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
            if (attrs.type === 'checkbox') {
                ngModel.$parsers.push(function(val) {
                    var values = [];
                    if (ngModel.$modelValue) {
                        values = ngModel.$modelValue.split(',');
                    }

                    var index = values.indexOf(attrs.value);

                    if (val === true && index === -1) {
                        values.push(attrs.value);
                    } else if (val === false && index !== -1) {
                        values.splice(index, 1);
                    }

                    return values.sort().join(',');
                });
                ngModel.$formatters.push(function(val) {
                    if (angular.isDefined(val) && val.split(',').indexOf(attrs.value) !== -1) {
                        return true;
                    } else {
                        return false;
                    }

                });
            } else if (attrs.type === 'range') {
                ngModel.$parsers.push(function(val) {
                    var min = parseFloat(attrs.minValue),
                        max = parseFloat(attrs.maxValue);

                    return 0.01 * (max - min) * (parseFloat(val) + min);
                });
                ngModel.$formatters.push(function(val) {
                    var min = parseFloat(attrs.minValue),
                        max = parseFloat(attrs.maxValue);

                    return 100.0 / (max - min) * (parseFloat(val) + min);
                });
            }
        }
    };
});

app.factory('QuestionsService', ['$http', '$timeout', '$location', function($http, $timeout, $location) {

    service = {};

    /* private varilables */

    var baseurl = angular.element('meta[name="baseurl"]').attr('content');

    var urls = {
        'projects': baseurl + 'api/projects/projects/',
        'value_entities': baseurl + 'api/projects/entities/',
        'values': baseurl + 'api/projects/values/',
        'valuesets': baseurl + 'api/projects/valuesets/',
        'question_entities': baseurl + 'api/questions/entities/'
    };

    /* private methods */

    function valueFactory() {
        return {
            'text': ''
        };
    }

    function valueSetFactory() {
        var values = {};
        angular.forEach(service.questions, function(question, index) {
            values[question.attribute.id] = [valueFactory()];
        });

        return {
            'values': values,
        };
    }

    function fetchQuestionEntity(entity_id) {
        var url = urls.question_entities;
        if (entity_id) {
            url += entity_id + '/';
        } else {
            url += 'first/?catalog=' + service.project.catalog;
        }

        $http.get(url).success(function(response) {
            service.entity = response;

            if (service.entity.is_set) {
                service.questions = service.entity.questions;
            } else {
                service.questions = [service.entity];
            }

            $location.path('/' + service.entity.id + '/');

            fetchValueEntities();
        });
    }

    function fetchValueEntities() {

        service.values = {};

        var params = {
            snapshot: service.project.current_snapshot
        };
        if (service.entity.is_set) {
            params.valueset__attributeset = service.entity.attributeset.id;
        } else {
            params.value__attribute = service.entity.attribute.id;
        }

        $http.get(urls.value_entities, {'params': params}).success(function(response) {

            if (service.entity.is_set) {
                // store response from server or create new valuesets array
                if (response.length > 0) {
                    service.valuesets = response;

                    angular.forEach(service.valuesets, function(valueset, index) {
                        var values_array = valueset.values;

                        valueset.values = {};
                        angular.forEach(service.entity.questions, function(question, index) {
                            valueset.values[question.attribute.id] = [];
                        });

                        angular.forEach(values_array, function(value, index) {
                            valueset.values[value.attribute].push(value);
                        });

                        angular.forEach(service.entity.questions, function(question, index) {
                            if (valueset.values[question.attribute.id].length === 0) {
                                valueset.values[question.attribute.id].push(valueFactory());
                            }
                        });
                    });

                } else {
                    service.valuesets = [valueSetFactory()];
                }

                service.values = service.valuesets[0].values;

            } else {
                // store response from server or create new values array
                if (response.length > 0) {
                    service.values[service.entity.attribute.id] = response;
                } else {
                    service.values[service.entity.attribute.id] = [valueFactory()];
                }
            }

            $timeout(function() {
                $('.datepicker').datetimepicker({
                    format: 'YYYY-MM-DD'
                }).on('dp.change', function () {
                    $('.datepicker input').trigger('input');
                });
            });
        });
    }

    function storeValues(valueset) {
        if (angular.isDefined(valueset)) {
            values = valueset.values;
        } else {
            values = service.values;
        }

        angular.forEach(service.questions, function(question) {
            angular.forEach(values[question.attribute.id], function(value, index) {
                if (value.removed) {
                    // delete the value if it alredy exists on the server
                    if (angular.isDefined(value.id)) {
                        $http.delete(urls.values + value.id + '/');
                    }
                } else {
                    // store the current index in the list
                    value.index = index;
                    value.attribute = question.attribute.id;
                    value.snapshot = service.project.current_snapshot;

                    if (angular.isDefined(valueset)) {
                        value.valueset = valueset.id;
                    }

                    if (angular.isDefined(value.id)) {
                        // update an existing value
                        $http.put(urls.values + value.id + '/', value).success(function(response) {
                            angular.extend(value, response);
                        });
                    } else {
                        // update a new value
                        $http.post(urls.values, value).success(function(response) {
                            angular.extend(value, response);
                        });
                    }
                }
            });
        });
    }

    function storeValueSets() {
        angular.forEach(service.valuesets, function(valueset, index) {
            if (valueset.removed) {
                // delete the valueset
                if (angular.isDefined(valueset.id)) {
                    $http.delete(urls.valuesets + valueset.id + '/').success(function(response) {
                        // delete all the values or the valueset
                        angular.forEach(valueset.values, function(values) {
                            angular.forEach(values, function(value) {
                                $http.delete(urls.values + value.id + '/');
                            });
                        });
                    });
                }
            } else {
                // store the current index in the list
                valueset.index = index;
                valueset.attributeset = service.entity.attributeset.id;
                valueset.snapshot = service.project.current_snapshot;

                if (angular.isDefined(valueset.id)) {
                    // update an existing valueset
                    $http.put(urls.valuesets + valueset.id + '/', valueset).success(function(response) {
                        // update the local valueset with the response from the server
                        angular.extend(valueset, response);

                        // // store values for this valueset
                        storeValues(valueset);
                    });
                } else {
                    // create a new valueset
                    $http.post(urls.valuesets, valueset).success(function(response) {
                        // update the local valueset with the response from the server
                        angular.extend(valueset, response);

                        // // store values for this valueset
                        storeValues(valueset);
                    });
                }
            }
        });
    }

    /* public methods */

    service.init = function(project_id) {

        $http.get(urls.projects + project_id + '/').success(function(response) {
            service.project = response;
            fetchQuestionEntity($location.path().replace(/\//g,''));
        });

    };

    service.prev = function() {
        if (service.entity.prev !== null) {
            fetchQuestionEntity(service.entity.prev);
        }
    };

    service.next = function() {
        if (service.entity.next !== null) {
            fetchQuestionEntity(service.entity.next);
        }
    };

    service.save = function(proceed) {
        if (service.entity.is_set) {
            storeValueSets();
        } else {
            storeValues();
        }

        if (angular.isDefined(proceed) && proceed) {
            service.next();
        }
    };

    service.addValue = function(attribute_id) {
        //  add new value to service.values
        if (angular.isUndefined(service.values[attribute_id])) {
            service.values[attribute_id] = [valueFactory()];
        } else {
            service.values[attribute_id].push(valueFactory());
        }
    };

    service.removeValue = function(attribute_id, index) {
        service.values[attribute_id][index].removed = true;
    };

    service.addValueSet = function() {
        // create a new valueset
        var valueset = valueSetFactory();

        // append the new valueset to the array of valuesets
        service.valuesets.push(valueset);

        // 'activate' the new valueset
        service.values = valueset.values;
    };

    service.removeValueSet = function() {
        // find current valueset, flag it for removal, and activate the one before
        for (var i = 0; i < service.valuesets.length; i++) {

            if (service.valuesets[i].values === service.values) {
                service.valuesets[i].removed = true;
                if (angular.isDefined(service.valuesets[i-1])) {
                    service.values = service.valuesets[i-1].values;
                } else if (angular.isDefined(service.valuesets[i+1])) {
                    service.values = service.valuesets[i+1].values;
                } else {
                    service.values = {};
                }
                break;
            }
        }
    };

    return service;

}]);

app.controller('QuestionsController', ['$scope', 'QuestionsService', function($scope, QuestionsService) {

    $scope.service = QuestionsService;

}]);
<commit_msg>fix valueset init<commit_after>var app = angular.module('project_questions', ['formgroup']);

// customizations for Django integration
app.config(['$httpProvider', '$interpolateProvider', '$locationProvider', function($httpProvider, $interpolateProvider, $locationProvider) {
    // use {$ and $} as tags for angular
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');

    // set Django's CSRF Cookie and Header
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

    // set the $location to not use #
    $locationProvider.html5Mode(true);
}]);

app.directive('input', function() {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
            if (attrs.type === 'checkbox') {
                ngModel.$parsers.push(function(val) {
                    var values = [];
                    if (ngModel.$modelValue) {
                        values = ngModel.$modelValue.split(',');
                    }

                    var index = values.indexOf(attrs.value);

                    if (val === true && index === -1) {
                        values.push(attrs.value);
                    } else if (val === false && index !== -1) {
                        values.splice(index, 1);
                    }

                    return values.sort().join(',');
                });
                ngModel.$formatters.push(function(val) {
                    if (angular.isDefined(val) && val.split(',').indexOf(attrs.value) !== -1) {
                        return true;
                    } else {
                        return false;
                    }

                });
            } else if (attrs.type === 'range') {
                ngModel.$parsers.push(function(val) {
                    var min = parseFloat(attrs.minValue),
                        max = parseFloat(attrs.maxValue);

                    return 0.01 * (max - min) * (parseFloat(val) + min);
                });
                ngModel.$formatters.push(function(val) {
                    var min = parseFloat(attrs.minValue),
                        max = parseFloat(attrs.maxValue);

                    return 100.0 / (max - min) * (parseFloat(val) + min);
                });
            }
        }
    };
});

app.factory('QuestionsService', ['$http', '$timeout', '$location', function($http, $timeout, $location) {

    service = {};

    /* private varilables */

    var baseurl = angular.element('meta[name="baseurl"]').attr('content');

    var urls = {
        'projects': baseurl + 'api/projects/projects/',
        'value_entities': baseurl + 'api/projects/entities/',
        'values': baseurl + 'api/projects/values/',
        'valuesets': baseurl + 'api/projects/valuesets/',
        'question_entities': baseurl + 'api/questions/entities/'
    };

    /* private methods */

    function valueFactory() {
        return {
            'text': ''
        };
    }

    function valueSetFactory() {
        var values = {};
        angular.forEach(service.questions, function(question, index) {
            values[question.attribute.id] = [valueFactory()];
        });

        return {
            'values': values,
        };
    }

    function fetchQuestionEntity(entity_id) {
        var url = urls.question_entities;
        if (entity_id) {
            url += entity_id + '/';
        } else {
            url += 'first/?catalog=' + service.project.catalog;
        }

        $http.get(url).success(function(response) {
            service.entity = response;

            if (service.entity.is_set) {
                service.questions = service.entity.questions;
            } else {
                service.questions = [service.entity];
            }

            $location.path('/' + service.entity.id + '/');

            fetchValueEntities();
        });
    }

    function fetchValueEntities() {

        service.values = {};

        var params = {
            snapshot: service.project.current_snapshot
        };
        if (service.entity.is_set) {
            params.valueset__attributeset = service.entity.attributeset.id;
        } else {
            params.value__attribute = service.entity.attribute.id;
        }

        $http.get(urls.value_entities, {'params': params}).success(function(response) {

            if (service.entity.is_set) {
                // store response from server or create new valuesets array
                if (response.length > 0) {
                    service.valuesets = response;

                    angular.forEach(service.valuesets, function(valueset, index) {
                        var values_array = valueset.values;

                        valueset.values = {};
                        angular.forEach(service.entity.questions, function(question, index) {
                            valueset.values[question.attribute.id] = [];
                        });

                        angular.forEach(values_array, function(value, index) {
                            if (angular.isDefined(valueset.values[value.attribute])) {
                                valueset.values[value.attribute].push(value);
                            }
                        });

                        angular.forEach(service.entity.questions, function(question, index) {
                            if (valueset.values[question.attribute.id].length === 0) {
                                valueset.values[question.attribute.id].push(valueFactory());
                            }
                        });
                    });

                } else {
                    service.valuesets = [valueSetFactory()];
                }

                service.values = service.valuesets[0].values;

            } else {
                // store response from server or create new values array
                if (response.length > 0) {
                    service.values[service.entity.attribute.id] = response;
                } else {
                    service.values[service.entity.attribute.id] = [valueFactory()];
                }
            }

            $timeout(function() {
                $('.datepicker').datetimepicker({
                    format: 'YYYY-MM-DD'
                }).on('dp.change', function () {
                    $('.datepicker input').trigger('input');
                });
            });
        });
    }

    function storeValues(valueset) {
        if (angular.isDefined(valueset)) {
            values = valueset.values;
        } else {
            values = service.values;
        }

        angular.forEach(service.questions, function(question) {
            angular.forEach(values[question.attribute.id], function(value, index) {
                if (value.removed) {
                    // delete the value if it alredy exists on the server
                    if (angular.isDefined(value.id)) {
                        $http.delete(urls.values + value.id + '/');
                    }
                } else {
                    // store the current index in the list
                    value.index = index;
                    value.attribute = question.attribute.id;
                    value.snapshot = service.project.current_snapshot;

                    if (angular.isDefined(valueset)) {
                        value.valueset = valueset.id;
                    }

                    if (angular.isDefined(value.id)) {
                        // update an existing value
                        $http.put(urls.values + value.id + '/', value).success(function(response) {
                            angular.extend(value, response);
                        });
                    } else {
                        // update a new value
                        $http.post(urls.values, value).success(function(response) {
                            angular.extend(value, response);
                        });
                    }
                }
            });
        });
    }

    function storeValueSets() {
        angular.forEach(service.valuesets, function(valueset, index) {
            if (valueset.removed) {
                // delete the valueset
                if (angular.isDefined(valueset.id)) {
                    $http.delete(urls.valuesets + valueset.id + '/').success(function(response) {
                        // delete all the values or the valueset
                        angular.forEach(valueset.values, function(values) {
                            angular.forEach(values, function(value) {
                                $http.delete(urls.values + value.id + '/');
                            });
                        });
                    });
                }
            } else {
                // store the current index in the list
                valueset.index = index;
                valueset.attributeset = service.entity.attributeset.id;
                valueset.snapshot = service.project.current_snapshot;

                if (angular.isDefined(valueset.id)) {
                    // update an existing valueset
                    $http.put(urls.valuesets + valueset.id + '/', valueset).success(function(response) {
                        // update the local valueset with the response from the server
                        angular.extend(valueset, response);

                        // // store values for this valueset
                        storeValues(valueset);
                    });
                } else {
                    // create a new valueset
                    $http.post(urls.valuesets, valueset).success(function(response) {
                        // update the local valueset with the response from the server
                        angular.extend(valueset, response);

                        // // store values for this valueset
                        storeValues(valueset);
                    });
                }
            }
        });
    }

    /* public methods */

    service.init = function(project_id) {

        $http.get(urls.projects + project_id + '/').success(function(response) {
            service.project = response;
            fetchQuestionEntity($location.path().replace(/\//g,''));
        });

    };

    service.prev = function() {
        if (service.entity.prev !== null) {
            fetchQuestionEntity(service.entity.prev);
        }
    };

    service.next = function() {
        if (service.entity.next !== null) {
            fetchQuestionEntity(service.entity.next);
        }
    };

    service.save = function(proceed) {
        if (service.entity.is_set) {
            storeValueSets();
        } else {
            storeValues();
        }

        if (angular.isDefined(proceed) && proceed) {
            service.next();
        }
    };

    service.addValue = function(attribute_id) {
        //  add new value to service.values
        if (angular.isUndefined(service.values[attribute_id])) {
            service.values[attribute_id] = [valueFactory()];
        } else {
            service.values[attribute_id].push(valueFactory());
        }
    };

    service.removeValue = function(attribute_id, index) {
        service.values[attribute_id][index].removed = true;
    };

    service.addValueSet = function() {
        // create a new valueset
        var valueset = valueSetFactory();

        // append the new valueset to the array of valuesets
        service.valuesets.push(valueset);

        // 'activate' the new valueset
        service.values = valueset.values;
    };

    service.removeValueSet = function() {
        // find current valueset, flag it for removal, and activate the one before
        for (var i = 0; i < service.valuesets.length; i++) {

            if (service.valuesets[i].values === service.values) {
                service.valuesets[i].removed = true;
                if (angular.isDefined(service.valuesets[i-1])) {
                    service.values = service.valuesets[i-1].values;
                } else if (angular.isDefined(service.valuesets[i+1])) {
                    service.values = service.valuesets[i+1].values;
                } else {
                    service.values = {};
                }
                break;
            }
        }
    };

    return service;

}]);

app.controller('QuestionsController', ['$scope', 'QuestionsService', function($scope, QuestionsService) {

    $scope.service = QuestionsService;

}]);
<|endoftext|>


<commit_before>angular.module('starter.controllers', ['starter.factory', 'hljs', 'starter.utils'])

  .controller('AppCtrl', function ($scope) {
  })

  .controller('AboutCtrl', function ($scope, $analytics) {
    $analytics.trackView('About Ctrl');
    $scope.isApp = window.cordova !== undefined;
  })

  .controller('skillTreeControl', function ($scope, $storageServices, $ionicModal, $analytics, $window) {
    var format = d3.format(",d"),
      color = d3.scale.category20c();

    console.log($window.innerWidth, $window.innerHeight);
    var bubble = d3.layout.pack()
      .sort(null)
      .size([$window.innerWidth, $window.innerHeight])
      .padding(1);

    var svg = d3.select("#skill").append("svg")
      .attr("width", $window.innerWidth)
      .attr("height", $window.innerHeight)
      .attr("class", "bubble");

    d3.json("assets/flare.json", function(error, root) {
      if (error) throw error;

      var node = svg.selectAll(".node")
        .data(bubble.nodes(classes(root))
          .filter(function(d) { return !d.children; }))
        .enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

      node.append("title")
        .text(function(d) { return d.className + ": " + format(d.value); });

      node.append("circle")
        .attr("r", function(d) { return d.r; })
        .style("fill", function(d) { return color(d.packageName); });

      node.append("text")
        .attr("dy", ".3em")
        .style("text-anchor", "middle")
        .text(function(d) { return d.className.substring(0, d.r / 3); });
    });

    function classes(root) {
      var classes = [];

      function recurse(name, node) {
        if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
        else classes.push({packageName: name, className: node.name, value: node.size});
      }

      recurse(null, root);
      return {children: classes};
    }

    d3.select(self.frameElement).style("height", $window.innerHeight + "px");

    $analytics.trackView('Skill Tree List');

    $scope.ratings = 0;
    $scope.isInfinite = false;
    $scope.learnedSkills = [];
    $scope.modal = null;

    $scope.openSkillsModal = function () {
      $analytics.trackView('All Skills');

      $ionicModal.fromTemplateUrl('templates/skills/skills.html', {
        id: 'skills',
        scope: $scope,
        animation: 'slide-in-up'
      }).then(function (modal) {
        modal.show();
        $scope.modal = modal;
      });
    };

    $scope.closeSkillsModal = function () {
      $scope.modal.hide();
    };

    $scope.$on('$ionicView.enter', function () {
      angular.forEach(AllSkills, function (skills) {
        angular.forEach(skills, function (skill) {
          $storageServices.get(skill.text, function (result) {
            var rating = parseInt(result);

            if (rating) {
              $scope.ratings = $scope.ratings + rating;
              if (rating >= 3) {
                $scope.learnedSkills.push({
                  skill: skill.text,
                  rating: rating
                });
              }
              if ($scope.ratings > 100) {
                $scope.isInfinite = true;
              }
            }
          })
        });
      });
    });
  })

  .controller('FeedbackCtrl', function ($scope, $http, $cordovaEmailComposer) {
    $scope.issues = [];
    $http.get('https://api.github.com/repos/phodal/growth/issues').then(function (response) {
      $scope.issues = response.data;
    });

    $scope.OpenIssue = function (url) {
      window.open(url, '_system', 'location=yes');
    };

    if (window.cordova) {
      $scope.sendMail = function () {
        $cordovaEmailComposer.isAvailable().then(function () {
        }, function () {
        });
        var email = {to: 'h@phodal.com', subject: '关于《Growth Ren》', body: '', isHtml: true};
        $cordovaEmailComposer.open(email).then(null, function () {
        });
      }
    }
  })

  .controller('ArticleCtrl', function ($scope, $sce, $stateParams, $http, $ionicLoading, marked, $filter, $analytics) {
    $analytics.trackView('Article Detail');

    $ionicLoading.show({
      animation: 'fade-in',
      template: 'Loading...'
    });
    $http({
      method: 'GET',
      url: 'article/' + $stateParams.slug + '.md'
    }).success(function (response) {
      $ionicLoading.hide();
      $scope.EditArticle = function () {
        window.open('https://github.com/phodal/growth/edit/master/www/article/' + $stateParams.slug + '.md', '_system', 'location=yes');
      };
      $scope.title = $filter('filter')(AllArticle, {"slug": $stateParams.slug})[0].title;
      $scope.htmlContent = $sce.trustAsHtml(marked(response))
    }).error(function (data, status) {
      alert(data + status);
    });
  })

  .controller('ArticleListCtrl', function ($scope, $analytics) {
    $analytics.trackView('Article List');
    $scope.articles = AllArticle;
  });
<commit_msg>build simple skill bublle<commit_after>angular.module('starter.controllers', ['starter.factory', 'hljs', 'starter.utils'])

  .controller('AppCtrl', function ($scope) {
  })

  .controller('AboutCtrl', function ($scope, $analytics) {
    $analytics.trackView('About Ctrl');
    $scope.isApp = window.cordova !== undefined;
  })

  .controller('skillTreeControl', function ($scope, $storageServices, $ionicModal, $analytics, $window) {
    $analytics.trackView('Skill Tree List');

    $scope.ratings = 0;
    $scope.isInfinite = false;
    $scope.learnedSkills = [];
    $scope.modal = null;

    $scope.openSkillsModal = function () {
      $analytics.trackView('All Skills');

      $ionicModal.fromTemplateUrl('templates/skills/skills.html', {
        id: 'skills',
        scope: $scope,
        animation: 'slide-in-up'
      }).then(function (modal) {
        modal.show();
        $scope.modal = modal;
      });
    };

    $scope.closeSkillsModal = function () {
      $scope.modal.hide();
    };

    $scope.$on('$ionicView.enter', function () {
      $scope.flare = {
        "name": "skill tree",
        "children": []
      };
      angular.forEach(AllSkills, function (skills, index) {
        var skillFlare = {
          "name": index,
          "children": []
        };
        angular.forEach(skills, function (skill) {
          $storageServices.get(skill.text, function (result) {
            var rating = parseInt(result);

            if (rating) {
              skillFlare.children.push({
                "name": skill.text,
                "size": rating
              });
              $scope.ratings = $scope.ratings + rating;
              if (rating >= 3) {
                $scope.learnedSkills.push({
                  skill: skill.text,
                  rating: rating
                });
              }
              if ($scope.ratings > 100) {
                $scope.isInfinite = true;
              }
            }
          })
        });
        $scope.flare.children.push(skillFlare);
      });
      console.log($scope.flare);

      var format = d3.format(",d"),
        color = d3.scale.category20c();

      var bubble = d3.layout.pack()
        .sort(null)
        .size([$window.innerWidth, $window.innerHeight])
        .padding(1);

      var svg = d3.select("#skill").append("svg")
        .attr("width", $window.innerWidth)
        .attr("height", $window.innerHeight)
        .attr("class", "bubble");

      var node = svg.selectAll(".node")
        .data(bubble.nodes(classes($scope.flare))
          .filter(function(d) { return !d.children; }))
        .enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

      node.append("title")
        .text(function(d) { return d.className + ": " + format(d.value); });

      node.append("circle")
        .attr("r", function(d) { return d.r; })
        .style("fill", function(d) { return color(d.packageName); });

      node.append("text")
        .attr("dy", ".3em")
        .style("text-anchor", "middle")
        .text(function(d) { return d.className.substring(0, d.r / 3); });

      function classes(root) {
        var classes = [];

        function recurse(name, node) {
          if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
          else classes.push({packageName: name, className: node.name, value: node.size});
        }

        recurse(null, root);
        return {children: classes};
      }

      d3.select(self.frameElement).style("height", $window.innerHeight + "px");
    });
  })

  .controller('FeedbackCtrl', function ($scope, $http, $cordovaEmailComposer) {
    $scope.issues = [];
    $http.get('https://api.github.com/repos/phodal/growth/issues').then(function (response) {
      $scope.issues = response.data;
    });

    $scope.OpenIssue = function (url) {
      window.open(url, '_system', 'location=yes');
    };

    if (window.cordova) {
      $scope.sendMail = function () {
        $cordovaEmailComposer.isAvailable().then(function () {
        }, function () {
        });
        var email = {to: 'h@phodal.com', subject: '关于《Growth Ren》', body: '', isHtml: true};
        $cordovaEmailComposer.open(email).then(null, function () {
        });
      }
    }
  })

  .controller('ArticleCtrl', function ($scope, $sce, $stateParams, $http, $ionicLoading, marked, $filter, $analytics) {
    $analytics.trackView('Article Detail');

    $ionicLoading.show({
      animation: 'fade-in',
      template: 'Loading...'
    });
    $http({
      method: 'GET',
      url: 'article/' + $stateParams.slug + '.md'
    }).success(function (response) {
      $ionicLoading.hide();
      $scope.EditArticle = function () {
        window.open('https://github.com/phodal/growth/edit/master/www/article/' + $stateParams.slug + '.md', '_system', 'location=yes');
      };
      $scope.title = $filter('filter')(AllArticle, {"slug": $stateParams.slug})[0].title;
      $scope.htmlContent = $sce.trustAsHtml(marked(response))
    }).error(function (data, status) {
      alert(data + status);
    });
  })

  .controller('ArticleListCtrl', function ($scope, $analytics) {
    $analytics.trackView('Article List');
    $scope.articles = AllArticle;
  });
<|endoftext|>


<commit_before>import { assert } from 'ember-metal/debug';
import { get } from 'ember-metal/property_get';
import { set } from 'ember-metal/property_set';
import {
  addObserver,
  removeObserver
} from 'ember-metal/observer';
import BasicStream from 'ember-metal/streams/stream';
import { isStream  } from 'ember-metal/streams/utils';

let KeyStream = BasicStream.extend({
  init(source, key) {
    assert('KeyStream error: source must be a stream', isStream(source)); // TODO: This isn't necessary.
    assert('KeyStream error: key must be a non-empty string', typeof key === 'string' && key.length > 0);
    assert('KeyStream error: key must not have a \'.\'', key.indexOf('.') === -1);

    var label = labelFor(source, key);

    this.path = label;
    this.observedObject = null;
    this.key = key;
    this.sourceDep = this.addMutableDependency(source);
    this.label = label;
  },

  compute() {
    let object = this.sourceDep.getValue();
    let type = typeof object;

    if (!object || type === 'boolean') {
      return;
    }

    if (type === 'object') {
      return get(object, this.key);
    }

    return object[this.key];
  },

  setValue(value) {
    var object = this.sourceDep.getValue();
    if (object) {
      set(object, this.key, value);
    }
  },

  setSource(source) {
    this.sourceDep.replace(source);
    this.notify();
  },

  _super$revalidate: BasicStream.prototype.revalidate,

  revalidate(value) {
    this._super$revalidate(value);

    var object = this.sourceDep.getValue();
    if (object !== this.observedObject) {
      this._clearObservedObject();

      if (object && typeof object === 'object') {
        addObserver(object, this.key, this, this.notify);
        this.observedObject = object;
      }
    }
  },

  _super$deactivate: BasicStream.prototype.deactivate,

  _clearObservedObject() {
    if (this.observedObject) {
      removeObserver(this.observedObject, this.key, this, this.notify);
      this.observedObject = null;
    }
  },

  deactivate() {
    this._super$deactivate();
    this._clearObservedObject();
  }
});

function labelFor(source, key) {
  return source.label ? source.label + '.' + key : key;
}

export default KeyStream;
<commit_msg>export default at definition so it is clearer<commit_after>import { assert } from 'ember-metal/debug';
import { get } from 'ember-metal/property_get';
import { set } from 'ember-metal/property_set';
import {
  addObserver,
  removeObserver
} from 'ember-metal/observer';
import BasicStream from 'ember-metal/streams/stream';
import { isStream  } from 'ember-metal/streams/utils';

function labelFor(source, key) {
  return source.label ? source.label + '.' + key : key;
}

export default BasicStream.extend({
  init(source, key) {
    assert('KeyStream error: source must be a stream', isStream(source)); // TODO: This isn't necessary.
    assert('KeyStream error: key must be a non-empty string', typeof key === 'string' && key.length > 0);
    assert('KeyStream error: key must not have a \'.\'', key.indexOf('.') === -1);

    var label = labelFor(source, key);

    this.path = label;
    this.observedObject = null;
    this.key = key;
    this.sourceDep = this.addMutableDependency(source);
    this.label = label;
  },

  compute() {
    let object = this.sourceDep.getValue();
    let type = typeof object;

    if (!object || type === 'boolean') {
      return;
    }

    if (type === 'object') {
      return get(object, this.key);
    }

    return object[this.key];
  },

  setValue(value) {
    var object = this.sourceDep.getValue();
    if (object) {
      set(object, this.key, value);
    }
  },

  setSource(source) {
    this.sourceDep.replace(source);
    this.notify();
  },

  _super$revalidate: BasicStream.prototype.revalidate,

  revalidate(value) {
    this._super$revalidate(value);

    var object = this.sourceDep.getValue();
    if (object !== this.observedObject) {
      this._clearObservedObject();

      if (object && typeof object === 'object') {
        addObserver(object, this.key, this, this.notify);
        this.observedObject = object;
      }
    }
  },

  _super$deactivate: BasicStream.prototype.deactivate,

  _clearObservedObject() {
    if (this.observedObject) {
      removeObserver(this.observedObject, this.key, this, this.notify);
      this.observedObject = null;
    }
  },

  deactivate() {
    this._super$deactivate();
    this._clearObservedObject();
  }
});
<|endoftext|>


<commit_before>angular.module('starter.controllers', ['ngCordova'])

.controller('AppCtrl', function($scope, $ionicModal, $timeout, $state, mySocket, $cordovaDevice) {
  // Form data for the login modal
  $scope.loginData = {};

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  },

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };

  $scope.changeState = function(state) {
    $state.go(state);
  };

  $scope.joinMultiplayer = function(username) {
    $state.go('app.multiplayer');
    mySocket.emit('matchmaking', {c: {uuid: getMyUUID(), name: username},  m: 'join'});
  };

  getMyUUID = function() {
    /*if($cordovaDevice.getDevice() == null) {
      return $cordovaDevice.getUUID();
    } else {
      return null;
    }*/
    return Date.now(); //Debug code for browser
  };

  mySocket.on('data', function(data) {
    console.log(data);

    switch(data.m) {
      case "updateRoom":
        console.log("UPDATE ROOM");
        break;
    }
  });

})

.controller('MultiCtrl', function($scope, $state, mySocket, $cordovaDevice, $cordovaVibration, twerkometer) {

  var myUUID = getMyUUID();
  var myUUDI = 1234;
  var playerReady = false;
  var countdownTimer;
  var matchInterval;

  $scope.leaveMultiplayer = function() {
    mySocket.emit('matchmaking', {m: 'leave'});
    $state.go('app.play');
  };

  $scope.readyCheck = function() {
    if(playerReady) {
      $scope.emitMessageData("unready");
      playerReady = false;
    } else {
      $scope.emitMessageData("ready");
      playerReady = true;
    }
  };

  $scope.startCountdown = function() {
    countdownTimer = setInterval(function() {
      $scope.countdown--;
      if($scope.countdown == 0) {
        clearInterval(countdownTimer);

        twerkometer.callback = function() {
          $scope.emitTwerkData(Math.random() * 450 + 50, Math.random * 100 + 20);
        };

        matchInterval = setInterval(function() {
          $scope.duration--;
          if($scope.duration == 0) {
            clearInterval(matchInterval);
            mySocket.emit('leave', {c: $scope.currentRoomID});
            $state.go('app.play');
          }
        }, 1000);
      }
    }, 1000);
  };

  $scope.emitTwerkData = function(t, tpm) {
    mySocket.emit('data', {c: {roomId: $scope.currentRoomID}, m:{twerk: {t: t, tpm: tpm, uuid: myUUID}}} );
  };

  $scope.emitMessageData = function(data) {
    mySocket.emit('data', {c: {roomId: $scope.currentRoomID}, m: data});
  };

  mySocket.on('data', function(data) {
    console.log(data);

    switch(data.m) {
      case "startMatch":
        console.log("START MATCH");
        $scope.countdown = data.c.countdown;
        $scope.duration = data.c.duration;
        $scope.startCountdown();
        break;
    }
  });

  mySocket.on('matchmaking', function(data) {
    console.log(data);

    switch(data.m) {
      case "joinRoom":
        console.log("JOIN ROOM: " + data.c.roomId);
        $scope.currentRoomID = data.c.roomId;
        $scope.roomJoined = true;
        break;
    }
  });

  mySocket.on('err', function(data) {
    console.log(data);
  });
})

.controller('GeoCtrl', function ($scope, $ionicLoading, $compile, $cordovaGeolocation) {
  $scope.info = "balasasd";
   function initialize() {
      $cordovaGeolocation.getCurrentPosition().then(function(position) {
            // Position here: position.coords.latitude, position.coords.longitude

          var myLatlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

          var mapOptions = {
            center: myLatlng,
            zoom: 16,
            mapTypeId: google.maps.MapTypeId.ROADMAP
          };
          var map = new google.maps.Map(document.getElementById("map"),
              mapOptions);

          //Marker + infowindow + angularjs compiled ng-click
          var contentString = "
Click me!
";
          var compiled = $compile(contentString)($scope);

          var infowindow = new google.maps.InfoWindow({
            content: compiled[0]
          });

          var marker = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: 'Uluru (Ayers Rock)'
          });

          google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
          });

          $scope.map = map;
        }, function(err) {
          // error
        });
      }
      //google.maps.event.addDomListener(window, 'load', initialize);
      initialize();

      $scope.centerOnMe = function() {
        if(!$scope.map) {
          return;
        }

        $scope.loading = $ionicLoading.show({
          content: 'Getting current location...',
          showBackdrop: false
        });

        $cordovaGeolocation.getCurrentPosition().then(function(pos) {
          $scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
          $ionicLoading.hide();
        }, function(error) {
          alert('Unable to get location: ' + error.message);
        });
      };

      $scope.clickTest = function() {
        alert('Example of infowindow with ng-click')
      };
})

.controller('SinglePlayerCtrl', function($scope, $cordovaDialogs, $cordovaDeviceMotion, $cordovaVibration, twerkometer) {

  $scope.twerks = 0;

  twerkometer.callback = function(message) {
    $scope.twerks++;
    $scope.$apply();
    $cordovaVibration.vibrate(50);
  }

});
<commit_msg>apply some shizz!<commit_after>angular.module('starter.controllers', ['ngCordova'])

.controller('AppCtrl', function($scope, $ionicModal, $timeout, $state, mySocket, $cordovaDevice) {
  // Form data for the login modal
  $scope.loginData = {};

  // Create the login modal that we will use later
  $ionicModal.fromTemplateUrl('templates/login.html', {
    scope: $scope
  }).then(function(modal) {
    $scope.modal = modal;
  });

  // Triggered in the login modal to close it
  $scope.closeLogin = function() {
    $scope.modal.hide();
  },

  // Open the login modal
  $scope.login = function() {
    $scope.modal.show();
  };

  // Perform the login action when the user submits the login form
  $scope.doLogin = function() {
    console.log('Doing login', $scope.loginData);

    // Simulate a login delay. Remove this and replace with your login
    // code if using a login system
    $timeout(function() {
      $scope.closeLogin();
    }, 1000);
  };

  $scope.changeState = function(state) {
    $state.go(state);
  };

  $scope.joinMultiplayer = function(username) {
    $state.go('app.multiplayer');
    mySocket.emit('matchmaking', {c: {uuid: getMyUUID(), name: username},  m: 'join'});
  };

  getMyUUID = function() {
    /*if($cordovaDevice.getDevice() == null) {
      return $cordovaDevice.getUUID();
    } else {
      return null;
    }*/
    return Date.now(); //Debug code for browser
  };

  mySocket.on('data', function(data) {
    console.log(data);

    switch(data.m) {
      case "updateRoom":
        console.log("UPDATE ROOM");
        break;
    }
  });

})

.controller('MultiCtrl', function($scope, $state, mySocket, $cordovaDevice, $cordovaVibration, twerkometer) {

  var myUUID = getMyUUID();
  var myUUDI = 1234;
  var playerReady = false;
  var countdownTimer;
  var matchInterval;

  $scope.leaveMultiplayer = function() {
    mySocket.emit('matchmaking', {m: 'leave'});
    $state.go('app.play');
  };

  $scope.readyCheck = function() {
    if(playerReady) {
      $scope.emitMessageData("unready");
      playerReady = false;
    } else {
      $scope.emitMessageData("ready");
      playerReady = true;
    }
  };

  $scope.startCountdown = function() {
    countdownTimer = setInterval(function() {
      $scope.countdown--;
      if($scope.countdown == 0) {
        clearInterval(countdownTimer);

        twerkometer.callback = function() {
          $scope.emitTwerkData(Math.random() * 450 + 50, Math.random * 100 + 20);
        };

        $scope.$apply();

        matchInterval = setInterval(function() {
          $scope.duration--;
          if($scope.duration == 0) {
            clearInterval(matchInterval);
            mySocket.emit('leave', {c: $scope.currentRoomID});
            $state.go('app.play');
          }
        }, 1000);
      }
    }, 1000);
  };

  $scope.emitTwerkData = function(t, tpm) {
    mySocket.emit('data', {c: {roomId: $scope.currentRoomID}, m:{twerk: {t: t, tpm: tpm, uuid: myUUID}}} );
  };

  $scope.emitMessageData = function(data) {
    mySocket.emit('data', {c: {roomId: $scope.currentRoomID}, m: data});
  };

  mySocket.on('data', function(data) {
    console.log(data);

    switch(data.m) {
      case "startMatch":
        console.log("START MATCH");
        $scope.countdown = data.c.countdown;
        $scope.duration = data.c.duration;
        $scope.startCountdown();
        break;
    }
  });

  mySocket.on('matchmaking', function(data) {
    console.log(data);

    switch(data.m) {
      case "joinRoom":
        console.log("JOIN ROOM: " + data.c.roomId);
        $scope.currentRoomID = data.c.roomId;
        $scope.roomJoined = true;
        break;
    }
  });

  mySocket.on('err', function(data) {
    console.log(data);
  });
})

.controller('GeoCtrl', function ($scope, $ionicLoading, $compile, $cordovaGeolocation) {
  $scope.info = "balasasd";
   function initialize() {
      $cordovaGeolocation.getCurrentPosition().then(function(position) {
            // Position here: position.coords.latitude, position.coords.longitude

          var myLatlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

          var mapOptions = {
            center: myLatlng,
            zoom: 16,
            mapTypeId: google.maps.MapTypeId.ROADMAP
          };
          var map = new google.maps.Map(document.getElementById("map"),
              mapOptions);

          //Marker + infowindow + angularjs compiled ng-click
          var contentString = "
Click me!
";
          var compiled = $compile(contentString)($scope);

          var infowindow = new google.maps.InfoWindow({
            content: compiled[0]
          });

          var marker = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: 'Uluru (Ayers Rock)'
          });

          google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
          });

          $scope.map = map;
        }, function(err) {
          // error
        });
      }
      //google.maps.event.addDomListener(window, 'load', initialize);
      initialize();

      $scope.centerOnMe = function() {
        if(!$scope.map) {
          return;
        }

        $scope.loading = $ionicLoading.show({
          content: 'Getting current location...',
          showBackdrop: false
        });

        $cordovaGeolocation.getCurrentPosition().then(function(pos) {
          $scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
          $ionicLoading.hide();
        }, function(error) {
          alert('Unable to get location: ' + error.message);
        });
      };

      $scope.clickTest = function() {
        alert('Example of infowindow with ng-click')
      };
})

.controller('SinglePlayerCtrl', function($scope, $cordovaDialogs, $cordovaDeviceMotion, $cordovaVibration, twerkometer) {

  $scope.twerks = 0;

  twerkometer.callback = function(message) {
    $scope.twerks++;
    $scope.$apply();
    $cordovaVibration.vibrate(50);
  }

});
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import { DateTime } from 'luxon';
import { format } from 'date-fns';
import { DateTimePicker } from '@voussoir/ui/src/primitives/forms';
import type { FilterProps } from '../../../types';

type Props = FilterProps<string>;

type State = {
  date: string,
  time: string,
  offset: string,
};

export default class CalendarDayFilterView extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    const value = DateTime.fromJSDate(new Date());
    const dt = DateTime.fromISO(value, { setZone: true });
    this.state = {
      date: value && dt.toFormat('yyyy-LL-dd'),
      time: value && dt.toFormat('HH:mm:ss.SSS'),
      offset: value && dt.toFormat('ZZ'),
    };
  }

  handleDayChange = (day: Date) => {
    const { onChange } = this.props;
    const newState = { ...this.state, date: format(day, 'YYYY-MM-DD') };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  handleTimeChange = (event: Object) => {
    const { onChange } = this.props;
    const newState = { ...this.state, time: event.target.value };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  handleOffsetChange = (event: Object) => {
    const { onChange } = this.props;
    const newState = { ...this.state, offset: event.value };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  componentDidUpdate(prevProps: Props) {
    const { filter } = this.props;

    if (prevProps.filter !== filter) {
      this.props.recalcHeight();
    }
  }

  render() {
    const { filter, field } = this.props;

    if (!filter) return null;

    const { date, time, offset } = this.state;
    const { handleDayChange, handleTimeChange, handleOffsetChange } = this;
    const { yearRangeFrom,  yearRangeTo, yearPickerType } = field.config;

    return (
      <DateTimePicker
        htmlID="calendar-day-filter"
        {...this.props}
        {...{
          date,
          time,
          offset,
          handleDayChange,
          handleTimeChange,
          handleOffsetChange,
          yearRangeFrom,
          yearRangeTo,
          yearPickerType
        }}
      />
    );
  }
}
<commit_msg>Prettier<commit_after>// @flow

import React, { Component } from 'react';
import { DateTime } from 'luxon';
import { format } from 'date-fns';
import { DateTimePicker } from '@voussoir/ui/src/primitives/forms';
import type { FilterProps } from '../../../types';

type Props = FilterProps<string>;

type State = {
  date: string,
  time: string,
  offset: string,
};

export default class CalendarDayFilterView extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    const value = DateTime.fromJSDate(new Date());
    const dt = DateTime.fromISO(value, { setZone: true });
    this.state = {
      date: value && dt.toFormat('yyyy-LL-dd'),
      time: value && dt.toFormat('HH:mm:ss.SSS'),
      offset: value && dt.toFormat('ZZ'),
    };
  }

  handleDayChange = (day: Date) => {
    const { onChange } = this.props;
    const newState = { ...this.state, date: format(day, 'YYYY-MM-DD') };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  handleTimeChange = (event: Object) => {
    const { onChange } = this.props;
    const newState = { ...this.state, time: event.target.value };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  handleOffsetChange = (event: Object) => {
    const { onChange } = this.props;
    const newState = { ...this.state, offset: event.value };
    onChange(`${newState.date}T${newState.time}${newState.offset}`);
    this.setState(newState);
  };

  componentDidUpdate(prevProps: Props) {
    const { filter } = this.props;

    if (prevProps.filter !== filter) {
      this.props.recalcHeight();
    }
  }

  render() {
    const { filter, field } = this.props;

    if (!filter) return null;

    const { date, time, offset } = this.state;
    const { handleDayChange, handleTimeChange, handleOffsetChange } = this;
    const { yearRangeFrom, yearRangeTo, yearPickerType } = field.config;

    return (
      <DateTimePicker
        htmlID="calendar-day-filter"
        {...this.props}
        {...{
          date,
          time,
          offset,
          handleDayChange,
          handleTimeChange,
          handleOffsetChange,
          yearRangeFrom,
          yearRangeTo,
          yearPickerType,
        }}
      />
    );
  }
}
<|endoftext|>


<commit_before>angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope, $state, WarningService) {

  $scope.warning = {
    id_contact_type: 3,
    browser: "android",
    operating_system: "android",
    device: "android",
    raw: "android",
    warning_resp: {},
    enableName: false,
    ip: "android",
    lang_key: "pt-br"
  };

  $scope.data = {
    sms: "",
    whatsapp: "",
    email: ""
  };

  var listContactType = WarningService.getContactTypes();
  listContactType.then(function(result) {
    if (result) {
		    $scope.contact_types = result;
		    //$scope.warning.id_message = $routeParams.id_message*1;
    }
  });

  var listMessage = WarningService.getMessages($scope.warning.lang_key);
  listMessage.then(function(result) {
    if (result) {
		    $scope.messages = result;
		    //$scope.warning.id_message = $routeParams.id_message*1;
    }
  });

  $scope.send = function(){

			$scope.warning.created_date = new Date();
			$scope.warning.timezone = (new Date()).getTimezoneOffset()+"";

			var warnService = WarningService.send($scope.warning);
			warnService.then(function(data) {
  			$scope.handleServerResponse(data);
        	}, function(error) {
  	       $scope.error = error;
	    });
    	$scope.error = null;

	};

  $scope.handleServerResponse = function (data){

			$scope.error = null;

			$scope.invalid_facebook = null;
			$scope.email_error = null;
			$scope.invalid_phone_number = null;
			$scope.invalid_ddd = null;
			$scope.server_msg_danger = null;
			$scope.server_msg_sucess = null;

			switch(data.id){
				case 200:

					$scope.server_msg_danger = null;
					$scope.server_msg_sucess = data.name;
	                $scope.warning.id_message = null;
	                $scope.warning.contact = null;
	                $scope.sms = null;
	                $scope.email = null;
	                $scope.facebook = null;

				break;

				default:
					$scope.server_msg_danger = data.name;
					$scope.server_msg_sucess = null;
				break;

			}
		};

    $scope.$watch('data.sms', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });

    $scope.$watch('data.whatsapp', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });

    $scope.$watch('data.email', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });

})

.controller('ChatsCtrl', function($scope, Chats) {
  // With the new view caching in Ionic, Controllers are only called
  // when they are recreated or on app start, instead of every page change.
  // To listen for when this page is active (for example, to refresh data),
  // listen for the $ionicView.enter event:
  //
  //$scope.$on('$ionicView.enter', function(e) {
  //});

  $scope.chats = Chats.all();
  $scope.remove = function(chat) {
    Chats.remove(chat);
  }
})

.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
  $scope.chat = Chats.get($stateParams.chatId);
})

.controller('AccountCtrl', function($scope, $translate) {

  $scope.settings = {
    lang_key: 'pt-br'
  };

  $scope.$watch('settings.lang_key', function(value, oldValue, scope) {
    $translate.use(String(value));
  });

});
<commit_msg>get mssages when change translate<commit_after>angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope, $rootScope, $state, WarningService) {

  $scope.warning = {
    id_contact_type: 3,
    browser: "android",
    operating_system: "android",
    device: "android",
    raw: "android",
    warning_resp: {},
    enableName: false,
    ip: "android",
    lang_key: "pt-br"
  };

  $scope.data = {
    sms: "",
    whatsapp: "",
    email: ""
  };

  var listContactType = WarningService.getContactTypes();
  listContactType.then(function(result) {
    if (result) {
		    $rootScope.contact_types = result;
		    //$scope.warning.id_message = $routeParams.id_message*1;
    }
  });

  var listMessage = WarningService.getMessages($scope.warning.lang_key);
  listMessage.then(function(result) {
    if (result) {
		    $rootScope.messages = result;
		    //$scope.warning.id_message = $routeParams.id_message*1;
    }
  });

  $scope.send = function(){

			$scope.warning.created_date = new Date();
			$scope.warning.timezone = (new Date()).getTimezoneOffset()+"";

			var warnService = WarningService.send($scope.warning);
			warnService.then(function(data) {
  			$scope.handleServerResponse(data);
        	}, function(error) {
  	       $scope.error = error;
	    });
    	$scope.error = null;

	};

  $scope.handleServerResponse = function (data){

			$scope.error = null;

			$scope.invalid_facebook = null;
			$scope.email_error = null;
			$scope.invalid_phone_number = null;
			$scope.invalid_ddd = null;
			$scope.server_msg_danger = null;
			$scope.server_msg_sucess = null;

			switch(data.id){
				case 200:

					$scope.server_msg_danger = null;
					$scope.server_msg_sucess = data.name;
	                $scope.warning.id_message = null;
	                $scope.warning.contact = null;
	                $scope.sms = null;
	                $scope.email = null;
	                $scope.facebook = null;

				break;

				default:
					$scope.server_msg_danger = data.name;
					$scope.server_msg_sucess = null;
				break;

			}
		};

    $scope.$watch('data.sms', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });

    $scope.$watch('data.whatsapp', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });

    $scope.$watch('data.email', function(value, oldValue, scope) {
      $scope.warning.contact = String(value);
    });
})

.controller('ChatsCtrl', function($scope, Chats) {
  // With the new view caching in Ionic, Controllers are only called
  // when they are recreated or on app start, instead of every page change.
  // To listen for when this page is active (for example, to refresh data),
  // listen for the $ionicView.enter event:
  //
  //$scope.$on('$ionicView.enter', function(e) {
  //});

  $scope.chats = Chats.all();
  $scope.remove = function(chat) {
    Chats.remove(chat);
  }
})

.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
  $scope.chat = Chats.get($stateParams.chatId);
})

.controller('AccountCtrl', function($scope, $rootScope, $translate, WarningService) {

  $scope.settings = {
    lang_key: 'pt-br'
  };

  $scope.$watch('settings.lang_key', function(value, oldValue, scope) {
    var lang_key = String(value);
    $translate.use(lang_key);
    var listMessage = WarningService.getMessages(lang_key);
    listMessage.then(function(result) {
      if (result) {
          $rootScope.messages = result;
          //$scope.warning.id_message = $routeParams.id_message*1;
      }
    });
  });

});
<|endoftext|>