<commit_before>var peliasConfig = require( 'pelias-config' ).generate();
var readStreamModule = require('./src/readStream');
var importStream = require('./src/importStream');
var peliasDbclient = require( 'pelias-dbclient' );
var peliasDocGenerators = require('./src/peliasDocGenerators');
var hierarchyFinder = require('./src/hierarchyFinder');
var checker = require('node-version-checker').default;
var bundles = require('./src/bundleList');

function hasDataDirectory() {
  return peliasConfig.imports.hasOwnProperty('whosonfirst') &&
          peliasConfig.imports.whosonfirst.hasOwnProperty('datapath');
}

checker();

if (!hasDataDirectory()) {
  console.error('Could not find whosonfirst data directory in configuration');
  process.exit( 2 );
}

var directory = peliasConfig.imports.whosonfirst.datapath;

if (directory.slice(-1) !== '/') {
  directory = directory + '/';
}

// a cache of only admin records, to be used to fill the hierarchy
// of other, lower admin records as well as venues
var wofAdminRecords = {};

var bundlesToImport = bundles.hierarchyBundles;

if (peliasConfig.imports.whosonfirst.importVenues) {
  bundlesToImport = bundlesToImport.concat(bundles.venueBundles);
}

var readStream = readStreamModule.create(directory, bundlesToImport, wofAdminRecords);

// how to convert WOF records to Pelias Documents
var documentGenerator = peliasDocGenerators.create(
  hierarchyFinder.hierarchies_walker(wofAdminRecords));

// the final destination of Pelias Documents
var dbClientStream = peliasDbclient();

// import WOF records into ES
importStream(readStream, documentGenerator, dbClientStream, function() {
  console.log('import finished');
});
<commit_msg>Improve clarity of version checker code<commit_after>var peliasConfig = require( 'pelias-config' ).generate();
var readStreamModule = require('./src/readStream');
var importStream = require('./src/importStream');
var peliasDbclient = require( 'pelias-dbclient' );
var peliasDocGenerators = require('./src/peliasDocGenerators');
var hierarchyFinder = require('./src/hierarchyFinder');
var version_checker = require('node-version-checker').default;
var bundles = require('./src/bundleList');

// print a warning if an unsupported Node.JS version is used
version_checker();

function hasDataDirectory() {
  return peliasConfig.imports.hasOwnProperty('whosonfirst') &&
          peliasConfig.imports.whosonfirst.hasOwnProperty('datapath');
}

if (!hasDataDirectory()) {
  console.error('Could not find whosonfirst data directory in configuration');
  process.exit( 2 );
}

var directory = peliasConfig.imports.whosonfirst.datapath;

if (directory.slice(-1) !== '/') {
  directory = directory + '/';
}

// a cache of only admin records, to be used to fill the hierarchy
// of other, lower admin records as well as venues
var wofAdminRecords = {};

var bundlesToImport = bundles.hierarchyBundles;

if (peliasConfig.imports.whosonfirst.importVenues) {
  bundlesToImport = bundlesToImport.concat(bundles.venueBundles);
}

var readStream = readStreamModule.create(directory, bundlesToImport, wofAdminRecords);

// how to convert WOF records to Pelias Documents
var documentGenerator = peliasDocGenerators.create(
  hierarchyFinder.hierarchies_walker(wofAdminRecords));

// the final destination of Pelias Documents
var dbClientStream = peliasDbclient();

// import WOF records into ES
importStream(readStream, documentGenerator, dbClientStream, function() {
  console.log('import finished');
});
<|endoftext|>


<commit_before>var semver = Npm.require('semver');

////////////////////////////////////////////////////////////////////////////////
// ConstraintsList
////////////////////////////////////////////////////////////////////////////////
// A persistent data-structure that keeps references to Constraint objects
// arranged by the "name" field of Constraint, exact field and version.
//
// Internal structure has the "byName" map that has the following structure:
// byName:
//   - nameOfPackage:
//     - exact:
//       - versionString <=> exactConstraintInstance
//     - inexact:
//       - versionString <=> inexactConstraintInstance
ConstraintSolver.ConstraintsList = function (prev) {
  var self = this;

  if (prev) {
    self.byName = prev.byName;
  } else {
    self.byName = mori.hash_map();
  }
};

ConstraintSolver.ConstraintsList.prototype.contains = function (c) {
  var self = this;
  if (! mori.has_key(self.byName, c.name))
    return false;

  var bn = mori.get(self.byName, c.name);
  var constraints = mori.get(bn, c.type === "exactly" ? "exact" : "inexact");
  return mori.has_key(constraints, c.version);
};

// returns a new version containing passed constraint
ConstraintSolver.ConstraintsList.prototype.push = function (c) {
  var self = this;

  if (self.contains(c)) {
    return self;
  }

  var newList = new ConstraintSolver.ConstraintsList(self);

  // create a record or update the lookup table
  if (! mori.has_key(self.byName, c.name)) {
    var exactMap = mori.hash_map();
    var inexactMap = mori.hash_map();

    if (c.type === "exactly") {
      exactMap = mori.assoc(exactMap, c.version, c);
    } else {
      inexactMap = mori.assoc(inexactMap, c.version, c);
    }

    var bn = mori.hash_map("exact", exactMap, "inexact", inexactMap);
    newList.byName = mori.assoc(newList.byName, c.name, bn);
  } else {
    var exactStr = c.type === "exactly" ? "exact" : "inexact";

    var bn = mori.get(newList.byName, c.name);
    var constraints = mori.get(bn, exactStr);
    constraints = mori.assoc(constraints, c.version, c);
    bn = mori.assoc(bn, exactStr, constraints);
    newList.byName = mori.assoc(newList.byName, c.name, bn);
  }

  return newList;
};

ConstraintSolver.ConstraintsList.prototype.forPackage = function (name, iter) {
  var self = this;
  var forPackage = mori.get(self.byName, name);
  var exact = mori.get(forPackage, "exact");
  var inexact = mori.get(forPackage, "inexact");

  var breaked = false;
  var niter = function (pair) {
    if (iter(mori.last(pair)) === BREAK) {
      breaked = true;
      return true;
    }
  };

  mori.some(niter, exact);
  if (breaked)
    return;
  mori.some(niter, inexact);
};

// doesn't break on the false return value
ConstraintSolver.ConstraintsList.prototype.each = function (iter) {
  var self = this;
  mori.each(self.byName, function (nameAndColl) {
    mori.each(mori.last(nameAndColl), function (exactInexactColl) {
      mori.each(mori.last(exactInexactColl), function (c) {
        iter(mori.last(c));
      });
    });
  });
};

// Checks if the passed unit version satisfies all of the constraints.
ConstraintSolver.ConstraintsList.prototype.isSatisfied = function (
    uv, resolver) {
  var self = this;

  var satisfied = true;

  self.forPackage(uv.name, function (c) {
    if (! c.isSatisfied(uv, resolver)) {
      satisfied = false;
      return BREAK;
    }
  });

  return satisfied;
};

ConstraintSolver.ConstraintsList.prototype.toString = function (simple) {
  var self = this;
  var str = "";

  var strs = [];

  self.each(function (c) {
    strs.push(c.toString());
  });

  strs.sort();

  _.each(strs, function (c) {
    if (str !== "") {
      str += simple ? " " : ", ";
    }
    str += c;
  });

  return simple ? str : "<constraints list: " + str + ">";
};
<commit_msg>Simplify ConstraintsList data structure<commit_after>var semver = Npm.require('semver');

////////////////////////////////////////////////////////////////////////////////
// ConstraintsList
////////////////////////////////////////////////////////////////////////////////
// A persistent data-structure that keeps references to Constraint objects
// arranged by the "name" field of Constraint and exactness of the constraint.
//
// Internal structure has two maps, 'exact' and 'inexact'; they each map
// unit name -> mori.set(Constraint).  (This relies on the fact that Constraints
// are interned, so that mori.set can use reference identity.)
//
// We separate the constraints by exactness so that the iteration functions
// (forPackage and each) can easily provide exact constraints before inexact
// constraints, because exact constraints generally help the consumer pare down
// their possibilities faster.
// XXX This is just a theory, and it's not clear that we have benchmarks that
//     prove it.
ConstraintSolver.ConstraintsList = function (prev) {
  var self = this;

  if (prev) {
    self.exact = prev.exact;
    self.inexact = prev.inexact;
  } else {
    self.exact = mori.hash_map();
    self.inexact = mori.hash_map();
  }
};

ConstraintSolver.ConstraintsList.prototype.contains = function (c) {
  var self = this;
  var map = c.type === 'exactly' ? self.exact : self.inexact;
  return !!mori.get_in(map, [c.name, c]);
};

// returns a new version containing passed constraint
ConstraintSolver.ConstraintsList.prototype.push = function (c) {
  var self = this;

  if (self.contains(c)) {
    return self;
  }

  var newList = new ConstraintSolver.ConstraintsList(self);
  var mapField = c.type === 'exactly' ? 'exact' : 'inexact';
  // Get the current constraints on this package of the exactness, or an empty
  // set.
  var currentConstraints = mori.get(newList[mapField], c.name, mori.set());
  // Add this one.
  newList[mapField] = mori.assoc(newList[mapField],
                                 c.name,
                                 mori.conj(currentConstraints, c));
  return newList;
};

ConstraintSolver.ConstraintsList.prototype.forPackage = function (name, iter) {
  var self = this;
  var exact = mori.get(self.exact, name);
  var inexact = mori.get(self.inexact, name);

  var breaked = false;
  var niter = function (constraint) {
    if (iter(constraint) === BREAK) {
      breaked = true;
      return true;
    }
  };

  exact && mori.some(niter, exact);
  if (breaked)
    return;
  inexact && mori.some(niter, inexact);
};

// doesn't break on the false return value
ConstraintSolver.ConstraintsList.prototype.each = function (iter) {
  var self = this;
  _.each([self.exact, self.inexact], function (map) {
    mori.each(map, function (nameAndConstraints) {
      mori.each(mori.last(nameAndConstraints), iter);
    });
  });
};

// Checks if the passed unit version satisfies all of the constraints.
ConstraintSolver.ConstraintsList.prototype.isSatisfied = function (
    uv, resolver) {
  var self = this;

  var satisfied = true;

  self.forPackage(uv.name, function (c) {
    if (! c.isSatisfied(uv, resolver)) {
      satisfied = false;
      return BREAK;
    }
  });

  return satisfied;
};

ConstraintSolver.ConstraintsList.prototype.toString = function () {
  var self = this;

  var strs = [];

  self.each(function (c) {
    strs.push(c.toString());
  });

  strs.sort();

  return "<constraints list: " + strs.join(", ") + ">";
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

require('dotenv').config();

const argv = require('minimist')(process.argv.slice(2));

const convertApi = require('./src/index');

const spaceId = process.env.CONTENTFUL_SPACE_ID;
const apiToken = process.env.CONTENTFUL_TOKEN;
const managementToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;

const usageHelp = `
Usage:
Running with distribution token:
  CONTENTFUL_TOKEN=xxx CONTENTFUL_SPACE_ID=yyy ./import.js

Running with management token:
  CONTENTFUL_MANAGEMENT_TOKEN=xxx CONTENTFUL_SPACE_ID=yyy ./import.js

Available options:
  --help (-h)          Display this help
  --dev (-d)           Include developer information - field Id's and entity Id's
  --hide-fields (-h)   Hide entity fields information, show only entity names and relationships
`;

if (argv.help || argv.h) {
  console.info(usageHelp);
  process.exit(0);
}

try {
  run(spaceId, managementToken, apiToken);
} catch (err) {
  console.warn(err);
}

async function run(spaceId, managementToken, apiToken) {
  let contentTypes;

  if (managementToken) {
    contentTypes = await convertApi.getContentTypesFromManagementApi(spaceId, managementToken);
  } else if (apiToken) {
    contentTypes = await convertApi.getContentTypesFromDistributionApi(spaceId, apiToken);
  } else {
    console.log(usageHelp);
    return false;
  }

  const options = {
    hideEntityFields: argv.n || argv['no-fields'],
    dev: argv.dev || argv.d
  };

  const modelsMap = convertApi.contentTypesToModelMap(contentTypes);
  const dotStr = convertApi.modelsMapToDot(modelsMap, options);

  console.log(dotStr);
}
<commit_msg>Fixed help<commit_after>#!/usr/bin/env node

require('dotenv').config();

const argv = require('minimist')(process.argv.slice(2));

const convertApi = require('./src/index');

const spaceId = process.env.CONTENTFUL_SPACE_ID;
const apiToken = process.env.CONTENTFUL_TOKEN;
const managementToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;

const usageHelp = `
Usage:
Running with distribution token:
  CONTENTFUL_TOKEN=xxx CONTENTFUL_SPACE_ID=yyy ./import.js

Running with management token:
  CONTENTFUL_MANAGEMENT_TOKEN=xxx CONTENTFUL_SPACE_ID=yyy ./import.js

Available options:
  --help (-h)          Display this help
  --dev (-d)           Include developer information - field Id's and entity Id's
  --no-fields (-n)     Hide entity fields information, show only entity names and relationships
`;

if (argv.help || argv.h) {
  console.info(usageHelp);
  process.exit(0);
}

try {
  run(spaceId, managementToken, apiToken);
} catch (err) {
  console.warn(err);
}

async function run(spaceId, managementToken, apiToken) {
  let contentTypes;

  if (managementToken) {
    contentTypes = await convertApi.getContentTypesFromManagementApi(spaceId, managementToken);
  } else if (apiToken) {
    contentTypes = await convertApi.getContentTypesFromDistributionApi(spaceId, apiToken);
  } else {
    console.log(usageHelp);
    return false;
  }

  const options = {
    hideEntityFields: argv.n || argv['no-fields'],
    dev: argv.dev || argv.d
  };

  const modelsMap = convertApi.contentTypesToModelMap(contentTypes);
  const dotStr = convertApi.modelsMapToDot(modelsMap, options);

  console.log(dotStr);
}
<|endoftext|>


<commit_before>/**
 * Connector element used to link inputs and other connectors together
 * @attribute inputs
 * @attribute outputs
 * @example <graph-connector
 *    inputs="[document.getElementById('input1'), document.getElementById('input2')]"
 *    outputs="[document.getElementById('output1'), document.getElementById('output2')]"
 * ></graph-connector>
 */
class InputConnectorElement extends HTMLElement {
  /**
   * Observed Attributes
   * @private
   * @constant {Array.<String>}
   */
  static get observedAttributes() {
    return ['inputs', 'outputs', 'connected'];
  }

  /**
   * Undefined type flag
   * @readonly
   * @constant {number}
   * @default 0
   */
  static get TYPE_UNDEFINED() {
    return 0;
  }

  /**
   * Input type flag
   * @readonly
   * @constant {number}
   * @default 1
   */
  static get TYPE_INPUT() {
    return 1;
  }

  /**
   * Output type flag
   * @readonly
   * @constant {number}
   * @default 2
   */
  static get TYPE_OUTPUT() {
    return 2;
  }

  /**
   * Both type flag
   * @readonly
   * @constant {number}
   * @default 3
   */
  static get TYPE_BOTH() {
    return 3;
  }

  /**
   * @abstract
   */
  constructor() {
    super();

    this.attachShadow({ mode: 'open' }).innerHTML = `
      <slot>

      </slot>
    `;

    this._onInputChangeBinded = this._onInputChange.bind(this);

    this._inputElementInputs = new Set();
    this._connectorElementInputs = new Set();

    this._inputElementOutputs = new Set();
    this._connectorElementOutputs = new Set();

    const self = this;

    this._inputs = new class extends Set {
      add(value) {
        if (this.has(value) || self === value) {
          return this;
        }
        super.add(value);
        if (value.value !== undefined) {
          self._value = value.value;
        }
        if (value instanceof InputConnectorElement) {
          self._connectorElementInputs.add(value);
          value.outputs.add(self);
        } else {
          self._inputElementInputs.add(value);
        }
        value.addEventListener('input', self._onInputChangeBinded);
        self._updateConnectedStatus();
        self.dispatchEvent(new InputEvent('input', {
          bubbles: true,
          composed: true,
        }));
        return this;
      }
      delete(value) {
        const returnValue = super.delete(value);
        if (!returnValue) {
          return;
        }
        value.removeEventListener('input', self._onInputChangeBinded);
        if (value instanceof InputConnectorElement) {
          self._connectorElementInputs.delete(value);
          value.outputs.delete(self);
        } else {
          self._inputElementInputs.delete(value);
        }
        self._updateConnectedStatus();
        return returnValue;
      }
      clear() {
        for (const value of this) {
          this.delete(value);
        }
      }
    };

    this._outputs = new class extends Set {
      add(value) {
        if (this.has(value) || self === value) {
          return this;
        }
        super.add(value);
        if (value instanceof InputConnectorElement) {
          self._connectorElementOutputs.add(value);
          value.inputs.add(self);
          self.dispatchEvent(new CustomEvent('connected', {
            bubbles: true,
            composed: true,
            detail: {
              output: value,
            },
          }));
        } else {
          self._inputElementOutputs.add(value);
        }
        self._updateConnectedStatus();
        self.dispatchEvent(new InputEvent('input', {
          bubbles: true,
          composed: true,
        }));
        return this;
      }
      delete(value) {
        const returnValue = super.delete(value);
        if (!returnValue) {
          return;
        }
        self._connectorElementOutputs.delete(value);
        self._inputElementOutputs.delete(value);
        if (value instanceof InputConnectorElement) {
          value.inputs.delete(self);
        }
        self._updateConnectedStatus();
        if (value instanceof InputConnectorElement) {
          self.dispatchEvent(new CustomEvent('disconnected', {
            bubbles: true,
            composed: true,
            detail: {
              output: value,
            },
          }));
        }
        return returnValue;
      }
      clear() {
        for (const value of this) {
          this.delete(value);
        }
      }
    };
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue === newValue) {
      return;
    }

    switch (name) {
      case 'inputs':
      case 'outputs':
        const array = new Function(`return ${newValue}`).apply(this);
        for (const value of array) {
          this[name].add(value);
        }
        break;
      case 'connected':
        if (!this.connected) {
          this._connectorElementInputs.clear();
          this._connectorElementOutputs.clear();
        }
        break;
    }
  }

  disconnectedCallback() {
    if (this.type & InputConnectorElement.TYPE_INPUT) {
      this.inputs.clear();
    }
    if (this.type & InputConnectorElement.TYPE_OUTPUT) {
      this.outputs.clear();
    }
  }

  set connected(value) {
    if (value) {
      this.setAttribute('connected', '');
    } else {
      this.removeAttribute('connected');
    }
  }

  get connected() {
    return this.hasAttribute('connected');
  }

  _onInputChange(event) {
    this._value = event.target.value;
    for (const output of this.outputs) {
      if (!(output instanceof InputConnectorElement)) {
        output.value = this._value;
      }
    }
    this.dispatchEvent(new event.constructor(event.type, event));
  }

  _updateConnectedStatus() {
    this.connected = !!this._connectorElementInputs.size || !!this._connectorElementOutputs.size;
    for (const output of this._inputElementOutputs) {
      output.disabled = this.connected;
    }
  }

  /**
   * Get current value stored in connector
   * @readonly
   */
  get value() {
    return this._value;
  }

  /**
   * Set of inputs
   * @readonly
   * @type {Set.<HTMLInputElement|InputConnectorElement>}
   */
  get inputs() {
    return this._inputs;
  }

  /**
   * Set of outputs
   * @readonly
   * @type {Set.<(HTMLInputElement|InputConnectorElement)>}
   */
  get outputs() {
    return this._outputs;
  }

  /**
   * Type of connector as flag
   * @readonly
   * @type {number}
   */
  get type() {
    return +!!this._inputElementInputs.size << 1 | +!!this._inputElementOutputs.size;
  }
}

export default InputConnectorElement;
<commit_msg>fix double event dispatch on connect<commit_after>/**
 * Connector element used to link inputs and other connectors together
 * @attribute inputs
 * @attribute outputs
 * @example <graph-connector
 *    inputs="[document.getElementById('input1'), document.getElementById('input2')]"
 *    outputs="[document.getElementById('output1'), document.getElementById('output2')]"
 * ></graph-connector>
 */
class InputConnectorElement extends HTMLElement {
  /**
   * Observed Attributes
   * @private
   * @constant {Array.<String>}
   */
  static get observedAttributes() {
    return ['inputs', 'outputs', 'connected'];
  }

  /**
   * Undefined type flag
   * @readonly
   * @constant {number}
   * @default 0
   */
  static get TYPE_UNDEFINED() {
    return 0;
  }

  /**
   * Input type flag
   * @readonly
   * @constant {number}
   * @default 1
   */
  static get TYPE_INPUT() {
    return 1;
  }

  /**
   * Output type flag
   * @readonly
   * @constant {number}
   * @default 2
   */
  static get TYPE_OUTPUT() {
    return 2;
  }

  /**
   * Both type flag
   * @readonly
   * @constant {number}
   * @default 3
   */
  static get TYPE_BOTH() {
    return 3;
  }

  /**
   * @abstract
   */
  constructor() {
    super();

    this.attachShadow({ mode: 'open' }).innerHTML = `
      <slot>

      </slot>
    `;

    this._onInputChangeBinded = this._onInputChange.bind(this);

    this._inputElementInputs = new Set();
    this._connectorElementInputs = new Set();

    this._inputElementOutputs = new Set();
    this._connectorElementOutputs = new Set();

    const self = this;

    this._inputs = new class extends Set {
      add(value) {
        if (this.has(value) || self === value) {
          return this;
        }
        super.add(value);
        if (value.value !== undefined) {
          self._value = value.value;
        }
        if (value instanceof InputConnectorElement) {
          self._connectorElementInputs.add(value);
          value.outputs.add(self);
        } else {
          self._inputElementInputs.add(value);
        }
        value.addEventListener('input', self._onInputChangeBinded);
        self._updateConnectedStatus();
        if (!(value instanceof InputConnectorElement)) {
          self.dispatchEvent(new InputEvent('input', {
            bubbles: true,
            composed: true,
          }));
        }
        return this;
      }
      delete(value) {
        const returnValue = super.delete(value);
        if (!returnValue) {
          return;
        }
        value.removeEventListener('input', self._onInputChangeBinded);
        if (value instanceof InputConnectorElement) {
          self._connectorElementInputs.delete(value);
          value.outputs.delete(self);
        } else {
          self._inputElementInputs.delete(value);
        }
        self._updateConnectedStatus();
        return returnValue;
      }
      clear() {
        for (const value of this) {
          this.delete(value);
        }
      }
    };

    this._outputs = new class extends Set {
      add(value) {
        if (this.has(value) || self === value) {
          return this;
        }
        super.add(value);
        if (value instanceof InputConnectorElement) {
          self._connectorElementOutputs.add(value);
          value.inputs.add(self);
          self.dispatchEvent(new CustomEvent('connected', {
            bubbles: true,
            composed: true,
            detail: {
              output: value,
            },
          }));
        } else {
          self._inputElementOutputs.add(value);
        }
        self._updateConnectedStatus();
        if (value instanceof InputConnectorElement) {
          self.dispatchEvent(new InputEvent('input', {
            bubbles: true,
            composed: true,
          }));
        }
        return this;
      }
      delete(value) {
        const returnValue = super.delete(value);
        if (!returnValue) {
          return;
        }
        self._connectorElementOutputs.delete(value);
        self._inputElementOutputs.delete(value);
        if (value instanceof InputConnectorElement) {
          value.inputs.delete(self);
        }
        self._updateConnectedStatus();
        if (value instanceof InputConnectorElement) {
          self.dispatchEvent(new CustomEvent('disconnected', {
            bubbles: true,
            composed: true,
            detail: {
              output: value,
            },
          }));
        }
        return returnValue;
      }
      clear() {
        for (const value of this) {
          this.delete(value);
        }
      }
    };
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue === newValue) {
      return;
    }

    switch (name) {
      case 'inputs':
      case 'outputs':
        const array = new Function(`return ${newValue}`).apply(this);
        for (const value of array) {
          this[name].add(value);
        }
        break;
      case 'connected':
        if (!this.connected) {
          this._connectorElementInputs.clear();
          this._connectorElementOutputs.clear();
        }
        break;
    }
  }

  disconnectedCallback() {
    if (this.type & InputConnectorElement.TYPE_INPUT) {
      this.inputs.clear();
    }
    if (this.type & InputConnectorElement.TYPE_OUTPUT) {
      this.outputs.clear();
    }
  }

  set connected(value) {
    if (value) {
      this.setAttribute('connected', '');
    } else {
      this.removeAttribute('connected');
    }
  }

  get connected() {
    return this.hasAttribute('connected');
  }

  _onInputChange(event) {
    this._value = event.target.value;
    for (const output of this.outputs) {
      if (!(output instanceof InputConnectorElement)) {
        output.value = this._value;
      }
    }
    this.dispatchEvent(new event.constructor(event.type, event));
  }

  _updateConnectedStatus() {
    this.connected = !!this._connectorElementInputs.size || !!this._connectorElementOutputs.size;
    for (const output of this._inputElementOutputs) {
      output.disabled = this.connected;
    }
  }

  /**
   * Get current value stored in connector
   * @readonly
   */
  get value() {
    return this._value;
  }

  /**
   * Set of inputs
   * @readonly
   * @type {Set.<HTMLInputElement|InputConnectorElement>}
   */
  get inputs() {
    return this._inputs;
  }

  /**
   * Set of outputs
   * @readonly
   * @type {Set.<(HTMLInputElement|InputConnectorElement)>}
   */
  get outputs() {
    return this._outputs;
  }

  /**
   * Type of connector as flag
   * @readonly
   * @type {number}
   */
  get type() {
    return +!!this._inputElementInputs.size << 1 | +!!this._inputElementOutputs.size;
  }
}

export default InputConnectorElement;
<|endoftext|>


<commit_before>(function () {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.common.PortfolioItemsGridBoardApp', {
        extend: 'Rally.app.GridBoardApp',
        requires: [
            'Rally.ui.cardboard.plugin.CollapsibleColumns',
            'Rally.ui.cardboard.plugin.FixedHeader'
        ],

        launch: function () {
            if (Rally.environment.getContext().getSubscription().isModuleEnabled('Rally Portfolio Manager')) {
                this.callParent(arguments);
            } else {
                this.add({
                    xtype: 'container',
                    html: '
You do not have RPM enabled for your subscription
'
                });

                this.publishComponentReady();
            }
        },

        loadModelNames: function () {
            return this._createPITypePicker().then({
                success: function (selectedType) {
                    this.currentType = selectedType;
                    return [selectedType.get('TypePath')];
                },
                scope: this
            });
        },

        addGridBoard: function () {
            if (this.gridboard && this.piTypePicker && this.piTypePicker.rendered) {
                this.piTypePicker.up().remove(this.piTypePicker, false);
            }
            this.callParent(arguments);
        },

        getHeaderControls: function () {
            return this.callParent(arguments).concat(this.piTypePicker);
        },

        getFilterControlConfig: function () {
            return {
                blackListFields: ['PortfolioItemType'],
                whiteListFields: ['Milestones']
            };
        },

        getFieldPickerConfig: function () {
            var blackListedFields = [];

            if(!this.getContext().isFeatureEnabled('S74502_PI_DEPENDENCIES_ON_EDP')) {
                blackListedFields.push('PredecessorsAndSuccessors');
            }
            return _.merge(this.callParent(arguments), {
                boardFieldDefaults: (this.getSetting('fields') || '').split(','),
                boardFieldBlackList: ['Predecessors', 'Successors'].concat(blackListedFields),
                gridFieldBlackList: blackListedFields,
                margin: '3 9 14 0'
            });
        },

        getCardBoardColumns: function () {
            return this._getStates().then({
                success: function (states) {
                    return this._buildColumns(states);
                },
                scope: this
            });
        },

        _buildColumns: function (states) {
            if (!states.length) {
                return undefined;
            }

            var columns = [
                {
                    columnHeaderConfig: {
                        headerTpl: 'No Entry'
                    },
                    value: null,
                    plugins: ['rallycardboardcollapsiblecolumns'].concat(this.getCardBoardColumnPlugins(null))
                }
            ];

            return columns.concat(_.map(states, function (state) {
                return {
                    value: state.get('_ref'),
                    wipLimit: state.get('WIPLimit'),
                    enableWipLimit: true,
                    columnHeaderConfig: {
                        record: state,
                        fieldToDisplay: 'Name',
                        editable: false
                    },
                    plugins: ['rallycardboardcollapsiblecolumns'].concat(this.getCardBoardColumnPlugins(state))
                };
            }, this));
        },

        _getStates: function () {
            var deferred = new Deft.Deferred();
            Ext.create('Rally.data.wsapi.Store', {
                model: Ext.identityFn('State'),
                context: this.getContext().getDataContext(),
                autoLoad: true,
                fetch: ['Name', 'WIPLimit', 'Description'],
                filters: [
                    {
                        property: 'TypeDef',
                        value: this.currentType.get('_ref')
                    },
                    {
                        property: 'Enabled',
                        value: true
                    }
                ],
                sorters: [
                    {
                        property: 'OrderIndex',
                        direction: 'ASC'
                    }
                ],
                listeners: {
                    load: function (store, records) {
                        deferred.resolve(records);
                    }
                }
            });
            return deferred.promise;
        },

        getCardBoardColumnPlugins: function (state) {
            return [];
        },

        getCardConfig: function () {
            return {};
        },

        getCardBoardConfig: function (options) {
            options = options || {};
            var currentTypePath = this.currentType.get('TypePath');
            var filters = [];

            if (this.getSetting('query')) {
                try {
                    filters.push(Rally.data.QueryFilter.fromQueryString(this.getSetting('query')));
                } catch (e) {
                    Rally.ui.notify.Notifier.showError({ message: e.message });
                }
            }

            return {
                attribute: 'State',
                cardConfig: _.merge({
                    editable: true,
                    showColorIcon: true
                }, this.getCardConfig()),
                columnConfig: {
                    xtype: 'rallycardboardcolumn',
                    enableWipLimit: true
                },
                columns: options.columns,
                ddGroup: currentTypePath,
                listeners: {
                    load: this.publishComponentReady,
                    cardupdated: this._publishContentUpdatedNoDashboardLayout,
                    scope: this
                },
                plugins: [{ ptype: 'rallyfixedheadercardboard' }],
                storeConfig: {
                    filters: filters,
                    context: this.getContext().getDataContext()
                }
            };
        },

        getGridStoreConfig: function () {
            return { models: this.piTypePicker.getAllTypeNames() };
        },

        _createPITypePicker: function () {
            if (this.piTypePicker) {
                this.piTypePicker.destroy();
            }

            var deferred = new Deft.Deferred();

            this.piTypePicker = Ext.create('Rally.ui.combobox.PortfolioItemTypeComboBox', {
                preferenceName: 'portfolioitems' + this.stateName + '-typepicker',
                value: this.getSetting('type'),
                context: this.getContext(),
                listeners: {
                    change: this._onTypeChange,
                    ready: {
                        fn: function (picker) {
                            deferred.resolve(picker.getSelectedType());
                        },
                        single: true
                    },
                    scope: this
                }
            });

            return deferred.promise;
        },

        _onTypeChange: function (picker) {
            var newType = picker.getSelectedType();

            if (this._pickerTypeChanged(picker)) {
                this.currentType = newType;
                this.modelNames = [newType.get('TypePath')];
                this.gridboard.fireEvent('modeltypeschange', this.gridboard, [newType]);
            }
        },

        _pickerTypeChanged: function(picker){
            var newType = picker.getSelectedType();
            return newType && this.currentType && newType.get('_ref') !== this.currentType.get('_ref');
        },

        _publishContentUpdatedNoDashboardLayout: function () {
            this.fireEvent('contentupdated', { dashboardLayout: false });
        }
    });
})();<commit_msg>S82550: Remove PI Dependencies toggles<commit_after>(function () {
    var Ext = window.Ext4 || window.Ext;

    Ext.define('Rally.apps.common.PortfolioItemsGridBoardApp', {
        extend: 'Rally.app.GridBoardApp',
        requires: [
            'Rally.ui.cardboard.plugin.CollapsibleColumns',
            'Rally.ui.cardboard.plugin.FixedHeader'
        ],

        launch: function () {
            if (Rally.environment.getContext().getSubscription().isModuleEnabled('Rally Portfolio Manager')) {
                this.callParent(arguments);
            } else {
                this.add({
                    xtype: 'container',
                    html: '
You do not have RPM enabled for your subscription
'
                });

                this.publishComponentReady();
            }
        },

        loadModelNames: function () {
            return this._createPITypePicker().then({
                success: function (selectedType) {
                    this.currentType = selectedType;
                    return [selectedType.get('TypePath')];
                },
                scope: this
            });
        },

        addGridBoard: function () {
            if (this.gridboard && this.piTypePicker && this.piTypePicker.rendered) {
                this.piTypePicker.up().remove(this.piTypePicker, false);
            }
            this.callParent(arguments);
        },

        getHeaderControls: function () {
            return this.callParent(arguments).concat(this.piTypePicker);
        },

        getFilterControlConfig: function () {
            return {
                blackListFields: ['PortfolioItemType'],
                whiteListFields: ['Milestones']
            };
        },

        getFieldPickerConfig: function () {
            return _.merge(this.callParent(arguments), {
                boardFieldDefaults: (this.getSetting('fields') || '').split(','),
                boardFieldBlackList: ['Predecessors', 'Successors'],
                margin: '3 9 14 0'
            });
        },

        getCardBoardColumns: function () {
            return this._getStates().then({
                success: function (states) {
                    return this._buildColumns(states);
                },
                scope: this
            });
        },

        _buildColumns: function (states) {
            if (!states.length) {
                return undefined;
            }

            var columns = [
                {
                    columnHeaderConfig: {
                        headerTpl: 'No Entry'
                    },
                    value: null,
                    plugins: ['rallycardboardcollapsiblecolumns'].concat(this.getCardBoardColumnPlugins(null))
                }
            ];

            return columns.concat(_.map(states, function (state) {
                return {
                    value: state.get('_ref'),
                    wipLimit: state.get('WIPLimit'),
                    enableWipLimit: true,
                    columnHeaderConfig: {
                        record: state,
                        fieldToDisplay: 'Name',
                        editable: false
                    },
                    plugins: ['rallycardboardcollapsiblecolumns'].concat(this.getCardBoardColumnPlugins(state))
                };
            }, this));
        },

        _getStates: function () {
            var deferred = new Deft.Deferred();
            Ext.create('Rally.data.wsapi.Store', {
                model: Ext.identityFn('State'),
                context: this.getContext().getDataContext(),
                autoLoad: true,
                fetch: ['Name', 'WIPLimit', 'Description'],
                filters: [
                    {
                        property: 'TypeDef',
                        value: this.currentType.get('_ref')
                    },
                    {
                        property: 'Enabled',
                        value: true
                    }
                ],
                sorters: [
                    {
                        property: 'OrderIndex',
                        direction: 'ASC'
                    }
                ],
                listeners: {
                    load: function (store, records) {
                        deferred.resolve(records);
                    }
                }
            });
            return deferred.promise;
        },

        getCardBoardColumnPlugins: function (state) {
            return [];
        },

        getCardConfig: function () {
            return {};
        },

        getCardBoardConfig: function (options) {
            options = options || {};
            var currentTypePath = this.currentType.get('TypePath');
            var filters = [];

            if (this.getSetting('query')) {
                try {
                    filters.push(Rally.data.QueryFilter.fromQueryString(this.getSetting('query')));
                } catch (e) {
                    Rally.ui.notify.Notifier.showError({ message: e.message });
                }
            }

            return {
                attribute: 'State',
                cardConfig: _.merge({
                    editable: true,
                    showColorIcon: true
                }, this.getCardConfig()),
                columnConfig: {
                    xtype: 'rallycardboardcolumn',
                    enableWipLimit: true
                },
                columns: options.columns,
                ddGroup: currentTypePath,
                listeners: {
                    load: this.publishComponentReady,
                    cardupdated: this._publishContentUpdatedNoDashboardLayout,
                    scope: this
                },
                plugins: [{ ptype: 'rallyfixedheadercardboard' }],
                storeConfig: {
                    filters: filters,
                    context: this.getContext().getDataContext()
                }
            };
        },

        getGridStoreConfig: function () {
            return { models: this.piTypePicker.getAllTypeNames() };
        },

        _createPITypePicker: function () {
            if (this.piTypePicker) {
                this.piTypePicker.destroy();
            }

            var deferred = new Deft.Deferred();

            this.piTypePicker = Ext.create('Rally.ui.combobox.PortfolioItemTypeComboBox', {
                preferenceName: 'portfolioitems' + this.stateName + '-typepicker',
                value: this.getSetting('type'),
                context: this.getContext(),
                listeners: {
                    change: this._onTypeChange,
                    ready: {
                        fn: function (picker) {
                            deferred.resolve(picker.getSelectedType());
                        },
                        single: true
                    },
                    scope: this
                }
            });

            return deferred.promise;
        },

        _onTypeChange: function (picker) {
            var newType = picker.getSelectedType();

            if (this._pickerTypeChanged(picker)) {
                this.currentType = newType;
                this.modelNames = [newType.get('TypePath')];
                this.gridboard.fireEvent('modeltypeschange', this.gridboard, [newType]);
            }
        },

        _pickerTypeChanged: function(picker){
            var newType = picker.getSelectedType();
            return newType && this.currentType && newType.get('_ref') !== this.currentType.get('_ref');
        },

        _publishContentUpdatedNoDashboardLayout: function () {
            this.fireEvent('contentupdated', { dashboardLayout: false });
        }
    });
})();<|endoftext|>


<commit_before>/* eslint max-len:0 */

export default {
  title: `Live at Fluent Conf`,
  time: '**12:45** PM **PST**',
  guests: [
    {
      name: 'Fluent Conf',
      twitter: 'fluentconf',
      squareImage: true,
    },
  ],
  description: `
    Live at [Fluent Conf](http://conferences.oreilly.com/fluent/javascript-html-us), the web conference from O'Reilly Media about JavaScript, HTML5, CSS, and the latest web development technologies and frameworks.
  `,
  hangoutId: 'c7vou4l3f49a9vcamh1it3mru5c',
  youTubeId: 'R0eIlOvo5Js',
  podbeanId: '',
  host: {
    links: [
    ],
    tips: [
    ],
    picks: [
    ],
  },
  panelists: [
    {
      twitter: 'dan_abramov',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'drboolean',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'getify',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'kwuchu',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'linclark',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'mzabriskie',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'pamasaur',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'tylermcginnis33',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
}

<commit_msg>Add stuff for #39 (Fluent Conf)<commit_after>/* eslint max-len:0 */

export default {
  title: `Live at Fluent Conf`,
  time: '**12:45** PM **PST**',
  guests: [
    {
      name: 'Fluent Conf',
      twitter: 'fluentconf',
      squareImage: true,
    },
  ],
  description: `
    Live at [Fluent Conf](http://conferences.oreilly.com/fluent/javascript-html-us), the web conference from O'Reilly Media about JavaScript, HTML5, CSS, and the latest web development technologies and frameworks.

  Guests:

- [Simon St. Laurent](https://twitter.com/simonstl) & [Peter Cooper](https://twitter.com/simonstl) - Fluent Conf chairs
- [Jen Looper](https://twitter.com/jenlooper) - Getting physical with the beacon-enabled Web
- [Maximiliano Firtman](https://twitter.com/firt) - Advanced mobile Web
- [Jen Kramer](https://twitter.com/jen4web) - Planning successful products
- [Rachel Andrew](https://twitter.com/rachelandrew) - Making sense of the new CSS layout
  `,
  hangoutId: 'c7vou4l3f49a9vcamh1it3mru5c',
  youTubeId: 'R0eIlOvo5Js',
  podbeanId: 'a2jc5-5d6380',
  shortUrl: 'http://jsair.io/fluent-conf',
  past: true,
  hideShowNotes: true,
}

<|endoftext|>


<commit_before>Core.Object.extend('Core.FilePostUploader',
/**@lends Core.FilePostUploader#*/
{
	/**
	 * Fires when each time upload progress, usefull to create a upload progress bar
	 * @name Core.FilePostUploader#progress
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 * @param {number} loaded Amount of bytes loaded
	 * @param {number} total Total amount of bytes to load
	 */
	/**
	 * Fires when upload request got status == 200
	 * @name Core.FilePostUploader#complete
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 */
	/**
	 * Fires when upload request got status != 200 or when there is a error while reading the file
	 * @name Core.FilePostUploader#complete
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 */

	file: undefined,
	destination: undefined,
	service: undefined,
	reader: undefined,
	request: undefined,
	binaryString: false,
	responseText: undefined,
	fileReader: undefined,
	boundary: undefined,
	method: 'POST',

	loadedOctets: undefined,
	totalOctets: undefined,

	/**
	*	@constructs
	*	@class Helper to allow file uploading with progress report and which
	* use the best technic (FileApi, FormData, input tag) depending on the browser capabilities.
	*	@extends Core.Object
	*/
	constructor: function(config) {
		this.addEvents('progress', 'complete', 'error');
	},

	setMethod: function(method) {
		this.method = method;
	},

	getFile: function() {
		return this.file;
	},

	setFile: function(file) {
		this.file = file;
	},

	setService: function(service) {
		this.service = service;
	},

	setDestination: function(destination) {
		this.destination = destination;
	},

	/**Send the file*/
	send: function() {
		/**#nocode+ Avoid Jsdoc warnings...*/
		if(this.file.fileApi != undefined) {
			if(navigator.supportFormData) {
				var formData = new FormData();
				if(this.destination == undefined)
					this.destination = this.file.getFileName();
				formData.append("destination", this.destination);
				formData.append("file", this.file.fileApi);

				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open(this.method, this.service);
				this.request.send(formData);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;
			}
			else {
				this.fileReader = new FileReader();
				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open(this.method, this.service);

				this.boundary = '----';
                var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                for(var i = 0; i < 16; i++)
					this.boundary += characters[Math.floor(Math.random()*characters.length)];
				this.boundary += '----';

				this.request.setRequestHeader("Content-Type", "multipart/form-data, boundary="+this.boundary);
				this.request.setRequestHeader("Content-Length", this.file.fileApi.size);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;

				var readerWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerWrapper.scope = this;
				readerWrapper.callback = this.onFileReaderLoad;
				this.fileReader.onload = readerWrapper;

				var readerErrorWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerErrorWrapper.scope = this;
				readerErrorWrapper.callback = this.onFileReaderError;
				this.fileReader.onerror = readerErrorWrapper;

				this.fileReader.readAsBinaryString(this.file.fileApi);
			}
		}
		else {
			this.file.form.action = this.service;

			var destDrawing = document.createElement('input');
			destDrawing.type = 'hidden';
			destDrawing.setAttribute('name', 'destination');
			destDrawing.setAttribute('value', this.destination);
			this.file.form.insertBefore(destDrawing, this.file.form.firstChild);

			this.connect(this.file.iframe, 'load', this.onIFrameLoad);
			var errorCount = 0;
			var done = false;
			while(!done && (errorCount < 5)) {
				try {
					this.file.form.submit();
					done = true;
				}
				catch(e) {
					errorCount++;
				}
			}
		}
	/**#nocode-*/
	},

	abort: function() {
		if(this.request != undefined)
			this.request.abort();
	},

	getResponseText: function() {
		return this.responseText;
	},

	getResponseJSON: function() {
		var res;
		try {
			res = JSON.parse(this.getResponseText());
		}
		catch(err) {
			res = undefined;
		}
		return res;
	},

	/**#@+
	* @private
	*/
	onStateChange: function(event) {
		if(this.request.readyState == 4) {
			if(this.request.status == 200) {
				this.responseText = this.request.responseText;
				this.fireEvent('complete', this);
			}
			else {
				this.responseText = this.request.responseText;
				this.fireEvent('error', this, this.request.status);
			}
			this.request = undefined;
		}
	},

	getTotal: function() {
		return this.totalOctets;
	},

	getLoaded: function() {
		return this.loadedOctets;
	},

	onUpdateProgress: function(event) {
		this.loadedOctets = event.loaded;
		this.totalOctets = event.total;
		this.fireEvent('progress', this, event.loaded, event.total);
	},

	onFileReaderError: function(event) {
		this.request.abort();
		this.request = undefined;
		this.fireEvent('error', this);
		this.fileReader = undefined;
	},

	onFileReaderLoad: function(event) {
		var body = '--'+this.boundary+'\r\n';
		body += "Content-Disposition: form-data; name='file'; filename='"+this.file.fileApi.name+"'\r\n";
		body += 'Content-Type: '+this.file.fileApi.type+'\r\n\r\n';
		body += event.target.result+'\r\n';
		body += '--'+this.boundary+'--';
		this.request.sendAsBinary(body);

		this.fileReader = undefined;
	},

	onIFrameLoad: function(event) {
		this.responseText = event.target.contentWindow.document.body.innerText;
		document.body.removeChild(this.file.iframe);
		this.fireEvent('complete', this);
	}
	/**#@-*/
});

<commit_msg>add setField to Core.FileUploader to allow custom multipart post parts<commit_after>Core.Object.extend('Core.FilePostUploader',
/**@lends Core.FilePostUploader#*/
{
	/**
	 * Fires when each time upload progress, usefull to create a upload progress bar
	 * @name Core.FilePostUploader#progress
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 * @param {number} loaded Amount of bytes loaded
	 * @param {number} total Total amount of bytes to load
	 */
	/**
	 * Fires when upload request got status == 200
	 * @name Core.FilePostUploader#complete
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 */
	/**
	 * Fires when upload request got status != 200 or when there is a error while reading the file
	 * @name Core.FilePostUploader#complete
	 * @event
	 * @param {Core.FilePostUploader} uploader The uploader itself
	 */

	file: undefined,
	service: undefined,
	reader: undefined,
	request: undefined,
	binaryString: false,
	responseText: undefined,
	fileReader: undefined,
	boundary: undefined,
	method: 'POST',
	fields: undefined,

	loadedOctets: undefined,
	totalOctets: undefined,

	/**
	*	@constructs
	*	@class Helper to allow file uploading with progress report and which
	* use the best technic (FileApi, FormData, input tag) depending on the browser capabilities.
	*	@extends Core.Object
	*/
	constructor: function(config) {
		this.addEvents('progress', 'complete', 'error');
		this.fields = {};
	},

	setMethod: function(method) {
		this.method = method;
	},

	getFile: function() {
		return this.file;
	},

	setFile: function(file) {
		this.file = file;
	},

	setService: function(service) {
		this.service = service;
	},

	setField: function(name, value) {
		this.fields[name] = value;
	},

	setDestination: function(destination) {
		this.setField('destination', destination);
	},

	/**Send the file*/
	send: function() {
		/**#nocode+ Avoid Jsdoc warnings...*/
		if(this.file.fileApi != undefined) {
			if(navigator.supportFormData) {
				var formData = new FormData();
				if(this.destination == undefined)
					this.destination = this.file.getFileName();
				for(var field in this.fields) {
					formData.append(field, this.fields[field]);
				}
				formData.append("file", this.file.fileApi);

				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open(this.method, this.service);
				this.request.send(formData);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;
			}
			else {
				this.fileReader = new FileReader();
				this.request = new XMLHttpRequest();
				if('upload' in this.request)
					this.connect(this.request.upload, 'progress', this.onUpdateProgress);
				this.request.open(this.method, this.service);

				this.boundary = '----';
                var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                for(var i = 0; i < 16; i++)
					this.boundary += characters[Math.floor(Math.random()*characters.length)];
				this.boundary += '----';

				this.request.setRequestHeader("Content-Type", "multipart/form-data, boundary="+this.boundary);
				this.request.setRequestHeader("Content-Length", this.file.fileApi.size);

				var wrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				wrapper.scope = this;
				wrapper.callback = this.onStateChange;
				this.request.onreadystatechange = wrapper;

				var readerWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerWrapper.scope = this;
				readerWrapper.callback = this.onFileReaderLoad;
				this.fileReader.onload = readerWrapper;

				var readerErrorWrapper = function() {
					return arguments.callee.callback.apply(arguments.callee.scope, arguments);
				}
				readerErrorWrapper.scope = this;
				readerErrorWrapper.callback = this.onFileReaderError;
				this.fileReader.onerror = readerErrorWrapper;

				this.fileReader.readAsBinaryString(this.file.fileApi);
			}
		}
		else {
			this.file.form.action = this.service;

			for(var field in this.fields) {
				var fieldDrawing = document.createElement('input');
				fieldDrawing.type = 'hidden';
				fieldDrawing.setAttribute('name', field);
				destDrawing.setAttribute('value', this.fields[field]);
				this.file.form.insertBefore(fieldDrawing, this.file.form.firstChild);
			}
			this.connect(this.file.iframe, 'load', this.onIFrameLoad);
			var errorCount = 0;
			var done = false;
			while(!done && (errorCount < 5)) {
				try {
					this.file.form.submit();
					done = true;
				}
				catch(e) {
					errorCount++;
				}
			}
		}
	/**#nocode-*/
	},

	abort: function() {
		if(this.request != undefined)
			this.request.abort();
	},

	getResponseText: function() {
		return this.responseText;
	},

	getResponseJSON: function() {
		var res;
		try {
			res = JSON.parse(this.getResponseText());
		}
		catch(err) {
			res = undefined;
		}
		return res;
	},

	/**#@+
	* @private
	*/
	onStateChange: function(event) {
		if(this.request.readyState == 4) {
			if(this.request.status == 200) {
				this.responseText = this.request.responseText;
				this.fireEvent('complete', this);
			}
			else {
				this.responseText = this.request.responseText;
				this.fireEvent('error', this, this.request.status);
			}
			this.request = undefined;
		}
	},

	getTotal: function() {
		return this.totalOctets;
	},

	getLoaded: function() {
		return this.loadedOctets;
	},

	onUpdateProgress: function(event) {
		this.loadedOctets = event.loaded;
		this.totalOctets = event.total;
		this.fireEvent('progress', this, event.loaded, event.total);
	},

	onFileReaderError: function(event) {
		this.request.abort();
		this.request = undefined;
		this.fireEvent('error', this);
		this.fileReader = undefined;
	},

	onFileReaderLoad: function(event) {
		var body = '--'+this.boundary+'\r\n';
		body += "Content-Disposition: form-data; name='file'; filename='"+this.file.fileApi.name+"'\r\n";
		body += 'Content-Type: '+this.file.fileApi.type+'\r\n\r\n';
		body += event.target.result+'\r\n';
		body += '--'+this.boundary+'--';
		this.request.sendAsBinary(body);

		this.fileReader = undefined;
	},

	onIFrameLoad: function(event) {
		this.responseText = event.target.contentWindow.document.body.innerText;
		document.body.removeChild(this.file.iframe);
		this.fireEvent('complete', this);
	}
	/**#@-*/
});

<|endoftext|>


<commit_before>/* global window document */
import React from 'react';
import Icon from '@economist/component-icon';
import reactCookie from 'react-cookie';
import LinkButton from '@economist/component-link-button';
import BarWrapper from '@economist/component-bar-wrapper';

const betaText = [
  (

      You’re viewing a beta release of

        {" The Economist’"}

      s new website

  ),
  (

      {' We would like to hear what you think'}

  ),
];

const googleForm = 'https://docs.google.com/forms/d/1ZCdwituoyhHAPKjCKvDvzRp66zwOv23GrCPH4rGINrE/viewform';

export default class BetaBar extends React.Component {
  static propTypes = {
    cookieName: React.PropTypes.string,
    cookieValue: React.PropTypes.string,
    closeCookieName: React.PropTypes.string,
    closeCookieValue: React.PropTypes.string,
    reactCookieInstance: React.PropTypes.shape({
      save: React.PropTypes.func,
    }),
    onFallback: React.PropTypes.func,
    stillRenderWhenClosed: React.PropTypes.bool,
  }
  static defaultProps = {
    cookieName: 'ec_blogsab',
    cookieValue: 'a',
    closeCookieName: 'ec_rvmp_beta_close',
    closeCookieValue: 'x',
    reactCookieInstance: reactCookie,
  }
  constructor(...args) {
    super(...args);
    this.handleFallback = this.handleFallback.bind(this);
    this.handleDismiss = this.handleDismiss.bind(this);
    if (!this.state) {
      this.state = {};
    }
  }
  handleFallback(event) {
    if (typeof window === 'undefined') { return; }
    const { cookieName, cookieValue, reactCookieInstance } = this.props;

    if (cookieName && cookieValue && reactCookieInstance) {
      reactCookieInstance.save(cookieName, cookieValue, {
        maxAge: 30 * 24 * 60 * 60,
        path: '/',
      });
      if (this.props.onFallback) {
        this.props.onFallback();
      }
    }

    if (event) {
      event.preventDefault();
    }
  }
  handleDismiss(event) {
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;

    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      reactCookieInstance.save(closeCookieName, closeCookieValue)
    }

    this.setState({ wasDismissed: true });

    if (event) {
      event.preventDefault();
    }
  }
  componentWillMount() {
    if (typeof window === 'undefined') { return; }
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;
    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      this.setState({
        wasDismissed: reactCookieInstance.load(this.props.closeCookieName) === this.props.closeCookieValue,
      });
    }
  }
  render() {
    let classNames = [ 'beta-bar' ];
    if (this.state && this.state.wasDismissed) {
      classNames = classNames.concat([ 'beta-bar--dismissed' ]);
    }

    const feedbackButtonProps = { className: "beta-bar--feedback", href: googleForm, target: "_blank", children: 'Leave feedback' }
    const feedbackButton = this.props.renderFeedbackLink ? this.props.renderFeedbackLink(feedbackButtonProps) : (
      <LinkButton {...feedbackButtonProps}></LinkButton>
    );

    const fallbackButtonProps = { className: "beta-bar--old-version", href: "#", onClick: this.handleFallback, children: 'Back to old version' }
    const fallbackButton = this.props.renderFallbackLink ? this.props.renderFallbackLink(fallbackButtonProps) : (

    );

    const displayCloseButton = !(this.state && this.state.wasDismissed);

    return (
      <BarWrapper className={classNames.join(' ')} classNamePrefix="beta-bar" onClose={this.handleDismiss} close={displayCloseButton}>
        {betaText}

          {feedbackButton}
          {fallbackButton}

      </BarWrapper>
    );
  }
}
<commit_msg>fix: Render the betabar when closed<commit_after>/* global window document */
import React from 'react';
import Icon from '@economist/component-icon';
import reactCookie from 'react-cookie';
import LinkButton from '@economist/component-link-button';
import BarWrapper from '@economist/component-bar-wrapper';

const betaText = [
  (

      You’re viewing a beta release of

        {" The Economist’"}

      s new website

  ),
  (

      {' We would like to hear what you think'}

  ),
];

const googleForm = 'https://docs.google.com/forms/d/1ZCdwituoyhHAPKjCKvDvzRp66zwOv23GrCPH4rGINrE/viewform';

export default class BetaBar extends React.Component {
  static propTypes = {
    cookieName: React.PropTypes.string,
    cookieValue: React.PropTypes.string,
    closeCookieName: React.PropTypes.string,
    closeCookieValue: React.PropTypes.string,
    reactCookieInstance: React.PropTypes.shape({
      save: React.PropTypes.func,
    }),
    onFallback: React.PropTypes.func,
    stillRenderWhenClosed: React.PropTypes.bool,
  }
  static defaultProps = {
    cookieName: 'ec_blogsab',
    cookieValue: 'a',
    closeCookieName: 'ec_rvmp_beta_close',
    closeCookieValue: 'x',
    reactCookieInstance: reactCookie,
  }
  constructor(...args) {
    super(...args);
    this.handleFallback = this.handleFallback.bind(this);
    this.handleDismiss = this.handleDismiss.bind(this);
    if (!this.state) {
      this.state = {};
    }
  }
  handleFallback(event) {
    if (typeof window === 'undefined') { return; }
    const { cookieName, cookieValue, reactCookieInstance } = this.props;

    if (cookieName && cookieValue && reactCookieInstance) {
      reactCookieInstance.save(cookieName, cookieValue, {
        maxAge: 30 * 24 * 60 * 60,
        path: '/',
      });
      if (this.props.onFallback) {
        this.props.onFallback();
      }
    }

    if (event) {
      event.preventDefault();
    }
  }
  handleDismiss(event) {
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;

    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      reactCookieInstance.save(closeCookieName, closeCookieValue)
    }

    this.setState({ wasDismissed: true });

    if (event) {
      event.preventDefault();
    }
  }
  componentWillMount() {
    if (typeof window === 'undefined') { return; }
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;
    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      this.setState({
        wasDismissed: reactCookieInstance.load(this.props.closeCookieName) === this.props.closeCookieValue,
      });
    }
  }
  render() {
    let classNames = [ 'beta-bar' ];
    if (this.state && this.state.wasDismissed) {
      classNames = classNames.concat([ 'beta-bar--dismissed' ]);
    }

    const feedbackButtonProps = { className: "beta-bar--feedback", href: googleForm, target: "_blank", children: 'Leave feedback' }
    const feedbackButton = this.props.renderFeedbackLink ? this.props.renderFeedbackLink(feedbackButtonProps) : (
      <LinkButton {...feedbackButtonProps}></LinkButton>
    );

    const fallbackButtonProps = { className: "beta-bar--old-version", href: "#", onClick: this.handleFallback, children: 'Back to old version' }
    const fallbackButton = this.props.renderFallbackLink ? this.props.renderFallbackLink(fallbackButtonProps) : (

    );

    const displayCloseButton = !(this.state && this.state.wasDismissed);

    return (
      <BarWrapper className={classNames.join(' ')} classNamePrefix="beta-bar" onClose={this.handleDismiss} close={displayCloseButton} stillRenderWhenClosed={this.props.stillRenderWhenClosed}>
        {betaText}

          {feedbackButton}
          {fallbackButton}

      </BarWrapper>
    );
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var parallel = require('run-parallel');

var errors = require('./errors');
var OutArgStream = require('./argstream').OutArgStream;

var emptyBuffer = Buffer(0);

var States = Object.create(null);
States.Initial = 0;
States.Streaming = 1;
States.Done = 2;
States.Error = 3;

function TChannelOutgoingRequest(id, options) {
    options = options || {};
    if (!options.sendFrame) {
        throw new Error('missing sendFrame');
    }
    var self = this;
    EventEmitter.call(self);
    self.logger = options.logger;
    self.random = options.random;
    self.timers = options.timers;

    self.remoteAddr = options.remoteAddr;
    self.state = States.Initial;
    self.id = id || 0;
    self.ttl = options.ttl || 0;
    self.tracing = options.tracing || null;
    self.service = options.service || '';
    self.headers = options.headers || {};
    self.checksumType = options.checksumType || 0;
    self.checksum = options.checksum || null;

    self.sendFrame = options.sendFrame;
    if (options.streamed) {
        self.streamed = true;
        self._argstream = OutArgStream();
        self.arg1 = self._argstream.arg1;
        self.arg2 = self._argstream.arg2;
        self.arg3 = self._argstream.arg3;
        self._argstream.on('error', function passError(err) {
            self.emit('error', err);
        });
        self._argstream.on('frame', function onFrame(parts, isLast) {
            self.sendParts(parts, isLast);
        });
        self._argstream.on('finish', function onFinish() {
            self.emit('finish');
        });
    } else {
        self.streamed = false;
        self._argstream = null;
        self.arg1 = null;
        self.arg2 = null;
        self.arg3 = null;
    }

    if (options.tracer) {
        // new span with new ids
        self.span = options.tracer.setupNewSpan({
            spanid: null,
            traceid: null,
            parentid: null,
            flags: options.trace? 1 : 0,
            hostPort: options.host,
            serviceName: options.serviceName,
            name: '' // fill this in later
        });

        self.tracing = self.span.getTracing();
    } else {
        self.span = null;
    }

    self.res = null;
    self.start = self.timers.now();
    self.timedOut = false;
}

inherits(TChannelOutgoingRequest, EventEmitter);

TChannelOutgoingRequest.prototype.sendParts = function sendParts(parts, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            self.sendCallRequestFrame(parts, isLast);
            break;
        case States.Streaming:
            self.sendCallRequestContFrame(parts, isLast);
            break;
        case States.Done:
            // TODO: could probably happen normally, like say if a
            // streaming request is canceled
            throw new Error('got frame in done state'); // TODO: typed error
        case States.Error:
            // TODO: log warn
            break;
    }
};

TChannelOutgoingRequest.prototype.sendCallRequestFrame = function sendCallRequestFrame(args, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            if (self.span) {
                self.span.annotate('cs');
            }
            self.sendFrame.callRequest(args, isLast);
            if (isLast) self.state = States.Done;
            else self.state = States.Streaming;
            break;
        case States.Streaming:
            throw new Error('first request frame already sent'); // TODO: typed error
        case States.Done:
            throw new Error('request already done'); // TODO: typed error
    }
};

TChannelOutgoingRequest.prototype.sendCallRequestContFrame = function sendCallRequestContFrame(args, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            throw new Error('first request frame not sent'); // TODO: typed error
        case States.Streaming:
            self.sendFrame.callRequestCont(args, isLast);
            if (isLast) self.state = States.Done;
            break;
        case States.Done:
            throw new Error('request already done'); // TODO: typed error
    }
};

TChannelOutgoingRequest.prototype.send = function send(arg1, arg2, arg3, callback) {
    var self = this;

    if (self.span) {
        self.span.name = String(arg1);
    }
    if (callback) self.hookupCallback(callback);
    if (self.streamed) {
        self.arg1.end(arg1);
        self.arg2.end(arg2);
        self.arg3.end(arg3);
    } else {
        self.sendCallRequestFrame([
            arg1 ? Buffer(arg1) : emptyBuffer,
            arg2 ? Buffer(arg2) : emptyBuffer,
            arg3 ? Buffer(arg3) : emptyBuffer
        ], true);
        self.emit('finish');
    }
    return self;
};

TChannelOutgoingRequest.prototype.hookupStreamCallback = function hookupCallback(callback) {
    var self = this;
    var called = false;
    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        callback(null, self, res);
    }

    return self;
};

TChannelOutgoingRequest.prototype.hookupCallback = function hookupCallback(callback) {
    var self = this;
    if (callback.canStream) {
        return self.hookupStreamCallback(callback);
    }
    var called = false;

    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        if (!res.streamed) {
            callback(null, res, res.arg2, res.arg3);
            return;
        }
        parallel({
            arg2: res.arg2.onValueReady,
            arg3: res.arg3.onValueReady
        }, compatCall);
        function compatCall(err, args) {
            callback(err, res, args.arg2, args.arg3);
        }
    }

    return self;
};

TChannelOutgoingRequest.prototype.checkTimeout = function checkTimeout() {
    var self = this;
    if (!self.timedOut) {
        var elapsed = self.timers.now() - self.start;
        if (elapsed > self.ttl) {
            self.timedOut = true;
            process.nextTick(function deferOutReqTimeoutErrorEmit() {
                self.emit('error', errors.TimeoutError({
                    id: self.id,
                    start: self.start,
                    elapsed: elapsed,
                    timeout: self.ttl
                }));
            });
        }
    }
    return self.timedOut;
};

TChannelOutgoingRequest.States = States;

module.exports = TChannelOutgoingRequest;
<commit_msg>TChannelOutgoingRequest: reach into self not options for span host/service<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var parallel = require('run-parallel');

var errors = require('./errors');
var OutArgStream = require('./argstream').OutArgStream;

var emptyBuffer = Buffer(0);

var States = Object.create(null);
States.Initial = 0;
States.Streaming = 1;
States.Done = 2;
States.Error = 3;

function TChannelOutgoingRequest(id, options) {
    options = options || {};
    if (!options.sendFrame) {
        throw new Error('missing sendFrame');
    }
    var self = this;
    EventEmitter.call(self);
    self.logger = options.logger;
    self.random = options.random;
    self.timers = options.timers;

    self.remoteAddr = options.remoteAddr;
    self.state = States.Initial;
    self.id = id || 0;
    self.ttl = options.ttl || 0;
    self.tracing = options.tracing || null;
    self.service = options.service || '';
    self.headers = options.headers || {};
    self.checksumType = options.checksumType || 0;
    self.checksum = options.checksum || null;

    self.sendFrame = options.sendFrame;
    if (options.streamed) {
        self.streamed = true;
        self._argstream = OutArgStream();
        self.arg1 = self._argstream.arg1;
        self.arg2 = self._argstream.arg2;
        self.arg3 = self._argstream.arg3;
        self._argstream.on('error', function passError(err) {
            self.emit('error', err);
        });
        self._argstream.on('frame', function onFrame(parts, isLast) {
            self.sendParts(parts, isLast);
        });
        self._argstream.on('finish', function onFinish() {
            self.emit('finish');
        });
    } else {
        self.streamed = false;
        self._argstream = null;
        self.arg1 = null;
        self.arg2 = null;
        self.arg3 = null;
    }

    if (options.tracer) {
        // new span with new ids
        self.span = options.tracer.setupNewSpan({
            spanid: null,
            traceid: null,
            parentid: null,
            flags: options.trace? 1 : 0,
            hostPort: self.remoteAddr,
            serviceName: self.service,
            name: '' // fill this in later
        });

        self.tracing = self.span.getTracing();
    } else {
        self.span = null;
    }

    self.res = null;
    self.start = self.timers.now();
    self.timedOut = false;
}

inherits(TChannelOutgoingRequest, EventEmitter);

TChannelOutgoingRequest.prototype.sendParts = function sendParts(parts, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            self.sendCallRequestFrame(parts, isLast);
            break;
        case States.Streaming:
            self.sendCallRequestContFrame(parts, isLast);
            break;
        case States.Done:
            // TODO: could probably happen normally, like say if a
            // streaming request is canceled
            throw new Error('got frame in done state'); // TODO: typed error
        case States.Error:
            // TODO: log warn
            break;
    }
};

TChannelOutgoingRequest.prototype.sendCallRequestFrame = function sendCallRequestFrame(args, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            if (self.span) {
                self.span.annotate('cs');
            }
            self.sendFrame.callRequest(args, isLast);
            if (isLast) self.state = States.Done;
            else self.state = States.Streaming;
            break;
        case States.Streaming:
            throw new Error('first request frame already sent'); // TODO: typed error
        case States.Done:
            throw new Error('request already done'); // TODO: typed error
    }
};

TChannelOutgoingRequest.prototype.sendCallRequestContFrame = function sendCallRequestContFrame(args, isLast) {
    var self = this;
    switch (self.state) {
        case States.Initial:
            throw new Error('first request frame not sent'); // TODO: typed error
        case States.Streaming:
            self.sendFrame.callRequestCont(args, isLast);
            if (isLast) self.state = States.Done;
            break;
        case States.Done:
            throw new Error('request already done'); // TODO: typed error
    }
};

TChannelOutgoingRequest.prototype.send = function send(arg1, arg2, arg3, callback) {
    var self = this;

    if (self.span) {
        self.span.name = String(arg1);
    }
    if (callback) self.hookupCallback(callback);
    if (self.streamed) {
        self.arg1.end(arg1);
        self.arg2.end(arg2);
        self.arg3.end(arg3);
    } else {
        self.sendCallRequestFrame([
            arg1 ? Buffer(arg1) : emptyBuffer,
            arg2 ? Buffer(arg2) : emptyBuffer,
            arg3 ? Buffer(arg3) : emptyBuffer
        ], true);
        self.emit('finish');
    }
    return self;
};

TChannelOutgoingRequest.prototype.hookupStreamCallback = function hookupCallback(callback) {
    var self = this;
    var called = false;
    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        callback(null, self, res);
    }

    return self;
};

TChannelOutgoingRequest.prototype.hookupCallback = function hookupCallback(callback) {
    var self = this;
    if (callback.canStream) {
        return self.hookupStreamCallback(callback);
    }
    var called = false;

    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        if (!res.streamed) {
            callback(null, res, res.arg2, res.arg3);
            return;
        }
        parallel({
            arg2: res.arg2.onValueReady,
            arg3: res.arg3.onValueReady
        }, compatCall);
        function compatCall(err, args) {
            callback(err, res, args.arg2, args.arg3);
        }
    }

    return self;
};

TChannelOutgoingRequest.prototype.checkTimeout = function checkTimeout() {
    var self = this;
    if (!self.timedOut) {
        var elapsed = self.timers.now() - self.start;
        if (elapsed > self.ttl) {
            self.timedOut = true;
            process.nextTick(function deferOutReqTimeoutErrorEmit() {
                self.emit('error', errors.TimeoutError({
                    id: self.id,
                    start: self.start,
                    elapsed: elapsed,
                    timeout: self.ttl
                }));
            });
        }
    }
    return self.timedOut;
};

TChannelOutgoingRequest.States = States;

module.exports = TChannelOutgoingRequest;
<|endoftext|>