<commit_before>// Metadata:

    // O.js v1.0.
    // Author: Aaron Roney.

// License:

    // The MIT License (MIT)

    // Copyright (c) 2016 Aaron Roney

    // 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.

// TODO:

    // Modularize.

;'use strict';

;(function() {

    // Signifies that an object is "realizable" via "$value()".
    class _Realizable_Base {
        $value() {
            throw Error('Subclass does not properly override "$value".');
        }
    }

    // Proxy handler that allows method call passthrough.
    var _O_Impl_Base_Proxy_Handler = {

        // Example: "O.someProp(value)" would result in target = O and name = "someProp".
        get: function(target, name) {
            if(target[name])
                return target[name];

            // The beauty of O.  "O.literallyAnything" resolves to this returned setter function.
            return function(value) {
                return target.$set(name, value);
            };
        },

        // Example: "O(someExistingObjectToWrap)".
        apply: function(target, thisArg, argumentsList) {
            var objectToWrap = argumentsList[0];

            if(objectToWrap instanceof _Realizable_Base)
                objectToWrap = objectToWrap.$value();

            if(!(objectToWrap instanceof Object))
                throw Error('Must initialize "O" with an array or an instance of "O".');

            return new target.constructor(objectToWrap);
        }
    };

    // Base class for "O" that provides all logic.
    class O_Impl_Base extends _Realizable_Base {

        constructor(root, path) {
            super();

            if (!root)
                root = {};
            this._$root = root;

            if (!path)
                path = [];
            this._$path = path;

            return this._$createProxy();
        }

        ///////////////////////////////////////
        // Private helper properties.
        ///////////////////////////////////////

        // Gets a deep copy of the last state and makes a "working" copy.
        get _$working() {
            if(this._$workingCopy)
                return this._$workingCopy;
            return this._$workingCopy = { _$root: Object.assign({}, this._$root), _$path: Object.assign([], this._$path) };
        }

        // Gets the location in the wrapped object along this._path.
        get _$workingLocation() {
            var loc = this._$working._$root;
            for(var path of this._$working._$path)
                loc = loc[path];
            return loc;
        }

        // Returns the "working" copy and clears the working copy.
        _$wrapWorking() {
            var result = new this.constructor(Object.assign({}, this._$workingCopy._$root), Object.assign([], this._$workingCopy._$path));
            this._$workingCopy = undefined;
            return result;
        }

        ///////////////////////////////////////
        // Private proxying methods.
        ///////////////////////////////////////

        // Create a proxy for passthrough.
        _$createProxy() {
            return new Proxy(this, _O_Impl_Base_Proxy_Handler);
        }

        ///////////////////////////////////////
        // Private logic methods.
        ///////////////////////////////////////

        // Sets a certain property name to a value at the current this._path.
        _$set(propertyName, propertyValue) {
            if(propertyValue === undefined)
                return this._$enter(propertyName);

            if(propertyValue instanceof _Realizable_Base)
                propertyValue = propertyValue.$value();

            this._$workingLocation[propertyName] = propertyValue;
        }

        // "Enters" an object by, creating it if necessary, and moving into it
        _$enter(propertyName) {
            if(this._$workingLocation[propertyName]) {
                if(this._$workingLocation[propertyName] instanceof Object)
                    throw Error('Invalid "enter" path.');
            }
            else
                this._$workingLocation[propertyName] = {};

            this._$working._$path.push(propertyName);
        }

        // "Leaves" the current this._path context.
        _$leave() {
            if(this._$working._$path.length === 0)
                throw Error('Mismatch in "enter"/"leave".');
            this._$working._$path.pop();
        }

        // Build some property/values in the current this._path context with data and a functor.
        _$from(data, func) {
            for(var k in data) {
                var res = func(data[k], k, data);

                if(res instanceof Object && res.hasOwnProperty('property') && res.hasOwnProperty('value'))
                    var {property, value} = res;
                else if(res instanceof Array && res.length === 2)
                    var [property, value] = res;
                else
                    throw Error('Functor does not return proper "{property, value}" pair.');

                this._$set(property, value);
            }
        }

        // Clears entire wrapped object.
        _$clear() {
            this._$working._$root = {};
            this._$working._$path = [];
        }

        // Sets the current context to the root.
        _$toRoot() {
            this._$working._$path = [];
        }
    }

    // "O" implementation.
    class O_Impl extends O_Impl_Base {

        ///////////////////////////////////////
        // Public methods.
        ///////////////////////////////////////

        $set(propertyName, propertyValue) {
            this._$set(propertyName, propertyValue);
            return this._$wrapWorking();
        }
        $with(propertyName, propertyValue) {
            return this.$set(propertyName, propertyValue);
        }

        $enter(propertyName) {
            this._$enter(propertyName);
            return this._$wrapWorking();
        }

        $leave() {
            this._$leave();
            return this._$wrapWorking();
        }

        $from(data, func) {
            this._$from(data, func);
            return this._$wrapWorking();
        }

        $clear() {
            this._$clear();
            return this._$wrapWorking();
        }

        $toRoot() {
            this._$toRoot();
            return this._$wrapWorking();
        }

        $value() {
            return this._$root;
        }
    }

    // Export "O".
    var O = window.O = new O_Impl();

    // Proxy handler that allows method call passthrough.
    var _A_Impl_Base_Proxy_Handler = {
        apply: function(target, thisArg, argumentsList) {
            var arrayToWrap = argumentsList[0];

            if(arrayToWrap instanceof _Realizable_Base)
                arrayToWrap = arrayToWrap.$value();

            if(!(arrayToWrap instanceof Array))
                throw Error('Must initialize "A" with an array or an instance of "A".');

            return new target.constructor(arrayToWrap);
        }
    };

    // Base class for "A" that contains all logic.
    class A_Impl_Base extends _Realizable_Base {

        constructor(array) {
            super();

            if (!array)
                array = [];
            this._$array = array;

            return this._$createProxy();
        }

        ///////////////////////////////////////
        // Private helper properties.
        ///////////////////////////////////////

        // Gets a deep copy of the last state and makes a "working" copy.
        get _$working() {
            if(this._$workingCopy)
                return this._$workingCopy;
            return this._$workingCopy = { _$array: Object.assign([], this._$array) };
        }

        // Returns the "working" copy.
        _$wrapWorking() {
            var result = new this.constructor(Object.assign([], this._$workingCopy._$array));
            this._$workingCopy = undefined;
            return result;
        }

        ///////////////////////////////////////
        // Private proxying methods.
        ///////////////////////////////////////

        // Create a proxy for passthrough.
        _$createProxy() {
            return new Proxy(this, _A_Impl_Base_Proxy_Handler);
        }

        ///////////////////////////////////////
        // Private helper methods.
        ///////////////////////////////////////

        // Adds an item to the wrapped array.
        _$item(value) {
            if(value instanceof _Realizable_Base)
                value = value.$value();

            this._$working._$array.push(value);
        }

        // Build and add some items with data and a functor.
        _$from(data, func) {
            for(var k in data) {
                var res = func(data[k], k, data);
                this._$item(res);
            }
        }

        // Clears entire wrapped array.
        _$clear() {
            this._$working._$array = [];
        }
    }

    // "A" implementation.
    class A_Impl extends A_Impl_Base {

        ///////////////////////////////////////
        // Public methods.
        ///////////////////////////////////////

        $item(value) {
            this._$item(value);
            return this._$wrapWorking();
        }
        $(value) {
            return this.$item(value);
        }

        $from(data, func) {
            this._$from(data, func);
            return this._$wrapWorking();
        }

        $clear() {
            this._$clear();
            return this._$wrapWorking();
        }

        $value() {
            return this._$array;
        }
    }

    // Export "A".
    var A = window.A = new A_Impl();

})();<commit_msg>Small naming fix.<commit_after>// Metadata:

    // O v1.0.
    // Author: Aaron Roney.

// License:

    // The MIT License (MIT)

    // Copyright (c) 2016 Aaron Roney

    // 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.

// TODO:

    // Modularize.

;'use strict';

;(function() {

    // Signifies that an object is "realizable" via "$value()".
    class _Realizable_Base {
        $value() {
            throw Error('Subclass does not properly override "$value".');
        }
    }

    // Proxy handler that allows method call passthrough.
    var _O_Impl_Base_Proxy_Handler = {

        // Example: "O.someProp(value)" would result in target = O and name = "someProp".
        get: function(target, name) {
            if(target[name])
                return target[name];

            // The beauty of O.  "O.literallyAnything" resolves to this returned setter function.
            return function(value) {
                return target.$set(name, value);
            };
        },

        // Example: "O(someExistingObjectToWrap)".
        apply: function(target, thisArg, argumentsList) {
            var objectToWrap = argumentsList[0];

            if(objectToWrap instanceof _Realizable_Base)
                objectToWrap = objectToWrap.$value();

            if(!(objectToWrap instanceof Object))
                throw Error('Must initialize "O" with an array or an instance of "O".');

            return new target.constructor(objectToWrap);
        }
    };

    // Base class for "O" that provides all logic.
    class O_Impl_Base extends _Realizable_Base {

        constructor(root, path) {
            super();

            if (!root)
                root = {};
            this._$root = root;

            if (!path)
                path = [];
            this._$path = path;

            return this._$createProxy();
        }

        ///////////////////////////////////////
        // Private helper properties.
        ///////////////////////////////////////

        // Gets a deep copy of the last state and makes a "working" copy.
        get _$working() {
            if(this._$workingCopy)
                return this._$workingCopy;
            return this._$workingCopy = { _$root: Object.assign({}, this._$root), _$path: Object.assign([], this._$path) };
        }

        // Gets the location in the wrapped object along this._path.
        get _$workingLocation() {
            var loc = this._$working._$root;
            for(var path of this._$working._$path)
                loc = loc[path];
            return loc;
        }

        // Returns the "working" copy and clears the working copy.
        _$wrapWorking() {
            var result = new this.constructor(Object.assign({}, this._$workingCopy._$root), Object.assign([], this._$workingCopy._$path));
            this._$workingCopy = undefined;
            return result;
        }

        ///////////////////////////////////////
        // Private proxying methods.
        ///////////////////////////////////////

        // Create a proxy for passthrough.
        _$createProxy() {
            return new Proxy(this, _O_Impl_Base_Proxy_Handler);
        }

        ///////////////////////////////////////
        // Private logic methods.
        ///////////////////////////////////////

        // Sets a certain property name to a value at the current this._path.
        _$set(propertyName, propertyValue) {
            if(propertyValue === undefined)
                return this._$enter(propertyName);

            if(propertyValue instanceof _Realizable_Base)
                propertyValue = propertyValue.$value();

            this._$workingLocation[propertyName] = propertyValue;
        }

        // "Enters" an object by, creating it if necessary, and moving into it
        _$enter(propertyName) {
            if(this._$workingLocation[propertyName]) {
                if(this._$workingLocation[propertyName] instanceof Object)
                    throw Error('Invalid "enter" path.');
            }
            else
                this._$workingLocation[propertyName] = {};

            this._$working._$path.push(propertyName);
        }

        // "Leaves" the current this._path context.
        _$leave() {
            if(this._$working._$path.length === 0)
                throw Error('Mismatch in "enter"/"leave".');
            this._$working._$path.pop();
        }

        // Build some property/values in the current this._path context with data and a functor.
        _$from(data, func) {
            for(var k in data) {
                var res = func(data[k], k, data);

                if(res instanceof Object && res.hasOwnProperty('property') && res.hasOwnProperty('value'))
                    var {property, value} = res;
                else if(res instanceof Array && res.length === 2)
                    var [property, value] = res;
                else
                    throw Error('Functor does not return proper "{property, value}" pair.');

                this._$set(property, value);
            }
        }

        // Clears entire wrapped object.
        _$clear() {
            this._$working._$root = {};
            this._$working._$path = [];
        }

        // Sets the current context to the root.
        _$toRoot() {
            this._$working._$path = [];
        }
    }

    // "O" implementation.
    class O_Impl extends O_Impl_Base {

        ///////////////////////////////////////
        // Public methods.
        ///////////////////////////////////////

        $set(propertyName, propertyValue) {
            this._$set(propertyName, propertyValue);
            return this._$wrapWorking();
        }
        $with(propertyName, propertyValue) {
            return this.$set(propertyName, propertyValue);
        }

        $enter(propertyName) {
            this._$enter(propertyName);
            return this._$wrapWorking();
        }

        $leave() {
            this._$leave();
            return this._$wrapWorking();
        }

        $from(data, func) {
            this._$from(data, func);
            return this._$wrapWorking();
        }

        $clear() {
            this._$clear();
            return this._$wrapWorking();
        }

        $toRoot() {
            this._$toRoot();
            return this._$wrapWorking();
        }

        $value() {
            return this._$root;
        }
    }

    // Export "O".
    var O = window.O = new O_Impl();

    // Proxy handler that allows method call passthrough.
    var _A_Impl_Base_Proxy_Handler = {
        apply: function(target, thisArg, argumentsList) {
            var arrayToWrap = argumentsList[0];

            if(arrayToWrap instanceof _Realizable_Base)
                arrayToWrap = arrayToWrap.$value();

            if(!(arrayToWrap instanceof Array))
                throw Error('Must initialize "A" with an array or an instance of "A".');

            return new target.constructor(arrayToWrap);
        }
    };

    // Base class for "A" that contains all logic.
    class A_Impl_Base extends _Realizable_Base {

        constructor(array) {
            super();

            if (!array)
                array = [];
            this._$array = array;

            return this._$createProxy();
        }

        ///////////////////////////////////////
        // Private helper properties.
        ///////////////////////////////////////

        // Gets a deep copy of the last state and makes a "working" copy.
        get _$working() {
            if(this._$workingCopy)
                return this._$workingCopy;
            return this._$workingCopy = { _$array: Object.assign([], this._$array) };
        }

        // Returns the "working" copy.
        _$wrapWorking() {
            var result = new this.constructor(Object.assign([], this._$workingCopy._$array));
            this._$workingCopy = undefined;
            return result;
        }

        ///////////////////////////////////////
        // Private proxying methods.
        ///////////////////////////////////////

        // Create a proxy for passthrough.
        _$createProxy() {
            return new Proxy(this, _A_Impl_Base_Proxy_Handler);
        }

        ///////////////////////////////////////
        // Private helper methods.
        ///////////////////////////////////////

        // Adds an item to the wrapped array.
        _$item(value) {
            if(value instanceof _Realizable_Base)
                value = value.$value();

            this._$working._$array.push(value);
        }

        // Build and add some items with data and a functor.
        _$from(data, func) {
            for(var k in data) {
                var res = func(data[k], k, data);
                this._$item(res);
            }
        }

        // Clears entire wrapped array.
        _$clear() {
            this._$working._$array = [];
        }
    }

    // "A" implementation.
    class A_Impl extends A_Impl_Base {

        ///////////////////////////////////////
        // Public methods.
        ///////////////////////////////////////

        $item(value) {
            this._$item(value);
            return this._$wrapWorking();
        }
        $(value) {
            return this.$item(value);
        }

        $from(data, func) {
            this._$from(data, func);
            return this._$wrapWorking();
        }

        $clear() {
            this._$clear();
            return this._$wrapWorking();
        }

        $value() {
            return this._$array;
        }
    }

    // Export "A".
    var A = window.A = new A_Impl();

})();<|endoftext|>


<commit_before>var Version = require("../version")
var Windows = require("prismarine-windows")(Version).windows
var ItemStack = require("prismarine-item")(Version)

module.exports.player=function(player)
{
  player.heldItemSlot = 0
  player.heldItem = new ItemStack(256, 1)
  player.inventory = new Windows.InventoryWindow(0, "Inventory", 44)

  player._client.on("held_item_slot", ({slotId} = {}) => {
    player.heldItemSlot = slotId;

    player.heldItem = player.inventory.itemsRange(36 + player.heldItemSlot, 36 + player.heldItemSlot + 1)
    player._writeOthersNearby("entity_equipment",{
        entityId: player.id,
        slot: 0,
        item: ItemStack.toNotch(player.heldItem)
    });
  });

  player._client.on("set_creative_slot", ({slot,item} ={}) => {
    if(item.blockId == -1){
      player.inventory.updateSlot(slot, undefined)
      return;
    }

    var newItem = new ItemStack(item.blockId, item.itemCount, item.metadata)
    player.inventory.updateSlot(slot, newItem)

    if (slot==36)
      player._writeOthersNearby("entity_equipment",{
        entityId:player.id,
        slot:0,
        item:item
      });
    if (slot==5)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:4,
                item:item
            });
    if (slot==6)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:3,
                item:item
            });
    if (slot==7)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:2,
                item:item
            });
    if (slot==8)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:1,
                item:item
            });

  });

  player.inventory.on("windowUpdate", function(){
    var items = player.inventory.slots

    for(var itemIndex in items){
      var item = items[itemIndex]
      player._client.write("set_slot", {
        windowId: 0,
        slot: itemIndex,
        item: ItemStack.toNotch(item)
      })
    }
  })
};
<commit_msg>Fixed sending malformed items, that caused the client to have visual bugs<commit_after>var Version = require("../version")
var Windows = require("prismarine-windows")(Version).windows
var ItemStack = require("prismarine-item")(Version)

module.exports.player=function(player)
{
  player.heldItemSlot = 0
  player.heldItem = new ItemStack(256, 1)
  player.inventory = new Windows.InventoryWindow(0, "Inventory", 44)

  player._client.on("held_item_slot", ({slotId} = {}) => {
    player.heldItemSlot = slotId;

    player.heldItem = player.inventory.slots[36 + player.heldItemSlot]
    player._writeOthersNearby("entity_equipment",{
        entityId: player.id,
        slot: 0,
        item: ItemStack.toNotch(player.heldItem)
    });
  });

  player._client.on("set_creative_slot", ({slot,item} ={}) => {
    if(item.blockId == -1){
      player.inventory.updateSlot(slot, undefined)
      return;
    }

    var newItem = new ItemStack(item.blockId, item.itemCount, item.metadata)
    player.inventory.updateSlot(slot, newItem)

    if (slot==36)
      player._writeOthersNearby("entity_equipment",{
        entityId:player.id,
        slot:0,
        item:item
      });
    if (slot==5)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:4,
                item:item
            });
    if (slot==6)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:3,
                item:item
            });
    if (slot==7)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:2,
                item:item
            });
    if (slot==8)
            player._writeOthersNearby("entity_equipment",{
                entityId:player.id,
                slot:1,
                item:item
            });

  });

  player.inventory.on("windowUpdate", function(){
    var items = player.inventory.slots

    for(var itemIndex in items){
      var item = items[itemIndex]
      player._client.write("set_slot", {
        windowId: 0,
        slot: itemIndex,
        item: ItemStack.toNotch(item)
      })
    }
  })
};
<|endoftext|>


<commit_before>

import React, { Component } from "react";
import PropTypes from "prop-types";

import BarSeries from "./BarSeries";
import LineSeries from "./LineSeries";
import StraightLine from "./StraightLine";

class MACDSeries extends Component {
	constructor(props) {
		super(props);
		this.yAccessorForMACD = this.yAccessorForMACD.bind(this);
		this.yAccessorForSignal = this.yAccessorForSignal.bind(this);
		this.yAccessorForDivergence = this.yAccessorForDivergence.bind(this);
		this.yAccessorForDivergenceBase = this.yAccessorForDivergenceBase.bind(this);
	}
	yAccessorForMACD(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).macd;
	}
	yAccessorForSignal(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).signal;
	}
	yAccessorForDivergence(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).divergence;
	}
	yAccessorForDivergenceBase(xScale, yScale/* , d */) {
		return yScale(0);
	}
	render() {
		const { className, opacity, divergenceStroke, widthRatio, width } = this.props;
		const { stroke, fill } = this.props;

		const { clip } = this.props;
		const { zeroLineStroke, zeroLineOpacity } = this.props;

		return (
			<g className={className}>
				<BarSeries
					baseAt={this.yAccessorForDivergenceBase}
					className="macd-divergence"
					width={width}
					widthRatio={widthRatio}
					stroke={divergenceStroke}
					fill={fill.divergence}
					opacity={opacity}
					clip={clip}
					yAccessor={this.yAccessorForDivergence} />
				<LineSeries
					yAccessor={this.yAccessorForMACD}
					stroke={stroke.macd}
					fill="none" />
				<LineSeries
					yAccessor={this.yAccessorForSignal}
					stroke={stroke.signal}
					fill="none" />
				<StraightLine
					stroke={zeroLineStroke}
					opacity={zeroLineOpacity}
					yValue={0} />
			</g>
		);
	}
}

MACDSeries.propTypes = {
	className: PropTypes.string,
	yAccessor: PropTypes.func.isRequired,
	opacity: PropTypes.number,
	divergenceStroke: PropTypes.bool,
	zeroLineStroke: PropTypes.string,
	zeroLineOpacity: PropTypes.number,
	clip: PropTypes.bool.isRequired,
	stroke: PropTypes.shape({
		macd: PropTypes.string.isRequired,
		signal: PropTypes.string.isRequired,
	}).isRequired,
	fill: PropTypes.shape({
		divergence: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
	}).isRequired,
	widthRatio: PropTypes.number,
	width: BarSeries.prototypes.width,
};

MACDSeries.defaultProps = {
	className: "react-stockcharts-macd-series",
	zeroLineStroke: "#000000",
	zeroLineOpacity: 0.3,
	opacity: 0.6,
	divergenceStroke: false,
	clip: true,
	widthRatio: 0.5,
	width: BarSeries.defaultProps.width,
};

export default MACDSeries;
<commit_msg>fix typo<commit_after>

import React, { Component } from "react";
import PropTypes from "prop-types";

import BarSeries from "./BarSeries";
import LineSeries from "./LineSeries";
import StraightLine from "./StraightLine";

class MACDSeries extends Component {
	constructor(props) {
		super(props);
		this.yAccessorForMACD = this.yAccessorForMACD.bind(this);
		this.yAccessorForSignal = this.yAccessorForSignal.bind(this);
		this.yAccessorForDivergence = this.yAccessorForDivergence.bind(this);
		this.yAccessorForDivergenceBase = this.yAccessorForDivergenceBase.bind(this);
	}
	yAccessorForMACD(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).macd;
	}
	yAccessorForSignal(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).signal;
	}
	yAccessorForDivergence(d) {
		const { yAccessor } = this.props;
		return yAccessor(d) && yAccessor(d).divergence;
	}
	yAccessorForDivergenceBase(xScale, yScale/* , d */) {
		return yScale(0);
	}
	render() {
		const { className, opacity, divergenceStroke, widthRatio, width } = this.props;
		const { stroke, fill } = this.props;

		const { clip } = this.props;
		const { zeroLineStroke, zeroLineOpacity } = this.props;

		return (
			<g className={className}>
				<BarSeries
					baseAt={this.yAccessorForDivergenceBase}
					className="macd-divergence"
					width={width}
					widthRatio={widthRatio}
					stroke={divergenceStroke}
					fill={fill.divergence}
					opacity={opacity}
					clip={clip}
					yAccessor={this.yAccessorForDivergence} />
				<LineSeries
					yAccessor={this.yAccessorForMACD}
					stroke={stroke.macd}
					fill="none" />
				<LineSeries
					yAccessor={this.yAccessorForSignal}
					stroke={stroke.signal}
					fill="none" />
				<StraightLine
					stroke={zeroLineStroke}
					opacity={zeroLineOpacity}
					yValue={0} />
			</g>
		);
	}
}

MACDSeries.propTypes = {
	className: PropTypes.string,
	yAccessor: PropTypes.func.isRequired,
	opacity: PropTypes.number,
	divergenceStroke: PropTypes.bool,
	zeroLineStroke: PropTypes.string,
	zeroLineOpacity: PropTypes.number,
	clip: PropTypes.bool.isRequired,
	stroke: PropTypes.shape({
		macd: PropTypes.string.isRequired,
		signal: PropTypes.string.isRequired,
	}).isRequired,
	fill: PropTypes.shape({
		divergence: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
	}).isRequired,
	widthRatio: PropTypes.number,
	width: BarSeries.propTypes.width,
};

MACDSeries.defaultProps = {
	className: "react-stockcharts-macd-series",
	zeroLineStroke: "#000000",
	zeroLineOpacity: 0.3,
	opacity: 0.6,
	divergenceStroke: false,
	clip: true,
	widthRatio: 0.5,
	width: BarSeries.defaultProps.width,
};

export default MACDSeries;
<|endoftext|>


<commit_before>
// Tyler Close
// Ported and revised by Kris Kowal
//
// This API varies from Tyler Closes ref_send in the
// following ways:
//
// * Promises can be resolved to function values.
// * Promises can be resolved to null or undefined.
// * Promises are distinguishable from arbitrary functions.
// * The promise API is abstracted with a Promise constructor
//   that accepts a descriptor that receives all of the
//   messages forwarded to that promise and handles the
//   common patterns for message receivers.  The promise
//   constructor also takes optional fallback and valueOf
//   methods which handle the cases for missing handlers on
//   the descriptor (rejection by default) and the valueOf
//   call (which returns the promise itself by default)
// * near(ref) has been changed to Promise.valueOf() in
//   keeping with JavaScript's existing Object.valueOf().
// * variadic arguments are used internally where
//   applicable. However, I have not altered the Q.post()
//   API to expand variadic arguments since Tyler Close
//   informed the CommonJS list that it would restrict
//   usage patterns for web_send, posting arbitrary JSON
//   objects as the "arguments" over HTTP.

/*
 * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
 * at http://www.opensource.org/licenses/mit-license.html
 * ref_send.js version: 2009-05-11
 */

/*
 * Copyright 2009-2010 Kris Kowal under the terms of the MIT
 * license found at http://github.com/kriskowal/q/raw/master/LICENSE
 */

/*whatsupdoc*/

// - the enclosure ensures that this module will function properly both as a
// CommonJS module and as a script in the browser.  In CommonJS, this module
// exports the "Q" API.  In the browser, this script creates a "Q" object in
// global scope.
// - the use of "undefined" on the enclosure is a micro-optmization for
// compression systems, permitting every occurrence of the "undefined" keyword
// bo be replaced with a single-character.
(function (exports, undefined) {
"use strict";

var enqueue;
try {
    // Narwhal, Node (with a package, wraps process.nextTick)
    enqueue = require("event-queue").enqueue;
} catch(e) {
    // browsers
    enqueue = function (task) {
        setTimeout(task, 0);
    };
}

var print;
if (typeof console !== "undefined") {
    // browsers in debug mode, Node
    print = function (message) {
        console.log(message);
    };
} else if (typeof require !== "undefined") {
    // Narwhal
    print = require("system").print;
} else {
    // browsers otherwise
    print = function () {}
}

// useful for an identity stub and default resolvers
function identity (x) {return x}

// ES5 shims
var freeze = Object.freeze || identity;
var create = Object.create || function create(prototype) {
    var Type = function () {};
    Type.prototype = prototype;
    object = new Type();
}

/**
 * Performs a task in a future turn of the event loop.
 * @param {Function} task
 */
exports.enqueue = enqueue;

/**
 * Constructs a {promise, resolve} object.
 *
 * The resolver is a callback to invoke with a more resolved value for the
 * promise. To fulfill the promise, invoke the resolver with any value that is
 * not a function. To reject the promise, invoke the resolver with a rejection
 * object. To put the promise in the same state as another promise, invoke the
 * resolver with that other promise.
 */
exports.defer = defer;

function defer() {
    // if "pending" is an "Array", that indicates that the promise has not yet
    // been resolved.  If it is "undefined", it has been resolved.  Each
    // element of the pending array is itself an array of complete arguments to
    // forward to the resolved promise.  We coerce the resolution value to a
    // promise using the ref promise because it handles both fully
    // resolved values and other promises gracefully.
    var pending = [], value;

    var promise = create(Promise.prototype);

    promise.emit = function () {
        var args = Array.prototype.slice.call(arguments);
        if (pending) {
            pending.push(args);
        } else {
            forward.apply(undefined, [value].concat(args));
        }
    };

    promise.valueOf = function () {
        if (pending)
            return promise;
        return value.valueOf();
    };

    var resolve = function (resolvedValue) {
        var i, ii, task;
        if (!pending)
            return;
        value = ref(resolvedValue);
        for (i = 0, ii = pending.length; i < ii; ++i) {
            forward.apply(undefined, [value].concat(pending[i]));
        }
        pending = undefined;
    };

    return {
        "promise": freeze(promise),
        "resolve": resolve,
        "reject": function (reason) {
            resolve(reject(reason));
        }
    };
}

/**
 * Constructs a Promise with a promise descriptor object and optional fallback
 * function.  The descriptor contains methods like when(rejected), get(name),
 * put(name, value), post(name, args), and delete(name), which all
 * return either a value, a promise for a value, or a rejection.  The fallback
 * accepts the operation name, a resolver, and any further arguments that would
 * have been forwarded to the appropriate method above had a method been
 * provided with the proper name.  The API makes no guarantees about the nature
 * of the returned object, apart from that it is usable whereever promises are
 * bought and sold.
 */
exports.Promise = Promise;

function Promise(descriptor, fallback, valueOf) {

    if (fallback === undefined) {
        fallback = function (op) {
            return reject("Promise does not support operation: " + op);
        };
    }

    var promise = create(Promise.prototype);

    promise.emit = function (op, resolved /* ...args */) {
        resolved = resolved || identity;
        var args = Array.prototype.slice.call(arguments, 2);
        var result;
        if (descriptor[op])
            result = descriptor[op].apply(descriptor, args);
        else
            result = fallback.apply(descriptor, arguments);
        return resolved(result);
    };

    if (valueOf)
        promise.valueOf = valueOf;

    return freeze(promise);
};

Promise.prototype.toSource = function () {
    return this.toString();
};

Promise.prototype.toString = function () {
    return '[object Promise]';
};

freeze(Promise.prototype);

/**
 * @returns whether the given object is a promise.
 * Otherwise it is a resolved value.
 */
exports.isPromise = isPromise;
function isPromise(object) {
    return object instanceof Promise;
};

/**
 * @returns whether the given object is a fully
 * resolved value.
 */
exports.isResolved = isResolved;
function isResolved(object) {
    if (object === undefined || object === null)
        return true;
    return !isPromise(object.valueOf());
};

/**
 * Constructs a rejected promise.
 * @param reason value describing the failure
 */
exports.reject = reject;
function reject(reason) {
    return Promise({
        "when": function (rejected) {
            return rejected ? rejected(reason) : reject(reason);
        }
    }, function fallback(op, resolved) {
        var rejection = reject(reason);
        return resolved ? resolved(rejection) : rejection;
    });
}

/**
 * Constructs a promise for an immediate reference.
 * @param value immediate reference
 */
exports.ref = ref;
function ref(object) {
    // If the object is already a Promise, return it directly.  This enables
    // the ref function to both be used to created references from
    // objects, but to tolerably coerce non-promises to refs if they are
    // not already Promises.
    if (isPromise(object))
        return object;
    return Promise({
        "when": function (rejected) {
            return object;
        },
        "get": function (name) {
            try {
                return object[name];
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "put": function (name, value) {
            try {
                object[name] = value;
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "delete": function (name) {
            try {
                delete object[name];
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "post": function (name, args) {
            try {
                return object[name].apply(object, args);
            } catch (exception) {
                return reject(exception.message)
            }
        }
    }, undefined, function valueOf() {
        return object;
    });
}

/**
 * Registers an observer on a promise.
 *
 * Guarantees:
 *
 * 1. that resolved and rejected will be called only once.
 * 2. that either the resolved callback or the rejected callback will be
 *    called, but not both.
 * 3. that resolved and rejected will not be called in this turn.
 *
 * @param value     promise or immediate reference to observe
 * @param resolve function to be called with the resolved value
 * @param rejected  function to be called with the rejection reason
 * @return promise for the return value from the invoked callback
 */
exports.when = when;
function when(value, resolved, rejected) {
    var deferred = defer();
    var done = false;   // ensure the untrusted promise makes at most a
                        // single call to one of the callbacks
    forward(ref(value), "when", function (value) {
        if (done)
            return;
        done = true;
        deferred.resolve(ref(value).emit("when", resolved, rejected));
    }, function (reason) {
        if (done)
            return;
        done = true;
        deferred.resolve(rejected ? rejected(reason) : reject(reason));
    });
    return deferred.promise;
}

/**
 * Like "when", but attempts to return a fully resolved
 * value in the same turn. If the given value is fully
 * resolved, and the value returned by the resolved
 * callback is fully resolved, asap returns the latter
 * value in the same turn. Otherwise, it returns a promise
 * that will be resolved in a future turn.
 *
 * This method is an experiment in providing an API
 * that can unify synchronous and asynchronous API's.
 * An API that uses "asap" guarantees that, if it
 * is provided fully resolved values, it would produce
 * fully resolved values, but if it is provided
 * asynchronous promises, it will produce asynchronous
 * promises.
 *
 * /!\ WARNING: this method is expiermental and likely
 * to be removed on the grounds that it probably
 * will result in composition hazards.
 */
exports.asap = function (value, resolved, rejected) {
    resolved = resolved || identity;
    if (isResolved(value))
        return resolved(value.valueOf()).valueOf();
    else
        return when(value, resolved, rejected);
};

/**
 * Constructs a promise method that can be used to safely observe resolution of
 * a promise for an arbitrarily named method like "propfind" in a future turn.
 *
 * "Method" constructs methods like "get(promise, name)" and "put(promise)".
 */
exports.Method = Method;
function Method (methodName) {
    return function (object) {
        var deferred = defer();
        var args = Array.prototype.slice.call(arguments, 1);
        forward.apply(undefined, [
            ref(object),
            methodName,
            deferred.resolve
        ].concat(args));
        return deferred.promise;
    };
}

/**
 * Gets the value of a property in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of property to get
 * @return promise for the property value
 */
exports.get = Method("get");

/**
 * Sets the value of a property in a future turn.
 * @param object    promise or immediate reference for object object
 * @param name      name of property to set
 * @param value     new value of property
 * @return promise for the return value
 */
exports.put = Method("put");

/**
 * Deletes a property in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of property to delete
 * @return promise for the return value
 */
exports.del = Method("del");

/**
 * Invokes a method in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of method to invoke
 * @param argv      array of invocation arguments
 * @return promise for the return value
 */
exports.post = Method("post");

/**
 * Guarantees that the give promise resolves to a defined, non-null value.
 */
exports.defined = function (value) {
    return exports.when(value, function (value) {
        if (value === undefined || value === null)
            return reject("Resolved undefined value: " + value);
        return value;
    });
};

/**
 * Throws an error with the given reason.
 */
exports.error = function (reason) {
    if (!(reason instanceof Error))
        reason = new Error(reason);
    throw reason;
};

/*
 * Enqueues a promise operation for a future turn.
 */
function forward(promise /*, op, resolved, ... */) {
    var args = Array.prototype.slice.call(arguments, 1);
    enqueue(function () {
        try {
            promise.emit.apply(promise, args);
        } catch (exception) {
            print(exception.stack || exception);
        }
    });
}

// Complete the closure: use either CommonJS exports or browser global Q object
// for the exports internally.
})(
    typeof exports !== "undefined" ?
    exports :
    this["/q"] = {}
);

<commit_msg>Adding vim settings to stick to the project coding-style.<commit_after>// vim:ts=4:sts=4:sw=4:
// Tyler Close
// Ported and revised by Kris Kowal
//
// This API varies from Tyler Closes ref_send in the
// following ways:
//
// * Promises can be resolved to function values.
// * Promises can be resolved to null or undefined.
// * Promises are distinguishable from arbitrary functions.
// * The promise API is abstracted with a Promise constructor
//   that accepts a descriptor that receives all of the
//   messages forwarded to that promise and handles the
//   common patterns for message receivers.  The promise
//   constructor also takes optional fallback and valueOf
//   methods which handle the cases for missing handlers on
//   the descriptor (rejection by default) and the valueOf
//   call (which returns the promise itself by default)
// * near(ref) has been changed to Promise.valueOf() in
//   keeping with JavaScript's existing Object.valueOf().
// * variadic arguments are used internally where
//   applicable. However, I have not altered the Q.post()
//   API to expand variadic arguments since Tyler Close
//   informed the CommonJS list that it would restrict
//   usage patterns for web_send, posting arbitrary JSON
//   objects as the "arguments" over HTTP.

/*
 * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
 * at http://www.opensource.org/licenses/mit-license.html
 * ref_send.js version: 2009-05-11
 */

/*
 * Copyright 2009-2010 Kris Kowal under the terms of the MIT
 * license found at http://github.com/kriskowal/q/raw/master/LICENSE
 */

/*whatsupdoc*/

// - the enclosure ensures that this module will function properly both as a
// CommonJS module and as a script in the browser.  In CommonJS, this module
// exports the "Q" API.  In the browser, this script creates a "Q" object in
// global scope.
// - the use of "undefined" on the enclosure is a micro-optmization for
// compression systems, permitting every occurrence of the "undefined" keyword
// bo be replaced with a single-character.
(function (exports, undefined) {
"use strict";

var enqueue;
try {
    // Narwhal, Node (with a package, wraps process.nextTick)
    enqueue = require("event-queue").enqueue;
} catch(e) {
    // browsers
    enqueue = function (task) {
        setTimeout(task, 0);
    };
}

var print;
if (typeof console !== "undefined") {
    // browsers in debug mode, Node
    print = function (message) {
        console.log(message);
    };
} else if (typeof require !== "undefined") {
    // Narwhal
    print = require("system").print;
} else {
    // browsers otherwise
    print = function () {}
}

// useful for an identity stub and default resolvers
function identity (x) {return x}

// ES5 shims
var freeze = Object.freeze || identity;
var create = Object.create || function create(prototype) {
    var Type = function () {};
    Type.prototype = prototype;
    object = new Type();
}

/**
 * Performs a task in a future turn of the event loop.
 * @param {Function} task
 */
exports.enqueue = enqueue;

/**
 * Constructs a {promise, resolve} object.
 *
 * The resolver is a callback to invoke with a more resolved value for the
 * promise. To fulfill the promise, invoke the resolver with any value that is
 * not a function. To reject the promise, invoke the resolver with a rejection
 * object. To put the promise in the same state as another promise, invoke the
 * resolver with that other promise.
 */
exports.defer = defer;

function defer() {
    // if "pending" is an "Array", that indicates that the promise has not yet
    // been resolved.  If it is "undefined", it has been resolved.  Each
    // element of the pending array is itself an array of complete arguments to
    // forward to the resolved promise.  We coerce the resolution value to a
    // promise using the ref promise because it handles both fully
    // resolved values and other promises gracefully.
    var pending = [], value;

    var promise = create(Promise.prototype);

    promise.emit = function () {
        var args = Array.prototype.slice.call(arguments);
        if (pending) {
            pending.push(args);
        } else {
            forward.apply(undefined, [value].concat(args));
        }
    };

    promise.valueOf = function () {
        if (pending)
            return promise;
        return value.valueOf();
    };

    var resolve = function (resolvedValue) {
        var i, ii, task;
        if (!pending)
            return;
        value = ref(resolvedValue);
        for (i = 0, ii = pending.length; i < ii; ++i) {
            forward.apply(undefined, [value].concat(pending[i]));
        }
        pending = undefined;
    };

    return {
        "promise": freeze(promise),
        "resolve": resolve,
        "reject": function (reason) {
            resolve(reject(reason));
        }
    };
}

/**
 * Constructs a Promise with a promise descriptor object and optional fallback
 * function.  The descriptor contains methods like when(rejected), get(name),
 * put(name, value), post(name, args), and delete(name), which all
 * return either a value, a promise for a value, or a rejection.  The fallback
 * accepts the operation name, a resolver, and any further arguments that would
 * have been forwarded to the appropriate method above had a method been
 * provided with the proper name.  The API makes no guarantees about the nature
 * of the returned object, apart from that it is usable whereever promises are
 * bought and sold.
 */
exports.Promise = Promise;

function Promise(descriptor, fallback, valueOf) {

    if (fallback === undefined) {
        fallback = function (op) {
            return reject("Promise does not support operation: " + op);
        };
    }

    var promise = create(Promise.prototype);

    promise.emit = function (op, resolved /* ...args */) {
        resolved = resolved || identity;
        var args = Array.prototype.slice.call(arguments, 2);
        var result;
        if (descriptor[op])
            result = descriptor[op].apply(descriptor, args);
        else
            result = fallback.apply(descriptor, arguments);
        return resolved(result);
    };

    if (valueOf)
        promise.valueOf = valueOf;

    return freeze(promise);
};

Promise.prototype.toSource = function () {
    return this.toString();
};

Promise.prototype.toString = function () {
    return '[object Promise]';
};

freeze(Promise.prototype);

/**
 * @returns whether the given object is a promise.
 * Otherwise it is a resolved value.
 */
exports.isPromise = isPromise;
function isPromise(object) {
    return object instanceof Promise;
};

/**
 * @returns whether the given object is a fully
 * resolved value.
 */
exports.isResolved = isResolved;
function isResolved(object) {
    if (object === undefined || object === null)
        return true;
    return !isPromise(object.valueOf());
};

/**
 * Constructs a rejected promise.
 * @param reason value describing the failure
 */
exports.reject = reject;
function reject(reason) {
    return Promise({
        "when": function (rejected) {
            return rejected ? rejected(reason) : reject(reason);
        }
    }, function fallback(op, resolved) {
        var rejection = reject(reason);
        return resolved ? resolved(rejection) : rejection;
    });
}

/**
 * Constructs a promise for an immediate reference.
 * @param value immediate reference
 */
exports.ref = ref;
function ref(object) {
    // If the object is already a Promise, return it directly.  This enables
    // the ref function to both be used to created references from
    // objects, but to tolerably coerce non-promises to refs if they are
    // not already Promises.
    if (isPromise(object))
        return object;
    return Promise({
        "when": function (rejected) {
            return object;
        },
        "get": function (name) {
            try {
                return object[name];
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "put": function (name, value) {
            try {
                object[name] = value;
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "delete": function (name) {
            try {
                delete object[name];
            } catch (exception) {
                return reject(exception.message)
            }
        },
        "post": function (name, args) {
            try {
                return object[name].apply(object, args);
            } catch (exception) {
                return reject(exception.message)
            }
        }
    }, undefined, function valueOf() {
        return object;
    });
}

/**
 * Registers an observer on a promise.
 *
 * Guarantees:
 *
 * 1. that resolved and rejected will be called only once.
 * 2. that either the resolved callback or the rejected callback will be
 *    called, but not both.
 * 3. that resolved and rejected will not be called in this turn.
 *
 * @param value     promise or immediate reference to observe
 * @param resolve function to be called with the resolved value
 * @param rejected  function to be called with the rejection reason
 * @return promise for the return value from the invoked callback
 */
exports.when = when;
function when(value, resolved, rejected) {
    var deferred = defer();
    var done = false;   // ensure the untrusted promise makes at most a
                        // single call to one of the callbacks
    forward(ref(value), "when", function (value) {
        if (done)
            return;
        done = true;
        deferred.resolve(ref(value).emit("when", resolved, rejected));
    }, function (reason) {
        if (done)
            return;
        done = true;
        deferred.resolve(rejected ? rejected(reason) : reject(reason));
    });
    return deferred.promise;
}

/**
 * Like "when", but attempts to return a fully resolved
 * value in the same turn. If the given value is fully
 * resolved, and the value returned by the resolved
 * callback is fully resolved, asap returns the latter
 * value in the same turn. Otherwise, it returns a promise
 * that will be resolved in a future turn.
 *
 * This method is an experiment in providing an API
 * that can unify synchronous and asynchronous API's.
 * An API that uses "asap" guarantees that, if it
 * is provided fully resolved values, it would produce
 * fully resolved values, but if it is provided
 * asynchronous promises, it will produce asynchronous
 * promises.
 *
 * /!\ WARNING: this method is expiermental and likely
 * to be removed on the grounds that it probably
 * will result in composition hazards.
 */
exports.asap = function (value, resolved, rejected) {
    resolved = resolved || identity;
    if (isResolved(value))
        return resolved(value.valueOf()).valueOf();
    else
        return when(value, resolved, rejected);
};

/**
 * Constructs a promise method that can be used to safely observe resolution of
 * a promise for an arbitrarily named method like "propfind" in a future turn.
 *
 * "Method" constructs methods like "get(promise, name)" and "put(promise)".
 */
exports.Method = Method;
function Method (methodName) {
    return function (object) {
        var deferred = defer();
        var args = Array.prototype.slice.call(arguments, 1);
        forward.apply(undefined, [
            ref(object),
            methodName,
            deferred.resolve
        ].concat(args));
        return deferred.promise;
    };
}

/**
 * Gets the value of a property in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of property to get
 * @return promise for the property value
 */
exports.get = Method("get");

/**
 * Sets the value of a property in a future turn.
 * @param object    promise or immediate reference for object object
 * @param name      name of property to set
 * @param value     new value of property
 * @return promise for the return value
 */
exports.put = Method("put");

/**
 * Deletes a property in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of property to delete
 * @return promise for the return value
 */
exports.del = Method("del");

/**
 * Invokes a method in a future turn.
 * @param object    promise or immediate reference for target object
 * @param name      name of method to invoke
 * @param argv      array of invocation arguments
 * @return promise for the return value
 */
exports.post = Method("post");

/**
 * Guarantees that the give promise resolves to a defined, non-null value.
 */
exports.defined = function (value) {
    return exports.when(value, function (value) {
        if (value === undefined || value === null)
            return reject("Resolved undefined value: " + value);
        return value;
    });
};

/**
 * Throws an error with the given reason.
 */
exports.error = function (reason) {
    if (!(reason instanceof Error))
        reason = new Error(reason);
    throw reason;
};

/*
 * Enqueues a promise operation for a future turn.
 */
function forward(promise /*, op, resolved, ... */) {
    var args = Array.prototype.slice.call(arguments, 1);
    enqueue(function () {
        try {
            promise.emit.apply(promise, args);
        } catch (exception) {
            print(exception.stack || exception);
        }
    });
}

// Complete the closure: use either CommonJS exports or browser global Q object
// for the exports internally.
})(
    typeof exports !== "undefined" ?
    exports :
    this["/q"] = {}
);

<|endoftext|>


<commit_before>import _ from 'lodash';

export default class StatePersistence {
    constructor(storageKey, state, storage, logger) {
        this.storageKey = storageKey;
        this.state = state;
        this.storage = storage;
        this.logger = logger;
        this.isPersisting = false;

        this.state.persistence = this;
    }

    async loadStateIfExists() {
        // If we have networks from a previous state, launch directly into it
        let storedState = await this.storage.get(this.storageKey);
        if (storedState) {
            if (this.logger) {
                this.logger('Importing state', storedState);
            }

            this.state.importState(storedState);
        }
    }

    watchStateForChanges() {
        // Throttle saving the state into storage so we don't thrash the disk
        let debouncedSaveState = _.debounce(() => {
            if (this.logger) {
                this.logger('State updated, setting localStorage');
            }

            this.storage.set(this.storageKey, this.state.exportState());
        }, 1000);

        this.state.$watch('networks', debouncedSaveState, { deep: true });
        this.state.$watch('user_settings', debouncedSaveState, { deep: true });

        this.isPersisting = true;
    }

    forgetState() {
        this.state.resetState();
        this.storage.set(this.storageKey, null);
    }
}
<commit_msg>ignoring state persistence functions if no stateKey is set<commit_after>import _ from 'lodash';

export default class StatePersistence {
    constructor(storageKey, state, storage, logger) {
        this.storageKey = storageKey;
        this.state = state;
        this.storage = storage;
        this.logger = logger;
        this.isPersisting = false;

        this.state.persistence = this;
    }

    async loadStateIfExists() {
        if (!this.storageKey) {
            return;
        }

        // If we have networks from a previous state, launch directly into it
        let storedState = await this.storage.get(this.storageKey);
        if (storedState) {
            if (this.logger) {
                this.logger('Importing state', storedState);
            }

            this.state.importState(storedState);
        }
    }

    watchStateForChanges() {
        if (!this.storageKey) {
            return;
        }

        // Throttle saving the state into storage so we don't thrash the disk
        let debouncedSaveState = _.debounce(() => {
            if (this.logger) {
                this.logger('State updated, setting localStorage');
            }

            this.storage.set(this.storageKey, this.state.exportState());
        }, 1000);

        this.state.$watch('networks', debouncedSaveState, { deep: true });
        this.state.$watch('user_settings', debouncedSaveState, { deep: true });

        this.isPersisting = true;
    }

    forgetState() {
        this.state.resetState();
        this.storage.set(this.storageKey, null);
    }
}
<|endoftext|>


<commit_before>/**
 * debounce
 * @param {integer} milliseconds This param indicates the number of milliseconds
 *     to wait after the last call before calling the original function .
 * @return {function} This returns a function that when called will wait the
 *     indicated number of milliseconds after the last call before
 *     calling the original function.
 */
Function.prototype.debounce = function (milliseconds) {
    var baseFunction = this,
        timer = null,
        wait = milliseconds;

    return function () {
        var self = this,
            args = arguments;

        function complete() {
            baseFunction.apply(self, args);
            timer = null;
        }

        if (timer) {
            clearTimeout(timer);
        }

        timer = setTimeout(complete, wait);
    };
};

/**
* throttle
* @param {integer} milliseconds This param indicates the number of milliseconds
*     to wait between calls before calling the original function.
* @return {function} This returns a function that when called will wait the
*     indicated number of milliseconds between calls before
*     calling the original function.
*/
Function.prototype.throttle = function (milliseconds) {
    var baseFunction = this,
        lastEventTimestamp = null,
        lastimit = milliseconds;

    return function () {
        var self = this,
            args = arguments,
            now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit) {
            lastEventTimestamp = now;
            baseFunction.apply(self, args);
        }
    };
};<commit_msg>Fixed typo.<commit_after>/**
 * debounce
 * @param {integer} milliseconds This param indicates the number of milliseconds
 *     to wait after the last call before calling the original function .
 * @return {function} This returns a function that when called will wait the
 *     indicated number of milliseconds after the last call before
 *     calling the original function.
 */
Function.prototype.debounce = function (milliseconds) {
    var baseFunction = this,
        timer = null,
        wait = milliseconds;

    return function () {
        var self = this,
            args = arguments;

        function complete() {
            baseFunction.apply(self, args);
            timer = null;
        }

        if (timer) {
            clearTimeout(timer);
        }

        timer = setTimeout(complete, wait);
    };
};

/**
* throttle
* @param {integer} milliseconds This param indicates the number of milliseconds
*     to wait between calls before calling the original function.
* @return {function} This returns a function that when called will wait the
*     indicated number of milliseconds between calls before
*     calling the original function.
*/
Function.prototype.throttle = function (milliseconds) {
    var baseFunction = this,
        lastEventTimestamp = null,
        limit = milliseconds;

    return function () {
        var self = this,
            args = arguments,
            now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit) {
            lastEventTimestamp = now;
            baseFunction.apply(self, args);
        }
    };
};<|endoftext|>


<commit_before>M.wrap('github/jillix/crud-links/dev/links.js', function (require, module, exports) {

var Events = require('github/jillix/events');

// function to clone a JSON object (it wil not clone function, dates, etc.)
function cloneJSON(obj) {
    // basic type deep copy
    if (obj === null || obj === undefined || typeof obj !== 'object')  {
        return obj
    }
    // array deep copy
    if (obj instanceof Array) {
        var cloneA = [];
        for (var i = 0; i < obj.length; ++i) {
            cloneA[i] = cloneJSON(obj[i]);
        }
        return cloneA;
    }
    // object deep copy
    var cloneO = {};
    for (var i in obj) {
        cloneO[i] = cloneJSON(obj[i]);
    }
    return cloneO;
}

function setData (data) {
    //console.log(data);
}

function setTemplate (template) {

    var self = this;

    if (!template || (self.template && self.template._id === template._id)) {
        return;
    }

    self.template = template;

    // uninit the clones
    for (var cloneMiid in self.clones) {
        self.uninit(cloneMiid);
    }

    // empty the clone cache
    self.clones = {};

    // nothing to do when there are no links
    if (!template.links) {
        return;
    }

    for (var i = 0, l = template.links.length; i < l; ++i) {
        var targetTemplateId = template.links[i]._tp;
        // we clone the default configurations because they will be modified by the modules
        var filterConfig = cloneJSON(self.config.clones.filter.config) || {};
        var tableConfig = cloneJSON(self.config.clones.table.config) || {};
        // the clone miids
        var filterCloneMiid = self.config.clones.filter.miid + '_' + template._id + '_' + targetTemplateId;
        var tableCloneMiid = self.config.clones.table.miid + '_' + template._id + '_' + targetTemplateId;

        // let CRUD know that he should listen to this new filter module
        self.emit('listenTo', [filterCloneMiid]);

        // the filter must wait for the table to load because it will notify the table about the template
        filterConfig.waitFor = filterConfig.waitFor || [];
        filterConfig.waitFor.push(tableCloneMiid);
        // configure the table to listen to the filter module
        filterConfig.listen = filterConfig.listen || {};
        filterConfig.listen[self.miid] = {};
        filterConfig.listen[self.miid][filterCloneMiid + '_setTemplate'] = [ { emit: 'setTemplate' } ];

        // configure the table to listen to the filter module
        tableConfig.listen = tableConfig.listen || {};
        tableConfig.listen[filterCloneMiid] = {
            result: [ { handler: 'renderItemsFromResult' } ],
            template: [ { handler: 'setTemplate' } ],
            filtersChanged: [ { handler: 'clearSkip' } ]
        };

        // links with table only option have only a filter with no UI
        if (!template.links[i].tableOnly && filterConfig.ui) {
            delete filterConfig.ui;
        }

        // emit a special event to set the template for this filter module
        (function(targetTemplateId){
            self.on('ready', filterCloneMiid, function() {
                self.emit(filterCloneMiid + '_setTemplate', targetTemplateId);
            });
        })(targetTemplateId);

        // clone the filters for this link
        M.clone('#linksContainer', self.config.clones.filter.miid, '_' + template._id + '_' + targetTemplateId, filterConfig, (function(filterCloneMiid) {
            return function(module) {
                self.clones[filterCloneMiid] = module;
            };
        })(filterCloneMiid));

        // clone the table for this link
        M.clone('#linksContainer', self.config.clones.table.miid, '_' + template._id + '_' + targetTemplateId, tableConfig, (function(tableCloneMiid) {
            return function(module) {
                self.clones[tableCloneMiid] = module;
            };
        })(tableCloneMiid));
    }
}

function init (config) {
    var self = this;
    self.config = config;

    self.on('setData', setData);
    self.on('setTemplate', setTemplate);

    // listen to external events
    Events.call(self, self.config);

    self.emit('ready');
}

module.exports = init;

return module; });
<commit_msg>corrected if logic for filter ui config<commit_after>M.wrap('github/jillix/crud-links/dev/links.js', function (require, module, exports) {

var Events = require('github/jillix/events');

// function to clone a JSON object (it wil not clone function, dates, etc.)
function cloneJSON(obj) {
    // basic type deep copy
    if (obj === null || obj === undefined || typeof obj !== 'object')  {
        return obj
    }
    // array deep copy
    if (obj instanceof Array) {
        var cloneA = [];
        for (var i = 0; i < obj.length; ++i) {
            cloneA[i] = cloneJSON(obj[i]);
        }
        return cloneA;
    }
    // object deep copy
    var cloneO = {};
    for (var i in obj) {
        cloneO[i] = cloneJSON(obj[i]);
    }
    return cloneO;
}

function setData (data) {
    //console.log(data);
}

function setTemplate (template) {

    var self = this;

    if (!template || (self.template && self.template._id === template._id)) {
        return;
    }

    self.template = template;

    // uninit the clones
    for (var cloneMiid in self.clones) {
        self.uninit(cloneMiid);
    }

    // empty the clone cache
    self.clones = {};

    // nothing to do when there are no links
    if (!template.links) {
        return;
    }

    for (var i = 0, l = template.links.length; i < l; ++i) {
        var targetTemplateId = template.links[i]._tp;
        // we clone the default configurations because they will be modified by the modules
        var filterConfig = cloneJSON(self.config.clones.filter.config) || {};
        var tableConfig = cloneJSON(self.config.clones.table.config) || {};
        // the clone miids
        var filterCloneMiid = self.config.clones.filter.miid + '_' + template._id + '_' + targetTemplateId;
        var tableCloneMiid = self.config.clones.table.miid + '_' + template._id + '_' + targetTemplateId;

        // let CRUD know that he should listen to this new filter module
        self.emit('listenTo', [filterCloneMiid]);

        // the filter must wait for the table to load because it will notify the table about the template
        filterConfig.waitFor = filterConfig.waitFor || [];
        filterConfig.waitFor.push(tableCloneMiid);
        // configure the table to listen to the filter module
        filterConfig.listen = filterConfig.listen || {};
        filterConfig.listen[self.miid] = {};
        filterConfig.listen[self.miid][filterCloneMiid + '_setTemplate'] = [ { emit: 'setTemplate' } ];

        // configure the table to listen to the filter module
        tableConfig.listen = tableConfig.listen || {};
        tableConfig.listen[filterCloneMiid] = {
            result: [ { handler: 'renderItemsFromResult' } ],
            template: [ { handler: 'setTemplate' } ],
            filtersChanged: [ { handler: 'clearSkip' } ]
        };

        // links with table only option have only a filter with no UI
        if (template.links[i].tableOnly && filterConfig.ui) {
            delete filterConfig.ui;
        }

        // emit a special event to set the template for this filter module
        (function(targetTemplateId){
            self.on('ready', filterCloneMiid, function() {
                self.emit(filterCloneMiid + '_setTemplate', targetTemplateId);
            });
        })(targetTemplateId);

        // clone the filters for this link
        M.clone('#linksContainer', self.config.clones.filter.miid, '_' + template._id + '_' + targetTemplateId, filterConfig, (function(filterCloneMiid) {
            return function(module) {
                self.clones[filterCloneMiid] = module;
            };
        })(filterCloneMiid));

        // clone the table for this link
        M.clone('#linksContainer', self.config.clones.table.miid, '_' + template._id + '_' + targetTemplateId, tableConfig, (function(tableCloneMiid) {
            return function(module) {
                self.clones[tableCloneMiid] = module;
            };
        })(tableCloneMiid));
    }
}

function init (config) {
    var self = this;
    self.config = config;

    self.on('setData', setData);
    self.on('setTemplate', setTemplate);

    // listen to external events
    Events.call(self, self.config);

    self.emit('ready');
}

module.exports = init;

return module; });
<|endoftext|>


<commit_before>import queryString from 'query-string';

import { getMapStateFromUrl, getMapStateDiffFromUrl } from 'fm3/urlMapUtils';

import { setEmbeddedMode } from 'fm3/actions/mainActions';
import { mapRefocus } from 'fm3/actions/mapActions';
import { routePlannerSetParams } from 'fm3/actions/routePlannerActions';
import { trackViewerDownloadTrack } from 'fm3/actions/trackViewerActions';

export default function handleLocationChange(store, location) {
  const query = queryString.parse(location.search);

  // TODO once we start listening for the location changes then we should not dispatch actions if nothing changes here
  if (query.tool === 'route-planner' && /car|walk|bicycle/.test(query.transport)) {
    const points = query.points.split(',').map(point => point.split('/').map(coord => parseFloat(coord)));

    if (points.length > 1 && points.every(point => point.length === 2)) {
      const latLons = points.map(([lat, lon]) => ({ lat, lon }));
      store.dispatch(routePlannerSetParams(latLons[0], latLons[latLons.length - 1], latLons.slice(1, latLons.length - 1), query.transport));
    }
  }

  // TODO once we start listening for the location changes then we should not dispatch actions if nothing changes here
  if (query.tool === 'track-viewer' && query['track-uid']) {
    store.dispatch(trackViewerDownloadTrack(query['track-uid']));
  }

  if (query.embed === 'true') {
    store.dispatch(setEmbeddedMode());
  }

  const diff = getMapStateDiffFromUrl(getMapStateFromUrl(location), store.getState().map);

  if (diff && Object.keys(diff).length) {
    store.dispatch(mapRefocus(diff));
  }
}
<commit_msg>prevented dispatching route planner params if url params were not changed (fixes #135)<commit_after>import queryString from 'query-string';

import { getMapStateFromUrl, getMapStateDiffFromUrl } from 'fm3/urlMapUtils';

import { setEmbeddedMode } from 'fm3/actions/mainActions';
import { mapRefocus } from 'fm3/actions/mapActions';
import { routePlannerSetParams } from 'fm3/actions/routePlannerActions';
import { trackViewerDownloadTrack } from 'fm3/actions/trackViewerActions';

export default function handleLocationChange(store, location) {
  const query = queryString.parse(location.search);

  if (query.tool === 'route-planner' && /car|walk|bicycle/.test(query.transport)) {
    const points = query.points.split(',').map(point => point.split('/').map(coord => parseFloat(coord)));

    const { start, finish, midpoints, transportType } = store.getState().routePlanner;

    if (points.length > 1 && points.every(point => point.length === 2)) {
      const latLons = points.map(([lat, lon]) => ({ lat, lon }));
      const nextStart = latLons[0];
      const nextMidpoints = latLons.slice(1, latLons.length - 1);
      const nextFinish = latLons[latLons.length - 1];
      if (query.transport !== transportType
          || !latLonEquals(start, nextStart)
          || !latLonEquals(finish, nextFinish)
          || midpoints.length !== nextMidpoints.length
          || midpoints.some((midpoint, i) => !latLonEquals(midpoint, nextMidpoints[i]))) {
        store.dispatch(routePlannerSetParams(nextStart, nextFinish, nextMidpoints, query.transport));
      }
    }
  }

  // TODO once we start listening for the location changes then we should not dispatch actions if nothing changes here
  if (query.tool === 'track-viewer' && query['track-uid']) {
    store.dispatch(trackViewerDownloadTrack(query['track-uid']));
  }

  if (query.embed === 'true') {
    store.dispatch(setEmbeddedMode());
  }

  const diff = getMapStateDiffFromUrl(getMapStateFromUrl(location), store.getState().map);

  if (diff && Object.keys(diff).length) {
    store.dispatch(mapRefocus(diff));
  }
}

function latLonEquals(ll1, ll2) {
  return !ll1 && !ll2 || ll1 && ll2 && ll1.lat === ll2.lat && ll1.lon === ll2.lon;
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { View, ListView, Text, ScrollView, TextInput, Dimensions, TouchableHighlight, Alert } from 'react-native';
import { Styles } from '../styles';
import Button from 'react-native-button';

export default class TodoListContainer extends Component {
  constructor() {
    super();

    var ds = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 });

    this._data = [
      'Kill the last 2 dragons',
      'Blast Kefka\'s face'
    ];

    this.state = {
      todoText: '',
      dataSource: ds.cloneWithRows(this._data),
      selectedIndex: null
    }

    this.testePress = this.testePress.bind(this);
  }

  testePress() {
    if (this.state.todoText.length > 0) {
      if (this.state.selectedIndex === null) { // Insert
        this._data = this._data.concat(this.state.todoText);
      } else { // Update
        var index = parseInt(this.state.selectedIndex);

        var newData = this._data.slice(0);
        newData[index] = this.state.todoText;

        this._data = newData;
      }

      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this._data),
        todoText: '',
        selectedIndex: null
      })
    }
  }

  onPressListItem(text, index) {
    this.setState({
      todoText: text,
      selectedIndex: index
    })
  }

  onLongPressListItem(index) {
    Alert.alert('Are you sure?', 'Are you sure you want to delete this row? This action cannot be reverted.', [
      { text: 'Yes', onPress: this.deleteItem.bind(this) },
      { text: 'No', onPress: () => false }
    ])
  }

  deleteItem(index) {
    var newData = this._data.slice(0);

    newData.splice(index, 1);

    this._data = newData;

    console.log(this._data);

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(this._data)
    });
  }

  render() {
    return (
      <ScrollView contentContainerStyle={Styles.container}>
        <ListView
          dataSource={this.state.dataSource}
          contentContainerStyle={{ justifyContent: 'center', alignItems: 'center' }}
          renderRow={
            (text, sectionID, rowID, highlightRow) =>
              <Text
                key={rowID}
                style={Styles.instructions}
                onPress={this.onPressListItem.bind(this, text, rowID)}
                onLongPress={this.onLongPressListItem.bind(this, rowID)}>
                  {text}
              </Text>}
          renderHeader={
            () =>
              <View style={{ flex: 1, width: Dimensions.get('window').width - 20, marginBottom: 10 }}>
                <TextInput
                  style={Styles.textInput}
                  placeholder="TODO"
                  onChangeText={(text) => this.setState({ todoText: text })}
                  value={ this.state.todoText }
                />
                <Button onPress={this.testePress}>
                  OK
                </Button>
              </View>
          }
          renderFooter={
            () =>
              <View contentContainerStyle={{ margin: 10 }}>
                <Text style={Styles.listFooter}>
                  Edit a row by tapping on it then changing its contents on the text field.
                </Text>
                <Text style={Styles.listFooter}>
                  Delete a row by long pressing it and confirming the prompt.
                </Text>
              </View>
          } />
      </ScrollView>
    )
  }
}<commit_msg>Fix deleting issue where index was being passed incorrectly<commit_after>import React, { Component } from 'react';
import { View, ListView, Text, ScrollView, TextInput, Dimensions, TouchableHighlight, Alert } from 'react-native';
import { Styles } from '../styles';
import Button from 'react-native-button';

export default class TodoListContainer extends Component {
  constructor() {
    super();

    var ds = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 });

    this._data = [
      'Kill the last 2 dragons',
      'Blast Kefka\'s face'
    ];

    this.state = {
      todoText: '',
      dataSource: ds.cloneWithRows(this._data),
      selectedIndex: null
    }

    this.testePress = this.testePress.bind(this);
  }

  testePress() {
    if (this.state.todoText.length > 0) {
      if (this.state.selectedIndex === null) { // Insert
        this._data = this._data.concat(this.state.todoText);
      } else { // Update
        var index = parseInt(this.state.selectedIndex);

        var newData = this._data.slice(0);
        newData[index] = this.state.todoText;

        this._data = newData;
      }

      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this._data),
        todoText: '',
        selectedIndex: null
      })
    }
  }

  onPressListItem(text, index) {
    this.setState({
      todoText: text,
      selectedIndex: index
    })
  }

  onLongPressListItem(text, index) {
    Alert.alert('Are you sure?', 'Are you sure you want to delete this row? This action cannot be reverted.', [
      { text: 'Yes', onPress: this.deleteItem.bind(this, text, index) },
      { text: 'No', onPress: () => false }
    ])
  }

  deleteItem(text, index) {
    var newData = this._data.slice(0);

    newData.splice(newData.indexOf(text), 1);

    this._data = newData;

    console.log(this._data);

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(this._data)
    });
  }

  render() {
    return (
      <ScrollView contentContainerStyle={Styles.container}>
        <ListView
          dataSource={this.state.dataSource}
          contentContainerStyle={{ justifyContent: 'center', alignItems: 'center' }}
          renderRow={
            (text, sectionID, rowID, highlightRow) =>
              <Text
                key={rowID}
                style={Styles.instructions}
                onPress={this.onPressListItem.bind(this, text, rowID)}
                onLongPress={this.onLongPressListItem.bind(this, text, rowID)}>
                  {text}
              </Text>
          }
          renderHeader={
            () =>
              <View style={{ flex: 1, width: Dimensions.get('window').width - 20, marginBottom: 10 }}>
                <TextInput
                  style={Styles.textInput}
                  placeholder="TODO"
                  onChangeText={(text) => this.setState({ todoText: text })}
                  value={ this.state.todoText }
                />
                <Button onPress={this.testePress}>
                  OK
                </Button>
              </View>
          }
          renderFooter={
            () =>
              <View contentContainerStyle={{ margin: 10 }}>
                <Text style={Styles.listFooter}>
                  Edit a row by tapping on it then changing its contents on the text field.
                </Text>
                <Text style={Styles.listFooter}>
                  Delete a row by long pressing it and confirming the prompt.
                </Text>
              </View>
          } />
      </ScrollView>
    )
  }
}<|endoftext|>


<commit_before>var format = require('util').format
var Promise = require('bluebird')
var request = require('request')
var post = Promise.promisify(request.post)

module.exports = {
  textForNewPost: function (post, community) {
    var relatedUser
    const creator = post.relations.user
    if (post.isWelcome()) {
      relatedUser = post.relations.relatedUsers.first()
      return format('<%s|%s> joined <%s|%s>',
        Frontend.Route.profile(relatedUser), relatedUser.get('name'),
        Frontend.Route.community(community), community.get('name'))
    } else {
      return format('<%s|%s> posted <%s|"%s"> in <%s|%s>',
        Frontend.Route.profile(creator), creator.get('name'),
        Frontend.Route.post(post), post.get('name'),
        Frontend.Route.community(community), community.get('name'))
    }
  },
  send: (message, uri) =>
    post({
      uri,
      body: {text: message},
      json: true // Automatically stringifies the body to JSON
    })
}
<commit_msg>add env var check before sending messages to Slack<commit_after>var format = require('util').format
var Promise = require('bluebird')
var request = require('request')
var post = Promise.promisify(request.post)

module.exports = {
  textForNewPost: function (post, community) {
    var relatedUser
    const creator = post.relations.user
    if (post.isWelcome()) {
      relatedUser = post.relations.relatedUsers.first()
      return format('<%s|%s> joined <%s|%s>',
        Frontend.Route.profile(relatedUser), relatedUser.get('name'),
        Frontend.Route.community(community), community.get('name'))
    } else {
      return format('<%s|%s> posted <%s|"%s"> in <%s|%s>',
        Frontend.Route.profile(creator), creator.get('name'),
        Frontend.Route.post(post), post.get('name'),
        Frontend.Route.community(community), community.get('name'))
    }
  },
  send: (message, uri) =>
    !process.env.DISABLE_SLACK_INTEGRATION && post({
      uri,
      body: {text: message},
      json: true // Automatically stringifies the body to JSON
    })
}
<|endoftext|>