<commit_before>import NodePatcher from './NodePatcher.js';
import type { Editor, Node, ParseContext, Token } from './types.js';

export default class SwitchCasePatcher extends NodePatcher {
  constructor(node: Node, context: ParseContext, editor: Editor, conditions: NodePatcher, consequent: NodePatcher) {
    super(node, context, editor);
    this.conditions = conditions;
    this.consequent = consequent;
  }

  patchAsStatement() {
    // `when a, b, c then d` → `a, b, c then d`
    //  ^^^^^
    let whenToken = this.getWhenToken();
    this.remove(whenToken.range[0], this.conditions[0].start);

    // `a, b, c then d` → `a b c then d`
    //   ^  ^
    this.getCommaTokens().forEach((comma) => {
      this.remove(...comma.range);
    });

    this.conditions.forEach((condition) => {
      // `a b c then d` → `case a: case b: case c: then d`
      //                   ^^^^^ ^^^^^^^ ^^^^^^^ ^
      condition.insertBefore('case ');
      condition.patch({ leftBrace: false, rightBrace: false });
      condition.insertAfter(':');
    });

    // `case a: case b: case c: then d → `case a: case b: case c: d`
    //                          ^^^^^
    let thenToken = this.getThenToken();
    if (thenToken) {
      this.remove(thenToken.range[0], this.consequent.start);
    }

    this.consequent.patch({ leftBrace: false, rightBrace: false });

    if (!this.getBreakToken() && !this.implicitlyReturns()) {
      if (thenToken) {
        // `case a: case b: case c: then d → `case a: case b: case c: d break`
        //                                                             ^^^^^^
        this.consequent.insertAfter(' break');
      } else {
        this.appendLineAfter('break', 1);
      }
    }
  }

  setImplicitlyReturns() {
    super.setImplicitlyReturns();
    this.consequent.setImplicitlyReturns();
  }

  patchAsExpression() {
    this.patchAsStatement();
  }

  negate() {
    this.conditions.forEach(condition => condition.negate());
  }

  /**
   * @private
   */
  getWhenToken(): ?Token {
    return this.tokens.find(token => token.type === 'LEADING_WHEN');
  }

  /**
   * @private
   */
  getCommaTokens(): Array<Token> {
    return this.tokens.filter(token => token.type === ',');
  }

  /**
   * @private
   */
  getBreakToken(): ?Token {
    return this.tokens.find(token => token.type === 'STATEMENT' && token.data === 'break');
  }

  /**
   * Gets the token representing the `then` between condition and consequent.
   *
   * @private
   */
  getThenToken(): ?Token {
    return this.tokenBetweenPatchersMatching(this.conditions[0], this.consequent, 'THEN');
  }

}
<commit_msg>Fix type signature for `SwitchCasePatcher` constructor.<commit_after>import NodePatcher from './NodePatcher.js';
import type { Editor, Node, ParseContext, Token } from './types.js';

export default class SwitchCasePatcher extends NodePatcher {
  constructor(node: Node, context: ParseContext, editor: Editor, conditions: Array<NodePatcher>, consequent: NodePatcher) {
    super(node, context, editor);
    this.conditions = conditions;
    this.consequent = consequent;
  }

  patchAsStatement() {
    // `when a, b, c then d` → `a, b, c then d`
    //  ^^^^^
    let whenToken = this.getWhenToken();
    this.remove(whenToken.range[0], this.conditions[0].start);

    // `a, b, c then d` → `a b c then d`
    //   ^  ^
    this.getCommaTokens().forEach((comma) => {
      this.remove(...comma.range);
    });

    this.conditions.forEach((condition) => {
      // `a b c then d` → `case a: case b: case c: then d`
      //                   ^^^^^ ^^^^^^^ ^^^^^^^ ^
      condition.insertBefore('case ');
      condition.patch({ leftBrace: false, rightBrace: false });
      condition.insertAfter(':');
    });

    // `case a: case b: case c: then d → `case a: case b: case c: d`
    //                          ^^^^^
    let thenToken = this.getThenToken();
    if (thenToken) {
      this.remove(thenToken.range[0], this.consequent.start);
    }

    this.consequent.patch({ leftBrace: false, rightBrace: false });

    if (!this.getBreakToken() && !this.implicitlyReturns()) {
      if (thenToken) {
        // `case a: case b: case c: then d → `case a: case b: case c: d break`
        //                                                             ^^^^^^
        this.consequent.insertAfter(' break');
      } else {
        this.appendLineAfter('break', 1);
      }
    }
  }

  setImplicitlyReturns() {
    super.setImplicitlyReturns();
    this.consequent.setImplicitlyReturns();
  }

  patchAsExpression() {
    this.patchAsStatement();
  }

  negate() {
    this.conditions.forEach(condition => condition.negate());
  }

  /**
   * @private
   */
  getWhenToken(): ?Token {
    return this.tokens.find(token => token.type === 'LEADING_WHEN');
  }

  /**
   * @private
   */
  getCommaTokens(): Array<Token> {
    return this.tokens.filter(token => token.type === ',');
  }

  /**
   * @private
   */
  getBreakToken(): ?Token {
    return this.tokens.find(token => token.type === 'STATEMENT' && token.data === 'break');
  }

  /**
   * Gets the token representing the `then` between condition and consequent.
   *
   * @private
   */
  getThenToken(): ?Token {
    return this.tokenBetweenPatchersMatching(this.conditions[0], this.consequent, 'THEN');
  }

}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react-native';
import { Animated, ART } from 'react-native';
const { Surface } = ART;

import Circle from './animated/Circle';

export default class Pulse extends Component {
  static propTypes = {
    size: PropTypes.number,
    color: PropTypes.string
  };

  static defaultProps = {
    size: 14,
    color: '#000'
  };

  state = {
    bounces: [
      new Animated.Value(1),
      new Animated.Value(0)
    ]
  };

  componentDidMount() {
    this.animate(0);
    setTimeout(() => this.animate(1), 1000);
  }

  componentWillUnmount() {
    this.unmounted = true;
  }

  animate(index) {
    Animated
      .sequence([
        Animated.timing(this.state.bounces[index], {
          toValue: 1,
          duration: 1000
        }),
        Animated.timing(this.state.bounces[index], {
          toValue: 0,
          duration: 1000
        })
      ])
      .start(() => {
        if (!this.unmounted) {
          this.animate(index);
        }
      });
  }

  render() {
    const { size, color } = this.props;
    const { bounces: [scale1, scale2] } = this.state;
    const width = size * 2;
    const height = size * 2;

    return (<Surface width={width} height={height}>
      <Circle
        radius={size}
        fill={color}
        scale={scale1}
        opacity={0.6}
        x={size}
        y={size}
      />
      <Circle
        radius={size}
        fill={color}
        scale={scale2}
        opacity={0.6}
        x={size}
        y={size}
      />
    </Surface>);
  }
}
<commit_msg>Update DoubleBounce.js<commit_after>import React, { Component, PropTypes } from 'react';
import { Animated, ART } from 'react-native';
const { Surface } = ART;

import Circle from './animated/Circle';

export default class Pulse extends Component {
  static propTypes = {
    size: PropTypes.number,
    color: PropTypes.string
  };

  static defaultProps = {
    size: 14,
    color: '#000'
  };

  state = {
    bounces: [
      new Animated.Value(1),
      new Animated.Value(0)
    ]
  };

  componentDidMount() {
    this.animate(0);
    setTimeout(() => this.animate(1), 1000);
  }

  componentWillUnmount() {
    this.unmounted = true;
  }

  animate(index) {
    Animated
      .sequence([
        Animated.timing(this.state.bounces[index], {
          toValue: 1,
          duration: 1000
        }),
        Animated.timing(this.state.bounces[index], {
          toValue: 0,
          duration: 1000
        })
      ])
      .start(() => {
        if (!this.unmounted) {
          this.animate(index);
        }
      });
  }

  render() {
    const { size, color } = this.props;
    const { bounces: [scale1, scale2] } = this.state;
    const width = size * 2;
    const height = size * 2;

    return (<Surface width={width} height={height}>
      <Circle
        radius={size}
        fill={color}
        scale={scale1}
        opacity={0.6}
        x={size}
        y={size}
      />
      <Circle
        radius={size}
        fill={color}
        scale={scale2}
        opacity={0.6}
        x={size}
        y={size}
      />
    </Surface>);
  }
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
 */

const traverse = require('../index');
const parser = require('../../parser');

const defaultAst = parser.parse('/[a-z]+a/i');

describe('traverse-basic', () => {

  it('visits each node', () => {
    const visited = [];

    traverse.traverse(defaultAst, {

      onRegExp(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('RegExp');
        expect(parent).toBe(null);
      },

      onAlternative(node, parent) {
        visited.push(node.type);

        expect(node.type === 'Alternative');
        expect(parent.type === 'RegExp');

        expect(node.expressions.length).toBe(2);
        expect(node.expressions[0].type).toBe('Repetition');
        expect(node.expressions[1].type).toBe('Char');
      },

      onRepetition(node, parent) {
        visited.push(node.type);

        expect(node.type === 'Repetition');
        expect(parent.type === 'Alternative');

        expect(node.expression.type).toBe('CharacterClass');
        expect(node.quantifier.type).toBe('+');
      },

      onCharacterClass(node, parent) {
        visited.push(node.type);

        expect(node.type === 'CharacterClass');
        expect(parent.type === 'Repetition');

        expect(node.expressions.length).toBe(1);
        expect(node.expressions[0].type).toBe('ClassRange');
      },

      onClassRange(node, parent, prop, index) {
        visited.push(node.type);

        expect(node.type === 'ClassRange');
        expect(parent.type === 'CharacterClass');

        expect(node.from.type).toBe('Char');
        expect(node.to.type).toBe('Char');

        expect(prop).toBe('expressions');
        expect(index).toBe(0);
      },

      onChar(node, parent) {
        visited.push(node.type);

        expect(node.type === 'Char');
        expect(parent.type === 'ClassRange');
      },
    });

    // Visit order.
    expect(visited).toEqual([
      'RegExp',
      'Alternative',
      'Repetition',
      'CharacterClass',
      'ClassRange',
      'Char',
      'Char',
      'Char',
    ]);
  });

});<commit_msg>Fix parent node check in traverse test<commit_after>/**
 * The MIT License (MIT)
 * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
 */

const traverse = require('../index');
const parser = require('../../parser');

const defaultAst = parser.parse('/[a-z]+a/i');

describe('traverse-basic', () => {

  it('visits each node', () => {
    const visited = [];

    traverse.traverse(defaultAst, {

      onRegExp(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('RegExp');
        expect(parent).toBe(null);
      },

      onAlternative(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('Alternative');
        expect(parent.type).toBe('RegExp');

        expect(node.expressions.length).toBe(2);
        expect(node.expressions[0].type).toBe('Repetition');
        expect(node.expressions[1].type).toBe('Char');
      },

      onRepetition(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('Repetition');
        expect(parent.type).toBe('Alternative');

        expect(node.expression.type).toBe('CharacterClass');
        expect(node.quantifier.type).toBe('+');
      },

      onCharacterClass(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('CharacterClass');
        expect(parent.type).toBe('Repetition');

        expect(node.expressions.length).toBe(1);
        expect(node.expressions[0].type).toBe('ClassRange');
      },

      onClassRange(node, parent, prop, index) {
        visited.push(node.type);

        expect(node.type).toBe('ClassRange');
        expect(parent.type).toBe('CharacterClass');

        expect(node.from.type).toBe('Char');
        expect(node.to.type).toBe('Char');

        expect(prop).toBe('expressions');
        expect(index).toBe(0);
      },

      onChar(node, parent) {
        visited.push(node.type);

        expect(node.type).toBe('Char');

        // Char appears only in these two parent nodes:
        expect(
          parent.type === 'ClassRange' ||
          parent.type === 'Alternative'
        ).toBe(true);
      },
    });

    // Visit order.
    expect(visited).toEqual([
      'RegExp',
      'Alternative',
      'Repetition',
      'CharacterClass',
      'ClassRange',
      'Char',
      'Char',
      'Char',
    ]);
  });

});<|endoftext|>


<commit_before>var JS = require('./js');
var Asset = Fire.Asset;
var callInNextTick = require('./utils').callInNextTick;
var LoadManager = require('./load-manager');
var JsonLoader = require('./loaders').JsonLoader;

/**
 * The asset library which managing loading/unloading assets in project.
 *
 * @class AssetLibrary
 * @static
 */
var AssetLibrary = (function () {

    // configs

    var _libraryBase = '';

    // variables

    // the loading uuid's callbacks
    var _uuidToCallbacks = new Fire.CallbacksInvoker();

    // temp deserialize info
    var _tdInfo = new Fire._DeserializeInfo();

    // create a loading context which reserves all relevant parameters
    function LoadingHandle (readMainCache, writeMainCache) {
        this.readMainCache = readMainCache;
        this.writeMainCache = writeMainCache;
        var needIndieCache = !(this.readMainCache && this.writeMainCache);
        this.taskIndieCache = needIndieCache ? {} : null;
    }
    LoadingHandle.prototype.readCache = function (uuid) {
        if (this.readMainCache && this.writeMainCache) {
            return AssetLibrary._uuidToAsset[uuid];
        }
        else {
            if (this.readMainCache) {
                // writeMainCache == false
                return AssetLibrary._uuidToAsset[uuid] || this.taskIndieCache[uuid];
            }
            else {
                return this.taskIndieCache[uuid];
            }
        }
    };
    LoadingHandle.prototype.writeCache = function (uuid, asset) {
        if (this.writeMainCache) {
            AssetLibrary._uuidToAsset[uuid] = asset;
        }
        if (this.taskIndieCache) {
            this.taskIndieCache[uuid] = asset;
        }
    };

    // publics

    var AssetLibrary = {
        /**
         * @callback loadCallback
         * @param {string} error - null or the error info
         * @param {Asset} data - the loaded asset or null
         */

        /**
         * @method loadAsset
         * @param {string} uuid
         * @param {loadCallback} callback - the callback function once load finished
         * @param {boolean} [readMainCache=true] - If false, the asset and all its depends assets will reload and create new instances from library.
         * @param {boolean} [writeMainCache=true] - If true, the result will cache to AssetLibrary, and MUST be unload by user manually.
         * @param {Asset} [existingAsset] - load to existing asset, this argument is only available in editor
         * @private
         */
        loadAsset: function (uuid, callback, readMainCache, writeMainCache, existingAsset) {
            readMainCache = typeof readMainCache !== 'undefined' ? readMainCache : true;
            writeMainCache = typeof writeMainCache !== 'undefined' ? writeMainCache : true;

            var handle = new LoadingHandle(readMainCache, writeMainCache);
            this._loadAssetByUuid(uuid, callback, handle, existingAsset);
        },

        _LoadingHandle: LoadingHandle,

        getUrl: function (uuid) {
            return _libraryBase + uuid.slice(0, 2) + Fire.Path.sep + uuid;
        },

        getUuid: function (url) {

            if ( url.indexOf(_libraryBase) === 0 ) {
                return url.slice( url.lastIndexOf('/') + 1, url.length );
            }

            // If url is not in the library, just return 0
            return 0;
        },

        /**
         * !#zh uuid加载流程：
         * 1. 查找_uuidToAsset，如果已经加载过，直接返回
         * 2. 查找_uuidToCallbacks，如果已经在加载，则注册回调，直接返回
         * 3. 如果没有url，则将uuid直接作为路径
         * 4. 递归加载Asset及其引用到的其它Asset
         *
         * @method _loadAssetByUuid
         * @param {string} uuid
         * @param {loadCallback} callback - the callback to receive the asset, can be null
         * @param {LoadingHandle} handle - the loading context which reserves all relevant parameters
         * @param {Asset} [existingAsset] - load to existing asset, this argument is only available in editor
         * @private
         */
        _loadAssetByUuid: function (uuid, callback, handle, existingAsset) {
            if (typeof uuid !== 'string') {
                callInNextTick(callback, '[AssetLibrary] uuid must be string', null);
                return;
            }
            // step 1
            if ( !existingAsset ) {
                var asset = handle.readCache(uuid);
                if (asset) {
                    callInNextTick(callback, null, asset);
                    return;
                }
            }

            // step 2
            // 如果必须重新加载，则不能合并到到 _uuidToCallbacks，否则现有的加载成功后会同时触发回调，
            // 导致提前返回的之前的资源。
            var canShareLoadingTask = handle.readMainCache && !existingAsset;
            if ( canShareLoadingTask && !_uuidToCallbacks.add(uuid, callback) ) {
                // already loading
                return;
            }

            // step 3

            if (FIRE_EDITOR && !_libraryBase) {
                callInNextTick(callback, 'Cannot load ' + uuid + ' in editor because AssetLibrary not yet initialized!', null);
                return;
            }
            var url = this.getUrl(uuid);

            // step 4
            LoadManager.loadByLoader(JsonLoader, url,
                function (error, json) {
                    function onDeserializedWithDepends (err, asset) {
                        if (asset) {
                            asset._uuid = uuid;
                            handle.writeCache(uuid, asset);
                        }
                        if ( canShareLoadingTask ) {
                            _uuidToCallbacks.invokeAndRemove(uuid, err, asset);
                        }
                        else if (callback) {
                            callback(err, asset);
                        }
                    }
                    if (json) {
                        AssetLibrary._deserializeWithDepends(json, url, onDeserializedWithDepends, handle, existingAsset);
                    }
                    else {
                        onDeserializedWithDepends(error, null);
                    }
                }
            );
        },

        /**
         * @method loadJson
         * @param {string|object} json
         * @param {loadCallback} callback
         * @param {boolean} [dontCache=false] - If false, the result will cache to AssetLibrary, and MUST be unload by user manually.
         * @private
         */
        loadJson: function (json, callback, dontCache) {
            var handle = new LoadingHandle(!dontCache, !dontCache);
            this._deserializeWithDepends(json, '', callback, handle);
        },

        /**
         * @method _deserializeWithDepends
         * @param {string|object} json
         * @param {string} url
         * @param {loadCallback} callback
         * @param {object} handle - the loading context which reserves all relevant parameters
         * @param {Asset} [existingAsset] - existing asset to reload
         * @private
         */
        _deserializeWithDepends: function (json, url, callback, handle, existingAsset) {
            // deserialize asset
            var isScene = json && json[0] && json[0].__type__ === JS._getClassId(Scene);
            var classFinder = isScene ? Fire._MissingScript.safeFindClass : function (id) {
                var cls = JS._getClassById(id);
                if (cls) {
                    return cls;
                }
                Fire.warn('Can not get class "%s"', id);
                return Object;
            };
            Engine._canModifyCurrentScene = false;
            var asset = Fire.deserialize(json, _tdInfo, {
                classFinder: classFinder,
                target: existingAsset
            });
            Engine._canModifyCurrentScene = true;

            // load depends
            var pendingCount = _tdInfo.uuidList.length;

            // load raw
            var rawProp = _tdInfo.rawProp;     // _tdInfo不能用在回调里！
            if (rawProp) {
                // load depends raw objects
                var attrs = Fire.attr(asset.constructor, _tdInfo.rawProp);
                var rawType = attrs.rawType;
                ++pendingCount;
                LoadManager.load(url, rawType, asset._rawext, function onRawObjLoaded (error, raw) {
                    if (error) {
                        Fire.error('[AssetLibrary] Failed to load %s of %s. %s', rawType, url, error);
                    }
                    asset[rawProp] = raw;
                    --pendingCount;
                    if (pendingCount === 0) {
                        callback(null, asset);
                    }
                });
            }

            if (pendingCount === 0) {
                callback(null, asset);
                // _tdInfo 是用来重用临时对象，每次使用后都要重设，这样才对 GC 友好。
                _tdInfo.reset();
                return;
            }

            /*
             如果依赖的所有资源都要重新下载，批量操作时将会导致同时执行多次重复下载。优化方法是增加一全局事件队列，
             队列保存每个任务的注册，启动，结束事件，任务从注册到启动要延迟几帧，每个任务都存有父任务。
             这样通过队列的事件序列就能做到合并批量任务。
             如果依赖的资源不重新下载也行，但要判断是否刚好在下载过程中，如果是的话必须等待下载完成才能结束本资源的加载，
             否则外部获取到的依赖资源就会是旧的。
             */

            // AssetLibrary._loadAssetByUuid 的回调有可能在当帧也可能延后执行，这里要判断是否由它调用 callback，
            // 否则 callback 可能会重复调用
            var invokeCbByDepends = false;

            // load depends assets
            for (var i = 0, len = _tdInfo.uuidList.length; i < len; i++) {
                var dependsUuid = _tdInfo.uuidList[i];
                if (FIRE_EDITOR && existingAsset) {
                    var existingDepends = _tdInfo.uuidObjList[i][_tdInfo.uuidPropList[i]];
                    if (existingDepends && existingDepends._uuid === dependsUuid) {
                        var dependsUrl = _libraryBase + dependsUuid.substring(0, 2) + Fire.Path.sep + dependsUuid;
                        if ( !LoadManager.isLoading(dependsUrl, true) ) {
                            // 如果有依赖但依赖不在加载过程中就直接略过
                            --pendingCount;
                        }
                        else {
                            // 等待依赖加载完成
                            (function (dependsUrl) {
                                var idToClear = setInterval(function () {
                                    if ( !LoadManager.isLoading(dependsUrl, true) ) {
                                        clearInterval(idToClear);
                                        --pendingCount;
                                        if (pendingCount === 0) {
                                            callback(null, asset);
                                        }
                                    }
                                }, 10);
                            })(dependsUrl);
                        }
                        continue;
                    }
                }
                var onDependsAssetLoaded = (function (dependsUuid, obj, prop) {
                    // create closure manually because its extremely faster than bind
                    return function (error, dependsAsset) {
                        if (FIRE_EDITOR && error) {
                            if (Editor.AssetDB && Editor.AssetDB.isValidUuid(dependsUuid)) {
                                Fire.error('[AssetLibrary] Failed to load "%s", %s', dependsUuid, error);
                            }
                        }
                        //else {
                        //    dependsAsset._uuid = dependsUuid;
                        //}
                        // update reference
                        obj[prop] = dependsAsset;
                        // check all finished
                        --pendingCount;
                        if (pendingCount === 0) {
                            callback(null, asset);
                        }
                    };
                })( dependsUuid, _tdInfo.uuidObjList[i], _tdInfo.uuidPropList[i] );
                AssetLibrary._loadAssetByUuid(dependsUuid, onDependsAssetLoaded, handle);
                invokeCbByDepends = true;
            }

            if (FIRE_EDITOR && !invokeCbByDepends && pendingCount === 0) {
                callback(null, asset);
            }

            // _tdInfo 是用来重用临时对象，每次使用后都要重设，这样才对 GC 友好。
            _tdInfo.reset();
        },

        /**
         * Get the exists asset by uuid.
         *
         * @method getAssetByUuid
         * @param {string} uuid
         * @return {Asset} - the existing asset, if not loaded, just returns null.
         * @private
         */
        getAssetByUuid: function (uuid) {
            return AssetLibrary._uuidToAsset[uuid] || null;
        },

        /**
         * !#en Kill references to the asset so it can be garbage collected.
         * Fireball will reload the asset from disk or remote if loadAssetByUuid being called again.
         * You rarely use this function in scripts, since it will be called automatically when the Asset is destroyed.
         * !#zh 手动卸载指定的资源，这个方法会在 Asset 被 destroy 时自动调用，一般不需要用到这个方法。卸载以后，Fireball 可以重新从硬盘或网络加载这个资源。
         *
         * 如果还有地方引用到asset，除非 destroyImmediated 为true，否则不应该执行这个方法，因为那样可能会导致 asset 被多次创建。
         *
         * @method unloadAsset
         * @param {Asset|string} assetOrUuid
         * @param {boolean} [destroy=false] - When destroyImmediate is true, if there are objects referencing the asset, the references will become invalid.
         */
        unloadAsset: function (assetOrUuid, destroy) {
            var asset;
            if (typeof assetOrUuid === 'string') {
                asset = AssetLibrary._uuidToAsset[assetOrUuid];
            }
            else {
                asset = assetOrUuid;
            }
            if (asset) {
                if (destroy && asset.isValid) {
                    asset.destroy();
                }
                delete AssetLibrary._uuidToAsset[asset._uuid];
            }
        },

        /**
         * init the asset library
         * @method init
         * @param {string} libraryPath
         */
        init: function (libraryPath) {
            if (FIRE_EDITOR && _libraryBase && !FIRE_TEST) {
                Fire.error('AssetLibrary has already been initialized!');
                return;
            }
            _libraryBase = Fire.Path.setEndWithSep(libraryPath);
            //Fire.log('[AssetLibrary] library: ' + _libraryBase);
        }

        ///**
        // * temporary flag for deserializing assets
        // * @property {boolean} Fire.AssetLibrary.isLoadingAsset
        // */
        //isLoadingAsset: false,
    };

    // unload asset if it is destoryed

    /**
     * !#en Caches uuid to all loaded assets in scenes.
     *
     * !#zh 这里保存所有已经加载的场景资源，防止同一个资源在内存中加载出多份拷贝。
     *
     * 这里用不了WeakMap，在浏览器中所有加载过的资源都只能手工调用 unloadAsset 释放。
     *
     * 参考：
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
     * https://github.com/TooTallNate/node-weak
     *
     * @property _uuidToAsset
     * @type {object}
     * @private
     */
    AssetLibrary._uuidToAsset = {};

    //暂时屏蔽，因为目前没有缓存任何asset
    //if (FIRE_DEV && Asset.prototype._onPreDestroy) {
    //    Fire.error('_onPreDestroy of Asset has already defined');
    //}
    //Asset.prototype._onPreDestroy = function () {
    //    if (AssetLibrary._uuidToAsset[this._uuid] === this) {
    //        AssetLibrary.unloadAsset(this);
    //    }
    //};

    return AssetLibrary;
})();

Fire.AssetLibrary = AssetLibrary;
<commit_msg>fixed syntax<commit_after>var JS = require('./js');
var Asset = Fire.Asset;
var callInNextTick = require('./utils').callInNextTick;
var LoadManager = require('./load-manager');
var JsonLoader = require('./loaders').JsonLoader;

/**
 * The asset library which managing loading/unloading assets in project.
 *
 * @class AssetLibrary
 * @static
 */
var AssetLibrary = (function () {

    // configs

    var _libraryBase = '';

    // variables

    // the loading uuid's callbacks
    var _uuidToCallbacks = new Fire.CallbacksInvoker();

    // temp deserialize info
    var _tdInfo = new Fire._DeserializeInfo();

    // create a loading context which reserves all relevant parameters
    function LoadingHandle (readMainCache, writeMainCache) {
        this.readMainCache = readMainCache;
        this.writeMainCache = writeMainCache;
        var needIndieCache = !(this.readMainCache && this.writeMainCache);
        this.taskIndieCache = needIndieCache ? {} : null;
    }
    LoadingHandle.prototype.readCache = function (uuid) {
        if (this.readMainCache && this.writeMainCache) {
            return AssetLibrary._uuidToAsset[uuid];
        }
        else {
            if (this.readMainCache) {
                // writeMainCache == false
                return AssetLibrary._uuidToAsset[uuid] || this.taskIndieCache[uuid];
            }
            else {
                return this.taskIndieCache[uuid];
            }
        }
    };
    LoadingHandle.prototype.writeCache = function (uuid, asset) {
        if (this.writeMainCache) {
            AssetLibrary._uuidToAsset[uuid] = asset;
        }
        if (this.taskIndieCache) {
            this.taskIndieCache[uuid] = asset;
        }
    };

    // publics

    var AssetLibrary = {
        /**
         * @callback loadCallback
         * @param {string} error - null or the error info
         * @param {Asset} data - the loaded asset or null
         */

        /**
         * @method loadAsset
         * @param {string} uuid
         * @param {loadCallback} callback - the callback function once load finished
         * @param {boolean} [readMainCache=true] - If false, the asset and all its depends assets will reload and create new instances from library.
         * @param {boolean} [writeMainCache=true] - If true, the result will cache to AssetLibrary, and MUST be unload by user manually.
         * @param {Asset} [existingAsset] - load to existing asset, this argument is only available in editor
         * @private
         */
        loadAsset: function (uuid, callback, readMainCache, writeMainCache, existingAsset) {
            readMainCache = typeof readMainCache !== 'undefined' ? readMainCache : true;
            writeMainCache = typeof writeMainCache !== 'undefined' ? writeMainCache : true;

            var handle = new LoadingHandle(readMainCache, writeMainCache);
            this._loadAssetByUuid(uuid, callback, handle, existingAsset);
        },

        _LoadingHandle: LoadingHandle,

        getUrl: function (uuid) {
            return _libraryBase + uuid.slice(0, 2) + Fire.Path.sep + uuid;
        },

        getUuid: function (url) {

            var hasUuid = url.indexOf(_libraryBase) === 0;
            if ( hasUuid ) {
                var basename = Fire.Path.basename(url);

                var hasSuffix = basename.indexOf('.');
                if ( hasSuffix ) {
                    basename = basename.split('.')[0];
                }

                return url.slice( basename );
            }

            // If url is not in the library, just return 0
            return "";
        },

        /**
         * !#zh uuid加载流程：
         * 1. 查找_uuidToAsset，如果已经加载过，直接返回
         * 2. 查找_uuidToCallbacks，如果已经在加载，则注册回调，直接返回
         * 3. 如果没有url，则将uuid直接作为路径
         * 4. 递归加载Asset及其引用到的其它Asset
         *
         * @method _loadAssetByUuid
         * @param {string} uuid
         * @param {loadCallback} callback - the callback to receive the asset, can be null
         * @param {LoadingHandle} handle - the loading context which reserves all relevant parameters
         * @param {Asset} [existingAsset] - load to existing asset, this argument is only available in editor
         * @private
         */
        _loadAssetByUuid: function (uuid, callback, handle, existingAsset) {
            if (typeof uuid !== 'string') {
                callInNextTick(callback, '[AssetLibrary] uuid must be string', null);
                return;
            }
            // step 1
            if ( !existingAsset ) {
                var asset = handle.readCache(uuid);
                if (asset) {
                    callInNextTick(callback, null, asset);
                    return;
                }
            }

            // step 2
            // 如果必须重新加载，则不能合并到到 _uuidToCallbacks，否则现有的加载成功后会同时触发回调，
            // 导致提前返回的之前的资源。
            var canShareLoadingTask = handle.readMainCache && !existingAsset;
            if ( canShareLoadingTask && !_uuidToCallbacks.add(uuid, callback) ) {
                // already loading
                return;
            }

            // step 3

            if (FIRE_EDITOR && !_libraryBase) {
                callInNextTick(callback, 'Cannot load ' + uuid + ' in editor because AssetLibrary not yet initialized!', null);
                return;
            }
            var url = this.getUrl(uuid);

            // step 4
            LoadManager.loadByLoader(JsonLoader, url,
                function (error, json) {
                    function onDeserializedWithDepends (err, asset) {
                        if (asset) {
                            asset._uuid = uuid;
                            handle.writeCache(uuid, asset);
                        }
                        if ( canShareLoadingTask ) {
                            _uuidToCallbacks.invokeAndRemove(uuid, err, asset);
                        }
                        else if (callback) {
                            callback(err, asset);
                        }
                    }
                    if (json) {
                        AssetLibrary._deserializeWithDepends(json, url, onDeserializedWithDepends, handle, existingAsset);
                    }
                    else {
                        onDeserializedWithDepends(error, null);
                    }
                }
            );
        },

        /**
         * @method loadJson
         * @param {string|object} json
         * @param {loadCallback} callback
         * @param {boolean} [dontCache=false] - If false, the result will cache to AssetLibrary, and MUST be unload by user manually.
         * @private
         */
        loadJson: function (json, callback, dontCache) {
            var handle = new LoadingHandle(!dontCache, !dontCache);
            this._deserializeWithDepends(json, '', callback, handle);
        },

        /**
         * @method _deserializeWithDepends
         * @param {string|object} json
         * @param {string} url
         * @param {loadCallback} callback
         * @param {object} handle - the loading context which reserves all relevant parameters
         * @param {Asset} [existingAsset] - existing asset to reload
         * @private
         */
        _deserializeWithDepends: function (json, url, callback, handle, existingAsset) {
            // deserialize asset
            var isScene = json && json[0] && json[0].__type__ === JS._getClassId(Scene);
            var classFinder = isScene ? Fire._MissingScript.safeFindClass : function (id) {
                var cls = JS._getClassById(id);
                if (cls) {
                    return cls;
                }
                Fire.warn('Can not get class "%s"', id);
                return Object;
            };
            Engine._canModifyCurrentScene = false;
            var asset = Fire.deserialize(json, _tdInfo, {
                classFinder: classFinder,
                target: existingAsset
            });
            Engine._canModifyCurrentScene = true;

            // load depends
            var pendingCount = _tdInfo.uuidList.length;

            // load raw
            var rawProp = _tdInfo.rawProp;     // _tdInfo不能用在回调里！
            if (rawProp) {
                // load depends raw objects
                var attrs = Fire.attr(asset.constructor, _tdInfo.rawProp);
                var rawType = attrs.rawType;
                ++pendingCount;
                LoadManager.load(url, rawType, asset._rawext, function onRawObjLoaded (error, raw) {
                    if (error) {
                        Fire.error('[AssetLibrary] Failed to load %s of %s. %s', rawType, url, error);
                    }
                    asset[rawProp] = raw;
                    --pendingCount;
                    if (pendingCount === 0) {
                        callback(null, asset);
                    }
                });
            }

            if (pendingCount === 0) {
                callback(null, asset);
                // _tdInfo 是用来重用临时对象，每次使用后都要重设，这样才对 GC 友好。
                _tdInfo.reset();
                return;
            }

            /*
             如果依赖的所有资源都要重新下载，批量操作时将会导致同时执行多次重复下载。优化方法是增加一全局事件队列，
             队列保存每个任务的注册，启动，结束事件，任务从注册到启动要延迟几帧，每个任务都存有父任务。
             这样通过队列的事件序列就能做到合并批量任务。
             如果依赖的资源不重新下载也行，但要判断是否刚好在下载过程中，如果是的话必须等待下载完成才能结束本资源的加载，
             否则外部获取到的依赖资源就会是旧的。
             */

            // AssetLibrary._loadAssetByUuid 的回调有可能在当帧也可能延后执行，这里要判断是否由它调用 callback，
            // 否则 callback 可能会重复调用
            var invokeCbByDepends = false;

            // load depends assets
            for (var i = 0, len = _tdInfo.uuidList.length; i < len; i++) {
                var dependsUuid = _tdInfo.uuidList[i];
                if (FIRE_EDITOR && existingAsset) {
                    var existingDepends = _tdInfo.uuidObjList[i][_tdInfo.uuidPropList[i]];
                    if (existingDepends && existingDepends._uuid === dependsUuid) {
                        var dependsUrl = _libraryBase + dependsUuid.substring(0, 2) + Fire.Path.sep + dependsUuid;
                        if ( !LoadManager.isLoading(dependsUrl, true) ) {
                            // 如果有依赖但依赖不在加载过程中就直接略过
                            --pendingCount;
                        }
                        else {
                            // 等待依赖加载完成
                            (function (dependsUrl) {
                                var idToClear = setInterval(function () {
                                    if ( !LoadManager.isLoading(dependsUrl, true) ) {
                                        clearInterval(idToClear);
                                        --pendingCount;
                                        if (pendingCount === 0) {
                                            callback(null, asset);
                                        }
                                    }
                                }, 10);
                            })(dependsUrl);
                        }
                        continue;
                    }
                }
                var onDependsAssetLoaded = (function (dependsUuid, obj, prop) {
                    // create closure manually because its extremely faster than bind
                    return function (error, dependsAsset) {
                        if (FIRE_EDITOR && error) {
                            if (Editor.AssetDB && Editor.AssetDB.isValidUuid(dependsUuid)) {
                                Fire.error('[AssetLibrary] Failed to load "%s", %s', dependsUuid, error);
                            }
                        }
                        //else {
                        //    dependsAsset._uuid = dependsUuid;
                        //}
                        // update reference
                        obj[prop] = dependsAsset;
                        // check all finished
                        --pendingCount;
                        if (pendingCount === 0) {
                            callback(null, asset);
                        }
                    };
                })( dependsUuid, _tdInfo.uuidObjList[i], _tdInfo.uuidPropList[i] );
                AssetLibrary._loadAssetByUuid(dependsUuid, onDependsAssetLoaded, handle);
                invokeCbByDepends = true;
            }

            if (FIRE_EDITOR && !invokeCbByDepends && pendingCount === 0) {
                callback(null, asset);
            }

            // _tdInfo 是用来重用临时对象，每次使用后都要重设，这样才对 GC 友好。
            _tdInfo.reset();
        },

        /**
         * Get the exists asset by uuid.
         *
         * @method getAssetByUuid
         * @param {string} uuid
         * @return {Asset} - the existing asset, if not loaded, just returns null.
         * @private
         */
        getAssetByUuid: function (uuid) {
            return AssetLibrary._uuidToAsset[uuid] || null;
        },

        /**
         * !#en Kill references to the asset so it can be garbage collected.
         * Fireball will reload the asset from disk or remote if loadAssetByUuid being called again.
         * You rarely use this function in scripts, since it will be called automatically when the Asset is destroyed.
         * !#zh 手动卸载指定的资源，这个方法会在 Asset 被 destroy 时自动调用，一般不需要用到这个方法。卸载以后，Fireball 可以重新从硬盘或网络加载这个资源。
         *
         * 如果还有地方引用到asset，除非 destroyImmediated 为true，否则不应该执行这个方法，因为那样可能会导致 asset 被多次创建。
         *
         * @method unloadAsset
         * @param {Asset|string} assetOrUuid
         * @param {boolean} [destroy=false] - When destroyImmediate is true, if there are objects referencing the asset, the references will become invalid.
         */
        unloadAsset: function (assetOrUuid, destroy) {
            var asset;
            if (typeof assetOrUuid === 'string') {
                asset = AssetLibrary._uuidToAsset[assetOrUuid];
            }
            else {
                asset = assetOrUuid;
            }
            if (asset) {
                if (destroy && asset.isValid) {
                    asset.destroy();
                }
                delete AssetLibrary._uuidToAsset[asset._uuid];
            }
        },

        /**
         * init the asset library
         * @method init
         * @param {string} libraryPath
         */
        init: function (libraryPath) {
            if (FIRE_EDITOR && _libraryBase && !FIRE_TEST) {
                Fire.error('AssetLibrary has already been initialized!');
                return;
            }
            _libraryBase = Fire.Path.setEndWithSep(libraryPath);
            //Fire.log('[AssetLibrary] library: ' + _libraryBase);
        }

        ///**
        // * temporary flag for deserializing assets
        // * @property {boolean} Fire.AssetLibrary.isLoadingAsset
        // */
        //isLoadingAsset: false,
    };

    // unload asset if it is destoryed

    /**
     * !#en Caches uuid to all loaded assets in scenes.
     *
     * !#zh 这里保存所有已经加载的场景资源，防止同一个资源在内存中加载出多份拷贝。
     *
     * 这里用不了WeakMap，在浏览器中所有加载过的资源都只能手工调用 unloadAsset 释放。
     *
     * 参考：
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
     * https://github.com/TooTallNate/node-weak
     *
     * @property _uuidToAsset
     * @type {object}
     * @private
     */
    AssetLibrary._uuidToAsset = {};

    //暂时屏蔽，因为目前没有缓存任何asset
    //if (FIRE_DEV && Asset.prototype._onPreDestroy) {
    //    Fire.error('_onPreDestroy of Asset has already defined');
    //}
    //Asset.prototype._onPreDestroy = function () {
    //    if (AssetLibrary._uuidToAsset[this._uuid] === this) {
    //        AssetLibrary.unloadAsset(this);
    //    }
    //};

    return AssetLibrary;
})();

Fire.AssetLibrary = AssetLibrary;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import Select from 'react-select';

import {
  Button
} from 'react-bootstrap';

import {
  Types
} from 'loom-data';

import DeleteButton from '../../../components/buttons/DeleteButton';
import styles from './styles.module.css';

const { SecurableTypes } = Types;

export default class DefineLinkedEntityType extends React.Component {
  static propTypes = {
    availablePropertyTypes: PropTypes.object.isRequired,
    linkFn: PropTypes.func.isRequired
  }

  constructor(props) {
    const selectedPropertyTypes = Object.keys(props.availablePropertyTypes).filter((id) => {
      return (!props.availablePropertyTypes[id].piiField);
    });

    super(props);
    this.state = {
      availablePropertyTypes: props.availablePropertyTypes,
      selectedPropertyTypes,
      primaryKey: [],
      addPropValue: '',
      noPrimaryKeyError: false,
      noTypeOrTitleError: false,
      deidentify: true
    };
  }

  componentWillReceiveProps(newProps) {
    let selectedPropertyTypes = Object.keys(newProps.availablePropertyTypes);
    if (this.state.deidentify) {
      selectedPropertyTypes = selectedPropertyTypes.filter((id) => {
        return (!newProps.availablePropertyTypes[id].piiField);
      });
    }
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (selectedPropertyTypes.includes(id));
    });
    this.setState({
      availablePropertyTypes: newProps.availablePropertyTypes,
      selectedPropertyTypes,
      primaryKey,
      addPropValue: '',
      noPrimaryKeyError: false
    });
  }

  deselectProp = (propertyTypeId) => {
    const selectedPropertyTypes = this.state.selectedPropertyTypes.filter((id) => {
      return (id !== propertyTypeId);
    });
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (id !== propertyTypeId);
    });
    this.setState({ selectedPropertyTypes, primaryKey });
  }

  toggleCheckbox = (checked, propertyTypeId) => {
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (id !== propertyTypeId);
    });
    if (checked) primaryKey.push(propertyTypeId);
    this.setState({ primaryKey });
  }

  renderPrimaryKeyCheckbox = (propertyTypeId) => {
    return (
      <input
          type="checkbox"
          id={`pkey-${propertyTypeId}`}
          onClick={(e) => {
            this.toggleCheckbox(e.target.checked, propertyTypeId);
          }} />
    );
  }

  addPropertyType = (e) => {
    const selectedPropertyTypes = this.state.selectedPropertyTypes;
    if (e && e.value && !selectedPropertyTypes.includes(e.value)) {
      selectedPropertyTypes.push(e.value);
      this.setState({
        selectedPropertyTypes,
        addPropValue: ''
      });
    }
  }

  getAvailablePropertyIds = () => {
    const availablePropertyTypes = this.state.availablePropertyTypes;
    const x = (!this.state.deidentify) ? Object.keys(availablePropertyTypes) :
      Object.keys(availablePropertyTypes).filter((propertyTypeId) => {
        return (!availablePropertyTypes[propertyTypeId].piiField);
      });
    return x;
  }

  renderAddPropertyType = () => {
    const { availablePropertyTypes, selectedPropertyTypes } = this.state;
    const availablePropertyIds = this.getAvailablePropertyIds();
    if (availablePropertyIds.length === selectedPropertyTypes.length) return null;
    const deselectedProps = availablePropertyIds.filter((id) => {
      return (!selectedPropertyTypes.includes(id));
    });
    const addPropOptions = deselectedProps.map((id) => {
      return { value: id, label: availablePropertyTypes[id].title };
    });

    return (

          <Select
              options={addPropOptions}
              value={this.state.addPropValue}
              onChange={this.addPropertyType} />

    );
  }

  link = () => {
    const {
      selectedPropertyTypes,
      primaryKey,
      deidentify
    } = this.state;
    const {
      title,
      description,
      name,
      namespace
    } = this.props.formData;
    console.log('props:', this.props);
    if (title.length < 1 || namespace.length < 1 || name.length < 1) {
      this.setState({ noTypeOrTitleError: true });
    }
    else if (primaryKey.length <= 0) {
      this.setState({ noPrimaryKeyError: true });
    }
    else {
      const entityType = {
        type: {
          namespace,
          name
        },
        title,
        description,
        key: primaryKey,
        properties: selectedPropertyTypes,
        category: SecurableTypes.LinkingEntityType,
        schemas: []
      };
      this.props.linkFn(entityType, deidentify);
      this.setState({
        noTypeOrTitleError: false,
        noPrimaryKeyError: false
      });
    }
  }

  handleDeidentifyChange = (e) => {
    const selectedPropertyTypes = (!e.target.checked) ? this.state.selectedPropertyTypes :
      this.state.selectedPropertyTypes.filter((propertyTypeId) => {
        return (!this.state.availablePropertyTypes[propertyTypeId].piiField);
      });

    const primaryKey = (!e.target.checked) ? this.state.primaryKey : this.state.primaryKey.filter((propertyTypeId) => {
      return (!this.state.availablePropertyTypes[propertyTypeId].piiField);
    });

    this.setState({
      deidentify: e.target.checked,
      selectedPropertyTypes,
      primaryKey
    });
  }

  renderDeidentify = () => {
    return (

        Deidentify:
        <input
            id="deidentify"
            type="checkbox"
            defaultChecked={this.state.deidentify}
            onChange={this.handleDeidentifyChange} />

    );
  }

  renderInputFields = () => {
    return (

            Namespace:

            <input
                id="namespace"
                type="text"
                value={this.props.formData.namespaceValue}
                onChange={this.props.handleNamespaceChange}
                className={styles.inputBox} />

            Name:

            <input
                id="name"
                type="text"
                value={this.props.formData.nameValue}
                onChange={this.props.handleNameChange}
                className={styles.inputBox} />

            Title:

            <input
                id="title"
                type="text"
                value={this.props.formData.titleValue}
                onChange={this.props.handleTitleChange}
                className={styles.inputBox} />

            Description:

            <input
                id="description"
                type="text"
                value={this.props.formData.descriptionValue}
                onChange={this.props.handleDescriptionChange}
                className={styles.inputBox} />

    );
  }

  renderError = () => {
    if (this.state.noTypeOrTitleError) {
      return (

You must choose a namespace, name, title, and primary key.

      );
    }
    if (this.state.noPrimaryKeyError) {
      return (

You must choose at least one property type as a primary key.

      );
    }
    return null;
  }

  render() {
    const propertyTypes = this.state.selectedPropertyTypes.map((propertyTypeId) => {
      return (

            <DeleteButton
                onClick={() => {
                  this.deselectProp(propertyTypeId);
                }} />
          {this.state.availablePropertyTypes[propertyTypeId].title}
          {this.renderPrimaryKeyCheckbox(propertyTypeId)}

      );
    });
    return (

          Step 3. Define the entity type for storing your linked results.

          {this.renderInputFields()}
          {this.renderDeidentify()}

                Property Type
                Primary Key

              {propertyTypes}
              {this.renderAddPropertyType()}

            Note: In most cases, primary keys should match the properties selected in Step 2.

          <Button
              bsStyle="primary"
              onClick={this.link}
              className={styles.linkButton}>Confirm linked entity type</Button>
          {this.renderError()}

    );
  }
}
<commit_msg>Clean up<commit_after>import React, { PropTypes } from 'react';
import Select from 'react-select';

import {
  Button
} from 'react-bootstrap';

import {
  Types
} from 'loom-data';

import DeleteButton from '../../../components/buttons/DeleteButton';
import styles from './styles.module.css';

const { SecurableTypes } = Types;

export default class DefineLinkedEntityType extends React.Component {
  static propTypes = {
    availablePropertyTypes: PropTypes.object.isRequired,
    linkFn: PropTypes.func.isRequired
  }

  constructor(props) {
    const selectedPropertyTypes = Object.keys(props.availablePropertyTypes).filter((id) => {
      return (!props.availablePropertyTypes[id].piiField);
    });

    super(props);
    this.state = {
      availablePropertyTypes: props.availablePropertyTypes,
      selectedPropertyTypes,
      primaryKey: [],
      addPropValue: '',
      noPrimaryKeyError: false,
      noTypeOrTitleError: false,
      deidentify: true
    };
  }

  componentWillReceiveProps(newProps) {
    let selectedPropertyTypes = Object.keys(newProps.availablePropertyTypes);
    if (this.state.deidentify) {
      selectedPropertyTypes = selectedPropertyTypes.filter((id) => {
        return (!newProps.availablePropertyTypes[id].piiField);
      });
    }
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (selectedPropertyTypes.includes(id));
    });
    this.setState({
      availablePropertyTypes: newProps.availablePropertyTypes,
      selectedPropertyTypes,
      primaryKey,
      addPropValue: '',
      noPrimaryKeyError: false
    });
  }

  deselectProp = (propertyTypeId) => {
    const selectedPropertyTypes = this.state.selectedPropertyTypes.filter((id) => {
      return (id !== propertyTypeId);
    });
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (id !== propertyTypeId);
    });
    this.setState({ selectedPropertyTypes, primaryKey });
  }

  toggleCheckbox = (checked, propertyTypeId) => {
    const primaryKey = this.state.primaryKey.filter((id) => {
      return (id !== propertyTypeId);
    });
    if (checked) primaryKey.push(propertyTypeId);
    this.setState({ primaryKey });
  }

  renderPrimaryKeyCheckbox = (propertyTypeId) => {
    return (
      <input
          type="checkbox"
          id={`pkey-${propertyTypeId}`}
          onClick={(e) => {
            this.toggleCheckbox(e.target.checked, propertyTypeId);
          }} />
    );
  }

  addPropertyType = (e) => {
    const selectedPropertyTypes = this.state.selectedPropertyTypes;
    if (e && e.value && !selectedPropertyTypes.includes(e.value)) {
      selectedPropertyTypes.push(e.value);
      this.setState({
        selectedPropertyTypes,
        addPropValue: ''
      });
    }
  }

  getAvailablePropertyIds = () => {
    const availablePropertyTypes = this.state.availablePropertyTypes;
    const x = (!this.state.deidentify) ? Object.keys(availablePropertyTypes) :
      Object.keys(availablePropertyTypes).filter((propertyTypeId) => {
        return (!availablePropertyTypes[propertyTypeId].piiField);
      });
    return x;
  }

  renderAddPropertyType = () => {
    const { availablePropertyTypes, selectedPropertyTypes } = this.state;
    const availablePropertyIds = this.getAvailablePropertyIds();
    if (availablePropertyIds.length === selectedPropertyTypes.length) return null;
    const deselectedProps = availablePropertyIds.filter((id) => {
      return (!selectedPropertyTypes.includes(id));
    });
    const addPropOptions = deselectedProps.map((id) => {
      return { value: id, label: availablePropertyTypes[id].title };
    });

    return (

          <Select
              options={addPropOptions}
              value={this.state.addPropValue}
              onChange={this.addPropertyType} />

    );
  }

  link = () => {
    const {
      selectedPropertyTypes,
      primaryKey,
      deidentify
    } = this.state;
    const {
      title,
      description,
      name,
      namespace
    } = this.props.formData;

    if (title.length < 1 || namespace.length < 1 || name.length < 1) {
      this.setState({ noTypeOrTitleError: true });
    }
    else if (primaryKey.length <= 0) {
      this.setState({ noPrimaryKeyError: true });
    }
    else {
      const entityType = {
        type: {
          namespace,
          name
        },
        title,
        description,
        key: primaryKey,
        properties: selectedPropertyTypes,
        category: SecurableTypes.LinkingEntityType,
        schemas: []
      };
      this.props.linkFn(entityType, deidentify);
      this.setState({
        noTypeOrTitleError: false,
        noPrimaryKeyError: false
      });
    }
  }

  handleDeidentifyChange = (e) => {
    const selectedPropertyTypes = (!e.target.checked) ? this.state.selectedPropertyTypes :
      this.state.selectedPropertyTypes.filter((propertyTypeId) => {
        return (!this.state.availablePropertyTypes[propertyTypeId].piiField);
      });

    const primaryKey = (!e.target.checked) ? this.state.primaryKey : this.state.primaryKey.filter((propertyTypeId) => {
      return (!this.state.availablePropertyTypes[propertyTypeId].piiField);
    });

    this.setState({
      deidentify: e.target.checked,
      selectedPropertyTypes,
      primaryKey
    });
  }

  renderDeidentify = () => {
    return (

        Deidentify:
        <input
            id="deidentify"
            type="checkbox"
            defaultChecked={this.state.deidentify}
            onChange={this.handleDeidentifyChange} />

    );
  }

  renderInputFields = () => {
    return (

            Namespace:

            <input
                id="namespace"
                type="text"
                value={this.props.formData.namespaceValue}
                onChange={this.props.handleNamespaceChange}
                className={styles.inputBox} />

            Name:

            <input
                id="name"
                type="text"
                value={this.props.formData.nameValue}
                onChange={this.props.handleNameChange}
                className={styles.inputBox} />

            Title:

            <input
                id="title"
                type="text"
                value={this.props.formData.titleValue}
                onChange={this.props.handleTitleChange}
                className={styles.inputBox} />

            Description:

            <input
                id="description"
                type="text"
                value={this.props.formData.descriptionValue}
                onChange={this.props.handleDescriptionChange}
                className={styles.inputBox} />

    );
  }

  renderError = () => {
    if (this.state.noTypeOrTitleError) {
      return (

You must choose a namespace, name, title, and primary key.

      );
    }
    if (this.state.noPrimaryKeyError) {
      return (

You must choose at least one property type as a primary key.

      );
    }
    return null;
  }

  render() {
    const propertyTypes = this.state.selectedPropertyTypes.map((propertyTypeId) => {
      return (

            <DeleteButton
                onClick={() => {
                  this.deselectProp(propertyTypeId);
                }} />
          {this.state.availablePropertyTypes[propertyTypeId].title}
          {this.renderPrimaryKeyCheckbox(propertyTypeId)}

      );
    });
    return (

          Step 3. Define the entity type for storing your linked results.

          {this.renderInputFields()}
          {this.renderDeidentify()}

                Property Type
                Primary Key

              {propertyTypes}
              {this.renderAddPropertyType()}

            Note: In most cases, primary keys should match the properties selected in Step 2.

          <Button
              bsStyle="primary"
              onClick={this.link}
              className={styles.linkButton}>Confirm linked entity type</Button>
          {this.renderError()}

    );
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

// @flow

import type { AstLocation, AstPosition } from "./types";

import get from "lodash/fp/get";
import findIndex from "lodash/findIndex";
import findLastIndex from "lodash/findLastIndex";

import { containsLocation, containsPosition } from "./utils/contains";

import getSymbols from "./getSymbols";

function findSymbols(source) {
  const { functions, comments } = getSymbols(source);
  return { functions, comments };
}

/**
 * Returns the location for a given function path. If the path represents a
 * function declaration, the location will begin after the function identifier
 * but before the function parameters.
 */

function getLocation(func) {
  const location = { ...func.location };

  // if the function has an identifier, start the block after it so the
  // identifier is included in the "scope" of its parent
  const identifierEnd = get("identifier.loc.end", func);
  if (identifierEnd) {
    location.start = identifierEnd;
  }

  return location;
}

/**
 * Find the nearest location containing the input position and
 * return new locations without inner locations under that nearest location
 *
 * @param locations Notice! The locations MUST be sorted by `sortByStart`
 *                  so that we can do linear time complexity operation.
 */
function removeInnerLocations(locations: AstLocation[], position: AstPosition) {
  // First, let's find the nearest position-enclosing function location,
  // which is to find the last location enclosing the position.
  const newLocs = locations.slice();
  const parentIndex = findLastIndex(newLocs, loc =>
    containsPosition(loc, position)
  );
  if (parentIndex < 0) {
    return newLocs;
  }

  // Second, from the nearest location, loop locations again, stop looping
  // once seeing the 1st location not enclosed by the nearest location
  // to find the last inner locations inside the nearest location.
  const innerStartIndex = parentIndex + 1;
  const parentLoc = newLocs[parentIndex];
  const outerBoundaryIndex = findIndex(
    newLocs,
    loc => !containsLocation(parentLoc, loc),
    innerStartIndex
  );
  const innerBoundaryIndex =
    outerBoundaryIndex < 0 ? newLocs.length - 1 : outerBoundaryIndex - 1;

  // Third, remove those inner functions
  newLocs.splice(innerStartIndex, innerBoundaryIndex - parentIndex);
  return newLocs;
}

/**
 * Return an new locations array which excludes
 * items that are completely enclosed by another location in the input locations
 *
 * @param locations Notice! The locations MUST be sorted by `sortByStart`
 *                  so that we can do linear time complexity operation.
 */
function removeOverlaps(locations: AstLocation[]) {
  if (locations.length == 0) {
    return [];
  }
  const firstParent = locations[0];
  return locations.reduce(deduplicateNode, [firstParent]);
}

function deduplicateNode(nodes, location) {
  const parent = nodes[nodes.length - 1];
  if (!containsLocation(parent, location)) {
    nodes.push(location);
  }
  return nodes;
}

/**
 * Sorts an array of locations by start position
 */
function sortByStart(a: AstLocation, b: AstLocation) {
  if (a.start.line < b.start.line) {
    return -1;
  } else if (a.start.line === b.start.line) {
    return a.start.column - b.start.column;
  }

  return 1;
}

/**
 * Returns an array of locations that are considered out of scope for the given
 * location.
 */
function findOutOfScopeLocations(
  sourceId: string,
  position: AstPosition
): AstLocation[] {
  const { functions, comments } = findSymbols(sourceId);
  const commentLocations = comments.map(c => c.location);
  let locations = functions
    .map(getLocation)
    .concat(commentLocations)
    .sort(sortByStart);
  // Must remove inner locations then filter, otherwise,
  // we will mis-judge in-scope inner locations as out of scope.
  locations = removeInnerLocations(locations, position).filter(
    loc => !containsPosition(loc, position)
  );
  return removeOverlaps(locations);
}

export default findOutOfScopeLocations;
<commit_msg>[Parser] Replace use of lodash/fp/get by lodash/get (#5576)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

// @flow

import type { AstLocation, AstPosition } from "./types";

import get from "lodash/get";
import findIndex from "lodash/findIndex";
import findLastIndex from "lodash/findLastIndex";

import { containsLocation, containsPosition } from "./utils/contains";

import getSymbols from "./getSymbols";

function findSymbols(source) {
  const { functions, comments } = getSymbols(source);
  return { functions, comments };
}

/**
 * Returns the location for a given function path. If the path represents a
 * function declaration, the location will begin after the function identifier
 * but before the function parameters.
 */

function getLocation(func) {
  const location = { ...func.location };

  // if the function has an identifier, start the block after it so the
  // identifier is included in the "scope" of its parent
  const identifierEnd = get(func, "identifier.loc.end");
  if (identifierEnd) {
    location.start = identifierEnd;
  }

  return location;
}

/**
 * Find the nearest location containing the input position and
 * return new locations without inner locations under that nearest location
 *
 * @param locations Notice! The locations MUST be sorted by `sortByStart`
 *                  so that we can do linear time complexity operation.
 */
function removeInnerLocations(locations: AstLocation[], position: AstPosition) {
  // First, let's find the nearest position-enclosing function location,
  // which is to find the last location enclosing the position.
  const newLocs = locations.slice();
  const parentIndex = findLastIndex(newLocs, loc =>
    containsPosition(loc, position)
  );
  if (parentIndex < 0) {
    return newLocs;
  }

  // Second, from the nearest location, loop locations again, stop looping
  // once seeing the 1st location not enclosed by the nearest location
  // to find the last inner locations inside the nearest location.
  const innerStartIndex = parentIndex + 1;
  const parentLoc = newLocs[parentIndex];
  const outerBoundaryIndex = findIndex(
    newLocs,
    loc => !containsLocation(parentLoc, loc),
    innerStartIndex
  );
  const innerBoundaryIndex =
    outerBoundaryIndex < 0 ? newLocs.length - 1 : outerBoundaryIndex - 1;

  // Third, remove those inner functions
  newLocs.splice(innerStartIndex, innerBoundaryIndex - parentIndex);
  return newLocs;
}

/**
 * Return an new locations array which excludes
 * items that are completely enclosed by another location in the input locations
 *
 * @param locations Notice! The locations MUST be sorted by `sortByStart`
 *                  so that we can do linear time complexity operation.
 */
function removeOverlaps(locations: AstLocation[]) {
  if (locations.length == 0) {
    return [];
  }
  const firstParent = locations[0];
  return locations.reduce(deduplicateNode, [firstParent]);
}

function deduplicateNode(nodes, location) {
  const parent = nodes[nodes.length - 1];
  if (!containsLocation(parent, location)) {
    nodes.push(location);
  }
  return nodes;
}

/**
 * Sorts an array of locations by start position
 */
function sortByStart(a: AstLocation, b: AstLocation) {
  if (a.start.line < b.start.line) {
    return -1;
  } else if (a.start.line === b.start.line) {
    return a.start.column - b.start.column;
  }

  return 1;
}

/**
 * Returns an array of locations that are considered out of scope for the given
 * location.
 */
function findOutOfScopeLocations(
  sourceId: string,
  position: AstPosition
): AstLocation[] {
  const { functions, comments } = findSymbols(sourceId);
  const commentLocations = comments.map(c => c.location);
  let locations = functions
    .map(getLocation)
    .concat(commentLocations)
    .sort(sortByStart);
  // Must remove inner locations then filter, otherwise,
  // we will mis-judge in-scope inner locations as out of scope.
  locations = removeInnerLocations(locations, position).filter(
    loc => !containsPosition(loc, position)
  );
  return removeOverlaps(locations);
}

export default findOutOfScopeLocations;
<|endoftext|>


<commit_before>export default(db,config) => {

  db.db.listCollections().toArray((err, names) => {
    if (err)
      console.log(err);
    config.database.mongo.db.seeds.forEach(seed => {
      switch (seed.seed) {
        case 'once':
          let found;
          names.forEach(elem => {
            if (`${seed.model.toLowerCase()}s` == elem.name) {
              found = true;
            }
          });
          if (!found)
            require(`${config.base}${seed.path}`);
          break;
        case 'alway':
          require(`${config.base}${seed.path}`);
          break;
        case 'never':
          console.log('No seeds were sown :)');
          break;
        default:
      }
    });
  });

}
<commit_msg>bug fixed seeds<commit_after>export default(connection, config) => {

  connection.db.listCollections().toArray((err, collections) => {
    if (err) {
      console.log(err);
    } else {
      config.database.mongo.db.seeds.forEach(seed => {
        let model = seed.path.split('/').reverse()[0].match(/\S+(?=.seed)/g)[0] + 's';
        switch (seed.plant) {
          case 'once':
            connection.db.collection(model).count((err, count) => {
              if (count <= 0) {
                connection.db.dropCollection(model, (err, res) => {
                  require(`${config.base}${seed.path}`);
                });
              }
            });
            break;
          case 'alway':
            connection.db.dropCollection(model);
            require(`${config.base}${seed.path}`);
            break;
          case 'never':
            console.log('No seeds were sown :)');
            break;
          default:
        }
      });
    }
  });

}
<|endoftext|>


<commit_before>// Parses an HTML element for data
module.exports = function( vars ) {

  var attributes = [ vars.color.value
                   , vars.icon.value
                   , vars.keywords.value
                   , vars.alt.value
                   , "style" ]

  if (!vars.text.value) {
    vars.self.text("text")
  }

  attributes = attributes.concat(vars.id.nesting)

  function get_attributes( obj , elem ) {
    [].forEach.call(elem.attributes, function(attr) {
        if (/^data-/.test(attr.name)) {
            var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
                return $1.toUpperCase();
            });
            obj[camelCaseName] = attr.value;
        }
    })

    attributes.forEach(function(a){

      if ( elem.getAttribute(a) !== null ) {
        obj[a] = elem.getAttribute(a)
      }

    })

  }

  vars.self.data({"element": vars.data.value})

  var elementTag  = vars.data.element.value.node().tagName.toLowerCase()
    , elementType = vars.data.element.value.attr("type")
    , elementData = []

  if ( elementTag === "select" ) {

    var elementID = vars.data.element.value.node().id
    if ( elementID ) {
      vars.self.container({"id": elementID})
    }

    vars.data.element.value.selectAll("option")
      .each(function( o , i ){

        var data_obj = {}

        data_obj.text = this.innerHTML

        get_attributes(data_obj,this)

        elementData.push(data_obj)

        if (this.selected) {
          for (var i = vars.id.nesting.length-1; i >= 0; i--) {
            var level = vars.id.nesting[i]
            if (level in data_obj) {
              vars.self.focus(data_obj[level])
              break
            }
          }
        }

      })

  }
  else if ( elementTag === "input" && elementType === "radio" ) {

    var elementName = vars.data.element.value.node().getAttribute("name")
    if ( elementName ) {
      vars.self.container({"id": elementName})
    }

    vars.data.element.value
      .each(function( o , i ){

        var data_obj = {}

        get_attributes(data_obj,this)

        var id = data_obj[vars.id.value] || this.id || false

        if ( id && isNaN(parseFloat(id)) ) {

          var label = d3.select("label[for="+id+"]")

          if ( !label.empty() ) {
            data_obj.text = label.html()
            label.call(hideElement)
          }

        }

        elementData.push(data_obj)

        if (this.checked) {
          vars.focus.value[0] = data_obj[vars.id.value]
        }

      })

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Get focus from data, if it hasn't been found or set.
  //----------------------------------------------------------------------------
  if ( !vars.focus.value.length && elementData.length ) {

    vars.data.element.value.node().selectedIndex = 0
    vars.self.focus(elementData[0][vars.id.value])

  }

  function hideElement( elem ) {

    elem
      .style("position","absolute","important")
      .style("clip","rect(1px 1px 1px 1px)","important")
      .style("clip","rect(1px, 1px, 1px, 1px)","important")
      .style("width","1px","important")
      .style("height","1px","important")
      .style("margin","-1px","important")
      .style("padding","0","important")
      .style("border","0","important")
      .style("overflow","hidden","important")

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // If a <legend> element exists, use it as the title.
  //----------------------------------------------------------------------------
  var elementLegend = d3.select("legend[for="+vars.container.id+"]")
  if ( !elementLegend.empty() ) {

    vars.self.title(elementLegend.html())
    elementLegend.call(hideElement)

  }

  var containerTag = vars.container.value
                   ? vars.container.value.node().tagName.toLowerCase() : false

  if ( vars.container.value === false || containerTag === "body" ) {
    vars.container.value = d3.select(vars.data.element.value.node().parentNode)
  }

  return elementData

}
<commit_msg>fixed finding default form focus<commit_after>// Parses an HTML element for data
module.exports = function( vars ) {

  var attributes = [ vars.color.value
                   , vars.icon.value
                   , vars.keywords.value
                   , vars.alt.value
                   , "style" ]

  if (!vars.text.value) {
    vars.self.text("text")
  }

  attributes = attributes.concat(vars.id.nesting)

  function get_attributes( obj , elem ) {
    [].forEach.call(elem.attributes, function(attr) {
        if (/^data-/.test(attr.name)) {
            var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
                return $1.toUpperCase();
            });
            obj[camelCaseName] = attr.value;
        }
    })

    attributes.forEach(function(a){

      if ( elem.getAttribute(a) !== null ) {
        obj[a] = elem.getAttribute(a)
      }

    })

  }

  vars.self.data({"element": vars.data.value})

  var elementTag  = vars.data.element.value.node().tagName.toLowerCase()
    , elementType = vars.data.element.value.attr("type")
    , elementData = []

  if ( elementTag === "select" ) {

    var elementID = vars.data.element.value.node().id
    if ( elementID ) {
      vars.self.container({"id": elementID})
    }

    vars.data.element.value.selectAll("option")
      .each(function( o , i ){

        var data_obj = {}

        data_obj.text = this.innerHTML

        get_attributes(data_obj,this)

        elementData.push(data_obj)

        if (this.selected) {
          for (var i = vars.id.nesting.length-1; i >= 0; i--) {
            var level = vars.id.nesting[i]
            if (level in data_obj) {
              vars.self.focus(data_obj[level])
              break
            }
          }
        }

      })

  }
  else if ( elementTag === "input" && elementType === "radio" ) {

    var elementName = vars.data.element.value.node().getAttribute("name")
    if ( elementName ) {
      vars.self.container({"id": elementName})
    }

    vars.data.element.value
      .each(function( o , i ){

        var data_obj = {}

        get_attributes(data_obj,this)

        var id = data_obj[vars.id.value] || this.id || false

        if ( id && isNaN(parseFloat(id)) ) {

          var label = d3.select("label[for="+id+"]")

          if ( !label.empty() ) {
            data_obj.text = label.html()
            label.call(hideElement)
          }

        }

        elementData.push(data_obj)

        if (this.checked) {
          vars.self.focus(data_obj[vars.id.value])
        }

      })

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Get focus from data, if it hasn't been found or set.
  //----------------------------------------------------------------------------
  if ( !vars.focus.value.length && elementData.length ) {

    vars.data.element.value.node().selectedIndex = 0
    vars.self.focus(elementData[0][vars.id.value])

  }

  function hideElement( elem ) {

    elem
      .style("position","absolute","important")
      .style("clip","rect(1px 1px 1px 1px)","important")
      .style("clip","rect(1px, 1px, 1px, 1px)","important")
      .style("width","1px","important")
      .style("height","1px","important")
      .style("margin","-1px","important")
      .style("padding","0","important")
      .style("border","0","important")
      .style("overflow","hidden","important")

  }

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // If a <legend> element exists, use it as the title.
  //----------------------------------------------------------------------------
  var elementLegend = d3.select("legend[for="+vars.container.id+"]")
  if ( !elementLegend.empty() ) {

    vars.self.title(elementLegend.html())
    elementLegend.call(hideElement)

  }

  var containerTag = vars.container.value
                   ? vars.container.value.node().tagName.toLowerCase() : false

  if ( vars.container.value === false || containerTag === "body" ) {
    vars.container.value = d3.select(vars.data.element.value.node().parentNode)
  }

  return elementData

}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'

class GoogleLogout extends Component {
  constructor(props) {
    super(props)
    this.state = {
      disabled: true,
    }
    this.signOut = this.signOut.bind(this)
  }
  componentDidMount() {
    ((d, s, id, cb) => {
      const element = d.getElementsByTagName(s)[0]
      const fjs = element
      let js = element
      js = d.createElement(s)
      js.id = id
      js.src = '//apis.google.com/js/client:platform.js'
      fjs.parentNode.insertBefore(js, fjs)
      js.onload = cb
    })(document, 'script', 'google-login', () => {
      window.gapi.load('auth2', () => {
        this.setState({
          disabled: false,
        })
      })
    })
  }

  signOut() {
    const auth2 = window.gapi.auth2.getAuthInstance()
    if (auth2 != null) {
      auth2.signOut().then(this.props.onLogoutSuccess)
    }
  }

  render() {
    const { tag, style, className, disabledStyle, buttonText, children } = this.props
    const disabled = this.state.disabled || this.props.disabled
    const initialStyle = {
      display: 'inline-block',
      background: '#d14836',
      color: '#fff',
      width: 190,
      paddingTop: 10,
      paddingBottom: 10,
      borderRadius: 2,
      border: '1px solid transparent',
      fontSize: 16,
      fontWeight: 'bold',
      fontFamily: 'Roboto',
    }
    const styleProp = (() => {
      if (style) {
        return style
      } else if (className && !style) {
        return {}
      }
      return initialStyle
    })()
    const defaultStyle = (() => {
      if (disabled) {
        return Object.assign({}, styleProp, disabledStyle)
      }
      return styleProp
    })()
    const googleLoginButton = React.createElement(
      tag, {
        onClick: this.signOut,
        style: defaultStyle,
        disabled,
        className,
      }, children || buttonText
    )
    return googleLoginButton
  }
}

GoogleLogout.propTypes = {
  buttonText: PropTypes.string,
  className: PropTypes.string,
  children: PropTypes.node,
  style: PropTypes.object,
  disabledStyle: PropTypes.object,
  disabled: PropTypes.bool,
}

GoogleLogout.defaultProps = {
  tag: 'button',
  buttonText: 'Logout',
  responseType: 'permission',
  disabledStyle: {
    opacity: 0.6,
  },
  onRequest: () => { },
}

export default GoogleLogout
<commit_msg>Update GoogleLogout props<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'

class GoogleLogout extends Component {
  constructor(props) {
    super(props)
    this.state = {
      disabled: true,
    }
    this.signOut = this.signOut.bind(this)
  }
  componentDidMount() {
    ((d, s, id, cb) => {
      const element = d.getElementsByTagName(s)[0]
      const fjs = element
      let js = element
      js = d.createElement(s)
      js.id = id
      js.src = '//apis.google.com/js/client:platform.js'
      fjs.parentNode.insertBefore(js, fjs)
      js.onload = cb
    })(document, 'script', 'google-login', () => {
      window.gapi.load('auth2', () => {
        this.setState({
          disabled: false,
        })
      })
    })
  }

  signOut() {
    const auth2 = window.gapi.auth2.getAuthInstance()
    if (auth2 != null) {
      auth2.signOut().then(this.props.onLogoutSuccess)
    }
  }

  render() {
    const { tag, style, className, disabledStyle, buttonText, children } = this.props
    const disabled = this.state.disabled || this.props.disabled
    const initialStyle = {
      display: 'inline-block',
      background: '#d14836',
      color: '#fff',
      width: 190,
      paddingTop: 10,
      paddingBottom: 10,
      borderRadius: 2,
      border: '1px solid transparent',
      fontSize: 16,
      fontWeight: 'bold',
      fontFamily: 'Roboto',
    }
    const styleProp = (() => {
      if (style) {
        return style
      } else if (className && !style) {
        return {}
      }
      return initialStyle
    })()
    const defaultStyle = (() => {
      if (disabled) {
        return Object.assign({}, styleProp, disabledStyle)
      }
      return styleProp
    })()
    const googleLoginButton = React.createElement(
      tag, {
        onClick: this.signOut,
        style: defaultStyle,
        disabled,
        className,
      }, children || buttonText
    )
    return googleLoginButton
  }
}

GoogleLogout.propTypes = {
  tag: PropTypes.string,
  buttonText: PropTypes.string,
  className: PropTypes.string,
  children: PropTypes.node,
  style: PropTypes.object,
  disabledStyle: PropTypes.object,
  disabled: PropTypes.bool,
  onLogoutSuccess: PropTypes.func,
}

GoogleLogout.defaultProps = {
  tag: 'button',
  buttonText: 'Logout',
  disabledStyle: {
    opacity: 0.6,
  },
}

export default GoogleLogout
<|endoftext|>


<commit_before>// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
  else if (typeof define == "function" && define.amd) // AMD
    define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
  else // Plain browser env
    mod(CodeMirror);
})(function(CodeMirror) {
  "use strict";

  CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
    if (typeof options == "string") options = {className: options};
    if (!options) options = {};
    return new SearchAnnotation(this, query, caseFold, options);
  });

  function SearchAnnotation(cm, query, caseFold, options) {
    this.cm = cm;
    this.options = options;
    var annotateOptions = {listenForChanges: false};
    for (var prop in options) annotateOptions[prop] = options[prop];
    if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
    this.annotation = cm.annotateScrollbar(annotateOptions);
    this.query = query;
    this.caseFold = caseFold;
    this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
    this.matches = [];
    this.update = null;

    this.findMatches();
    this.annotation.update(this.matches);

    var self = this;
    cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
  }

  var MAX_MATCHES = 1000;

  SearchAnnotation.prototype.findMatches = function() {
    if (!this.gap) return;
    for (var i = 0; i < this.matches.length; i++) {
      var match = this.matches[i];
      if (match.from.line >= this.gap.to) break;
      if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
    }
    var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
    var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
    while (cursor.findNext()) {
      var match = {from: cursor.from(), to: cursor.to()};
      if (match.from.line >= this.gap.to) break;
      this.matches.splice(i++, 0, match);
      if (this.matches.length > maxMatches) break;
    }
    this.gap = null;
  };

  function offsetLine(line, changeStart, sizeChange) {
    if (line <= changeStart) return line;
    return Math.max(changeStart, line + sizeChange);
  }

  SearchAnnotation.prototype.onChange = function(change) {
    var startLine = change.from.line;
    var endLine = CodeMirror.changeEnd(change).line;
    var sizeChange = endLine - change.to.line;
    if (this.gap) {
      this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
      this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
    } else {
      this.gap = {from: change.from.line, to: endLine + 1};
    }

    if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
      var match = this.matches[i];
      var newFrom = offsetLine(match.from.line, startLine, sizeChange);
      if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
      var newTo = offsetLine(match.to.line, startLine, sizeChange);
      if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
    }
    clearTimeout(this.update);
    var self = this;
    this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
  };

  SearchAnnotation.prototype.updateAfterChange = function() {
    this.findMatches();
    this.annotation.update(this.matches);
  };

  SearchAnnotation.prototype.clear = function() {
    this.cm.off("change", this.changeHandler);
    this.annotation.clear();
  };
});
<commit_msg>Remove unnecessary files<commit_after><|endoftext|>


<commit_before>(function($mao) {

    "use strict";

    /**
     * @controller ApplicationController
     * @author Adam Timberlake
     * @module Mao
     */
    $mao.controller('ApplicationController', ['$scope',

    function applicationController($scope) {

        /**
         * @property filtersOpen
         * @type {Boolean}
         * @default false
         */
        $scope.filtersOpen = false;

        /**
         * @property modalOpen
         * @type {Boolean}
         * @default false
         */
        $scope.modalOpen = false;

        /**
         * @method keyUp
         * @param event {Object}
         * @return {void}
         */
        $scope.keyUp = function keyUp(event) {
            console.log('Close?');
        };

    }]);

})(window.maoApp);<commit_msg>JSHint passing<commit_after>(function($mao) {

    "use strict";

    /**
     * @controller ApplicationController
     * @author Adam Timberlake
     * @module Mao
     */
    $mao.controller('ApplicationController', ['$scope',

    function applicationController($scope) {

        /**
         * @property filtersOpen
         * @type {Boolean}
         * @default false
         */
        $scope.filtersOpen = false;

        /**
         * @property modalOpen
         * @type {Boolean}
         * @default false
         */
        $scope.modalOpen = false;

        /**
         * @method keyUp
         * @param event {Object}
         * @return {void}
         */
//        $scope.keyUp = function keyUp(event) {
//            console.log('Close?');
//        };

    }]);

})(window.maoApp);<|endoftext|>


<commit_before>import {
  SIGN_OUT_SUCCESS
} from 'core/auth';

import {
  CREATE_TASK_SUCCESS,
  DELETE_TASK_SUCCESS,
  UPDATE_TASK_SUCCESS
} from './action-types';

export function tasksReducer(state = [], action) {
  switch (action.type) {
    case CREATE_TASK_SUCCESS:
      return [ action.task, ...state ];

    case DELETE_TASK_SUCCESS:
      return state.filter(task => {
        return task.key !== action.task.key;
      });

    case UPDATE_TASK_SUCCESS:
      return state.map(task => {
        return task.key === action.task.key ?
          Object.assign({}, task, action.task) : task;
      });

    case SIGN_OUT_SUCCESS:
      return [];

    default:
      return state;
  }
}
<commit_msg>fix(travis): Object.assign is undefined<commit_after>import assign from 'object-assign';

import {
  SIGN_OUT_SUCCESS
} from 'core/auth';

import {
  CREATE_TASK_SUCCESS,
  DELETE_TASK_SUCCESS,
  UPDATE_TASK_SUCCESS
} from './action-types';

export function tasksReducer(state = [], action) {
  switch (action.type) {
    case CREATE_TASK_SUCCESS:
      return [ action.task, ...state ];

    case DELETE_TASK_SUCCESS:
      return state.filter(task => {
        return task.key !== action.task.key;
      });

    case UPDATE_TASK_SUCCESS:
      return state.map(task => {
        return task.key === action.task.key ?
          assign({}, task, action.task) : task;
      });

    case SIGN_OUT_SUCCESS:
      return [];

    default:
      return state;
  }
}
<|endoftext|>


<commit_before>import React, { PropTypes, PureComponent } from 'react'
import { connect } from 'react-redux'
import Mousetrap from 'mousetrap'
import { SHORTCUT_KEYS } from '../constants/application_types'
import { selectAvatar } from '../selectors/profile'
import { closeOmnibar } from '../actions/omnibar'
import { Omnibar } from '../components/omnibar/Omnibar'

export function mapStateToProps(state) {
  return {
    avatar: selectAvatar(state),
    classList: state.omnibar.get('classList'),
    isActive: state.omnibar.get('isActive'),
  }
}

class OmnibarContainer extends PureComponent {
  static propTypes = {
    avatar: PropTypes.object,
    classList: PropTypes.string,
    dispatch: PropTypes.func.isRequired,
    isActive: PropTypes.bool.isRequired,
  }

  static defaultProps = {
    avatar: null,
    classList: null,
  }

  componentWillMount() {
    this.state = {
      isFullScreen: false,
    }
  }

  componentDidMount() {
    Mousetrap.bind(SHORTCUT_KEYS.FULLSCREEN, () => { this.onToggleFullScreen() })
  }

  componentDidUpdate() {
    const { isActive } = this.props
    if (isActive) {
      document.body.classList.add('isOmnibarActive')
    } else if (!isActive) {
      document.body.classList.remove('isOmnibarActive')
    }
  }

  componentWillUnmount() {
    Mousetrap.unbind(SHORTCUT_KEYS.FULLSCREEN)
  }

  onToggleFullScreen = () => {
    const { isFullScreen } = this.state
    this.setState({ isFullScreen: !isFullScreen })
  }

  onClickCloseOmnibar = () => {
    const { isActive, dispatch } = this.props
    if (isActive) {
      dispatch(closeOmnibar())
    }
  }

  render() {
    const { avatar, classList, isActive } = this.props
    const { isFullScreen } = this.state
    const elementProps = { avatar, classList, isActive, isFullScreen }
    return <Omnibar {...elementProps} onClickCloseOmnibar={this.onClickCloseOmnibar} />
  }
}

export default connect(mapStateToProps)(OmnibarContainer)

<commit_msg>Decrease the render amount on the Omnibar<commit_after>import Immutable from 'immutable'
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import Mousetrap from 'mousetrap'
import { SHORTCUT_KEYS } from '../constants/application_types'
import { selectAvatar } from '../selectors/profile'
import { closeOmnibar } from '../actions/omnibar'
import { Omnibar } from '../components/omnibar/Omnibar'

export function mapStateToProps(state) {
  return {
    avatar: selectAvatar(state),
    classList: state.omnibar.get('classList'),
    isActive: state.omnibar.get('isActive'),
  }
}

class OmnibarContainer extends Component {
  static propTypes = {
    avatar: PropTypes.object,
    classList: PropTypes.string,
    dispatch: PropTypes.func.isRequired,
    isActive: PropTypes.bool.isRequired,
  }

  static defaultProps = {
    avatar: null,
    classList: null,
  }

  componentWillMount() {
    this.state = {
      isFullScreen: false,
    }
  }

  componentDidMount() {
    Mousetrap.bind(SHORTCUT_KEYS.FULLSCREEN, () => { this.onToggleFullScreen() })
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !Immutable.is(nextProps.avatar, this.props.avatar) ||
      ['classList', 'isActive'].some(prop =>
        nextProps[prop] !== this.props[prop],
      ) ||
      ['isFullScreen'].some(prop =>
        nextState[prop] !== this.state[prop],
      )
  }

  componentDidUpdate() {
    const { isActive } = this.props
    if (isActive) {
      document.body.classList.add('isOmnibarActive')
    } else if (!isActive) {
      document.body.classList.remove('isOmnibarActive')
    }
  }

  componentWillUnmount() {
    Mousetrap.unbind(SHORTCUT_KEYS.FULLSCREEN)
  }

  onToggleFullScreen = () => {
    const { isFullScreen } = this.state
    this.setState({ isFullScreen: !isFullScreen })
  }

  onClickCloseOmnibar = () => {
    const { isActive, dispatch } = this.props
    if (isActive) {
      dispatch(closeOmnibar())
    }
  }

  render() {
    const { avatar, classList, isActive } = this.props
    const { isFullScreen } = this.state
    const elementProps = { avatar, classList, isActive, isFullScreen }
    return <Omnibar {...elementProps} onClickCloseOmnibar={this.onClickCloseOmnibar} />
  }
}

export default connect(mapStateToProps)(OmnibarContainer)

<|endoftext|>


<commit_before>
"use strict";

let service;
let loc;
let language;

class LoginController {

    constructor($location, Auth, moLanguage) {
        service = Auth;
        loc = $location;
        language = moLanguage;
    }

    attempt() {
        service.login(this.username, this.password).success(result => {
            loc.path('/' + language.current + '/');
        });
    }

};

LoginController.$inject = ['$location', 'moAuthentication', 'moLanguage'];

export {LoginController};

<commit_msg>empty default<commit_after>
"use strict";

let service;
let loc;
let language;

class LoginController {

    constructor($location, Auth, moLanguage) {
        service = Auth;
        loc = $location;
        language = moLanguage;
        this.credentials = [];
    }

    attempt() {
        service.attempt(...this.credentials).success(result => {
            loc.path('/' + language.current + '/');
        });
    }

};

LoginController.$inject = ['$location', 'Authentication', 'moLanguage'];

export {LoginController};

<|endoftext|>