<commit_before>import { fromJS, Map } from 'immutable';

// Action constants
const CONFIRM_OPERATION = 'transaction/CONFIRM_OPERATION';
const HIDE_CONFIRM = 'transaction/HIDE_CONFIRM';
export const BROADCAST_OPERATION = 'transaction/BROADCAST_OPERATION';
const ERROR = 'transaction/ERROR'; // Has a watcher in SagaShared
const DELETE_ERROR = 'transaction/DELETE_ERROR';
const DISMISS_ERROR = 'transaction/DISMISS_ERROR';
const SET = 'transaction/SET';
const REMOVE = 'transaction/REMOVE';
// Saga-related
const defaultState = fromJS({
    operations: [],
    status: { key: '', error: false, busy: false },
    errors: {
        bandwidthError: false,
    },
});

function last_part(value, sep) {
    const parts = value.split(sep);
    return parts[parts.length - 1];
}

export default function reducer(state = defaultState, action) {
    const payload = action.payload;

    switch (action.type) {
        case CONFIRM_OPERATION: {
            const operation = fromJS(payload.operation);
            const confirm = payload.confirm;
            const warning = payload.warning;
            return state.merge({
                show_confirm_modal: true,
                confirmBroadcastOperation: operation,
                confirmErrorCallback: payload.errorCallback,
                confirm,
                warning,
            });
        }

        case HIDE_CONFIRM:
            return state.merge({
                show_confirm_modal: false,
                confirmBroadcastOperation: undefined,
                confirm: undefined,
            });

        case BROADCAST_OPERATION:
            // See TransactionSaga.js
            return state;

        case ERROR: {
            const { operations, error, errorCallback } = payload;

            let msg;
            let key = error.toString().replace(/rethrow$/, '');

            if (/You may only post once every/.test(key)) {
                // Assert Exception:( now - auth.last_root_post ) > STEEM_MIN_ROOT_COMMENT_INTERVAL: You may only post once every 5 minutes.
                msg = 'You may only post once every five minutes.';
            } else if (
                /Your current vote on this comment is identical/.test(key)
            ) {
                // Assert Exception:itr->vote_percent != o.weight: Your current vote on this comment is identical to this vote.
                msg =
                    'Your current vote on this comment is identical to this vote.';
            } else if (/Please wait to transact, or power up STEEM/.test(key)) {
                // plugin exception:Account: test-safari has 1154101776 RC, needs 1274161808 RC. Please wait to transact, or power up STEEM.rethrow
                try {
                    const m = [...key.matchAll(/(\d+) RC/g)];
                    const spv = 0.0005;
                    const fudge = 1.1;
                    const has_vests = parseInt(m[0][1], 10) / 1e6;
                    const needs_vests = parseInt(m[1][1], 10) / 1e6;
                    const sp = (
                        (needs_vests - has_vests) *
                        spv *
                        fudge
                    ).toFixed(3);
                    msg = `Bandwidth error: insufficient Resource Credits. Please wait to transact, or power up ${
                        sp
                    } STEEM.`;
                } catch (e) {
                    console.error('bandwidth parse error', key);
                    msg = 'Bandwidth error: ' + last_part(key, ':');
                }
            } else if (/unknown key: /.test(key)) {
                // RPCError: unknown key:unknown key:
                msg = "Transaction failed: Steem account doesn't exist.";
            } else if (/missing required posting authority/.test(key)) {
                // missing required posting authority:Missing Posting Authority test-safari
                msg = last_part(key, ':');
            } else if (
                /Cannot delete a comment with net positive votes/.test(key)
            ) {
                // Assert Exception:comment.net_rshares <= 0: Cannot delete a comment with net positive votes.
                msg = last_part(key, ':');
            } else {
                msg = 'Transaction broadcast error: ' + last_part(key, ':');
                console.error('unhandled error:', key, 'msg:', error.message);
            }

            // SagaShared / showTransactionErrorNotification
            state = state.update('errors', errors => {
                return errors ? errors.set(key, msg) : Map({ [key]: msg });
            });

            if (msg.includes('RC')) {
                state = state.setIn(['errors', 'bandwidthError'], true); //show_bandwidth_error_modal
            }

            if (!errorCallback)
                throw new Error(`PANIC: no error callback for '${key}'`);
            errorCallback(msg);

            return state;
        }

        case DELETE_ERROR:
            return state.deleteIn(['errors', payload.key]);

        case DISMISS_ERROR:
            return state.setIn(['errors', payload.key], false);

        case SET:
            return state.setIn(
                Array.isArray(payload.key) ? payload.key : [payload.key],
                fromJS(payload.value)
            );

        case REMOVE:
            return state.removeIn(
                Array.isArray(payload.key) ? payload.key : [payload.key]
            );

        default:
            return state;
    }
}

// Action creators
export const confirmOperation = payload => ({
    type: CONFIRM_OPERATION,
    payload,
});

export const hideConfirm = payload => ({
    type: HIDE_CONFIRM,
    payload,
});

export const broadcastOperation = payload => ({
    type: BROADCAST_OPERATION,
    payload,
});

export const error = payload => ({
    type: ERROR,
    payload,
});

export const deleteError = payload => ({
    type: DELETE_ERROR,
    payload,
});

export const dismissError = payload => ({
    type: DISMISS_ERROR,
    payload,
});

export const set = payload => ({
    type: SET,
    payload,
});

export const remove = payload => ({
    type: REMOVE,
    payload,
});
<commit_msg>handle identical vote error<commit_after>import { fromJS, Map } from 'immutable';

// Action constants
const CONFIRM_OPERATION = 'transaction/CONFIRM_OPERATION';
const HIDE_CONFIRM = 'transaction/HIDE_CONFIRM';
export const BROADCAST_OPERATION = 'transaction/BROADCAST_OPERATION';
const ERROR = 'transaction/ERROR'; // Has a watcher in SagaShared
const DELETE_ERROR = 'transaction/DELETE_ERROR';
const DISMISS_ERROR = 'transaction/DISMISS_ERROR';
const SET = 'transaction/SET';
const REMOVE = 'transaction/REMOVE';
// Saga-related
const defaultState = fromJS({
    operations: [],
    status: { key: '', error: false, busy: false },
    errors: {
        bandwidthError: false,
    },
});

function last_part(value, sep) {
    const parts = value.split(sep);
    return parts[parts.length - 1];
}

export default function reducer(state = defaultState, action) {
    const payload = action.payload;

    switch (action.type) {
        case CONFIRM_OPERATION: {
            const operation = fromJS(payload.operation);
            const confirm = payload.confirm;
            const warning = payload.warning;
            return state.merge({
                show_confirm_modal: true,
                confirmBroadcastOperation: operation,
                confirmErrorCallback: payload.errorCallback,
                confirm,
                warning,
            });
        }

        case HIDE_CONFIRM:
            return state.merge({
                show_confirm_modal: false,
                confirmBroadcastOperation: undefined,
                confirm: undefined,
            });

        case BROADCAST_OPERATION:
            // See TransactionSaga.js
            return state;

        case ERROR: {
            const { operations, error, errorCallback } = payload;

            let msg;
            let key = error.toString().replace(/rethrow$/, '');

            if (/You may only post once every/.test(key)) {
                // Assert Exception:( now - auth.last_root_post ) > STEEM_MIN_ROOT_COMMENT_INTERVAL: You may only post once every 5 minutes.
                msg = 'You may only post once every five minutes.';
            } else if (
                /Your current vote on this comment is identical/.test(key)
            ) {
                // Assert Exception:itr->vote_percent != o.weight: Your current vote on this comment is identical to this vote.
                msg =
                    'Your current vote on this comment is identical to this vote.';
            } else if (/Please wait to transact, or power up STEEM/.test(key)) {
                // plugin exception:Account: test-safari has 1154101776 RC, needs 1274161808 RC. Please wait to transact, or power up STEEM.rethrow
                try {
                    const m = [...key.matchAll(/(\d+) RC/g)];
                    const spv = 0.0005;
                    const fudge = 1.1;
                    const has_vests = parseInt(m[0][1], 10) / 1e6;
                    const needs_vests = parseInt(m[1][1], 10) / 1e6;
                    const sp = (
                        (needs_vests - has_vests) *
                        spv *
                        fudge
                    ).toFixed(3);
                    msg = `Bandwidth error: insufficient Resource Credits. Please wait to transact, or power up ${
                        sp
                    } STEEM.`;
                } catch (e) {
                    console.error('bandwidth parse error', key);
                    msg = 'Bandwidth error: ' + last_part(key, ':');
                }
            } else if (/unknown key: /.test(key)) {
                // RPCError: unknown key:unknown key:
                msg = "Transaction failed: Steem account doesn't exist.";
            } else if (/missing required posting authority/.test(key)) {
                // missing required posting authority:Missing Posting Authority test-safari
                msg = last_part(key, ':');
            } else if (/Cannot delete a comment with net positive/.test(key)) {
                // Assert Exception:comment.net_rshares <= 0: Cannot delete a comment with net positive votes.
                msg = last_part(key, ':');
            } else if (/current vote on this comment is identical/.test(key)) {
                // Assert Exception:itr->vote_percent != o.weight: Your current vote on this comment is identical to this vote.
                msg = 'You already voted on this post.';
            } else {
                msg = 'Transaction broadcast error: ' + last_part(key, ':');
                console.error('unhandled error:', key, 'msg:', error.message);
            }

            // SagaShared / showTransactionErrorNotification
            state = state.update('errors', errors => {
                return errors ? errors.set(key, msg) : Map({ [key]: msg });
            });

            if (msg.includes('RC')) {
                state = state.setIn(['errors', 'bandwidthError'], true); //show_bandwidth_error_modal
            }

            if (!errorCallback)
                throw new Error(`PANIC: no error callback for '${key}'`);
            errorCallback(msg);

            return state;
        }

        case DELETE_ERROR:
            return state.deleteIn(['errors', payload.key]);

        case DISMISS_ERROR:
            return state.setIn(['errors', payload.key], false);

        case SET:
            return state.setIn(
                Array.isArray(payload.key) ? payload.key : [payload.key],
                fromJS(payload.value)
            );

        case REMOVE:
            return state.removeIn(
                Array.isArray(payload.key) ? payload.key : [payload.key]
            );

        default:
            return state;
    }
}

// Action creators
export const confirmOperation = payload => ({
    type: CONFIRM_OPERATION,
    payload,
});

export const hideConfirm = payload => ({
    type: HIDE_CONFIRM,
    payload,
});

export const broadcastOperation = payload => ({
    type: BROADCAST_OPERATION,
    payload,
});

export const error = payload => ({
    type: ERROR,
    payload,
});

export const deleteError = payload => ({
    type: DELETE_ERROR,
    payload,
});

export const dismissError = payload => ({
    type: DISMISS_ERROR,
    payload,
});

export const set = payload => ({
    type: SET,
    payload,
});

export const remove = payload => ({
    type: REMOVE,
    payload,
});
<|endoftext|>


<commit_before>MathJax.Extension["TeX/mediawiki-texvc"] = {
	version: "2.5.0"
};

MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () {
	MathJax.InputJax.TeX.Definitions.Add({
		macros: {
			alef: ["Macro", "\\aleph"],
			alefsym: ["Macro", "\\aleph"],
			Alpha: ["Macro", "\\mathrm{A}"],
			and: ["Macro", "\\land"],
			ang: ["Macro", "\\angle"],
			Bbb: ["Macro", "\\mathbb"],
			Beta: ["Macro", "\\mathrm{B}"],
			bold: ["Macro", "\\mathbf"],
			bull: ["Macro", "\\bullet"],
			C: ["Macro", "\\mathbb{C}"],
			Chi: ["Macro", "\\mathrm{X}"],
			clubs: ["Macro", "\\clubsuit"],
			cnums: ["Macro", "\\mathbb{C}"],
			Complex: ["Macro", "\\mathbb{C}"],
			Dagger: ["Macro", "\\ddagger"],
			darr: ["Macro", "\\downarrow"],
			dArr: ["Macro", "\\Downarrow"],
			Darr: ["Macro", "\\Downarrow"],
			diamonds: ["Macro", "\\diamondsuit"],
			empty: ["Macro", "\\emptyset"],
			Epsilon: ["Macro", "\\mathrm{E}"],
			Eta: ["Macro", "\\mathrm{H}"],
			exist: ["Macro", "\\exists"],
			H: ["Macro", "\\mathbb{H}"],
			hAar: ["Macro", "\\Leftrightarrow"],
			harr: ["Macro", "\\leftrightarrow"],
			Harr: ["Macro", "\\Leftrightarrow"],
			hearts: ["Macro", "\\heartsuit"],
			image: ["Macro", "\\Im"],
			infin: ["Macro", "\\infty"],
			Iota: ["Macro", "\\mathrm{I}"],
			isin: ["Macro", "\\in"],
			Kappa: ["Macro", "\\mathrm{K}"],
			lang: ["Macro", "\\langle"],
			larr: ["Macro", "\\leftarrow"],
			Larr: ["Macro", "\\Leftarrow"],
			lArr: ["Macro", "\\Leftarrow"],
			lrarr: ["Macro", "\\leftrightarrow"],
			Lrarr: ["Macro", "\\Leftrightarrow"],
			lrArr: ["Macro", "\\Leftrightarrow"],
			Mu: ["Macro", "\\mathrm{M}"],
			N: ["Macro", "\\mathbb{N}"],
			natnums: ["Macro", "\\mathbb{N}"],
			Nu: ["Macro", "\\mathrm{N}"],
			O: ["Macro", "\\emptyset"],
			Omicron: ["Macro", "\\mathrm{O}"],
			or: ["Macro", "\\lor"],
			part: ["Macro", "\\partial"],
			plusmn: ["Macro", "\\pm"],
			Q: ["Macro", "\\mathbb{Q}"],
			R: ["Macro", "\\mathbb{R}"],
			rang: ["Macro", "\\rangle"],
			rarr: ["Macro", "\\rightarrow"],
			Rarr: ["Macro", "\\Rightarrow"],
			rArr: ["Macro", "\\Rightarrow"],
			real: ["Macro", "\\Re"],
			reals: ["Macro", "\\mathbb{R}"],
			Reals: ["Macro", "\\mathbb{R}"],
			Rho: ["Macro", "\\mathrm{P}"],
			sdot: ["Macro", "\\cdot"],
			sect: ["Macro", "\\S"],
			spades: ["Macro", "\\spadesuit"],
			sub: ["Macro", "\\subset"],
			sube: ["Macro", "\\subseteq"],
			supe: ["Macro", "\\supseteq"],
			Tau: ["Macro", "\\mathrm{T}"],
			thetasym: ["Macro", "\\vartheta"],
			uarr: ["Macro", "\\uparrow"],
			uArr: ["Macro", "\\Uparrow"],
			Uarr: ["Macro", "\\Uparrow"],
			varcoppa: ["Macro", "\\mbox{\u03D9}"],
			weierp: ["Macro", "\\wp"],
			Z: ["Macro", "\\mathbb{Z}"],
			Zeta: ["Macro", "\\mathrm{Z}"]
		}
	});
});

MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mediawiki-texvc.js");<commit_msg>Add pagecolor support<commit_after>MathJax.Extension["TeX/mediawiki-texvc"] = {
	version: "2.5.0"
};

MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () {
	MathJax.InputJax.TeX.Definitions.Add({
		macros: {
			alef: ["Macro", "\\aleph"],
			alefsym: ["Macro", "\\aleph"],
			Alpha: ["Macro", "\\mathrm{A}"],
			and: ["Macro", "\\land"],
			ang: ["Macro", "\\angle"],
			Bbb: ["Macro", "\\mathbb"],
			Beta: ["Macro", "\\mathrm{B}"],
			bold: ["Macro", "\\mathbf"],
			bull: ["Macro", "\\bullet"],
			C: ["Macro", "\\mathbb{C}"],
			Chi: ["Macro", "\\mathrm{X}"],
			clubs: ["Macro", "\\clubsuit"],
			cnums: ["Macro", "\\mathbb{C}"],
			Complex: ["Macro", "\\mathbb{C}"],
			Dagger: ["Macro", "\\ddagger"],
			darr: ["Macro", "\\downarrow"],
			dArr: ["Macro", "\\Downarrow"],
			Darr: ["Macro", "\\Downarrow"],
			diamonds: ["Macro", "\\diamondsuit"],
			empty: ["Macro", "\\emptyset"],
			Epsilon: ["Macro", "\\mathrm{E}"],
			Eta: ["Macro", "\\mathrm{H}"],
			exist: ["Macro", "\\exists"],
			H: ["Macro", "\\mathbb{H}"],
			hAar: ["Macro", "\\Leftrightarrow"],
			harr: ["Macro", "\\leftrightarrow"],
			Harr: ["Macro", "\\Leftrightarrow"],
			hearts: ["Macro", "\\heartsuit"],
			image: ["Macro", "\\Im"],
			infin: ["Macro", "\\infty"],
			Iota: ["Macro", "\\mathrm{I}"],
			isin: ["Macro", "\\in"],
			Kappa: ["Macro", "\\mathrm{K}"],
			lang: ["Macro", "\\langle"],
			larr: ["Macro", "\\leftarrow"],
			Larr: ["Macro", "\\Leftarrow"],
			lArr: ["Macro", "\\Leftarrow"],
			lrarr: ["Macro", "\\leftrightarrow"],
			Lrarr: ["Macro", "\\Leftrightarrow"],
			lrArr: ["Macro", "\\Leftrightarrow"],
			Mu: ["Macro", "\\mathrm{M}"],
			N: ["Macro", "\\mathbb{N}"],
			natnums: ["Macro", "\\mathbb{N}"],
			Nu: ["Macro", "\\mathrm{N}"],
			O: ["Macro", "\\emptyset"],
			Omicron: ["Macro", "\\mathrm{O}"],
			or: ["Macro", "\\lor"],
			pagecolor: ['Macro','',1],  // ignore \pagecolor{}
			part: ["Macro", "\\partial"],
			plusmn: ["Macro", "\\pm"],
			Q: ["Macro", "\\mathbb{Q}"],
			R: ["Macro", "\\mathbb{R}"],
			rang: ["Macro", "\\rangle"],
			rarr: ["Macro", "\\rightarrow"],
			Rarr: ["Macro", "\\Rightarrow"],
			rArr: ["Macro", "\\Rightarrow"],
			real: ["Macro", "\\Re"],
			reals: ["Macro", "\\mathbb{R}"],
			Reals: ["Macro", "\\mathbb{R}"],
			Rho: ["Macro", "\\mathrm{P}"],
			sdot: ["Macro", "\\cdot"],
			sect: ["Macro", "\\S"],
			spades: ["Macro", "\\spadesuit"],
			sub: ["Macro", "\\subset"],
			sube: ["Macro", "\\subseteq"],
			supe: ["Macro", "\\supseteq"],
			Tau: ["Macro", "\\mathrm{T}"],
			thetasym: ["Macro", "\\vartheta"],
			uarr: ["Macro", "\\uparrow"],
			uArr: ["Macro", "\\Uparrow"],
			Uarr: ["Macro", "\\Uparrow"],
			varcoppa: ["Macro", "\\mbox{\u03D9}"],
			weierp: ["Macro", "\\wp"],
			Z: ["Macro", "\\mathbb{Z}"],
			Zeta: ["Macro", "\\mathrm{Z}"]
		}
	});
});

MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mediawiki-texvc.js");
<|endoftext|>


<commit_before>var EventSocket = require('eventsocket');
var _ = require('lodash');
var log = require('debug')('JGF:client');

function Client(io, ip, port) {
    var client = this;
    var info = {};
    var diff = {};
    var map = {};
    var status = {};
    var turn = -1;
    var views = {};

    log('connecting... %s:%s', ip, port);

    var socket = new EventSocket(port, ip);

    socket.on('connect', function () {
        socket.emit('token', '00000000000000000000000000000000');
    });

    socket.on('disconnect', function () {
        log('disconnect');
    });

    socket.on('init', function (_info, _map, _diff) {
        info = _info || {};
        turn = info.turn || -1;
        _diff = _diff || {};
        diff = {};
        map = _map || {};
        status = {};

        io.to('_clients').emit('info', info);
        io.to('_clients').emit('map', map);
        io.to('_clients').emit('status', status);

        views = {};
        _(info.views)
            .each(function (view) {
                views[view] = true;
                diff[view] = {};
                _(_diff[view])
                    .each(function (item) {
                        diff[view][item.id] = item;
                    })
                    .value();
                io.to(view).emit('diff', diff[view]);
            })
            .value();
    });

    socket.on('turn', function (_turn, _diff) {
        log('turn', _turn, _diff);
        turn = _turn;
        _(_diff)
            .each(function (data) {
                var view = data.view;
                log('view ' + view);
                var outDiff = {
                    statics: [],
                    dynamics: [],
                    transients: []
                };
                if (diff[view] == undefined) {
                    diff[view] = {};
                }
                _(data.statics)
                    .each(function (item) {
                        diff[view][item.id] = item;
                        outDiff.statics.push(item);
                    })
                    .value();
                outDiff.statics = data.statics || [];
                outDiff.dynamics = data.dynamics || [];
                outDiff.transients = data.transients || [];
                io.to(view).emit('turn', turn, outDiff);
            })
            .value();
    });

    socket.on('msgs', function (_msgs) {
        io.to('_clients').emit('msgs', _msgs);
    });
    socket.on('status', function (_status) {
        status = _status || {};
        io.to('_clients').emit('status', _status);
    });

    client.getInfo = function () {
        return info;
    };
    client.getViews = function () {
        return views;
    };
    client.getViewData = function (view) {
        return _.values(diff[view]);
    };
    client.getMap = function () {
        return map;
    };
    client.getStatus = function () {
        return status;
    };
}
module.exports = Client;<commit_msg>fix client _diff<commit_after>var EventSocket = require('eventsocket');
var _ = require('lodash');
var log = require('debug')('JGF:client');

function Client(io, ip, port) {
    var client = this;
    var info = {};
    var diff = {};
    var map = {};
    var status = {};
    var turn = -1;
    var views = {};

    log('connecting... %s:%s', ip, port);

    var socket = new EventSocket(port, ip);

    socket.on('connect', function () {
        socket.emit('token', '00000000000000000000000000000000');
    });

    socket.on('disconnect', function () {
        log('disconnect');
    });

    socket.on('init', function (_info, _map, _diff) {
        info = _info || {};
        turn = info.turn || -1;
        _diff = _diff || {};
        diff = {};
        map = _map || {};
        status = {};

        io.to('_clients').emit('info', info);
        io.to('_clients').emit('map', map);
        io.to('_clients').emit('status', status);

        views = {};
        _(info.views)
            .each(function (view) {
                views[view] = true;
            })
            .value();

        _(_diff)
            .each(function (_diffView) {
                var view = _diffView.view;
                diff[view] = {};
                _(_diffView.statics)
                    .each(function (item) {
                        diff[view][item.id] = item;
                    })
                    .value();
                io.to(view).emit('diff', diff[view]);
            })
            .value();
    });

    socket.on('turn', function (_turn, _diff) {
        log('turn', _turn, _diff);
        turn = _turn;
        _(_diff)
            .each(function (data) {
                var view = data.view;
                log('view ' + view);
                var outDiff = {
                    statics: [],
                    dynamics: [],
                    transients: []
                };
                if (diff[view] == undefined) {
                    diff[view] = {};
                }
                _(data.statics)
                    .each(function (item) {
                        diff[view][item.id] = item;
                        outDiff.statics.push(item);
                    })
                    .value();
                outDiff.statics = data.statics || [];
                outDiff.dynamics = data.dynamics || [];
                outDiff.transients = data.transients || [];
                io.to(view).emit('turn', turn, outDiff);
            })
            .value();
    });

    socket.on('msgs', function (_msgs) {
        io.to('_clients').emit('msgs', _msgs);
    });
    socket.on('status', function (_status) {
        status = _status || {};
        io.to('_clients').emit('status', _status);
    });

    client.getInfo = function () {
        return info;
    };
    client.getViews = function () {
        return views;
    };
    client.getViewData = function (view) {
        return _.values(diff[view]);
    };
    client.getMap = function () {
        return map;
    };
    client.getStatus = function () {
        return status;
    };
}
module.exports = Client;<|endoftext|>


<commit_before>// TESTBROWSER!!!!???
import { get, puid } from 'brisky-struct'
import fragment from './fragment'
import { property, element, isStatic, staticProps } from '../../../static'
import { cache, tag } from '../../../../get'

const injectable = {}
const xmlns = 'http://www.w3.org/2000/svg'

export default injectable

const resolveState = (t, pnode, id, state) => {
  if (!pnode && t.node) {
    t.node.removeAttribute('id')
    return t.node
  } else {
    const children = pnode.childNodes
    id = (id * 33 ^ puid(state)) >>> 0
    var i = children.length
    while (i--) {
      if (children[i].id == id) { // eslint-disable-line
        children[i].removeAttribute('id')
        return children[i]
      }
    }
  }
}

const hasStateProperties = t => {
  const keys = t.keys()
  if (keys) {
    let i = keys.length
    while (i--) {
      let check = get(t, keys[i])
      if (!check.isElement && !isStatic(check)) {
        return true
      }
    }
  }
}

const staticFromCache = (cached) => {
  const node = cached.cloneNode(true)
  if (cached._index) node._index = cached._index
  if (cached._last) node._last = cached._last
  return node
}

const createElement = nodeType => {
  if (nodeType === 'div') {
    return document.createElement(nodeType)
  } else {
    return nodeType === 'svg' ||
      nodeType === 'path' ||
      nodeType === 'g' ||
      nodeType === 'rect' ||
      nodeType === 'circle' ||
      nodeType === 'ellipse'
      ? document.createElementNS(xmlns, nodeType)
      : document.createElement(nodeType)
  }
}

// indexes need to be copied when adding from pre-render
injectable.static = (t, pnode, noResolve) => {
  // the cache node is nto good of course!
  const cached = cache(t)
  var node
  if (!t.resolve && cached && isStatic(t)) {
    node = staticFromCache(cached)
  } else {
    if (cached) {
      throw new Error('static but its not static..... very strange....' + t.path())
    } else {
      const nodeType = tag(t)
      if (nodeType === 'fragment') {
        console.error('not handeling static fragments yet')
      } else {
        node = createElement(nodeType)
        property(t, node)
        element(t, node, true)
        t._cachedNode = node
      }
    }
  }
  return node
}

// fn for cached
injectable.state = (t, type, subs, tree, id, pnode, state) => {
  // need to re-add cache ofc
  var cached = !t.resolve && cache(t)
  var node
  // @todo: this copies unwanted styles / props -- need to add an extra clonenode for this
  if (cached) {
    node = cached.cloneNode(false)
    tree._[id] = node
    if (cached._last) {
      node._last = cached._last
    }
    if (cached._index) {
      node._index = cached._index
    }
    element(t, node)
  } else {
    const nodeType = tag(t)
    if (nodeType === 'fragment') {
      return fragment(t, pnode, id, tree)
    } else {
      // will become an argument in render or something
      if (t.resolve) {
        // dont resolve this
        if (!tree._p || !tree._p._key !== 'client') {
          node = resolveState(t, pnode, id, state)
        }
        if (!node) {
          node = createElement(nodeType)
          const hasStaticProps = staticProps(t).length
          if (hasStaticProps) {
            t._cachedNode = node
            property(t, node)
            if (hasStateProperties(t)) {
              node = t._cachedNode.cloneNode(false)
            }
          }
          element(t, node)
        }
      } else {
        node = createElement(nodeType)
        const hasStaticProps = staticProps(t).length
        if (hasStaticProps) {
          t._cachedNode = node
          property(t, node)
          if (hasStateProperties(t)) {
            node = t._cachedNode.cloneNode(false)
          }
        }
        element(t, node)
      }
    }
    tree._[id] = node
  }
  // element(t, node)
  return node
}
<commit_msg>added gaurd for no children on resolve<commit_after>// TESTBROWSER!!!!???
import { get, puid } from 'brisky-struct'
import fragment from './fragment'
import { property, element, isStatic, staticProps } from '../../../static'
import { cache, tag } from '../../../../get'

const injectable = {}
const xmlns = 'http://www.w3.org/2000/svg'

export default injectable

const resolveState = (t, pnode, id, state) => {
  if (!pnode && t.node) {
    t.node.removeAttribute('id')
    return t.node
  } else {
    const children = pnode.childNodes
    if (children) {
      id = (id * 33 ^ puid(state)) >>> 0
      var i = children.length
      while (i--) {
        if (children[i].id == id) { // eslint-disable-line
          children[i].removeAttribute('id')
          return children[i]
        }
      }
    }
  }
}

const hasStateProperties = t => {
  const keys = t.keys()
  if (keys) {
    let i = keys.length
    while (i--) {
      let check = get(t, keys[i])
      if (!check.isElement && !isStatic(check)) {
        return true
      }
    }
  }
}

const staticFromCache = (cached) => {
  const node = cached.cloneNode(true)
  if (cached._index) node._index = cached._index
  if (cached._last) node._last = cached._last
  return node
}

const createElement = nodeType => {
  if (nodeType === 'div') {
    return document.createElement(nodeType)
  } else {
    return nodeType === 'svg' ||
      nodeType === 'path' ||
      nodeType === 'g' ||
      nodeType === 'rect' ||
      nodeType === 'circle' ||
      nodeType === 'ellipse'
      ? document.createElementNS(xmlns, nodeType)
      : document.createElement(nodeType)
  }
}

// indexes need to be copied when adding from pre-render
injectable.static = (t, pnode, noResolve) => {
  // the cache node is nto good of course!
  const cached = cache(t)
  var node
  if (!t.resolve && cached && isStatic(t)) {
    node = staticFromCache(cached)
  } else {
    if (cached) {
      throw new Error('static but its not static..... very strange....' + t.path())
    } else {
      const nodeType = tag(t)
      if (nodeType === 'fragment') {
        console.error('not handeling static fragments yet')
      } else {
        node = createElement(nodeType)
        property(t, node)
        element(t, node, true)
        t._cachedNode = node
      }
    }
  }
  return node
}

// fn for cached
injectable.state = (t, type, subs, tree, id, pnode, state) => {
  // need to re-add cache ofc
  var cached = !t.resolve && cache(t)
  var node
  // @todo: this copies unwanted styles / props -- need to add an extra clonenode for this
  if (cached) {
    node = cached.cloneNode(false)
    tree._[id] = node
    if (cached._last) {
      node._last = cached._last
    }
    if (cached._index) {
      node._index = cached._index
    }
    element(t, node)
  } else {
    const nodeType = tag(t)
    if (nodeType === 'fragment') {
      return fragment(t, pnode, id, tree)
    } else {
      // will become an argument in render or something
      if (t.resolve) {
        // dont resolve this
        if (!tree._p || !tree._p._key !== 'client') {
          node = resolveState(t, pnode, id, state)
        }
        if (!node) {
          node = createElement(nodeType)
          const hasStaticProps = staticProps(t).length
          if (hasStaticProps) {
            t._cachedNode = node
            property(t, node)
            if (hasStateProperties(t)) {
              node = t._cachedNode.cloneNode(false)
            }
          }
          element(t, node)
        }
      } else {
        node = createElement(nodeType)
        const hasStaticProps = staticProps(t).length
        if (hasStaticProps) {
          t._cachedNode = node
          property(t, node)
          if (hasStateProperties(t)) {
            node = t._cachedNode.cloneNode(false)
          }
        }
        element(t, node)
      }
    }
    tree._[id] = node
  }
  // element(t, node)
  return node
}
<|endoftext|>


<commit_before>ZBase.registerView((function() {

  var load = function(url) {
    $.showLoader();

    $.httpGet("/api/v1/tables", function(r) {
      if (r.status == 200) {
        render(JSON.parse(r.response).tables);
      } else {
        $.fatalError();
      }
      $.hideLoader();
    });
  };

  var render = function(tables) {
    var page = $.getTemplate(
        "views/datastore_tables",
        "zbase_datastore_tables_list_tpl");

    var menu = HomeMenu();
    menu.render($(".zbase_home_menu_sidebar", page));

    var tbody = $("tbody", page);
    tables.forEach(function(table) {
      renderRow(tbody, table);
    });

    $.handleLinks(page);
    $.replaceViewport(page);
  };

  var renderRow = function(tbody, table) {
    var elem = $.getTemplate(
        "views/datastore_tables",
        "zbase_datastore_tables_list_row_tpl");

    var url = "/a/table/" + table.name;

    var table_name = $(".table_name", elem);
    table_name.innerHTML = table.name;
    table_name.href = url;
    //$(".table_description", elem).innerHTML = table[1];

    tbody.appendChild(elem);
  };

  return {
    name: "datastore_tables",
    loadView: function(params) { load(params.url); },
    unloadView: function() {},
    handleNavigationChange: render
  };
})());
<commit_msg>destroy<commit_after>ZBase.registerView((function() {

  var load = function(url) {
    $.showLoader();

    $.httpGet("/api/v1/tables", function(r) {
      if (r.status == 200) {
        render(JSON.parse(r.response).tables);
      } else {
        $.fatalError();
      }
      $.hideLoader();
    });
  };

  var destroy = function() {
    //abort http request
  };

  var render = function(tables) {
    var page = $.getTemplate(
        "views/datastore_tables",
        "zbase_datastore_tables_list_tpl");

    var menu = HomeMenu();
    menu.render($(".zbase_home_menu_sidebar", page));

    var tbody = $("tbody", page);
    tables.forEach(function(table) {
      renderRow(tbody, table);
    });

    $.handleLinks(page);
    $.replaceViewport(page);
  };

  var renderRow = function(tbody, table) {
    var elem = $.getTemplate(
        "views/datastore_tables",
        "zbase_datastore_tables_list_row_tpl");

    var url = "/a/table/" + table.name;

    var table_name = $(".table_name", elem);
    table_name.innerHTML = table.name;
    table_name.href = url;
    //$(".table_description", elem).innerHTML = table[1];

    tbody.appendChild(elem);
  };

  return {
    name: "datastore_tables",
    loadView: function(params) { load(params.url); },
    unloadView: destroy,
    handleNavigationChange: render
  };
})());
<|endoftext|>


<commit_before>import '../testHelper';
import { addAssignment, deleteAssignment } from '../../app/assets/javascripts/actions/assignment_actions.js';

describe('AssignmentActions', () => {
  const testAssignment = { title: 'Foo', user_id: 1, id: 4 };
  const initialAssignments = [];
  sinon.stub($, 'ajax').yieldsTo('success', { assignment: testAssignment });
  it('.addAssignment sets a new assignment and .deleteAssignment removes one', () => {
    expect(reduxStore.getState().assignments.assignments).to.deep.eq(initialAssignments);
    addAssignment(testAssignment)(reduxStore.dispatch)
      .then(() => {
        const updatedAssignments = reduxStore.getState().assignments.assignments;
        expect(updatedAssignments[0].article_title).to.eq(testAssignment.title);
        expect(updatedAssignments[0].user_id).to.eq(testAssignment.user_id);
        expect(updatedAssignments.length).to.eq(1);
      })
      .then(() => {
        const updatedAssignments = reduxStore.getState().assignments.assignments;
        deleteAssignment(updatedAssignments[0])(reduxStore.dispatch);
      })
      .then(() => {
        const assignmentsAfterDelete = reduxStore.getState().assignments.assignments;
        expect(assignmentsAfterDelete.length).to.eq(0);
      });
  });
});
<commit_msg>Fix broken test<commit_after>import '../testHelper';
import { addAssignment, deleteAssignment } from '../../app/assets/javascripts/actions/assignment_actions.js';

describe('AssignmentActions', () => {
  const testAssignment = { article_title: 'Foo', user_id: 1, id: 4 };
  const initialAssignments = [];
  sinon.stub($, 'ajax').yieldsTo('success', testAssignment);
  it('.addAssignment sets a new assignment and .deleteAssignment removes one', (done) => {
    expect(reduxStore.getState().assignments.assignments).to.deep.eq(initialAssignments);
    addAssignment(testAssignment)(reduxStore.dispatch)
      .then(() => {
        const updatedAssignments = reduxStore.getState().assignments.assignments;
        expect(updatedAssignments[0].article_title).to.eq(testAssignment.article_title);
        expect(updatedAssignments[0].user_id).to.eq(testAssignment.user_id);
        expect(updatedAssignments.length).to.eq(1);
      })
      .then(() => {
        const updatedAssignments = reduxStore.getState().assignments.assignments;
        const deletionResponse = { assignmentId: updatedAssignments[0].id };
        $.ajax.restore();
        sinon.stub($, 'ajax').yieldsTo('success', deletionResponse);
        deleteAssignment(updatedAssignments[0])(reduxStore.dispatch);
      })
      .then(() => {
        const assignmentsAfterDelete = reduxStore.getState().assignments.assignments;
        expect(assignmentsAfterDelete.length).to.eq(0);
        done();
      });
  });
});
<|endoftext|>


<commit_before>import postcss from 'postcss'
import { readFileSync as slurp } from 'fs'
import { resolve, isAbsolute } from 'path'
import { parse as parseUrl } from 'url'
import { default as rebaseUrl } from 'postcss-url'

export default function rebase(pkg, opts, filename) {
  return postcss([
      rebaseUrl({
        url: (url, decl, from, dirname, to, options, result) => {
          let parsed = parseUrl(url, true, true)

          if (parsed.host || isAbsolute(parsed.pathname)) {
            return url
          } else {
            let resolved = pkg.relative(resolve(dirname, parsed.pathname)).replace(/\\/g, '/')
            return resolved + (parsed.search || '') + (parsed.hash || '')
          }
        }
      })
    ]).process(slurp(filename, 'utf8'),
      { from: filename
      , to: pkg.resolve(`${pkg.name}-min.css`)
      }
    ).css
}<commit_msg>Don't clobber source map comment urls in *-min.css<commit_after>import postcss from 'postcss'
import { readFileSync as slurp } from 'fs'
import { resolve, isAbsolute } from 'path'
import { parse as parseUrl } from 'url'
import { default as rebaseUrl } from 'postcss-url'

export default function rebase(pkg, opts, filename) {
  return postcss([
      rebaseUrl({
        url: (url, decl, from, dirname, to, options, result) => {
          let parsed = parseUrl(url, true, true)

          if (parsed.host || isAbsolute(parsed.pathname)) {
            return url
          } else {
            let resolved = pkg.relative(resolve(dirname, parsed.pathname)).replace(/\\/g, '/')
            return resolved + (parsed.search || '') + (parsed.hash || '')
          }
        }
      })
    ]).process(slurp(filename, 'utf8'), { from: filename }).css
}<|endoftext|>


<commit_before>/*! dollar 10-06-2014 */
!function(a,b){"use strict";var c=function(c){var d=function(c){var e=function(a,c){var d;if("NodeList"==a.constructor.name){for(var e=0;e<a.length;e++)if(d=c(a[e],e),d!==b)return d}else d=c(a);return d||a};return c.on=function(a,b){return e(this,function(c){c.addEventListener(a,b)})},c.off=function(a,b){return e(this,function(c){c.removeEventListener(a,b)})},c.fadeIn=function(b){return b||(b=400),e(this,function(c){c.style.opacity=0;var d=+new Date,e=function(){c.style.opacity=+c.style.opacity+(new Date-d)/b,d=+new Date,+c.style.opacity<1&&(a.requestAnimationFrame?a.requestAnimationFrame(e):setTimeout(e,16))};e()})},c.hide=function(){return e(this,function(a){a.style.display="none"})},c.show=function(){return e(this,function(a){a.style.display=""})},c.addClass=function(a){return e(this,function(b){b.classList?b.classList.add(a):b.className+=" "+a})},c.removeClass=function(a){return e(this,function(b){b.classList?b.classList.remove(a):b.className=b.className.replace(new RegExp("(^|\\b)"+a.split(" ").join("|")+"(\\b|$)","gi")," ")})},c.each=function(a){Array.prototype.forEach.call(this,function(b,c){a(c,b)})},c.trigger=function(b,c){return e(this,function(d){var e;c?(a.CustomEvent?e=new a.CustomEvent(b,{detail:c}):(e=a.document.createEvent("CustomEvent"),e.initCustomEvent(b,!0,!0,c)),d.dispatchEvent(e)):(e=a.document.createEvent("HTMLEvents"),e.initEvent(b,!0,!1),d.dispatchEvent(e))})},c.find=function(a){return d(this.querySelectorAll(a))},c.parent=function(){return e(this,function(a){return a.parentNode})},c.css=function(b){return e(this,function(c){return a.getComputedStyle(c)[b]})},c.attr=function(a){return e(this,function(b){return b.getAttribute(a)})},c.html=function(a){return e(this,function(b){return a?void(b.innerHTML=a):b.innerHTML})},c.text=function(a){return e(this,function(b){return a?void(b.textContent=a):b.textContent})},c.hasClass=function(a){return e(this,function(b){return b.classList?b.classList.contains(a):new RegExp("(^| )"+a+"( |$)","gi").test(b.className)})},c};if(c){if("function"!=typeof c){if("object"==typeof c)return d(c);var e=a.document.querySelectorAll(c);return d(e)}a.document.addEventListener("DOMContentLoaded",c)}};c.getJSON=function(b,c,d){var e=new a.XMLHttpRequest;e.open("GET","/my/url",!0),e.onload=function(){if(e.status>=200&&e.status<400){var a=JSON.parse(e.responseText);c(a)}else d("We reached our target server, but it returned an error")},e.onerror=function(){d("There was a connection error of some sort")},e.send()},c.VERSION="0.0.0",a.dollar=c,a.$||(a.$=c)}(this);<commit_msg>Fix getJSON<commit_after>/*! dollar 11-06-2014 */
!function(a,b){"use strict";var c=function(c){var d=function(c){var e=function(a,c){var d;if("NodeList"==a.constructor.name){for(var e=0;e<a.length;e++)if(d=c(a[e],e),d!==b)return d}else d=c(a);return d||a};return c.on=function(a,b){return e(this,function(c){c.addEventListener(a,b)})},c.off=function(a,b){return e(this,function(c){c.removeEventListener(a,b)})},c.fadeIn=function(b){return b||(b=400),e(this,function(c){c.style.opacity=0;var d=+new Date,e=function(){c.style.opacity=+c.style.opacity+(new Date-d)/b,d=+new Date,+c.style.opacity<1&&(a.requestAnimationFrame?a.requestAnimationFrame(e):setTimeout(e,16))};e()})},c.hide=function(){return e(this,function(a){a.style.display="none"})},c.show=function(){return e(this,function(a){a.style.display=""})},c.addClass=function(a){return e(this,function(b){b.classList?b.classList.add(a):b.className+=" "+a})},c.removeClass=function(a){return e(this,function(b){b.classList?b.classList.remove(a):b.className=b.className.replace(new RegExp("(^|\\b)"+a.split(" ").join("|")+"(\\b|$)","gi")," ")})},c.each=function(a){Array.prototype.forEach.call(this,function(b,c){a(c,b)})},c.trigger=function(b,c){return e(this,function(d){var e;c?(a.CustomEvent?e=new a.CustomEvent(b,{detail:c}):(e=a.document.createEvent("CustomEvent"),e.initCustomEvent(b,!0,!0,c)),d.dispatchEvent(e)):(e=a.document.createEvent("HTMLEvents"),e.initEvent(b,!0,!1),d.dispatchEvent(e))})},c.find=function(a){return d(this.querySelectorAll(a))},c.parent=function(){return e(this,function(a){return a.parentNode})},c.css=function(b){return e(this,function(c){return a.getComputedStyle(c)[b]})},c.attr=function(a){return e(this,function(b){return b.getAttribute(a)})},c.html=function(a){return e(this,function(b){return a?void(b.innerHTML=a):b.innerHTML})},c.text=function(a){return e(this,function(b){return a?void(b.textContent=a):b.textContent})},c.hasClass=function(a){return e(this,function(b){return b.classList?b.classList.contains(a):new RegExp("(^| )"+a+"( |$)","gi").test(b.className)})},c};if(c){if("function"!=typeof c){if("object"==typeof c)return d(c);var e=a.document.querySelectorAll(c);return d(e)}a.document.addEventListener("DOMContentLoaded",c)}};c.getJSON=function(b,c,d){var e=new a.XMLHttpRequest;e.open("GET","/my/url",!0),e.onload=function(){if(e.status>=200&&e.status<400){var a=JSON.parse(e.responseText);c(a)}else d("We reached our target server, but it returned an error")},e.onerror=function(){d("There was a connection error of some sort")},e.send()},c.VERSION="0.0.0",a.dollar=c,a.$||(a.$=c)}(this);<|endoftext|>


<commit_before>(function(doc) {

  log = noop; // noOp, remove this line to enable debugging

  var coordinateSystemForElementFromPoint;

  function main(config) {
    config = config || {};

    coordinateSystemForElementFromPoint = navigator.userAgent.match(/OS [1-4](?:_\d+)+ like Mac/) ? "page" : "client";

    var div = doc.createElement('div');
    var dragDiv = 'draggable' in div;
    var evts = 'ondragstart' in div && 'ondrop' in div;

    var needsPatch = !(dragDiv || evts) || /iPad|iPhone|iPod|Android/.test(navigator.userAgent);
    log((needsPatch ? "" : "not ") + "patching html5 drag drop");

    if(!needsPatch) return;

    if(!config.enableEnterLeave) {
      DragDrop.prototype.synthesizeEnterLeave = noop;
    }

    doc.addEventListener("touchstart", touchstart);
  }

  function DragDrop(event, el) {

    this.dragData = {};
    this.dragDataTypes = [];
    this.dragImage = null;
    this.dragImageTransform = null;
    this.dragImageWebKitTransform = null;
    this.el = el || event.target

    log("dragstart");

    this.dispatchDragStart()
    this.createDragImage();

    this.listen()

  }

  DragDrop.prototype = {
    listen: function() {
      var move = onEvt(doc, "touchmove", this.move, this);
      var end = onEvt(doc, "touchend", ontouchend, this);
      var cancel = onEvt(doc, "touchcancel", cleanup, this);

      function ontouchend(event) {
        this.dragend(event, event.target);
        cleanup.call(this);
      }
      function cleanup() {
        log("cleanup");
        this.dragDataTypes = [];
        if (this.dragImage != null) {
          this.dragImage.parentNode.removeChild(this.dragImage);
          this.dragImage = null;
          this.dragImageTransform = null;
          this.dragImageWebKitTransform = null;
        }
        this.el = this.dragData = null;
        return [move, end, cancel].forEach(function(handler) {
          return handler.off();
        });
      }
    },
    move: function(event) {
      var pageXs = [], pageYs = [];
      [].forEach.call(event.changedTouches, function(touch, index) {
        pageXs.push(touch.pageX);
        pageYs.push(touch.pageY);
      });

      var x = average(pageXs) - (parseInt(this.dragImage.offsetWidth, 10) / 2);
      var y = average(pageYs) - (parseInt(this.dragImage.offsetHeight, 10) / 2);
      this.translateDragImage(x, y);

      this.synthesizeEnterLeave(event);
    },
    // We use translate instead of top/left because of sub-pixel rendering and for the hope of better performance
    // http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
    translateDragImage: function(x, y) {
      var translate = " translate(" + x + "px," + y + "px)";

      if (this.dragImageWebKitTransform !== null) {
        this.dragImage.style["-webkit-transform"] = this.dragImageWebKitTransform + translate;
      }
      if (this.dragImageTransform !== null) {
        this.dragImage.style["transform"] = this.dragImageTransform + translate;
      }
    },
    synthesizeEnterLeave: function(event) {
      var target = elementFromTouchEvent(this.el,event)
      if (target != this.lastEnter) {
        if (this.lastEnter) {
          this.dispatchLeave(event);
        }
        this.lastEnter = target;
        if (this.lastEnter) {
          this.dispatchEnter(event);
        }
      }
      if (this.lastEnter) {
        this.dispatchOver(event);
      }
    },
    dragend: function(event) {

      // we'll dispatch drop if there's a target, then dragEnd.
      // drop comes first http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
      log("dragend");

      if (this.lastEnter) {
        this.dispatchLeave(event);
      }

      var target = elementFromTouchEvent(this.el,event)
      if (target) {
        log("found drop target " + target.tagName);
        this.dispatchDrop(target, event)
      } else {
        log("no drop target")
      }

      var dragendEvt = doc.createEvent("Event");
      dragendEvt.initEvent("dragend", true, true);
      this.el.dispatchEvent(dragendEvt);
    },
    dispatchDrop: function(target, event) {
      var dropEvt = doc.createEvent("Event");
      dropEvt.initEvent("drop", true, true);

      var touch = event.changedTouches[0];
      var x = touch[coordinateSystemForElementFromPoint + 'X'];
      var y = touch[coordinateSystemForElementFromPoint + 'Y'];
      dropEvt.offsetX = x - target.x;
      dropEvt.offsetY = y - target.y;

      dropEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };
      dropEvt.preventDefault = function() {
         // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14638 - if we don't cancel it, we'll snap back
      }.bind(this);

      once(doc, "drop", function() {
        log("drop event not canceled");
      },this);

      target.dispatchEvent(dropEvt);
    },
    dispatchEnter: function(event) {

      var enterEvt = doc.createEvent("Event");
      enterEvt.initEvent("dragenter", true, true);
      enterEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      enterEvt.pageX = touch.pageX;
      enterEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(enterEvt);
    },
    dispatchOver: function(event) {

      var overEvt = doc.createEvent("Event");
      overEvt.initEvent("dragover", true, true);
      overEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      overEvt.pageX = touch.pageX;
      overEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(overEvt);
    },
    dispatchLeave: function(event) {

      var leaveEvt = doc.createEvent("Event");
      leaveEvt.initEvent("dragleave", true, true);
      leaveEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      leaveEvt.pageX = touch.pageX;
      leaveEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(leaveEvt);
      this.lastEnter = null;
    },
    dispatchDragStart: function() {
      var evt = doc.createEvent("Event");
      evt.initEvent("dragstart", true, true);
      evt.dataTransfer = {
        setData: function(type, val) {
          this.dragData[type] = val;
          if (this.dragDataTypes.indexOf(type) == -1) {
            this.dragDataTypes[this.dragDataTypes.length] = type;
          }
          return val;
        }.bind(this),
        dropEffect: "move"
      };
      this.el.dispatchEvent(evt);
    },
    createDragImage: function() {
      this.dragImage = this.el.cloneNode(true);

      duplicateStyle(this.el, this.dragImage);

      this.dragImage.style["opacity"] = "0.5";
      this.dragImage.style["position"] = "absolute";
      this.dragImage.style["left"] = "0px";
      this.dragImage.style["top"] = "0px";
      this.dragImage.style["z-index"] = "999999";

      var transform = this.dragImage.style["transform"];
      if (typeof transform !== "undefined") {
        this.dragImageTransform = "";
        if (transform != "none") {
          this.dragImageTransform = transform.replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
        }
      }

      var webkitTransform = this.dragImage.style["-webkit-transform"];
      if (typeof webkitTransform !== "undefined") {
        this.dragImageWebKitTransform = "";
        if (webkitTransform != "none") {
          this.dragImageWebKitTransform = webkitTransform.replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
        }
      }

      this.translateDragImage(-9999, -9999);

      doc.body.appendChild(this.dragImage);
    }
  }

  // event listeners
  function touchstart(evt) {
    var el = evt.target;
    do {
      if (el.draggable === true) {
        // If draggable isn't explicitly set for anchors, then simulate a click event.
        // Otherwise plain old vanilla links will stop working.
        // https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events#Handling_clicks
        if (!el.hasAttribute("draggable") && el.tagName.toLowerCase() == "a") {
          var clickEvt = document.createEvent("MouseEvents");
          clickEvt.initMouseEvent("click", true, true, el.ownerDocument.defaultView, 1,
            evt.screenX, evt.screenY, evt.clientX, evt.clientY,
            evt.ctrlKey, evt.altKey, evt.shiftKey, evt.metaKey, 0, null);
          el.dispatchEvent(clickEvt);
          log("Simulating click to anchor");
        }
        evt.preventDefault();
        new DragDrop(evt,el);
      }
    } while((el = el.parentNode) && el !== doc.body)
  }

  // DOM helpers
  function elementFromTouchEvent(el,event) {
    var touch = event.changedTouches[0];
    var target = doc.elementFromPoint(
      touch[coordinateSystemForElementFromPoint + "X"],
      touch[coordinateSystemForElementFromPoint + "Y"]
    );
    return target
  }

  function onEvt(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    el.addEventListener(event, handler);
    return {
      off: function() {
        return el.removeEventListener(event, handler);
      }
    };
  }

  function once(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    function listener(evt) {
      handler(evt);
      return el.removeEventListener(event,listener);
    }
    return el.addEventListener(event,listener);
  }

  // duplicateStyle expects dstNode to be a clone of srcNode
  function duplicateStyle(srcNode, dstNode) {
    // Is this node an element?
    if (srcNode.nodeType == 1) {
      // Remove any potential conflict attributes
      dstNode.removeAttribute("id");
      dstNode.removeAttribute("class");
      dstNode.removeAttribute("style");
      dstNode.removeAttribute("draggable");

      // Clone the style
      var cs = window.getComputedStyle(srcNode);
      for (var i = 0; i < cs.length; i++) {
        var csName = cs[i];
        dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));
      }

      // Pointer events as none makes the drag image transparent to document.elementFromPoint()
      dstNode.style.pointerEvents = "none";
    }

    // Do the same for the children
    if (srcNode.hasChildNodes()) {
      for (var i = 0; i < srcNode.childNodes.length; i++) {
        duplicateStyle(srcNode.childNodes[i], dstNode.childNodes[i]);
      }
    }
  }

  // general helpers
  function log(msg) {
    console.log(msg);
  }

  function average(arr) {
    if (arr.length === 0) return 0;
    return arr.reduce((function(s, v) {
      return v + s;
    }), 0) / arr.length;
  }

  function noop() {}

  main(window.iosDragDropShim);

})(document);
<commit_msg>fix merge conflicts with JonDum's patch<commit_after>(function(doc) {

  log = noop; // noOp, remove this line to enable debugging

  var coordinateSystemForElementFromPoint;

  function main(config) {
    config = config || {};

    coordinateSystemForElementFromPoint = navigator.userAgent.match(/OS [1-4](?:_\d+)+ like Mac/) ? "page" : "client";

    var div = doc.createElement('div');
    var dragDiv = 'draggable' in div;
    var evts = 'ondragstart' in div && 'ondrop' in div;

    var needsPatch = !(dragDiv || evts) || /iPad|iPhone|iPod|Android/.test(navigator.userAgent);
    log((needsPatch ? "" : "not ") + "patching html5 drag drop");

    if(!needsPatch) {
        return;
    }

    if(!config.enableEnterLeave) {
      DragDrop.prototype.synthesizeEnterLeave = noop;
    }

    doc.addEventListener("touchstart", touchstart);
  }

  function DragDrop(event, el) {

    this.dragData = {};
    this.dragDataTypes = [];
    this.dragImage = null;
    this.dragImageTransform = null;
    this.dragImageWebKitTransform = null;
    this.el = el || event.target;

    log("dragstart");

    this.dispatchDragStart();
    this.createDragImage();

    this.listen();

  }

  DragDrop.prototype = {
    listen: function() {
      var move = onEvt(doc, "touchmove", this.move, this);
      var end = onEvt(doc, "touchend", ontouchend, this);
      var cancel = onEvt(doc, "touchcancel", cleanup, this);

      function ontouchend(event) {
        this.dragend(event, event.target);
        cleanup.call(this);
      }
      function cleanup() {
        log("cleanup");
        this.dragDataTypes = [];
        if (this.dragImage !== null) {
          this.dragImage.parentNode.removeChild(this.dragImage);
          this.dragImage = null;
          this.dragImageTransform = null;
          this.dragImageWebKitTransform = null;
        }
        this.el = this.dragData = null;
        return [move, end, cancel].forEach(function(handler) {
          return handler.off();
        });
      }
    },
    move: function(event) {
      var pageXs = [], pageYs = [];
      [].forEach.call(event.changedTouches, function(touch) {
        pageXs.push(touch.pageX);
        pageYs.push(touch.pageY);
      });

      var x = average(pageXs) - (parseInt(this.dragImage.offsetWidth, 10) / 2);
      var y = average(pageYs) - (parseInt(this.dragImage.offsetHeight, 10) / 2);
      this.translateDragImage(x, y);

      this.synthesizeEnterLeave(event);
    },
    // We use translate instead of top/left because of sub-pixel rendering and for the hope of better performance
    // http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
    translateDragImage: function(x, y) {
      var translate = " translate(" + x + "px," + y + "px)";

      if (this.dragImageWebKitTransform !== null) {
        this.dragImage.style["-webkit-transform"] = this.dragImageWebKitTransform + translate;
      }
      if (this.dragImageTransform !== null) {
        this.dragImage.style.transform = this.dragImageTransform + translate;
      }
    },
    synthesizeEnterLeave: function(event) {
      var target = elementFromTouchEvent(this.el,event)
      if (target != this.lastEnter) {
        if (this.lastEnter) {
          this.dispatchLeave(event);
        }
        this.lastEnter = target;
        if (this.lastEnter) {
          this.dispatchEnter(event);
        }
      }
      if (this.lastEnter) {
        this.dispatchOver(event);
      }
    },
    dragend: function(event) {

      // we'll dispatch drop if there's a target, then dragEnd.
      // drop comes first http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
      log("dragend");

      if (this.lastEnter) {
        this.dispatchLeave(event);
      }

      var target = elementFromTouchEvent(this.el,event)
      if (target) {
        log("found drop target " + target.tagName);
        this.dispatchDrop(target, event);
      } else {
        log("no drop target");
      }

      var dragendEvt = doc.createEvent("Event");
      dragendEvt.initEvent("dragend", true, true);
      this.el.dispatchEvent(dragendEvt);
    },
    dispatchDrop: function(target, event) {
      var dropEvt = doc.createEvent("Event");
      dropEvt.initEvent("drop", true, true);

      var touch = event.changedTouches[0];
      var x = touch[coordinateSystemForElementFromPoint + 'X'];
      var y = touch[coordinateSystemForElementFromPoint + 'Y'];
      dropEvt.offsetX = x - target.x;
      dropEvt.offsetY = y - target.y;

      dropEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };
      dropEvt.preventDefault = function() {
         // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14638 - if we don't cancel it, we'll snap back
      }.bind(this);

      once(doc, "drop", function() {
        log("drop event not canceled");
      },this);

      target.dispatchEvent(dropEvt);
    },
    dispatchEnter: function(event) {

      var enterEvt = doc.createEvent("Event");
      enterEvt.initEvent("dragenter", true, true);
      enterEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      enterEvt.pageX = touch.pageX;
      enterEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(enterEvt);
    },
    dispatchOver: function(event) {

      var overEvt = doc.createEvent("Event");
      overEvt.initEvent("dragover", true, true);
      overEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      overEvt.pageX = touch.pageX;
      overEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(overEvt);
    },
    dispatchLeave: function(event) {

      var leaveEvt = doc.createEvent("Event");
      leaveEvt.initEvent("dragleave", true, true);
      leaveEvt.dataTransfer = {
        types: this.dragDataTypes,
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      var touch = event.changedTouches[0];
      leaveEvt.pageX = touch.pageX;
      leaveEvt.pageY = touch.pageY;

      this.lastEnter.dispatchEvent(leaveEvt);
      this.lastEnter = null;
    },
    dispatchDragStart: function() {
      var evt = doc.createEvent("Event");
      evt.initEvent("dragstart", true, true);
      evt.dataTransfer = {
        setData: function(type, val) {
          this.dragData[type] = val;
          if (this.dragDataTypes.indexOf(type) == -1) {
            this.dragDataTypes[this.dragDataTypes.length] = type;
          }
          return val;
        }.bind(this),
        dropEffect: "move"
      };
      this.el.dispatchEvent(evt);
    },
    createDragImage: function() {
      this.dragImage = this.el.cloneNode(true);

      duplicateStyle(this.el, this.dragImage);

      this.dragImage.style.opacity = "0.5";
      this.dragImage.style.position = "absolute";
      this.dragImage.style.left = "0px";
      this.dragImage.style.top = "0px";
      this.dragImage.style.zIndex = "999999";

      var transform = this.dragImage.style.transform;
      if (typeof transform !== "undefined") {
        this.dragImageTransform = "";
        if (transform != "none") {
          this.dragImageTransform = transform.replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
        }
      }

      var webkitTransform = this.dragImage.style["-webkit-transform"];
      if (typeof webkitTransform !== "undefined") {
        this.dragImageWebKitTransform = "";
        if (webkitTransform != "none") {
          this.dragImageWebKitTransform = webkitTransform.replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
        }
      }

      this.translateDragImage(-9999, -9999);

      doc.body.appendChild(this.dragImage);
    }
  };

  // event listeners
  function touchstart(evt) {
    var el = evt.target;
    do {
      if (el.draggable === true) {
        // If draggable isn't explicitly set for anchors, then simulate a click event.
        // Otherwise plain old vanilla links will stop working.
        // https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events#Handling_clicks
        if (!el.hasAttribute("draggable") && el.tagName.toLowerCase() == "a") {
          var clickEvt = document.createEvent("MouseEvents");
          clickEvt.initMouseEvent("click", true, true, el.ownerDocument.defaultView, 1,
            evt.screenX, evt.screenY, evt.clientX, evt.clientY,
            evt.ctrlKey, evt.altKey, evt.shiftKey, evt.metaKey, 0, null);
          el.dispatchEvent(clickEvt);
          log("Simulating click to anchor");
        }
        evt.preventDefault();
        new DragDrop(evt,el);
      }
    } while((el = el.parentNode) && el !== doc.body);
  }

  // DOM helpers
  function elementFromTouchEvent(el,event) {
    var touch = event.changedTouches[0];
    var target = doc.elementFromPoint(
      touch[coordinateSystemForElementFromPoint + "X"],
      touch[coordinateSystemForElementFromPoint + "Y"]
    );
    return target;
  }

  function onEvt(el, event, handler, context) {
    if(context) {
      handler = handler.bind(context);
    }
    el.addEventListener(event, handler);
    return {
      off: function() {
        return el.removeEventListener(event, handler);
      }
    };
  }

  function once(el, event, handler, context) {
    if(context) {
      handler = handler.bind(context);
    }
    function listener(evt) {
      handler(evt);
      return el.removeEventListener(event,listener);
    }
    return el.addEventListener(event,listener);
  }

  // duplicateStyle expects dstNode to be a clone of srcNode
  function duplicateStyle(srcNode, dstNode) {
    // Is this node an element?
    if (srcNode.nodeType == 1) {
      // Remove any potential conflict attributes
      dstNode.removeAttribute("id");
      dstNode.removeAttribute("class");
      dstNode.removeAttribute("style");
      dstNode.removeAttribute("draggable");

      // Clone the style
      var cs = window.getComputedStyle(srcNode);
      for (var i = 0; i < cs.length; i++) {
        var csName = cs[i];
        dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));
      }

      // Pointer events as none makes the drag image transparent to document.elementFromPoint()
      dstNode.style.pointerEvents = "none";
    }

    // Do the same for the children
    if (srcNode.hasChildNodes()) {
      for (var j = 0; j < srcNode.childNodes.length; j++) {
        duplicateStyle(srcNode.childNodes[j], dstNode.childNodes[j]);
      }
    }
  }

  // general helpers
  function log(msg) {
    console.log(msg);
  }

  function average(arr) {
    if (arr.length === 0) return 0;
    return arr.reduce((function(s, v) {
      return v + s;
    }), 0) / arr.length;
  }

  function noop() {}

  main(window.iosDragDropShim);

})(document);
<|endoftext|>


<commit_before>// Style Constants
var darkGray = '0x30302f';
var blue = '0x3b4c60';
var turqoise = '0x386055';
var red = '0xb01d19';
var orange = '0xd04900';
var background = '0xeae1cc'; //jshint ignore:line
var lightPink = '0xE61945'; //jshint ignore:line
var fuchsia = '0xC00029'; //jshint ignore:line

var blueText = '#3b4c60';

var midasParticleStartColor = 'ffcc00';
var midasParticleEndColor = '545454';

var ballStyle = {
    fillStyle: orange
};

var goalStyle = {
    fillStyle: blue,

    layer: 5
};

var bumperStyle = {
    fillStyle: darkGray,
    layer: 6
};

var paddleStyle = {
    fillStyle: red
};

var blackholeStyle = {
    fillStyle: turqoise,
    icon: '\uf069',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var kingMidasStyle = {
    fillStyle: turqoise,
    icon: '\uf219',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var bulletTimeStyle = {
    fillStyle: turqoise,
    icon: '\uf254',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var fontStyle = {
    font : '24px Cabin',
    fill : '#000000',
    strokeThickness : 2
};

var titleFontStyle = {
    font : '96px Cabin',
    fill : '#000000',
    strokeThickness : 6
};

exports.ballStyle = ballStyle;
exports.goalStyle = goalStyle;
exports.bumperStyle = bumperStyle;
exports.paddleStyle = paddleStyle;
exports.blackholeStyle = blackholeStyle;
exports.kingMidasStyle = kingMidasStyle;
exports.midasParticleStartColor = midasParticleStartColor;
exports.midasParticleEndColor = midasParticleEndColor;
exports.bulletTimeStyle = bulletTimeStyle;
exports.fontStyle = fontStyle;
exports.titleFontStyle = titleFontStyle;<commit_msg>change king midas particles to ball color at start.<commit_after>// Style Constants
var darkGray = '0x30302f';
var blue = '0x3b4c60';
var turqoise = '0x386055';
var red = '0xb01d19';
var orange = '0xd04900';
var background = '0xeae1cc'; //jshint ignore:line
var lightPink = '0xE61945'; //jshint ignore:line
var fuchsia = '0xC00029'; //jshint ignore:line

var blueText = '#3b4c60';

var midasParticleStartColor = 'd04900';
var midasParticleEndColor = '545454';

var ballStyle = {
    fillStyle: orange
};

var goalStyle = {
    fillStyle: blue,

    layer: 5
};

var bumperStyle = {
    fillStyle: darkGray,
    layer: 6
};

var paddleStyle = {
    fillStyle: red
};

var blackholeStyle = {
    fillStyle: turqoise,
    icon: '\uf069',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var kingMidasStyle = {
    fillStyle: turqoise,
    icon: '\uf219',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var bulletTimeStyle = {
    fillStyle: turqoise,
    icon: '\uf254',
    fontstyle: {
        fill: blueText,
        font: '30px fontawesome'
    }
};

var fontStyle = {
    font : '24px Cabin',
    fill : '#000000',
    strokeThickness : 2
};

var titleFontStyle = {
    font : '96px Cabin',
    fill : '#000000',
    strokeThickness : 6
};

exports.ballStyle = ballStyle;
exports.goalStyle = goalStyle;
exports.bumperStyle = bumperStyle;
exports.paddleStyle = paddleStyle;
exports.blackholeStyle = blackholeStyle;
exports.kingMidasStyle = kingMidasStyle;
exports.midasParticleStartColor = midasParticleStartColor;
exports.midasParticleEndColor = midasParticleEndColor;
exports.bulletTimeStyle = bulletTimeStyle;
exports.fontStyle = fontStyle;
exports.titleFontStyle = titleFontStyle;<|endoftext|>


<commit_before>const fetch = require('node-fetch');
const raven = require('raven');
const winston = require('winston');

const Config = require('../config/Config.js');

/**
* Configure Sentry using the env vars pased if in production
* @param {string} sentryDSN The url given by Sentry tied to your account
* @param {string} environment dev, testing, peoduction etc.
* @param {string} loggingLevel error, info, warn etc.
* @return {object} return raven object if in production
*/
function setupSentry(sentryDSN, environment, loggingLevel) {
  raven.config(sentryDSN, {
    logger: loggingLevel,
    environment,
  }).install();

  if (Config.environment === 'production') {
    return raven;
  }
  return null;
}

const sentry = setupSentry(Config.sentryDSN, Config.environment, 'error');

/**
* Call json function in the response object
* @param {object} response a http response object
* @return {String} JSON string from the response object
*/
function extractJsonFromResponse(response) {
  return response.json();
}

/**
* A function to send rejected promise errors to both winston and sentry
* @param {string} text the promise rejection error text
*/
function genericCatchRejectedPromise(text) {
  let message = 'Promise rejected: ' + text;
  winston.log('error', message);
  if (Config.environment === 'production') {
    sentry.captureMessage(message);
  }
}

/**
* Generalize making http requests with node fetch
* retry failed requests with exponential backoff
* @param {string} url the request url
* @param {object} httpArguments
{
  method The HTTP method e.g POST or GET; default GET,
  headers HTTP request headers,
  body The request payload/HTTP request body
}
* @param {string} rejectionText
* @param {int} maxRetries Number of times to retry a failed request; default 3
* @param {Integer} backoff
* @return {object} parsed JSON response as a JS object
*/
function request(url,
                 {method, headers, body},
                 rejectionText,
                 maxRetries = 3,
                 backoff = 60000) {
  return fetch(url, {method, headers, body})
    .then((response) => {
      const jsonResponse = extractJsonFromResponse(response);
      if (response.status < 300) {
        jsonResponse.then((json) => {
          const jsonString = JSON.stringify(json);
          winston.log('info',
                      `{Status: ${response.status}} ` +
                      `{Response: ${jsonString}}`);
        })
          .catch((reason) =>
                 genericCatchRejectedPromise('Extract JSON from response' +
                                             reason));
        return jsonResponse;
      } else {
        if (maxRetries > 0) {
          console.log('retrying');
          console.log(backoff);
          console.log(maxRetries);
          setTimeout(() => request(url,
                                   {method, headers, body},
                                   rejectionText,
                                   (maxRetries-1),
                                   (backoff*2)),
                     backoff);
        } else {
          jsonResponse.then((json) => {
            const jsonResponseString = JSON.stringify(json);
            winston.log('error',
                        `{Status: ${response.status}}` +
                        ` {Payload: ${body}}` +
                        ` {Response: ${jsonResponseString}}`);
            if (Config.environment === 'production') {
              sentry.captureMessage(`${rejectionText} failed\n` +
                                    `{Status: ${response.status}}\n` +
                                    `{Payload: ${body}}\n` +
                                    `{Response: ${jsonResponseString}}`);
            }
})
            .catch((reason) =>
                   genericCatchRejectedPromise(
                     'Extract JSON from response' + reason));
          }
}
})
    .catch((reason) => genericCatchRejectedPromise(rejectionText + reason));
}

module.exports = {request,
                  sentry,
                  genericCatchRejectedPromise};
<commit_msg>Remove console.log messages from requests<commit_after>const fetch = require('node-fetch');
const raven = require('raven');
const winston = require('winston');

const Config = require('../config/Config.js');

/**
* Configure Sentry using the env vars pased if in production
* @param {string} sentryDSN The url given by Sentry tied to your account
* @param {string} environment dev, testing, peoduction etc.
* @param {string} loggingLevel error, info, warn etc.
* @return {object} return raven object if in production
*/
function setupSentry(sentryDSN, environment, loggingLevel) {
  raven.config(sentryDSN, {
    logger: loggingLevel,
    environment,
  }).install();

  if (Config.environment === 'production') {
    return raven;
  }
  return null;
}

const sentry = setupSentry(Config.sentryDSN, Config.environment, 'error');

/**
* Call json function in the response object
* @param {object} response a http response object
* @return {String} JSON string from the response object
*/
function extractJsonFromResponse(response) {
  return response.json();
}

/**
* A function to send rejected promise errors to both winston and sentry
* @param {string} text the promise rejection error text
*/
function genericCatchRejectedPromise(text) {
  let message = 'Promise rejected: ' + text;
  winston.log('error', message);
  if (Config.environment === 'production') {
    sentry.captureMessage(message);
  }
}

/**
* Generalize making http requests with node fetch
* retry failed requests with exponential backoff
* @param {string} url the request url
* @param {object} httpArguments
{
  method The HTTP method e.g POST or GET; default GET,
  headers HTTP request headers,
  body The request payload/HTTP request body
}
* @param {string} rejectionText
* @param {int} maxRetries Number of times to retry a failed request; default 3
* @param {Integer} backoff
* @return {object} parsed JSON response as a JS object
*/
function request(url,
                 {method, headers, body},
                 rejectionText,
                 maxRetries = 3,
                 backoff = 60000) {
  return fetch(url, {method, headers, body})
    .then((response) => {
      const jsonResponse = extractJsonFromResponse(response);
      if (response.status < 300) {
        jsonResponse.then((json) => {
          const jsonString = JSON.stringify(json);
          winston.log('info',
                      `{Status: ${response.status}} ` +
                      `{Response: ${jsonString}}`);
        })
          .catch((reason) =>
                 genericCatchRejectedPromise('Extract JSON from response' +
                                             reason));
        return jsonResponse;
      } else {
        if (maxRetries > 0) {
          setTimeout(() => request(url,
                                   {method, headers, body},
                                   rejectionText,
                                   (maxRetries-1),
                                   (backoff*2)),
                     backoff);
        } else {
          jsonResponse.then((json) => {
            const jsonResponseString = JSON.stringify(json);
            winston.log('error',
                        `{Status: ${response.status}}` +
                        ` {Payload: ${body}}` +
                        ` {Response: ${jsonResponseString}}`);
            if (Config.environment === 'production') {
              sentry.captureMessage(`${rejectionText} failed\n` +
                                    `{Status: ${response.status}}\n` +
                                    `{Payload: ${body}}\n` +
                                    `{Response: ${jsonResponseString}}`);
            }
})
            .catch((reason) =>
                   genericCatchRejectedPromise(
                     'Extract JSON from response' + reason));
          }
}
})
    .catch((reason) => genericCatchRejectedPromise(rejectionText + reason));
}

module.exports = {request,
                  sentry,
                  genericCatchRejectedPromise};
<|endoftext|>


<commit_before>import { isUndefined, keys } from 'underscore';
import PropertyCompositeView from './PropertyCompositeView';
import LayersView from './LayersView';
import CssGenerator from 'code_manager/model/CssGenerator';

const cssGen = new CssGenerator();

export default PropertyCompositeView.extend({
  templateInput() {
    const pfx = this.pfx;
    const ppfx = this.ppfx;
    return `

        <button type="button" id="${pfx}add" data-add-layer>+</button>

    `;
  },

  init() {
    const model = this.model;
    const pfx = this.pfx;
    model.set('stackIndex', null);
    this.events[`click [data-add-layer]`] = 'addLayer';
    this.listenTo(model, 'change:stackIndex', this.indexChanged);
    this.listenTo(model, 'updateValue', this.inputValueChanged);
    this.delegateEvents();
  },

  /**
   * Fired when the target is updated.
   * With detached mode the component will be always empty as its value
   * so we gonna check all props and find if it has any difference
   * */
  targetUpdated(...args) {
    if (!this.model.get('detached')) {
      PropertyCompositeView.prototype.targetUpdated.apply(this, args);
    } else {
      const { status } = this._getTargetData();
      this.setStatus(status);
      this.checkVisibility();
    }

    this.refreshLayers();
  },

  /**
   * Returns the collection of layers
   * @return {Collection}
   */
  getLayers() {
    return this.model.get('layers');
  },

  /**
   * Triggered when another layer has been selected.
   * This allow to move all rendered properties to a new
   * selected layer
   * @param {Event}
   *
   * @return {Object}
   * */
  indexChanged(e) {
    const model = this.model;
    this.getLayers().active(model.get('stackIndex'));
  },

  addLayer() {
    const model = this.model;
    const layers = this.getLayers();
    const properties = model.get('properties').deepClone();
    properties.each(property => property.set('value', ''));
    const layer = layers.add({ properties });

    // In detached mode inputValueChanged will add new 'layer value'
    // to all subprops
    this.inputValueChanged();

    // This will set subprops with a new default values
    model.set('stackIndex', layers.indexOf(layer));
  },

  inputValueChanged() {
    const model = this.model;
    this.elementUpdated();

    // If not detached I'll just put all the values from layers to property
    // eg. background: layer1Value, layer2Value, layer3Value, ...
    if (!model.get('detached')) {
      model.set('value', this.getLayerValues());
    } else {
      model.get('properties').each(prop => prop.trigger('change:value'));
    }
  },

  /**
   * There is no need to handle input update by the property itself,
   * this will be done by layers
   * @private
   */
  setValue() {},

  /**
   * Create value by layers
   * @return string
   * */
  getLayerValues() {
    return this.getLayers().getFullValue();
  },

  _getClassRule(opts = {}) {
    const { em } = this;
    const { skipAdd = 1 } = opts;
    const selected = em.getSelected();
    const targetAlt = em.get('StyleManager').getModelToStyle(selected, {
      skipAdd,
      useClasses: 1
    });
    return targetAlt !== selected && targetAlt;
  },

  /**
   * Return the parent style rule of the passed one
   * @private
   */
  _getParentTarget(target, opts = {}) {
    const { em, model } = this;
    const property = model.get('property');
    const isValid = opts.isValid || (rule => rule.getStyle()[property]);
    const targetsDevice = em
      .get('CssComposer')
      .getAll()
      .filter(rule => rule.selectorsToString() === target.getSelectorsString());
    const map = targetsDevice.reduce((acc, rule) => {
      acc[rule.getAtRule()] = rule;
      return acc;
    }, {});
    const mapSorted = cssGen.sortMediaObject(map);
    const sortedRules = mapSorted.map(item => item.value);
    const currIndex = sortedRules.indexOf(target);
    const rulesToCheck = sortedRules.splice(0, currIndex);
    let result;

    for (let i = rulesToCheck.length - 1; i > -1; i--) {
      const rule = rulesToCheck[i];
      if (isValid(rule)) {
        // only for not detached
        result = rule;
        break;
      }
    }

    return result;
  },

  /**
   * Refresh layers
   * */
  refreshLayers() {
    let layersObj = [];
    const { model, em } = this;
    const layers = this.getLayers();
    const detached = model.get('detached');
    const property = model.get('property');
    const target = this.getTarget();
    const valueComput = this.getComputedValue();
    const selected = em.getSelected();
    let style, targetAlt, targetAltDevice, valueTargetAlt, valueTrgAltDvc;

    // With detached layers values will be assigned to their properties
    if (detached) {
      style = target ? target.getStyle() : {};
      const hasDetachedStyle = rule => {
        const name = model
          .get('properties')
          .at(0)
          .get('property');
        return rule && !isUndefined(rule.getStyle()[name]);
      };

      // If the style object is empty but the target has a computed value,
      // that means the style might exist in some other place
      if (!keys(style).length && valueComput && selected) {
        // Styles of the same target but with a higher rule
        const parentOpts = { isValid: rule => hasDetachedStyle(rule) };
        targetAltDevice = this._getParentTarget(target, parentOpts);

        if (targetAltDevice) {
          style = targetAltDevice.getStyle();
        } else {
          // The target is a component but the style is in the class rules
          targetAlt = this._getClassRule();
          valueTargetAlt = hasDetachedStyle(targetAlt) && targetAlt.getStyle();
          targetAltDevice =
            !valueTargetAlt &&
            this._getParentTarget(
              this._getClassRule({ skipAdd: 0 }),
              parentOpts
            );
          valueTrgAltDvc =
            hasDetachedStyle(targetAltDevice) && targetAltDevice.getStyle();
          style = valueTargetAlt || valueTrgAltDvc || {};
        }
      }

      layersObj = layers.getLayersFromStyle(style);
    } else {
      const valueTrg = this.getTargetValue({ ignoreDefault: 1 });
      let value = valueTrg;

      // Try to check if the style is in another rule
      if (!value && valueComput) {
        // Styles of the same target but with a higher rule
        targetAltDevice = this._getParentTarget(target);

        if (targetAltDevice) {
          value = targetAltDevice.getStyle()[property];
        } else {
          // Computed value is not always reliable due to the browser's CSSOM parser
          // here we try to look for the style in class rules
          targetAlt = this._getClassRule();
          const valueTargetAlt = targetAlt && targetAlt.getStyle()[property];
          targetAltDevice =
            !valueTargetAlt &&
            this._getParentTarget(this._getClassRule({ skipAdd: 0 }));
          const valueTrgAltDvc =
            targetAltDevice && targetAltDevice.getStyle()[property];
          value = valueTargetAlt || valueTrgAltDvc || valueComput;
        }
      }

      value = value == model.getDefaultValue() ? '' : value;
      layersObj = layers.getLayersFromValue(value);
    }

    const toAdd = model.getLayersFromTarget(target) || layersObj;
    layers.reset();
    layers.add(toAdd);
    model.set({ stackIndex: null }, { silent: true });
  },

  getTargetValue(opts = {}) {
    let result = PropertyCompositeView.prototype.getTargetValue.call(
      this,
      opts
    );
    const { detached } = this.model.attributes;

    // It might happen that the browser split properties on CSSOM parse
    if (isUndefined(result) && !detached) {
      result = this.model.getValueFromStyle(this.getTarget().getStyle());
    }

    return result;
  },

  onRender() {
    const self = this;
    const model = this.model;
    const fieldEl = this.el.querySelector('[data-layers-wrapper]');
    const PropertiesView = require('./PropertiesView').default;
    const propsConfig = {
      target: this.target,
      propTarget: this.propTarget,

      // Things to do when a single sub-property is changed
      onChange(el, view, opt) {
        const subModel = view.model;

        if (model.get('detached')) {
          const subProp = subModel.get('property');
          const values = self.getLayers().getPropertyValues(subProp);
          view.updateTargetStyle(values, null, opt);
        } else {
          // Update only if there is an actual update (to avoid changes for computed styles)
          // ps: status is calculated in `targetUpdated` method
          if (model.get('status') == 'updated') {
            const value = model.getFullValue();
            model.set('value', value, opt);
            // Try to remove detached properties
            !value && view.updateTargetStyle(value, null, opt);
          }
        }
      }
    };
    const layers = new LayersView({
      collection: this.getLayers(),
      stackModel: model,
      preview: model.get('preview'),
      config: this.config,
      propsConfig
    }).render().el;

    // Will use it to propogate changes
    new PropertiesView({
      target: this.target,
      collection: this.model.get('properties'),
      stackModel: model,
      config: this.config,
      onChange: propsConfig.onChange,
      propTarget: propsConfig.propTarget
    }).render();

    //model.get('properties')
    fieldEl.appendChild(layers);
  }
});
<commit_msg>Pass resultValue to getLayersFromTarget<commit_after>import { isUndefined, keys } from 'underscore';
import PropertyCompositeView from './PropertyCompositeView';
import LayersView from './LayersView';
import CssGenerator from 'code_manager/model/CssGenerator';

const cssGen = new CssGenerator();

export default PropertyCompositeView.extend({
  templateInput() {
    const pfx = this.pfx;
    const ppfx = this.ppfx;
    return `

        <button type="button" id="${pfx}add" data-add-layer>+</button>

    `;
  },

  init() {
    const model = this.model;
    const pfx = this.pfx;
    model.set('stackIndex', null);
    this.events[`click [data-add-layer]`] = 'addLayer';
    this.listenTo(model, 'change:stackIndex', this.indexChanged);
    this.listenTo(model, 'updateValue', this.inputValueChanged);
    this.delegateEvents();
  },

  /**
   * Fired when the target is updated.
   * With detached mode the component will be always empty as its value
   * so we gonna check all props and find if it has any difference
   * */
  targetUpdated(...args) {
    if (!this.model.get('detached')) {
      PropertyCompositeView.prototype.targetUpdated.apply(this, args);
    } else {
      const { status } = this._getTargetData();
      this.setStatus(status);
      this.checkVisibility();
    }

    this.refreshLayers();
  },

  /**
   * Returns the collection of layers
   * @return {Collection}
   */
  getLayers() {
    return this.model.get('layers');
  },

  /**
   * Triggered when another layer has been selected.
   * This allow to move all rendered properties to a new
   * selected layer
   * @param {Event}
   *
   * @return {Object}
   * */
  indexChanged(e) {
    const model = this.model;
    this.getLayers().active(model.get('stackIndex'));
  },

  addLayer() {
    const model = this.model;
    const layers = this.getLayers();
    const properties = model.get('properties').deepClone();
    properties.each(property => property.set('value', ''));
    const layer = layers.add({ properties });

    // In detached mode inputValueChanged will add new 'layer value'
    // to all subprops
    this.inputValueChanged();

    // This will set subprops with a new default values
    model.set('stackIndex', layers.indexOf(layer));
  },

  inputValueChanged() {
    const model = this.model;
    this.elementUpdated();

    // If not detached I'll just put all the values from layers to property
    // eg. background: layer1Value, layer2Value, layer3Value, ...
    if (!model.get('detached')) {
      model.set('value', this.getLayerValues());
    } else {
      model.get('properties').each(prop => prop.trigger('change:value'));
    }
  },

  /**
   * There is no need to handle input update by the property itself,
   * this will be done by layers
   * @private
   */
  setValue() {},

  /**
   * Create value by layers
   * @return string
   * */
  getLayerValues() {
    return this.getLayers().getFullValue();
  },

  _getClassRule(opts = {}) {
    const { em } = this;
    const { skipAdd = 1 } = opts;
    const selected = em.getSelected();
    const targetAlt = em.get('StyleManager').getModelToStyle(selected, {
      skipAdd,
      useClasses: 1
    });
    return targetAlt !== selected && targetAlt;
  },

  /**
   * Return the parent style rule of the passed one
   * @private
   */
  _getParentTarget(target, opts = {}) {
    const { em, model } = this;
    const property = model.get('property');
    const isValid = opts.isValid || (rule => rule.getStyle()[property]);
    const targetsDevice = em
      .get('CssComposer')
      .getAll()
      .filter(rule => rule.selectorsToString() === target.getSelectorsString());
    const map = targetsDevice.reduce((acc, rule) => {
      acc[rule.getAtRule()] = rule;
      return acc;
    }, {});
    const mapSorted = cssGen.sortMediaObject(map);
    const sortedRules = mapSorted.map(item => item.value);
    const currIndex = sortedRules.indexOf(target);
    const rulesToCheck = sortedRules.splice(0, currIndex);
    let result;

    for (let i = rulesToCheck.length - 1; i > -1; i--) {
      const rule = rulesToCheck[i];
      if (isValid(rule)) {
        // only for not detached
        result = rule;
        break;
      }
    }

    return result;
  },

  /**
   * Refresh layers
   * */
  refreshLayers() {
    let layersObj = [];
    const { model, em } = this;
    const layers = this.getLayers();
    const detached = model.get('detached');
    const property = model.get('property');
    const target = this.getTarget();
    const valueComput = this.getComputedValue();
    const selected = em.getSelected();
    let resultValue,
      style,
      targetAlt,
      targetAltDevice,
      valueTargetAlt,
      valueTrgAltDvc;

    // With detached layers values will be assigned to their properties
    if (detached) {
      style = target ? target.getStyle() : {};
      const hasDetachedStyle = rule => {
        const name = model
          .get('properties')
          .at(0)
          .get('property');
        return rule && !isUndefined(rule.getStyle()[name]);
      };

      // If the style object is empty but the target has a computed value,
      // that means the style might exist in some other place
      if (!keys(style).length && valueComput && selected) {
        // Styles of the same target but with a higher rule
        const parentOpts = { isValid: rule => hasDetachedStyle(rule) };
        targetAltDevice = this._getParentTarget(target, parentOpts);

        if (targetAltDevice) {
          style = targetAltDevice.getStyle();
        } else {
          // The target is a component but the style is in the class rules
          targetAlt = this._getClassRule();
          valueTargetAlt = hasDetachedStyle(targetAlt) && targetAlt.getStyle();
          targetAltDevice =
            !valueTargetAlt &&
            this._getParentTarget(
              this._getClassRule({ skipAdd: 0 }),
              parentOpts
            );
          valueTrgAltDvc =
            hasDetachedStyle(targetAltDevice) && targetAltDevice.getStyle();
          style = valueTargetAlt || valueTrgAltDvc || {};
        }
      }

      resultValue = style;
      layersObj = layers.getLayersFromStyle(style);
    } else {
      const valueTrg = this.getTargetValue({ ignoreDefault: 1 });
      let value = valueTrg;

      // Try to check if the style is in another rule
      if (!value && valueComput) {
        // Styles of the same target but with a higher rule
        targetAltDevice = this._getParentTarget(target);

        if (targetAltDevice) {
          value = targetAltDevice.getStyle()[property];
        } else {
          // Computed value is not always reliable due to the browser's CSSOM parser
          // here we try to look for the style in class rules
          targetAlt = this._getClassRule();
          valueTargetAlt = targetAlt && targetAlt.getStyle()[property];
          targetAltDevice =
            !valueTargetAlt &&
            this._getParentTarget(this._getClassRule({ skipAdd: 0 }));
          valueTrgAltDvc =
            targetAltDevice && targetAltDevice.getStyle()[property];
          value = valueTargetAlt || valueTrgAltDvc || valueComput;
        }
      }

      value = value == model.getDefaultValue() ? '' : value;
      resultValue = value;
      layersObj = layers.getLayersFromValue(value);
    }

    const toAdd =
      model.getLayersFromTarget(target, { resultValue }) || layersObj;
    layers.reset();
    layers.add(toAdd);
    model.set({ stackIndex: null }, { silent: true });
  },

  getTargetValue(opts = {}) {
    let result = PropertyCompositeView.prototype.getTargetValue.call(
      this,
      opts
    );
    const { detached } = this.model.attributes;

    // It might happen that the browser split properties on CSSOM parse
    if (isUndefined(result) && !detached) {
      result = this.model.getValueFromStyle(this.getTarget().getStyle());
    }

    return result;
  },

  onRender() {
    const self = this;
    const model = this.model;
    const fieldEl = this.el.querySelector('[data-layers-wrapper]');
    const PropertiesView = require('./PropertiesView').default;
    const propsConfig = {
      target: this.target,
      propTarget: this.propTarget,

      // Things to do when a single sub-property is changed
      onChange(el, view, opt) {
        const subModel = view.model;

        if (model.get('detached')) {
          const subProp = subModel.get('property');
          const values = self.getLayers().getPropertyValues(subProp);
          view.updateTargetStyle(values, null, opt);
        } else {
          // Update only if there is an actual update (to avoid changes for computed styles)
          // ps: status is calculated in `targetUpdated` method
          if (model.get('status') == 'updated') {
            const value = model.getFullValue();
            model.set('value', value, opt);
            // Try to remove detached properties
            !value && view.updateTargetStyle(value, null, opt);
          }
        }
      }
    };
    const layers = new LayersView({
      collection: this.getLayers(),
      stackModel: model,
      preview: model.get('preview'),
      config: this.config,
      propsConfig
    }).render().el;

    // Will use it to propogate changes
    new PropertiesView({
      target: this.target,
      collection: this.model.get('properties'),
      stackModel: model,
      config: this.config,
      onChange: propsConfig.onChange,
      propTarget: propsConfig.propTarget
    }).render();

    //model.get('properties')
    fieldEl.appendChild(layers);
  }
});
<|endoftext|>


<commit_before>// Given a _sharedData from instagram script, return a JSON.

class YourClass {
  constructor(say) {
    this.say = say;
  }

  speak() {
    console.log('I am saying: ' + this.say);
  }
}

function areYouHappy(bool) {
  if (bool) {
    console.log('I am happy0');
  } else {
    console.log('I want to be happy.');
  }
}

module.exports = {
  YourClass,
  areYouHappy
}
<commit_msg>for testing git<commit_after>// Given a _sharedData from instagram script, return a JSON.

class YourClass {
  constructor(say) {
    this.say = say;
  }

  speak() {
    console.log('I am saying: ' + this.say);
  }
}

function areYouHappy(bool) {
  if (bool) {
    console.log('I am happy0');
  } else {
    console.log('I want to be happ');
  }
}

module.exports = {
  YourClass,
  areYouHappy
}
<|endoftext|>