<commit_before>const GAMES = require('@anyware/game-logic/lib/constants/games');
const SculptureStore = require('@anyware/game-logic/lib/sculpture-store');
const SculptureActionCreator = require('@anyware/game-logic/lib/actions/sculpture-action-creator');

const SerialManager = require('../serial/serial-manager');
const serialProtocol = require('../serial/serial-protocol');
const {SerialProtocolCommandParser, SerialProtocolCommandBuilder} = serialProtocol;

export default class HandshakeView {
  constructor(store, config, dispatcher, serialManager) {
    this.store = store;
    this.config = config;
    this.serialManager = serialManager;
    this.serialManager.on(SerialManager.EVENT_COMMAND, this._handleCommand.bind(this));

    this.sculptureActionCreator = new SculptureActionCreator(dispatcher);

    this._pulseInterval = null;
    this._complete = false;

    this.store.on(SculptureStore.EVENT_CHANGE, this._handleChanges.bind(this));
  }

  reset() {
  }

  get handshakes() {
    return this.store.data.get('handshakes');
  }

  _handleChanges(changes) {
    this._handleCurrentGameChanges(changes);
    this._handleHandshakesChanges(changes);
  }

  _handleHandshakesChanges(changes) {
    const handshakesChanges = changes.handshakes;
    if (!handshakesChanges || !this.store.isReady) {
      return;
    }

    this._updateHandshakeVibrationIntensity();

    for (let username of Object.keys(handshakesChanges)) {
      if (handshakesChanges[username]) {
        this._activateUserPanel(username);

        if (username === this.store.username) {
          this._activateMiddlePanel();
        }
      }
      else {
        this._deactivateUserPanel(username);

        if (username === this.store.username) {
          this._deactivateMiddlePanel();
        }
      }
    }
  }

  _activateUserPanel(username) {
    const intensity = this.config.HANDSHAKE_HARDWARE.USER_PANEL_ON_INTENSITY;
    const color = this.config.getUserColor(username);
    const easing = this.config.HANDSHAKE_HARDWARE.USER_PANEL_ON_EASING;

    this._userPanelSet(username, {intensity, color, easing});
  }

  _deactivateUserPanel(username) {
    const intensity = this.config.HANDSHAKE_HARDWARE.USER_PANEL_OFF_INTENSITY;
    const easing = this.config.HANDSHAKE_HARDWARE.USER_PANEL_OFF_EASING;

    this._userPanelSet(username, {intensity, easing});
  }

  _activateMiddlePanel() {
    const intensity = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_INTENSITY;
    const color = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_COLOR || this.store.userColor;
    const easing = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_EASING;

    this._middlePanelSet({intensity, color, easing});
  }

  _deactivateMiddlePanel() {
    const intensity = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_INTENSITY;
    const color = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_COLOR;
    const easing = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_EASING;

    this._middlePanelSet({intensity, color, easing});
  }

  _userPanelSet(username, {intensity, color, easing}) {
    const userPanel = this.config.HANDSHAKE_HARDWARE.USER_PANELS[username];

    this._handshakePanelSet(userPanel, {intensity, color, easing});
  }

  _middlePanelSet({intensity, color, easing}) {
    const panel = this.config.HANDSHAKE_HARDWARE.MIDDLE_PANEL;
    this._handshakePanelSet(panel, {intensity, color, easing});
  }

  _handshakePanelSet(panel, {intensity, color, easing}) {
    const commandString = SerialProtocolCommandBuilder.buildPanelSet({
      stripId: this.config.LIGHTS.HANDSHAKE_STRIP,
      panelId: panel,
      intensity: intensity,
      color: color,
      easing: easing
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _updateHandshakeVibrationIntensity() {
    const handshakes = this.handshakes;
    const count = Array.from(handshakes).reduce((total, username) => {
      return total + (handshakes.get(username) ? 1 : 0);
    }, 0);
    const commandString = SerialProtocolCommandBuilder.buildHandshake({
      numUsers: count
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _handleCurrentGameChanges(changes) {
    if (!changes.hasOwnProperty("currentGame")) {
      return
    }

    if (changes.currentGame === GAMES.HANDSHAKE) {
      // starting handshake game
      this._complete = false;
      this._beginPulsing();
    }
    else {
      this._endPulsing();
      this._complete = true;
    }
  }

  _beginPulsing() {
    // ensure that we can never orphan a timer
    this._endPulsing();

    this._pulse();

    this._pulseInterval = setInterval(() => {
      if (this._complete) {
        return;
      }

      this._pulse();
    }, this.config.HANDSHAKE_HARDWARE.PULSE_DELAY);
  }

  _endPulsing() {
    clearInterval(this._pulseInterval);
  }

  _pulse() {
    const commandString = SerialProtocolCommandBuilder.buildPanelPulse({
      stripId: this.config.LIGHTS.HANDSHAKE_STRIP,
      panelId: '3',
      intensity: 100,
      color: 'white',
      easing: 'sleep'
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _handleCommand(commandName, commandArgs) {
    if (commandName === serialProtocol.HANDSHAKE_COMMAND) {
      let {numUsers} = commandArgs;

      if (parseInt(numUsers) > 0) {
        this.sculptureActionCreator.sendHandshakeActivate(this.config.username);
      }
      else {
        this.sculptureActionCreator.sendHandshakeDeactivate(this.config.username);
      }
    }
  }
}
<commit_msg>Fixed bug with pulsing not stopping right away<commit_after>const GAMES = require('@anyware/game-logic/lib/constants/games');
const SculptureStore = require('@anyware/game-logic/lib/sculpture-store');
const SculptureActionCreator = require('@anyware/game-logic/lib/actions/sculpture-action-creator');

const SerialManager = require('../serial/serial-manager');
const serialProtocol = require('../serial/serial-protocol');
const {SerialProtocolCommandParser, SerialProtocolCommandBuilder} = serialProtocol;

export default class HandshakeView {
  constructor(store, config, dispatcher, serialManager) {
    this.store = store;
    this.config = config;
    this.serialManager = serialManager;
    this.serialManager.on(SerialManager.EVENT_COMMAND, this._handleCommand.bind(this));

    this.sculptureActionCreator = new SculptureActionCreator(dispatcher);

    this._pulseInterval = null;
    this._complete = false;

    this.store.on(SculptureStore.EVENT_CHANGE, this._handleChanges.bind(this));
  }

  reset() {
  }

  get handshakes() {
    return this.store.data.get('handshakes');
  }

  _handleChanges(changes) {
    this._handleCurrentGameChanges(changes);
    this._handleHandshakesChanges(changes);
  }

  _handleHandshakesChanges(changes) {
    const handshakesChanges = changes.handshakes;
    if (!handshakesChanges || !this.store.isReady) {
      return;
    }

    this._updateHandshakeVibrationIntensity();

    for (let username of Object.keys(handshakesChanges)) {
      if (handshakesChanges[username]) {
        this._activateUserPanel(username);

        if (username === this.store.username) {
          // Pulsing needs to be stopped if the user has activated the
          // handshake because both cannot happen at once
          this._endPulsing();
          this._activateMiddlePanel();
        }
      }
      else {
        this._deactivateUserPanel(username);

        if (username === this.store.username) {
          this._deactivateMiddlePanel();
        }
      }
    }
  }

  _activateUserPanel(username) {
    const intensity = this.config.HANDSHAKE_HARDWARE.USER_PANEL_ON_INTENSITY;
    const color = this.config.getUserColor(username);
    const easing = this.config.HANDSHAKE_HARDWARE.USER_PANEL_ON_EASING;

    this._userPanelSet(username, {intensity, color, easing});
  }

  _deactivateUserPanel(username) {
    const intensity = this.config.HANDSHAKE_HARDWARE.USER_PANEL_OFF_INTENSITY;
    const easing = this.config.HANDSHAKE_HARDWARE.USER_PANEL_OFF_EASING;

    this._userPanelSet(username, {intensity, easing});
  }

  _activateMiddlePanel() {
    const intensity = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_INTENSITY;
    const color = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_COLOR || this.store.userColor;
    const easing = this.config.HANDSHAKE_HARDWARE.MIDDLE_ON_EASING;

    this._middlePanelSet({intensity, color, easing});
  }

  _deactivateMiddlePanel() {
    const intensity = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_INTENSITY;
    const color = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_COLOR;
    const easing = this.config.HANDSHAKE_HARDWARE.MIDDLE_OFF_EASING;

    this._middlePanelSet({intensity, color, easing});
  }

  _userPanelSet(username, {intensity, color, easing}) {
    const userPanel = this.config.HANDSHAKE_HARDWARE.USER_PANELS[username];

    this._handshakePanelSet(userPanel, {intensity, color, easing});
  }

  _middlePanelSet({intensity, color, easing}) {
    const panel = this.config.HANDSHAKE_HARDWARE.MIDDLE_PANEL;
    this._handshakePanelSet(panel, {intensity, color, easing});
  }

  _handshakePanelSet(panel, {intensity, color, easing}) {
    const commandString = SerialProtocolCommandBuilder.buildPanelSet({
      stripId: this.config.LIGHTS.HANDSHAKE_STRIP,
      panelId: panel,
      intensity: intensity,
      color: color,
      easing: easing
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _updateHandshakeVibrationIntensity() {
    const handshakes = this.handshakes;
    const count = Array.from(handshakes).reduce((total, username) => {
      return total + (handshakes.get(username) ? 1 : 0);
    }, 0);
    const commandString = SerialProtocolCommandBuilder.buildHandshake({
      numUsers: count
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _handleCurrentGameChanges(changes) {
    if (!changes.hasOwnProperty("currentGame")) {
      return
    }

    if (changes.currentGame === GAMES.HANDSHAKE) {
      // starting handshake game
      this._complete = false;
      this._beginPulsing();
    }
    else {
      this._endPulsing();
      this._complete = true;
    }
  }

  _beginPulsing() {
    // ensure that we can never orphan a timer
    this._endPulsing();

    this._pulse();

    this._pulseInterval = setInterval(() => {
      if (this._complete) {
        return;
      }

      this._pulse();
    }, this.config.HANDSHAKE_HARDWARE.PULSE_DELAY);
  }

  _endPulsing() {
    clearInterval(this._pulseInterval);
    this._pulseInterval = null;
  }

  _pulse() {
    const commandString = SerialProtocolCommandBuilder.buildPanelPulse({
      stripId: this.config.LIGHTS.HANDSHAKE_STRIP,
      panelId: '3',
      intensity: 100,
      color: 'white',
      easing: 'sleep'
    });
    this.serialManager.dispatchCommand(commandString);
  }

  _handleCommand(commandName, commandArgs) {
    if (commandName === serialProtocol.HANDSHAKE_COMMAND) {
      let {numUsers} = commandArgs;

      if (parseInt(numUsers) > 0) {
        this.sculptureActionCreator.sendHandshakeActivate(this.config.username);
      }
      else {
        this.sculptureActionCreator.sendHandshakeDeactivate(this.config.username);
      }
    }
  }
}
<|endoftext|>


<commit_before>const express = require('express');
const request = require('request');
const moment = require('moment');
const bodyParser = require('body-parser');

var bu;

var app;
var e = module.exports;
var bot;
var server;

e.init = (b, blargutil) => {
    bot = b;
    bu = blargutil;
    app = express();
    app.use(bodyParser.json());

    server = app.listen(8081, function () {
        var host = server.address().address;
        var port = server.address().port;
        console.log('Interface listening at http://%s:%s', host, port);
    });

    app.post('/gitlog/push', (req, res) => {
        var responseObj = {
            status: 401,
            desc: 'no u'
        };
        console.log(req.get('X-Hub-Signature'), bu.config.general.gitlogHash);
        if (req.get('X-Hub-Signature') == bu.config.general.gitlogHash) {
            console.dir(req);
            let body = req.body;
            responseObj = {
                status: 200,
                desc: 'whew such a professional interface'
            };
            let toSend = {
                username: 'Gumdrop',
                text: '**__New Commit__**',
                attachments: [
                    {
                        author_icon: body.sender.avatar_url,
                        author_name: body.sender.login,
                        text: `From \`${body.before}\` to \`${body.after}\``,
                        color: '#36a64f',
                        mrkdwn_in: ['text', 'fields'],
                        fields: []
                    }
                ],
                mrkdwn: true
            };
            for (let i = 0; i < body.commits.length; i++) {
                let commit = {
                    title: '',
                    value: '',
                    short: true
                };
                commit.title = body.commits[i].message;
                commit.value = moment(body.commits[i].timestamp).format('LLLL');
                toSend.attachments[0].fields.push(commit);
            }
            console.log(`Executing webhook...`);
            bot.executeSlackWebhook(bu.config.general.gitlogWebhookID, bu.config.general.gitlogWebhookToken, toSend).then(() => {
              console.log('Webhook executed.');
            }).catch(err => {
              console.log(err.stack);
            });
        }
        console.log(`Ending POST request to /gitlog/push with ${JSON.stringify(responseObj, null, 4)}`);

        res.status(responseObj.status).send(JSON.stringify(responseObj, null, 4));
    });

    app.get('/user/:id', (req, res) => {
        //console.log()
        //   console.dir(req.params)
        var user = bot.users.get(req.params.id);
        var objectToSend;
        if (user) {
            objectToSend = {
                id: user.id,
                username: user.username,
                discriminator: user.discriminator,
                avatarURL: user.avatarURL,
                bot: user.bot
            };
            res.end(checkAuth(objectToSend, req, res));

        } else {
            bu.db.query(`select username, isbot, discriminator from user where userid = ?`, [req.params.id], (err, rows) => {
                if (rows && rows[0]) {
                    objectToSend = {
                        id: req.param.id,
                        username: rows[0].username,
                        discriminator: rows[0].discriminator || '????',
                        avatarURL: 'not found',
                        bot: rows[0].isbot
                    };
                } else {
                    objectToSend = notFound;
                }
                res.end(checkAuth(objectToSend, req, res));

            });
        }
    });

    app.get('/channel/:id', (req, res) => {
        var channel = bot.getChannel(req.params.id);
        var objectToSend = {};
        if (channel) {
            objectToSend = {
                id: channel.id,
                name: channel.name,
                guildid: channel.guild.id,
                guildname: channel.guild.name
            };
        } else {
            objectToSend = notFound;
        }
        res.end(checkAuth(objectToSend, req));
    });

    app.get('/guild/:id', (req, res) => {
        var guild = bot.guilds.get(req.params.id);
        var objectToSend;
        if (guild) {
            objectToSend = {
                id: guild.id,
                name: guild.name
            };
        } else {
            objectToSend = notFound;
        }
        res.end(checkAuth(objectToSend, req));
    });
};

e.kill = () => {
    server.close();
};

function checkAuth(object, req, res) {
    //  console.dir(req.get('key'), bu.config.general.interface_key);
    if (bu.config.general.interface_key != req.get('key'))
        object = {
            error: 401,
            desc: 'who the fuck are you get off my lawn'
        };
    return JSON.stringify(object, null, 4);
}

var notFound = {
    error: 404,
    desc: 'you fucked up kthx'
};<commit_msg>tst commit please ignore<commit_after>const express = require('express');
const request = require('request');
const moment = require('moment');
const bodyParser = require('body-parser');

var bu;

var app;
var e = module.exports;
var bot;
var server;

e.init = (b, blargutil) => {
    bot = b;
    bu = blargutil;
    app = express();
    app.use(bodyParser.json());

    server = app.listen(8081, function () {
        var host = server.address().address;
        var port = server.address().port;
        console.log('Interface listening at http://%s:%s', host, port);
    });

    app.post('/gitlog/push', (req, res) => {
        var responseObj = {
            status: 401,
            desc: 'no u'
        };
        console.log(req.get('X-Hub-Signature'), bu.config.general.gitlogHash);
        if (req.get('X-Hub-Signature') == bu.config.general.gitlogHash) {
            console.dir(req);
            let body = req.body;
            responseObj = {
                status: 200,
                desc: 'whew such a professional interface'
            };
            let toSend = {
                username: 'Gumdrop',
                text: '**__New Commit__**',
                attachments: [
                    {
                        author_icon: body.sender.avatar_url,
                        author_name: body.sender.login,
                        text: `From \`${body.before}\` to \`${body.after}\``,
                        color: '#36a64f',
                        mrkdwn_in: ['text', 'fields'],
                        fields: []
                    }
                ],
                mrkdwn: true
            };
            for (let i = 0; i < body.commits.length; i++) {
                let commit = {
                    title: '',
                    value: '',
                    short: true
                };
                commit.title = body.commits[i].message;
                commit.value = moment(body.commits[i].timestamp).format('LLLL');
                toSend.attachments[0].fields.push(commit);
            }
            console.log(`Executing webhook...`);
            bot.executeSlackWebhook(bu.config.general.gitlogWebhookID, bu.config.general.gitlogWebhookToken, toSend).then(() => {
              console.log('Webhook executed.');
            }).catch(err => {
              console.log(err.stack);
            });
        }
        console.log(`Ending POST request to /gitlog/push with ${JSON.stringify(responseObj, null, 4)}`);

        res.status(responseObj.status).send(JSON.stringify(responseObj, null, 4));
    });

    app.get('/user/:id', (req, res) => {
        //console.log()
        //   console.dir(req.params)
        var user = bot.users.get(req.params.id);
        var objectToSend;
        if (user) {
            objectToSend = {
                id: user.id,
                username: user.username,
                discriminator: user.discriminator,
                avatarURL: user.avatarURL,
                bot: user.bot
            };
            res.end(checkAuth(objectToSend, req, res));

        } else {
            bu.db.query(`select username, isbot, discriminator from user where userid = ?`, [req.params.id], (err, rows) => {
                if (rows && rows[0]) {
                    objectToSend = {
                        id: req.param.id,
                        username: rows[0].username,
                        discriminator: rows[0].discriminator || '????',
                        avatarURL: 'not found',
                        bot: rows[0].isbot
                    };
                } else {
                    objectToSend = notFound;
                }
                res.end(checkAuth(objectToSend, req, res));

            });
        }
    });

    app.get('/channel/:id', (req, res) => {
        var channel = bot.getChannel(req.params.id);
        var objectToSend = {};
        if (channel) {
            objectToSend = {
                id: channel.id,
                name: channel.name,
                guildid: channel.guild.id,
                guildname: channel.guild.name
            };
        } else {
            objectToSend = notFound;
        }
        res.end(checkAuth(objectToSend, req));
    });

    app.get('/guild/:id', (req, res) => {
        var guild = bot.guilds.get(req.params.id);
        var objectToSend;
        if (guild) {
            objectToSend = {
                id: guild.id,
                name: guild.name
            };
        } else {
            objectToSend = notFound;
        }
        res.end(checkAuth(objectToSend, req));
    });
};

e.kill = () => {
    server.close();
};

function checkAuth(object, req, res) {
    //  console.dir(req.get('key'), bu.config.general.interface_key);
    if (bu.config.general.interface_key != req.get('key'))
        object = {
            error: 401,
            desc: 'who the fuck are you get off my lawn'
        };
    return JSON.stringify(object, null, 4);
}

var notFound = {
    error: 404,
    desc: 'you fucked up kthx'
};<|endoftext|>


<commit_before>// This file is a fallback for a consumer who is not yet on React 16
// as createPortal was introduced in React 16

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

export default class Portal extends React.Component {
  componentDidMount() {
    this.renderPortal();
  }

  componentWillReceiveProps(props) {
    this.renderPortal();
  }

  componentWillUnmount() {
    if (this.props.node) {
      document.body.removeChild(this.props.node);
    }
    if (this.defaultNode) {
      document.body.removeChild(this.defaultNode);
    }
    this.defaultNode = null;
    this.portal = null;
  }

  renderPortal(props) {
    if (!this.props.node && !this.defaultNode) {
      this.defaultNode = document.createElement('div');
      document.body.appendChild(this.defaultNode);
    }

    let children = this.props.children;
    // https://gist.github.com/jimfb/d99e0678e9da715ccf6454961ef04d1b
    if (typeof this.props.children.type === 'function') {
      children = React.cloneElement(this.props.children);
    }

    this.portal = ReactDOM.unstable_renderSubtreeIntoContainer(
      this,
      children,
      this.props.node || this.defaultNode
    );
  }

  render() {
    return null;
  }
}

Portal.propTypes = {
  children: PropTypes.node.isRequired,
  node: PropTypes.any
};
<commit_msg>issue #185: fix out of date props render bug<commit_after>// This file is a fallback for a consumer who is not yet on React 16
// as createPortal was introduced in React 16

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

export default class Portal extends React.Component {
  componentDidMount() {
    this.renderPortal();
  }

  componentDidUpdate(props) {
    this.renderPortal();
  }

  componentWillUnmount() {
    if (this.props.node) {
      document.body.removeChild(this.props.node);
    }
    if (this.defaultNode) {
      document.body.removeChild(this.defaultNode);
    }
    this.defaultNode = null;
    this.portal = null;
  }

  renderPortal(props) {
    if (!this.props.node && !this.defaultNode) {
      this.defaultNode = document.createElement('div');
      document.body.appendChild(this.defaultNode);
    }

    let children = this.props.children;
    // https://gist.github.com/jimfb/d99e0678e9da715ccf6454961ef04d1b
    if (typeof this.props.children.type === 'function') {
      children = React.cloneElement(this.props.children);
    }

    this.portal = ReactDOM.unstable_renderSubtreeIntoContainer(
      this,
      children,
      this.props.node || this.defaultNode
    );
  }

  render() {
    return null;
  }
}

Portal.propTypes = {
  children: PropTypes.node.isRequired,
  node: PropTypes.any
};
<|endoftext|>


<commit_before>var https = require('https');
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
var pty = require('node-pty');
var cors = require('cors');
app.use(cors());
app.options('*', cors());
var cwds = {};
var cmd = require('node-cmd');

/*
##########################################################
###################FOR TERMINAL DEMO ONLY ################
##########################################################
*/
  app.use('/build', express.static(__dirname + '/../build'));

  app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
  });

  app.get('/style.css', function(req, res){
    res.sendFile(__dirname + '/style.css');
  });

  app.get('/main.js', function(req, res){
    res.sendFile(__dirname + '/main.js');
  });
/*
##########################################################
###################FOR TERMINAL DEMO ONLY ################
##########################################################
*/

/*
##########get user info and .pem file path###############
*/
function getTerm(token) {
    return new Promise((resolve, reject) => {
      try {
        return https.get({
            host: 'api.commit.live',
            path: '/v1/users/' + token,
            headers: {'access-token': token}
        }, function(response) {
            // Continuously update stream with data
            var body = '';
            response.on('data', function(d) {
                body += d;
            });
            response.on('end', function() {
                //console.log(body);
                try {
                    return resolve(JSON.parse(body));
                } catch (err) {
                    console.log('Parse failed');
                    console.log(err);
                }
            });
        });
      } catch (err) {
        console.log('Api failed');
        console.log(err);
        reject;
      }
    })
}

/*
##########xterm over WebSocket###############
##########Do not edit code below if you are not sure & know what you are doing ###############
*/
app.ws('/terminals/:pid', function (ws, req) {
  try {
    getTerm(req.params.pid)
      .then(user_info => {
        console.log(user_info);
        var pcwd = process.env.PWD;
        if(cwds[req.params.pid]){
          pcwd = cwds[req.params.pid];
        }
        // var term = pty.spawn('ssh', ["-i", user_info.pem_file, user_info.user_host], {
        var term = pty.spawn('sudo', ['su','-',user_info.data.username], {
          name: 'xterm-color',
          cwd: pcwd,
          env: process.env
        });

        term.on('data', function(data) {
          ws.send(data);
        });

        ws.on('message', function(msg) {
          term.write(msg);
        });

        ws.on('close', function () {
          var command = "lsof -a -p "+term.pid+" -d cwd -n | tail -1 | awk '{print $NF}'"
          cmd.get(
              command,
              function(err, data, stderr){
                  cwds[req.params.pid] = data.trim();
                  process.kill(term.pid);
              }
          );
        });
      })
      .catch(err => {
        // console.log(err);
      })
  } catch (err) {
      console.log('Terminal webSocket failed');
      console.log(err);
  }
});

/*
##########listen server at port 30000################
*/
console.log('App listening to *:3000');
app.listen(3000);
<commit_msg>Update app.js<commit_after>var https = require('https');
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
var pty = require('node-pty');
var cors = require('cors');
app.use(cors());
app.options('*', cors());
var cwds = {};
var cmd = require('node-cmd');

/*
##########################################################
###################FOR TERMINAL DEMO ONLY ################
##########################################################
*/
  app.use('/build', express.static(__dirname + '/../build'));

  app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
  });

  app.get('/style.css', function(req, res){
    res.sendFile(__dirname + '/style.css');
  });

  app.get('/main.js', function(req, res){
    res.sendFile(__dirname + '/main.js');
  });
/*
##########################################################
###################FOR TERMINAL DEMO ONLY ################
##########################################################
*/

/*
##########get user info and .pem file path###############
*/
function getTerm(token) {
    return new Promise((resolve, reject) => {
      try {
        return https.get({
            host: 'api.commit.live',
            path: '/v1/users/' + token,
            headers: {'access-token': token}
        }, function(response) {
            // Continuously update stream with data
            var body = '';
            response.on('data', function(d) {
                body += d;
            });
            response.on('end', function() {
                //console.log(body);
                try {
                    return resolve(JSON.parse(body));
                } catch (err) {
                    console.log('Parse failed');
                    console.log(err);
                }
            });
        });
      } catch (err) {
        console.log('Api failed');
        console.log(err);
        reject;
      }
    })
}

/*
##########xterm over WebSocket###############
##########Do not edit code below if you are not sure & know what you are doing ###############
*/
app.ws('/terminals/:pid', function (ws, req) {
  try {
    getTerm(req.params.pid)
      .then(user_info => {
        console.log(user_info);
        var pcwd = process.env.PWD;
        console.log('i am here');
        console.log(pcwd);
        if(cwds[req.params.pid]){
          pcwd = cwds[req.params.pid];
        }
        // var term = pty.spawn('ssh', ["-i", user_info.pem_file, user_info.user_host], {
        var term = pty.spawn('sudo', ['su','-',user_info.data.username], {
          name: 'xterm-color',
          cwd: pcwd,
          env: process.env
        });

        term.on('data', function(data) {
          try {
            ws.send(data);
            var command = "lsof -a -p "+term.pid+" -d cwd -n | tail -1 | awk '{print $NF}'"
            cmd.get(
                command,
                function(err, data, stderr){
                    cwds[req.params.pid] = data.trim();
                    process.kill(term.pid);
                }
            );
          } catch (err) {
          }
        });

        ws.on('message', function(msg) {
          term.write(msg);
        });

        ws.on('close', function () {
          console.log('socket disconnecting');
          var command = "lsof -a -p "+term.pid+" -d cwd -n | tail -1 | awk '{print $NF}'"
          cmd.get(
              command,
              function(err, data, stderr){
                  cwds[req.params.pid] = data.trim();
                  process.kill(term.pid);
              }
          );
        });
      })
      .catch(err => {
        // console.log(err);
      })
  } catch (err) {
      console.log('Terminal webSocket failed');
      console.log(err);
  }
});

/*
##########listen server at port 30000################
*/
console.log('App listening to *:3000');
app.listen(3000);
<|endoftext|>


<commit_before>
var Factory = require( __core + 'entities/factory' );

describe( 'a factory', function() {
  var factory;

  beforeEach( function() {
    factory = new Factory( {
      name: 'Toy - Factory'
    } );
  } );

  it( 'has a name', function() {
    expect( factory.name ).toBeDefined();
    expect( factory.name ).toBe( 'Toy Factory' );
  } );
} );

<commit_msg>Changed Factory Test Results to a Vaild Value.<commit_after>
var Factory = require( __core + 'entities/factory' );

describe( 'a factory', function() {
  var factory;

  beforeEach( function() {
    factory = new Factory( {
      name: 'Toy Factory'
    } );
  } );

  it( 'has a name', function() {
    expect( factory.name ).toBeDefined();
    expect( factory.name ).toBe( 'Toy Factory' );
  } );
} );

<|endoftext|>


<commit_before>import Stream from "stream";
import _ from 'lodash';
import {Parser} from "binary-parser";
import AuroraConstants from './AuroraConstants';

export default class AuroraCmdTransformBinary extends Stream.Transform {

    static defaultOptions = {
        dataType: AuroraConstants.DataTypes.UINT8,
        parseType: undefined,
        parseTypeLength: undefined
    };

    constructor(options) {

        super();

        this.options = _.defaultsDeep(options, AuroraCmdTransformBinary.defaultOptions);

        if (typeof this.options.parseType == 'undefined') {

            this.options.parseType = this._getParseTypeFromDataType(this.options.dataType);
        }

        if (typeof this.options.parseTypeLength == 'undefined') {

            this.options.parseTypeLength = this._getParseTypeLengthFromDataType(this.options.dataType);
        }

        this.parser = new Parser();

        this.leftoverBuffer = null;
        this.hasData = false;

        this.parser.array('values', {
            type: this.options.parseType,
            readUntil: 'eof',
            formatter: function(values) {
                console.log('parse', values).join(',');
                return values.join(',');
            }
        });
    }

    _transform(respChunk, encoding, done) {

        console.log('chunk', respChunk);

        if (Buffer.isBuffer(this.leftoverBuffer)){

            respChunk = Buffer.concat([this.leftoverBuffer, respChunk], this.leftoverBuffer.length + respChunk.length);
            this.leftoverBuffer = null;
        }

        if (respChunk.length < this.options.parseTypeLength) {

            this.leftoverBuffer = respChunk;
            done();
            return;
        }

        this.hasData = true;

        const numBytesLeftover = respChunk.length % this.options.parseTypeLength;

        console.log('bytes leftover', numBytesLeftover);

        if (numBytesLeftover) {

            this.push((this.hasData ? ',' : '') + this.parser.parse(respChunk.slice(0, -numBytesLeftover)));
            this.leftoverBuffer = respChunk.slice(-numBytesLeftover);
        }
        else {
            this.push((this.hasData ? ',' : '') + this.parser.parse(respChunk));
        }

        done();
    }

    _flush(done) {

        if (this.leftoverBuffer) {
            console.log("Unparsed binary buffer: ", this.leftoverBuffer);
        }

        this.hasData = false;

        done();
    }

    _getParseTypeFromDataType(dataType) {

        switch(dataType){

            case AuroraConstants.DataTypes.INT8 :
                return 'int8';

            case AuroraConstants.DataTypes.UINT16 :
                return 'uint16le';

            case AuroraConstants.DataTypes.INT16 :
                return 'int16le';

            case AuroraConstants.DataTypes.FLOAT :
                return 'floatle';

            case AuroraConstants.DataTypes.UINT32 :
            case AuroraConstants.DataTypes.STR :
            case AuroraConstants.DataTypes.PTR :

                return 'uint32le';

            case AuroraConstants.DataTypes.INT32 :
                return 'int32le';

            case AuroraConstants.DataTypes.UINT8 :
            case AuroraConstants.DataTypes.CHAR :
            default:
                return 'uint8';

        }
    }

    _getParseTypeLengthFromDataType(dataType) {

        switch(dataType){

            case AuroraConstants.DataTypes.UINT16 :
            case AuroraConstants.DataTypes.INT16 :
                return 2;

            case AuroraConstants.DataTypes.UINT32 :
            case AuroraConstants.DataTypes.FLOAT :
            case AuroraConstants.DataTypes.STR :
            case AuroraConstants.DataTypes.PTR :
            case AuroraConstants.DataTypes.INT32 :
                return 4;

            case AuroraConstants.DataTypes.UINT8 :
            case AuroraConstants.DataTypes.CHAR :
            case AuroraConstants.DataTypes.INT8 :
            default:
                return 1;

        }
    }

}<commit_msg>Output of binary parser is an object, not a string.<commit_after>import Stream from "stream";
import _ from 'lodash';
import {Parser} from "binary-parser";
import AuroraConstants from './AuroraConstants';

export default class AuroraCmdTransformBinary extends Stream.Transform {

    static defaultOptions = {
        dataType: AuroraConstants.DataTypes.UINT8,
        parseType: undefined,
        parseTypeLength: undefined
    };

    constructor(options) {

        super();

        this.options = _.defaultsDeep(options, AuroraCmdTransformBinary.defaultOptions);

        if (typeof this.options.parseType == 'undefined') {

            this.options.parseType = this._getParseTypeFromDataType(this.options.dataType);
        }

        if (typeof this.options.parseTypeLength == 'undefined') {

            this.options.parseTypeLength = this._getParseTypeLengthFromDataType(this.options.dataType);
        }

        this.parser = new Parser();

        this.leftoverBuffer = null;
        this.hasData = false;

        this.parser.array('values', {
            type: this.options.parseType,
            readUntil: 'eof',
            formatter: function(values) {
                console.log('parse', values).join(',');
                return values.join(',');
            }
        });
    }

    _transform(respChunk, encoding, done) {

        console.log('chunk', respChunk);

        if (Buffer.isBuffer(this.leftoverBuffer)){

            respChunk = Buffer.concat([this.leftoverBuffer, respChunk], this.leftoverBuffer.length + respChunk.length);
            this.leftoverBuffer = null;
        }

        if (respChunk.length < this.options.parseTypeLength) {

            this.leftoverBuffer = respChunk;
            done();
            return;
        }

        const numBytesLeftover = respChunk.length % this.options.parseTypeLength;

        console.log('bytes leftover', numBytesLeftover);

        let parsedChunk;

        if (numBytesLeftover) {

            parsedChunk = this.parser.parse(respChunk.slice(0, -numBytesLeftover));

            this.leftoverBuffer = respChunk.slice(-numBytesLeftover);

        } else {

            parsedChunk = this.parser.parse(respChunk);
        }

        this.push((this.hasData ? ',' : '') + parsedChunk.values);

        this.hasData = true;

        done();
    }

    _flush(done) {

        if (this.leftoverBuffer) {
            console.log("Unparsed binary buffer: ", this.leftoverBuffer);
        }

        this.hasData = false;

        done();
    }

    _getParseTypeFromDataType(dataType) {

        switch(dataType){

            case AuroraConstants.DataTypes.INT8 :
                return 'int8';

            case AuroraConstants.DataTypes.UINT16 :
                return 'uint16le';

            case AuroraConstants.DataTypes.INT16 :
                return 'int16le';

            case AuroraConstants.DataTypes.FLOAT :
                return 'floatle';

            case AuroraConstants.DataTypes.UINT32 :
            case AuroraConstants.DataTypes.STR :
            case AuroraConstants.DataTypes.PTR :

                return 'uint32le';

            case AuroraConstants.DataTypes.INT32 :
                return 'int32le';

            case AuroraConstants.DataTypes.UINT8 :
            case AuroraConstants.DataTypes.CHAR :
            default:
                return 'uint8';

        }
    }

    _getParseTypeLengthFromDataType(dataType) {

        switch(dataType){

            case AuroraConstants.DataTypes.UINT16 :
            case AuroraConstants.DataTypes.INT16 :
                return 2;

            case AuroraConstants.DataTypes.UINT32 :
            case AuroraConstants.DataTypes.FLOAT :
            case AuroraConstants.DataTypes.STR :
            case AuroraConstants.DataTypes.PTR :
            case AuroraConstants.DataTypes.INT32 :
                return 4;

            case AuroraConstants.DataTypes.UINT8 :
            case AuroraConstants.DataTypes.CHAR :
            case AuroraConstants.DataTypes.INT8 :
            default:
                return 1;

        }
    }

}<|endoftext|>


<commit_before>import $ from 'jquery';
import _ from 'underscore';
import React from 'react';
import PropTypes from 'prop-types';
import autoBind from 'react-autobind';
import reactMixin from 'react-mixin';
import Reflux from 'reflux';
import alertify from 'alertifyjs';
import stores from '../../stores';
import bem from '../../bem';
import actions from '../../actions';
import mixins from '../../mixins';
import {dataInterface} from '../../dataInterface';
import {
  t,
  formatTime
} from '../../utils';
import {
  HOOK_LOG_STATUSES,
  MODAL_TYPES
} from '../../constants';

export default class RESTServiceLogs extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      hookName: null,
      isHookActive: false,
      assetUid: props.assetUid,
      hookUid: props.hookUid,
      isLoadingHook: true,
      isLoadingLogs: true,
      logs: [],
      nextPageUrl: null
    };
    autoBind(this);
  }

  componentDidMount() {
    this.listenTo(
      actions.hooks.getLogs.completed,
      this.onLogsUpdated
    );

    dataInterface.getHook(this.state.assetUid, this.state.hookUid)
      .done((data) => {
        this.setState({
          isLoadingHook: false,
          hookName: data.name,
          isHookActive: data.active
        });
      })
      .fail((data) => {
        this.setState({
          isLoadingHook: false
        });
        alertify.error(t('Could not load REST Service'));
      });

    actions.hooks.getLogs(
      this.state.assetUid,
      this.state.hookUid,
      {
        onComplete: (data) => {
          this.setState({
            isLoadingLogs: false,
            logs: data.results,
            nextPageUrl: data.next,
            totalLogsCount: data.count
          });
        },
        onFail: (data) => {
          this.setState({
            isLoadingLogs: false
          });
          alertify.error(t('Could not load REST Service logs'));
        }
      }
    );
  }

  loadMore() {
    this.setState({isLoadingLogs: false});

    dataInterface.loadNextPageUrl(this.state.nextPageUrl)
      .done((data) => {
        const newLogs = [].concat(this.state.logs, data.results);
        this.setState({
          isLoadingLogs: false,
          logs: newLogs,
          nextPageUrl: data.next,
          totalLogsCount: data.count
        });
      })
      .fail((data) => {
        this.setState({isLoadingLogs: false});
        alertify.error(t('Could not load REST Service logs'));
      });
  }

  onLogsUpdated(data) {
    this.setState({logs: data.results});
  }

  retryAll(evt) {
    const failedLogUids = [];
    this.state.logs.forEach((log) => {
      if (log.status === HOOK_LOG_STATUSES.FAILED) {
        failedLogUids.push(log.uid);
      }
    });
    this.overrideLogsStatus(failedLogUids, HOOK_LOG_STATUSES.PENDING);

    actions.hooks.retryLogs(
      this.state.assetUid,
      this.state.hookUid,
      {
        onComplete: (response) => {
          this.overrideLogsStatus(response.pending_uids, HOOK_LOG_STATUSES.PENDING);
        }
      }
    );
  }

  retryLog(log, evt) {
    // make sure to allow only retrying failed logs
    if (log.status !== HOOK_LOG_STATUSES.FAILED) {
      return;
    }

    this.overrideLogsStatus([log.uid], HOOK_LOG_STATUSES.PENDING);

    actions.hooks.retryLog(
      this.state.assetUid,
      this.state.hookUid,
      log.uid, {
        onFail: (response) => {
          if (response.responseJSON && response.responseJSON.detail) {
            this.overrideLogMessage(log.uid, response.responseJSON.detail);
          }
          this.overrideLogsStatus([log.uid], HOOK_LOG_STATUSES.FAILED);
        }
      }
    );
  }

  overrideLogMessage(logUid, newMessage) {
    const currentLogs = this.state.logs;
    currentLogs.forEach((currentLog) => {
      if (currentLog.uid === logUid) {
        currentLog.message = newMessage;
      }
    });
    this.setState({
      logs: currentLogs
    });
  }

  // useful to mark logs as pending, before BE tells about it
  // NOTE: logUids is an array
  overrideLogsStatus(logUids, newStatus) {
    const currentLogs = this.state.logs;
    currentLogs.forEach((currentLog) => {
      if (logUids.includes(currentLog.uid)) {
        currentLog.status = newStatus;
      }
    });
    this.setState({
      logs: currentLogs
    });
  }

  showLogInfo(log, evt) {
    const title = t('Submission Failure Detail (##id##)').replace('##id##', log.instance_id);
    const escapedMessage = $('
').text(log.message).html();
    alertify.alert(title, `<pre>${escapedMessage}</pre>`);
  }

  openSubmissionModal(log) {
    const currentAsset = this.currentAsset();
    stores.pageState.switchModal({
      type: MODAL_TYPES.SUBMISSION,
      sid: log.instance_id,
      asset: currentAsset,
      ids: [log.instance_id]
    });
  }

  hasAnyFailedLogs() {
    let hasAny = false;
    this.state.logs.forEach((log) => {
      if (log.status === HOOK_LOG_STATUSES.FAILED) {
        hasAny = true;
      }
    });
    return hasAny;
  }

  hasInfoToDisplay(log) {
    return log.status !== HOOK_LOG_STATUSES.SUCCESS && log.message.length > 0;
  }

  /*
   * rendering methods
   */

  renderHeader() {
    return (

        <a
          className='rest-services-list__header-back-button'
          href={`/#/forms/${this.state.assetUid}/settings/rest`}
        >

          {t('Back to REST Services')}

          {this.state.hookName}

    )
  }

  renderLoadMoreButton() {
    if (this.state.nextPageUrl === null) {
      return null;
    }

    return (
      <bem.ServiceRowButton
        m={this.state.isLoadingLogs ? 'loading' : null}
        onClick={this.loadMore}
      >
        {this.state.isLoadingLogs ? t('Loading…') : t('Load more')}
      </bem.ServiceRowButton>
    )
  }

  renderEmptyView() {
    return (
      <bem.FormView__cell m='rest-services-list' className='rest-services-list--empty'>
        {this.renderHeader()}

        <bem.EmptyContent>
          <bem.EmptyContent__message>
            {t('There are no logs yet')}
          </bem.EmptyContent__message>
        </bem.EmptyContent>
      </bem.FormView__cell>
    );
  }

  renderListView() {
    return (
      <bem.FormView__cell m='rest-services-list'>
        {this.renderHeader()}

        <bem.FormView__cell m={['box']}>
          <bem.ServiceRow m='header'>
            <bem.ServiceRow__column m='submission'>{t('Submission')}</bem.ServiceRow__column>
            <bem.ServiceRow__column m='status'>
              {t('Status')}
              { this.hasAnyFailedLogs() &&
                <bem.ServiceRow__actionButton
                  onClick={this.retryAll.bind(this)}
                  data-tip={t('Retry all submissions')}
                  disabled={!this.state.isHookActive}
                >

                </bem.ServiceRow__actionButton>
              }
            </bem.ServiceRow__column>
            <bem.ServiceRow__column m='date'>{t('Date')}</bem.ServiceRow__column>
          </bem.ServiceRow>

          {this.state.logs.map((log, n) => {
            let statusMod = '';
            let statusLabel = '';
            if (log.status === HOOK_LOG_STATUSES.SUCCESS) {
              statusMod = 'success';
              statusLabel = t('Success');
            }
            if (log.status === HOOK_LOG_STATUSES.PENDING) {
              statusMod = 'pending';
              statusLabel = t('Pending');

              if (log.tries && log.tries > 1) {
                statusLabel = t('Pending (##count##×)').replace('##count##', log.tries);
              }
            }
            if (log.status === HOOK_LOG_STATUSES.FAILED) {
              statusMod = 'failed';
              statusLabel = t('Failed');
            }

            return (
              <bem.ServiceRow
                m='clickable'
                onClick={this.openSubmissionModal.bind(this, log)}
                key={n}
              >
                <bem.ServiceRow__column m='submission'>
                  {log.instance_id}
                </bem.ServiceRow__column>

                <bem.ServiceRow__column
                  m={['status', statusMod]}
                >
                  {statusLabel}

                  {log.status === HOOK_LOG_STATUSES.FAILED &&
                    <bem.ServiceRow__actionButton
                      disabled={!this.state.isHookActive}
                      onClick={this.retryLog.bind(this, log)}
                      data-tip={t('Retry submission')}
                    >

                    </bem.ServiceRow__actionButton>
                  }

                  {this.hasInfoToDisplay(log) &&
                    <bem.ServiceRow__actionButton
                      onClick={this.showLogInfo.bind(this, log)}
                      data-tip={t('More info')}
                    >

                    </bem.ServiceRow__actionButton>
                  }
                </bem.ServiceRow__column>

                <bem.ServiceRow__column m='date'>
                  {formatTime(log.date_modified)}
                </bem.ServiceRow__column>
              </bem.ServiceRow>
            );
          })}
        </bem.FormView__cell>

        {this.renderLoadMoreButton()}
      </bem.FormView__cell>
    );
  }

  render() {
    if (this.state.isLoadingHook || (this.state.isLoadingLogs && this.state.logs.length === 0)) {
      return (
        <bem.Loading>
          <bem.Loading__inner>

            {t('loading...')}
          </bem.Loading__inner>
        </bem.Loading>
      )
    } else if (this.state.logs.length === 0) {
      return this.renderEmptyView();
    } else {
      return this.renderListView();
    }
  }
}

reactMixin(RESTServiceLogs.prototype, Reflux.ListenerMixin);
reactMixin(RESTServiceLogs.prototype, mixins.contextRouter);

RESTServiceLogs.contextTypes = {
  router: PropTypes.object
};
<commit_msg>make only successful rows clickable<commit_after>import $ from 'jquery';
import _ from 'underscore';
import React from 'react';
import PropTypes from 'prop-types';
import autoBind from 'react-autobind';
import reactMixin from 'react-mixin';
import Reflux from 'reflux';
import alertify from 'alertifyjs';
import stores from '../../stores';
import bem from '../../bem';
import actions from '../../actions';
import mixins from '../../mixins';
import {dataInterface} from '../../dataInterface';
import {
  t,
  formatTime
} from '../../utils';
import {
  HOOK_LOG_STATUSES,
  MODAL_TYPES
} from '../../constants';

export default class RESTServiceLogs extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      hookName: null,
      isHookActive: false,
      assetUid: props.assetUid,
      hookUid: props.hookUid,
      isLoadingHook: true,
      isLoadingLogs: true,
      logs: [],
      nextPageUrl: null
    };
    autoBind(this);
  }

  componentDidMount() {
    this.listenTo(
      actions.hooks.getLogs.completed,
      this.onLogsUpdated
    );

    dataInterface.getHook(this.state.assetUid, this.state.hookUid)
      .done((data) => {
        this.setState({
          isLoadingHook: false,
          hookName: data.name,
          isHookActive: data.active
        });
      })
      .fail((data) => {
        this.setState({
          isLoadingHook: false
        });
        alertify.error(t('Could not load REST Service'));
      });

    actions.hooks.getLogs(
      this.state.assetUid,
      this.state.hookUid,
      {
        onComplete: (data) => {
          this.setState({
            isLoadingLogs: false,
            logs: data.results,
            nextPageUrl: data.next,
            totalLogsCount: data.count
          });
        },
        onFail: (data) => {
          this.setState({
            isLoadingLogs: false
          });
          alertify.error(t('Could not load REST Service logs'));
        }
      }
    );
  }

  loadMore() {
    this.setState({isLoadingLogs: false});

    dataInterface.loadNextPageUrl(this.state.nextPageUrl)
      .done((data) => {
        const newLogs = [].concat(this.state.logs, data.results);
        this.setState({
          isLoadingLogs: false,
          logs: newLogs,
          nextPageUrl: data.next,
          totalLogsCount: data.count
        });
      })
      .fail((data) => {
        this.setState({isLoadingLogs: false});
        alertify.error(t('Could not load REST Service logs'));
      });
  }

  onLogsUpdated(data) {
    this.setState({logs: data.results});
  }

  retryAll(evt) {
    const failedLogUids = [];
    this.state.logs.forEach((log) => {
      if (log.status === HOOK_LOG_STATUSES.FAILED) {
        failedLogUids.push(log.uid);
      }
    });
    this.overrideLogsStatus(failedLogUids, HOOK_LOG_STATUSES.PENDING);

    actions.hooks.retryLogs(
      this.state.assetUid,
      this.state.hookUid,
      {
        onComplete: (response) => {
          this.overrideLogsStatus(response.pending_uids, HOOK_LOG_STATUSES.PENDING);
        }
      }
    );
  }

  retryLog(log, evt) {
    // make sure to allow only retrying failed logs
    if (log.status !== HOOK_LOG_STATUSES.FAILED) {
      return;
    }

    this.overrideLogsStatus([log.uid], HOOK_LOG_STATUSES.PENDING);

    actions.hooks.retryLog(
      this.state.assetUid,
      this.state.hookUid,
      log.uid, {
        onFail: (response) => {
          if (response.responseJSON && response.responseJSON.detail) {
            this.overrideLogMessage(log.uid, response.responseJSON.detail);
          }
          this.overrideLogsStatus([log.uid], HOOK_LOG_STATUSES.FAILED);
        }
      }
    );
  }

  overrideLogMessage(logUid, newMessage) {
    const currentLogs = this.state.logs;
    currentLogs.forEach((currentLog) => {
      if (currentLog.uid === logUid) {
        currentLog.message = newMessage;
      }
    });
    this.setState({
      logs: currentLogs
    });
  }

  // useful to mark logs as pending, before BE tells about it
  // NOTE: logUids is an array
  overrideLogsStatus(logUids, newStatus) {
    const currentLogs = this.state.logs;
    currentLogs.forEach((currentLog) => {
      if (logUids.includes(currentLog.uid)) {
        currentLog.status = newStatus;
      }
    });
    this.setState({
      logs: currentLogs
    });
  }

  showLogInfo(log, evt) {
    const title = t('Submission Failure Detail (##id##)').replace('##id##', log.instance_id);
    const escapedMessage = $('
').text(log.message).html();
    alertify.alert(title, `<pre>${escapedMessage}</pre>`);
  }

  openSubmissionModal(log) {
    const currentAsset = this.currentAsset();
    stores.pageState.switchModal({
      type: MODAL_TYPES.SUBMISSION,
      sid: log.instance_id,
      asset: currentAsset,
      ids: [log.instance_id]
    });
  }

  hasAnyFailedLogs() {
    let hasAny = false;
    this.state.logs.forEach((log) => {
      if (log.status === HOOK_LOG_STATUSES.FAILED) {
        hasAny = true;
      }
    });
    return hasAny;
  }

  hasInfoToDisplay(log) {
    return log.status !== HOOK_LOG_STATUSES.SUCCESS && log.message.length > 0;
  }

  /*
   * rendering methods
   */

  renderHeader() {
    return (

        <a
          className='rest-services-list__header-back-button'
          href={`/#/forms/${this.state.assetUid}/settings/rest`}
        >

          {t('Back to REST Services')}

          {this.state.hookName}

    )
  }

  renderLoadMoreButton() {
    if (this.state.nextPageUrl === null) {
      return null;
    }

    return (
      <bem.ServiceRowButton
        m={this.state.isLoadingLogs ? 'loading' : null}
        onClick={this.loadMore}
      >
        {this.state.isLoadingLogs ? t('Loading…') : t('Load more')}
      </bem.ServiceRowButton>
    )
  }

  renderEmptyView() {
    return (
      <bem.FormView__cell m='rest-services-list' className='rest-services-list--empty'>
        {this.renderHeader()}

        <bem.EmptyContent>
          <bem.EmptyContent__message>
            {t('There are no logs yet')}
          </bem.EmptyContent__message>
        </bem.EmptyContent>
      </bem.FormView__cell>
    );
  }

  renderListView() {
    return (
      <bem.FormView__cell m='rest-services-list'>
        {this.renderHeader()}

        <bem.FormView__cell m={['box']}>
          <bem.ServiceRow m='header'>
            <bem.ServiceRow__column m='submission'>{t('Submission')}</bem.ServiceRow__column>
            <bem.ServiceRow__column m='status'>
              {t('Status')}
              { this.hasAnyFailedLogs() &&
                <bem.ServiceRow__actionButton
                  onClick={this.retryAll.bind(this)}
                  data-tip={t('Retry all submissions')}
                  disabled={!this.state.isHookActive}
                >

                </bem.ServiceRow__actionButton>
              }
            </bem.ServiceRow__column>
            <bem.ServiceRow__column m='date'>{t('Date')}</bem.ServiceRow__column>
          </bem.ServiceRow>

          {this.state.logs.map((log, n) => {
            const rowProps = {
              key: n
            };
            let statusMod = '';
            let statusLabel = '';
            if (log.status === HOOK_LOG_STATUSES.SUCCESS) {
              statusMod = 'success';
              statusLabel = t('Success');
              rowProps.m = 'clickable';
              rowProps.onClick = this.openSubmissionModal.bind(this, log);
            }
            if (log.status === HOOK_LOG_STATUSES.PENDING) {
              statusMod = 'pending';
              statusLabel = t('Pending');

              if (log.tries && log.tries > 1) {
                statusLabel = t('Pending (##count##×)').replace('##count##', log.tries);
              }
            }
            if (log.status === HOOK_LOG_STATUSES.FAILED) {
              statusMod = 'failed';
              statusLabel = t('Failed');
            }

            return (
              <bem.ServiceRow {...rowProps}>
                <bem.ServiceRow__column m='submission'>
                  {log.instance_id}
                </bem.ServiceRow__column>

                <bem.ServiceRow__column
                  m={['status', statusMod]}
                >
                  {statusLabel}

                  {log.status === HOOK_LOG_STATUSES.FAILED &&
                    <bem.ServiceRow__actionButton
                      disabled={!this.state.isHookActive}
                      onClick={this.retryLog.bind(this, log)}
                      data-tip={t('Retry submission')}
                    >

                    </bem.ServiceRow__actionButton>
                  }

                  {this.hasInfoToDisplay(log) &&
                    <bem.ServiceRow__actionButton
                      onClick={this.showLogInfo.bind(this, log)}
                      data-tip={t('More info')}
                    >

                    </bem.ServiceRow__actionButton>
                  }
                </bem.ServiceRow__column>

                <bem.ServiceRow__column m='date'>
                  {formatTime(log.date_modified)}
                </bem.ServiceRow__column>
              </bem.ServiceRow>
            );
          })}
        </bem.FormView__cell>

        {this.renderLoadMoreButton()}
      </bem.FormView__cell>
    );
  }

  render() {
    if (this.state.isLoadingHook || (this.state.isLoadingLogs && this.state.logs.length === 0)) {
      return (
        <bem.Loading>
          <bem.Loading__inner>

            {t('loading...')}
          </bem.Loading__inner>
        </bem.Loading>
      )
    } else if (this.state.logs.length === 0) {
      return this.renderEmptyView();
    } else {
      return this.renderListView();
    }
  }
}

reactMixin(RESTServiceLogs.prototype, Reflux.ListenerMixin);
reactMixin(RESTServiceLogs.prototype, mixins.contextRouter);

RESTServiceLogs.contextTypes = {
  router: PropTypes.object
};
<|endoftext|>


<commit_before>'use strict';

describe('myApp.view1 module', function() {

  beforeEach(module('myApp.view1'));

  describe('view1 controller', function(){

    it('should ....', inject(function($controller) {
      //spec body
      var $scope = {};

      var view1Ctrl = $controller('View1Ctrl', { $scope: $scope });
      expect(view1Ctrl).toBeDefined();
    }));

  });

  describe('view1 timeSlotService', function(){

  	var timeSlotService, mockCurrentTimeService

  	beforeEach(function() {

      mockCurrentTimeService = new Date(2014, 8, 4, 6, 0, 0);

      module(function ($provide) {
          $provide.value('currentTimeService', mockCurrentTimeService);
      });

  	  // inject(function($injector) {
  	  //   timeSlotService = $injector.get('timeSlotService');
  	  // });

    });

    it('should populate 34 half hour slots for a full day', inject(function(timeSlotService) {
      //spec body
      expect(timeSlotService.slots.length).toEqual(12);
    }));

  });

});<commit_msg>corrected some date code<commit_after>'use strict';

describe('myApp.view1 module', function() {

  beforeEach(module('myApp.view1'));

  describe('view1 controller', function(){

    it('should ....', inject(function($controller) {
      //spec body
      var $scope = {};

      var view1Ctrl = $controller('View1Ctrl', { $scope: $scope });
      expect(view1Ctrl).toBeDefined();
    }));

  });

  describe('view1 timeSlotService', function(){

  	var timeSlotService, mockCurrentTimeService

  	beforeEach(function() {

      mockCurrentTimeService = new Date(2015, 1, 16, 0, 0, 0);

      module(function ($provide) {
          $provide.value('currentTimeService', mockCurrentTimeService);
      });

  	  // inject(function($injector) {
  	  //   timeSlotService = $injector.get('timeSlotService');
  	  // });

    });

    it('should populate 34 half hour slots for a full day', inject(function(timeSlotService) {
      //spec body
      expect(timeSlotService.slots.length).toEqual(34);
    }));

  });

});<|endoftext|>


<commit_before>/* global angular */
'use strict';

/**
 * dragular Module by Luckylooke https://github.com/luckylooke
 *
 * Angular version of dragula https://github.com/bevacqua/dragula
 */

angular.module('dragularModule', []).factory('dragularService', function dragula() {
  return function(initialContainers, options) {
    var body = document.body;
    var documentElement = document.documentElement;
    var _mirror; // mirror image
    var _source; // source container
    var _item; // item being dragged
    var _offsetX; // reference x
    var _offsetY; // reference y
    var _initialSibling; // reference sibling when grabbed
    var _currentSibling; // reference sibling now
    var _copy; // item used for copying
    var _containers = []; // containers managed by the drake

    var o = {
      classes: {
        mirror: 'gu-mirror',
        hide: 'gu-hide',
        unselectable: 'gu-unselectable',
        transit: 'gu-transit'
      },
      moves: always,
      accepts: always,
      copy: false,
      revertOnSpill: false,
      removeOnSpill: false
    };

    if (options && options.scope) {
      var temp = options.scope;
      options.scope = undefined;
      angular.merge(o, options);
      options.scope = o.scope = temp;
    } else {
      angular.merge(o, options);
    }

    var api = {
      addContainer: manipulateContainers('add'),
      removeContainer: manipulateContainers('remove'),
      start: start,
      end: end,
      cancel: cancel,
      remove: remove,
      destroy: destroy,
      dragging: false
    };

    events();
    api.addContainer(initialContainers);

    return api;

    function manipulateContainers(op) {
      return function addOrRemove(all) {
        var changes = Array.isArray(all) ? all : makeArray(all);
        changes.forEach(track);
        if (op === 'add') {
          _containers = _containers.concat(changes);
        } else {
          _containers = _containers.filter(removals);
        }

        function makeArray(all) {
          if (all.length) {
            var iAll = all.length,
              newArray = [];
            while (iAll) {
              iAll--;
              newArray.push(all[iAll]);
            }
            return newArray;
          } else {
            return [all];
          }
        }

        function track(container) {
          regEvent(container, op === 'add' ? 'on' : 'off', 'mousedown', grab);
        }

        function removals(container) {
          return changes.indexOf(container) === -1;
        }
      };
    }

    function events(rem) {
      var op = rem ? 'off' : 'on';
      regEvent(documentElement, op, 'mouseup', release);
    }

    function destroy() {
      events(true);
      api.removeContainer(_containers);
      release({});
    }

    function grab(e) {
      var item = e.target;

      if ((e.which !== 0 && e.which !== 1) || e.metaKey || e.ctrlKey) {
        return; // we only care about honest-to-god left clicks and touch events
      }
      if (start(item) !== true) {
        return;
      }

      var offset = getOffset(_item);
      _offsetX = getCoord('pageX', e) - offset.left;
      _offsetY = getCoord('pageY', e) - offset.top;
      renderMirrorImage();
      drag(e);
      e.preventDefault();
    }

    function start(item) {
      var handle = item;

      if (api.dragging && _mirror) {
        return false;
      }

      if (_containers.indexOf(item) !== -1) {
        return false; // don't drag container itself
      }
      while (_containers.indexOf(item.parentElement) === -1) {
        if (invalidTarget(item)) {
          return false;
        }
        item = item.parentElement; // drag target should be a top element
      }
      if (invalidTarget(item)) {
        return false;
      }

      var container = item.parentElement;
      var movable = o.moves(item, container, handle);
      if (!movable) {
        return false;
      }

      end();

      if (o.copy) {
        _copy = item.cloneNode(true);
        addClass(_copy, o.classes.transit);
        if (o.scope) {
          o.scope.$emit('cloned', _copy, item);
        }
      } else {
        addClass(item, o.classes.transit);
      }

      _source = container;
      _item = item;
      _initialSibling = _currentSibling = nextEl(item);

      api.dragging = true;
      if (o.scope) {
        o.scope.$emit('drag', _item, _source);
      }

      return true;
    }

    function invalidTarget(el) {
      return el.tagName === 'A' || el.tagName === 'BUTTON';
    }

    function end() {
      if (!api.dragging) {
        return;
      }
      var item = _copy || _item;
      drop(item, item.parentElement);
    }

    function release(e) {
      if (!api.dragging) {
        return;
      }

      var item = _copy || _item;
      var clientX = getCoord('clientX', e);
      var clientY = getCoord('clientY', e);
      var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
      var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
      if (dropTarget && (o.copy === false || dropTarget !== _source)) {
        drop(item, dropTarget);
      } else if (o.removeOnSpill) {
        remove();
      } else {
        cancel();
      }
    }

    function drop(item, target) {
      if (o.scope && isInitialPlacement(target)) {
        o.scope.$emit('cancel', item, _source);
      } else if (o.scope) {
        o.scope.$emit('drop', item, target, _source);
      }
      cleanup();
    }

    function remove() {
      if (!api.dragging) {
        return;
      }
      var item = _copy || _item;
      var parent = item.parentElement;
      if (parent) {
        parent.removeChild(item);
      }
      if (o.scope) {
        o.scope.$emit(o.copy ? 'cancel' : 'remove', item, parent);
      }
      cleanup();
    }

    function cancel(revert) {
      if (!api.dragging) {
        return;
      }
      var reverts = arguments.length > 0 ? revert : o.revertOnSpill;
      var item = _copy || _item;
      var parent = item.parentElement;
      if (parent === _source && o.copy) {
        parent.removeChild(_copy);
      }
      var initial = isInitialPlacement(parent);
      if (initial === false && o.copy === false && reverts) {
        _source.insertBefore(item, _initialSibling);
      }
      if (o.scope && (initial || reverts)) {
        o.scope.$emit('cancel', item, _source);
      } else if (o.scope) {
        o.scope.$emit('drop', item, parent, _source);
      }
      cleanup();
    }

    function cleanup() {
      var item = _copy || _item;
      removeMirrorImage();
      rmClass(item, o.classes.transit);
      _source = _item = _copy = _initialSibling = _currentSibling = null;
      api.dragging = false;
      if (o.scope) {
        o.scope.$emit('dragend', item);
      }
    }

    function isInitialPlacement(target, s) {
      var sibling;
      if (s !== void 0) {
        sibling = s;
      } else if (_mirror) {
        sibling = _currentSibling;
      } else {
        sibling = nextEl(_item || _copy);
      }
      return target === _source && sibling === _initialSibling;
    }

    function findDropTarget(elementBehindCursor, clientX, clientY) {
      var target = elementBehindCursor;
      while (target && !accepted()) {
        target = target.parentElement;
      }
      return target;

      function accepted() {
        var droppable = _containers.indexOf(target) !== -1;
        if (droppable === false) {
          return false;
        }

        var immediate = getImmediateChild(target, elementBehindCursor);
        var reference = getReference(target, immediate, clientX, clientY);
        var initial = isInitialPlacement(target, reference);
        if (initial) {
          return true; // should always be able to drop it right back where it was
        }
        return o.accepts(_item, target, _source, reference);
      }
    }

    function drag(e) {
      if (!_mirror) {
        return;
      }

      var clientX = getCoord('clientX', e);
      var clientY = getCoord('clientY', e);
      var x = clientX - _offsetX;
      var y = clientY - _offsetY;

      _mirror.style.left = x + 'px';
      _mirror.style.top = y + 'px';

      var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
      var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
      if (dropTarget === _source && o.copy) {
        return;
      }
      var reference;
      var item = _copy || _item;
      var immediate = getImmediateChild(dropTarget, elementBehindCursor);
      if (immediate !== null) {
        reference = getReference(dropTarget, immediate, clientX, clientY);
      } else if (o.revertOnSpill === true) {
        reference = _initialSibling;
        dropTarget = _source;
      } else {
        return;
      }
      if (reference === null || reference !== item && reference !== nextEl(item)) {
        _currentSibling = reference;
        dropTarget.insertBefore(item, reference);
        if (o.scope) {
          o.scope.$emit('shadow', item, dropTarget);
        }
      }
    }

    function renderMirrorImage() {
      if (_mirror) {
        return;
      }
      var rect = _item.getBoundingClientRect();
      _mirror = _item.cloneNode(true);
      _mirror.style.width = rect.width + 'px';
      _mirror.style.height = rect.height + 'px';
      rmClass(_mirror, o.classes.transit);
      addClass(_mirror, o.classes.mirror);
      body.appendChild(_mirror);
      regEvent(documentElement, 'on', 'mousemove', drag);
      addClass(body, o.classes.unselectable);
      if (o.scope) {
        o.scope.$emit('cloned', _mirror, _item);
      }
    }

    function removeMirrorImage() {
      if (_mirror) {
        rmClass(body, o.classes.unselectable);
        regEvent(documentElement, 'off', 'mousemove', drag);
        _mirror.parentElement.removeChild(_mirror);
        _mirror = null;
      }
    }

    function getImmediateChild(dropTarget, target) {
      var immediate = target;
      while (immediate !== dropTarget && immediate.parentElement !== dropTarget) {
        immediate = immediate.parentElement;
      }
      if (immediate === documentElement) {
        return null;
      }
      return immediate;
    }

    function getReference(dropTarget, target, x, y) {
      var horizontal = o.direction === 'horizontal';
      var reference = target !== dropTarget ? inside() : outside();
      return reference;

      function outside() { // slower, but able to figure out any position
        var len = dropTarget.children.length;
        var i;
        var el;
        var rect;
        for (i = 0; i < len; i++) {
          el = dropTarget.children[i];
          rect = el.getBoundingClientRect();
          if (horizontal && rect.left > x) {
            return el;
          }
          if (!horizontal && rect.top > y) {
            return el;
          }
        }
        return null;
      }

      function inside() { // faster, but only available if dropped inside a child element
        var rect = target.getBoundingClientRect();
        if (horizontal) {
          return resolve(x > rect.left + rect.width / 2);
        }
        return resolve(y > rect.top + rect.height / 2);
      }

      function resolve(after) {
        return after ? nextEl(target) : target;
      }
    }

    function getScroll(scrollProp, offsetProp) {
      if (typeof window[offsetProp] !== 'undefined') {
        return window[offsetProp];
      }
      if (documentElement.clientHeight) {
        return documentElement[scrollProp];
      }
      return body[scrollProp];
    }

    function getOffset(el) {
      var rect = el.getBoundingClientRect();
      return {
        left: rect.left + getScroll('scrollLeft', 'pageXOffset'),
        top: rect.top + getScroll('scrollTop', 'pageYOffset')
      };
    }

    function getElementBehindPoint(point, x, y) {
      if (!x && !y) {
        return null;
      }
      var p = point || {};
      var state = p.className;
      var el;
      p.className += ' ' + o.classes.hide;
      el = document.elementFromPoint(x, y);
      p.className = state;
      return el;
    }
  };

  function regEvent(el, op, type, fn) {
    el = angular.element(el);
    var touch = {
      mouseup: 'touchend',
      mousedown: 'touchstart',
      mousemove: 'touchmove'
    };
    var microsoft = {
      mouseup: 'MSPointerUp',
      mousedown: 'MSPointerDown',
      mousemove: 'MSPointerMove'
    };
    if (window.navigator.msPointerEnabled) {
      el[op](microsoft[type], fn);
    }
    el[op](touch[type], fn);
    el[op](type, fn);
  }

  function always() {
    return true;
  }

  function nextEl(el) {
    return el.nextElementSibling || manually();

    function manually() {
      var sibling = el;
      do {
        sibling = sibling.nextSibling;
      } while (sibling && sibling.nodeType !== 1);
      return sibling;
    }
  }

  function addClass(el, className) {
    if (el.className.indexOf(' ' + className) === -1) {
      el.className += ' ' + className;
    }
  }

  function rmClass(el, className) {
    el.className = el.className.replace(new RegExp(' ' + className, 'g'), '');
  }

  function getCoord(coord, e) {
    if (typeof e.targetTouches === 'undefined') {
      return e[coord];
    }
    // on touchend event, we have to use `e.changedTouches`
    // see http://stackoverflow.com/questions/7192563/touchend-event-properties
    // see https://github.com/bevacqua/dragula/issues/34
    return (
      (e.targetTouches && e.targetTouches.length && e.targetTouches[0][coord]) ||
      (e.changedTouches && e.changedTouches.length && e.changedTouches[0][coord]) ||
      0
    );
  }

}).directive('dragular', function(dragularService) {
  // Runs during compile
  return {
    // name: '',
    // priority: 1,
    // terminal: true,
    // scope: {}, // {} = isolate, true = child, false/undefined = no change
    // controller: function($scope, $element, $attrs, $transclude) {},
    // require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
    // restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
    // template: '',
    // templateUrl: '',
    // replace: true,
    // transclude: true,
    // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
    link: function($scope, iElm, iAttrs) {
      dragularService(iElm[0], $scope[iAttrs.dragular || 'undefined']);
    }
  };
});
<commit_msg>angular.merge polyfill for angular < 1.4.0<commit_after>/* global angular */
'use strict';

/**
 * dragular Module by Luckylooke https://github.com/luckylooke
 *
 * Angular version of dragula https://github.com/bevacqua/dragula
 */

angular.module('dragularModule', []).factory('dragularService', function dragula() {
  return function(initialContainers, options) {
    var body = document.body,
      documentElement = document.documentElement,
      _mirror, // mirror image
      _source, // source container
      _item, // item being dragged
      _offsetX, // reference x
      _offsetY, // reference y
      _initialSibling, // reference sibling when grabbed
      _currentSibling, // reference sibling now
      _copy, // item used for copying
      _containers = [], // containers managed by the drake
      _containersNameSpaced = {}, // namespaced containers managed by the drakes
      o = { // options
        classes: {
          mirror: 'gu-mirror',
          hide: 'gu-hide',
          unselectable: 'gu-unselectable',
          transit: 'gu-transit'
        },
        moves: always,
        accepts: always,
        copy: false,
        revertOnSpill: false,
        removeOnSpill: false
      };

    if (!angular.merge) {
      angular.merge = (function mergePollyfill() {
        function setHashKey(obj, h) {
          if (h) {
            obj.$$hashKey = h;
          } else {
            delete obj.$$hashKey;
          }
        }

        function baseExtend(dst, objs, deep) {
          var h = dst.$$hashKey;

          for (var i = 0, ii = objs.length; i < ii; ++i) {
            var obj = objs[i];
            if (!angular.isObject(obj) && !angular.isFunction(obj)) continue;
            var keys = Object.keys(obj);
            for (var j = 0, jj = keys.length; j < jj; j++) {
              var key = keys[j];
              var src = obj[key];

              if (deep && angular.isObject(src)) {
                if (isDate(src)) {
                  dst[key] = new Date(src.valueOf());
                } else {
                  if (!angular.isObject(dst[key])) dst[key] = angular.isArray(src) ? [] : {};
                  baseExtend(dst[key], [src], true);
                }
              } else {
                dst[key] = src;
              }
            }
          }

          setHashKey(dst, h);
          return dst;
        }

        return function merge(dst) {
          return baseExtend(dst, [].slice.call(arguments, 1), true);
        }
      })();
    }

    if (options && options.scope) {
      var temp = options.scope;
      options.scope = undefined;
      angular.merge(o, options);
      options.scope = o.scope = temp;
    } else {
      angular.merge(o, options);
    }

    var api = {
      addContainer: manipulateContainers('add'),
      removeContainer: manipulateContainers('remove'),
      start: start,
      end: end,
      cancel: cancel,
      remove: remove,
      destroy: destroy,
      dragging: false
    };

    events();
    api.addContainer(initialContainers);

    return api;

    function manipulateContainers(op) {
      return function addOrRemove(all) {
        var changes = Array.isArray(all) ? all : makeArray(all);
        changes.forEach(track);
        if (op === 'add') {
          _containers = _containers.concat(changes);
        } else {
          _containers = _containers.filter(removals);
        }

        function makeArray(all) {
          if (all.length) {
            var iAll = all.length,
              newArray = [];
            while (iAll) {
              iAll--;
              newArray.push(all[iAll]);
            }
            return newArray;
          } else {
            return [all];
          }
        }

        function track(container) {
          regEvent(container, op === 'add' ? 'on' : 'off', 'mousedown', grab);
        }

        function removals(container) {
          return changes.indexOf(container) === -1;
        }
      };
    }

    function events(rem) {
      var op = rem ? 'off' : 'on';
      regEvent(documentElement, op, 'mouseup', release);
    }

    function destroy() {
      events(true);
      api.removeContainer(_containers);
      release({});
    }

    function grab(e) {
      var item = e.target;

      if ((e.which !== 0 && e.which !== 1) || e.metaKey || e.ctrlKey) {
        return; // we only care about honest-to-god left clicks and touch events
      }
      if (start(item) !== true) {
        return;
      }

      var offset = getOffset(_item);
      _offsetX = getCoord('pageX', e) - offset.left;
      _offsetY = getCoord('pageY', e) - offset.top;
      renderMirrorImage();
      drag(e);
      e.preventDefault();
    }

    function start(item) {
      var handle = item;

      if (api.dragging && _mirror) {
        return false;
      }

      if (_containers.indexOf(item) !== -1) {
        return false; // don't drag container itself
      }
      while (_containers.indexOf(item.parentElement) === -1) {
        if (invalidTarget(item)) {
          return false;
        }
        item = item.parentElement; // drag target should be a top element
      }
      if (invalidTarget(item)) {
        return false;
      }

      var container = item.parentElement;
      var movable = o.moves(item, container, handle);
      if (!movable) {
        return false;
      }

      end();

      if (o.copy) {
        _copy = item.cloneNode(true);
        addClass(_copy, o.classes.transit);
        if (o.scope) {
          o.scope.$emit('cloned', _copy, item);
        }
      } else {
        addClass(item, o.classes.transit);
      }

      _source = container;
      _item = item;
      _initialSibling = _currentSibling = nextEl(item);

      api.dragging = true;
      if (o.scope) {
        o.scope.$emit('drag', _item, _source);
      }

      return true;
    }

    function invalidTarget(el) {
      return el.tagName === 'A' || el.tagName === 'BUTTON';
    }

    function end() {
      if (!api.dragging) {
        return;
      }
      var item = _copy || _item;
      drop(item, item.parentElement);
    }

    function release(e) {
      if (!api.dragging) {
        return;
      }

      var item = _copy || _item;
      var clientX = getCoord('clientX', e);
      var clientY = getCoord('clientY', e);
      var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
      var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
      if (dropTarget && (o.copy === false || dropTarget !== _source)) {
        drop(item, dropTarget);
      } else if (o.removeOnSpill) {
        remove();
      } else {
        cancel();
      }
    }

    function drop(item, target) {
      if (o.scope && isInitialPlacement(target)) {
        o.scope.$emit('cancel', item, _source);
      } else if (o.scope) {
        o.scope.$emit('drop', item, target, _source);
      }
      cleanup();
    }

    function remove() {
      if (!api.dragging) {
        return;
      }
      var item = _copy || _item;
      var parent = item.parentElement;
      if (parent) {
        parent.removeChild(item);
      }
      if (o.scope) {
        o.scope.$emit(o.copy ? 'cancel' : 'remove', item, parent);
      }
      cleanup();
    }

    function cancel(revert) {
      if (!api.dragging) {
        return;
      }
      var reverts = arguments.length > 0 ? revert : o.revertOnSpill;
      var item = _copy || _item;
      var parent = item.parentElement;
      if (parent === _source && o.copy) {
        parent.removeChild(_copy);
      }
      var initial = isInitialPlacement(parent);
      if (initial === false && o.copy === false && reverts) {
        _source.insertBefore(item, _initialSibling);
      }
      if (o.scope && (initial || reverts)) {
        o.scope.$emit('cancel', item, _source);
      } else if (o.scope) {
        o.scope.$emit('drop', item, parent, _source);
      }
      cleanup();
    }

    function cleanup() {
      var item = _copy || _item;
      removeMirrorImage();
      rmClass(item, o.classes.transit);
      _source = _item = _copy = _initialSibling = _currentSibling = null;
      api.dragging = false;
      if (o.scope) {
        o.scope.$emit('dragend', item);
      }
    }

    function isInitialPlacement(target, s) {
      var sibling;
      if (s !== void 0) {
        sibling = s;
      } else if (_mirror) {
        sibling = _currentSibling;
      } else {
        sibling = nextEl(_item || _copy);
      }
      return target === _source && sibling === _initialSibling;
    }

    function findDropTarget(elementBehindCursor, clientX, clientY) {
      var target = elementBehindCursor;
      while (target && !accepted()) {
        target = target.parentElement;
      }
      return target;

      function accepted() {
        var droppable = _containers.indexOf(target) !== -1;
        if (droppable === false) {
          return false;
        }

        var immediate = getImmediateChild(target, elementBehindCursor);
        var reference = getReference(target, immediate, clientX, clientY);
        var initial = isInitialPlacement(target, reference);
        if (initial) {
          return true; // should always be able to drop it right back where it was
        }
        return o.accepts(_item, target, _source, reference);
      }
    }

    function drag(e) {
      if (!_mirror) {
        return;
      }

      var clientX = getCoord('clientX', e);
      var clientY = getCoord('clientY', e);
      var x = clientX - _offsetX;
      var y = clientY - _offsetY;

      _mirror.style.left = x + 'px';
      _mirror.style.top = y + 'px';

      var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
      var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
      if (dropTarget === _source && o.copy) {
        return;
      }
      var reference;
      var item = _copy || _item;
      var immediate = getImmediateChild(dropTarget, elementBehindCursor);
      if (immediate !== null) {
        reference = getReference(dropTarget, immediate, clientX, clientY);
      } else if (o.revertOnSpill === true) {
        reference = _initialSibling;
        dropTarget = _source;
      } else {
        return;
      }
      if (reference === null || reference !== item && reference !== nextEl(item)) {
        _currentSibling = reference;
        dropTarget.insertBefore(item, reference);
        if (o.scope) {
          o.scope.$emit('shadow', item, dropTarget);
        }
      }
    }

    function renderMirrorImage() {
      if (_mirror) {
        return;
      }
      var rect = _item.getBoundingClientRect();
      _mirror = _item.cloneNode(true);
      _mirror.style.width = rect.width + 'px';
      _mirror.style.height = rect.height + 'px';
      rmClass(_mirror, o.classes.transit);
      addClass(_mirror, o.classes.mirror);
      body.appendChild(_mirror);
      regEvent(documentElement, 'on', 'mousemove', drag);
      addClass(body, o.classes.unselectable);
      if (o.scope) {
        o.scope.$emit('cloned', _mirror, _item);
      }
    }

    function removeMirrorImage() {
      if (_mirror) {
        rmClass(body, o.classes.unselectable);
        regEvent(documentElement, 'off', 'mousemove', drag);
        _mirror.parentElement.removeChild(_mirror);
        _mirror = null;
      }
    }

    function getImmediateChild(dropTarget, target) {
      var immediate = target;
      while (immediate !== dropTarget && immediate.parentElement !== dropTarget) {
        immediate = immediate.parentElement;
      }
      if (immediate === documentElement) {
        return null;
      }
      return immediate;
    }

    function getReference(dropTarget, target, x, y) {
      var horizontal = o.direction === 'horizontal';
      var reference = target !== dropTarget ? inside() : outside();
      return reference;

      function outside() { // slower, but able to figure out any position
        var len = dropTarget.children.length;
        var i;
        var el;
        var rect;
        for (i = 0; i < len; i++) {
          el = dropTarget.children[i];
          rect = el.getBoundingClientRect();
          if (horizontal && rect.left > x) {
            return el;
          }
          if (!horizontal && rect.top > y) {
            return el;
          }
        }
        return null;
      }

      function inside() { // faster, but only available if dropped inside a child element
        var rect = target.getBoundingClientRect();
        if (horizontal) {
          return resolve(x > rect.left + rect.width / 2);
        }
        return resolve(y > rect.top + rect.height / 2);
      }

      function resolve(after) {
        return after ? nextEl(target) : target;
      }
    }

    function getScroll(scrollProp, offsetProp) {
      if (typeof window[offsetProp] !== 'undefined') {
        return window[offsetProp];
      }
      if (documentElement.clientHeight) {
        return documentElement[scrollProp];
      }
      return body[scrollProp];
    }

    function getOffset(el) {
      var rect = el.getBoundingClientRect();
      return {
        left: rect.left + getScroll('scrollLeft', 'pageXOffset'),
        top: rect.top + getScroll('scrollTop', 'pageYOffset')
      };
    }

    function getElementBehindPoint(point, x, y) {
      if (!x && !y) {
        return null;
      }
      var p = point || {};
      var state = p.className;
      var el;
      p.className += ' ' + o.classes.hide;
      el = document.elementFromPoint(x, y);
      p.className = state;
      return el;
    }
  };

  function regEvent(el, op, type, fn) {
    el = angular.element(el);
    var touch = {
      mouseup: 'touchend',
      mousedown: 'touchstart',
      mousemove: 'touchmove'
    };
    var microsoft = {
      mouseup: 'MSPointerUp',
      mousedown: 'MSPointerDown',
      mousemove: 'MSPointerMove'
    };
    if (window.navigator.msPointerEnabled) {
      el[op](microsoft[type], fn);
    }
    el[op](touch[type], fn);
    el[op](type, fn);
  }

  function always() {
    return true;
  }

  function nextEl(el) {
    return el.nextElementSibling || manually();

    function manually() {
      var sibling = el;
      do {
        sibling = sibling.nextSibling;
      } while (sibling && sibling.nodeType !== 1);
      return sibling;
    }
  }

  function addClass(el, className) {
    if (el.className.indexOf(' ' + className) === -1) {
      el.className += ' ' + className;
    }
  }

  function rmClass(el, className) {
    el.className = el.className.replace(new RegExp(' ' + className, 'g'), '');
  }

  function getCoord(coord, e) {
    if (typeof e.targetTouches === 'undefined') {
      return e[coord];
    }
    // on touchend event, we have to use `e.changedTouches`
    // see http://stackoverflow.com/questions/7192563/touchend-event-properties
    // see https://github.com/bevacqua/dragula/issues/34
    return (
      (e.targetTouches && e.targetTouches.length && e.targetTouches[0][coord]) ||
      (e.changedTouches && e.changedTouches.length && e.changedTouches[0][coord]) ||
      0
    );
  }

}).directive('dragular', function(dragularService) {
  // Runs during compile
  return {
    // name: '',
    // priority: 1,
    // terminal: true,
    // scope: {}, // {} = isolate, true = child, false/undefined = no change
    // controller: function($scope, $element, $attrs, $transclude) {},
    // require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
    // restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
    // template: '',
    // templateUrl: '',
    // replace: true,
    // transclude: true,
    // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
    link: function($scope, iElm, iAttrs) {
      dragularService(iElm[0], $scope[iAttrs.dragular || 'undefined']);
    }
  };
});
<|endoftext|>


<commit_before>/**
 * @fileOverview The "token" plugin.
 *
 */

'use strict';

( function() {
	CKEDITOR.plugins.add( 'token', {
		requires: 'widget,dialog',
		lang: 'af,ar,bg,ca,cs,cy,da,de,el,en,en-gb,eo,es,et,eu,fa,fi,fr,fr-ca,gl,he,hr,hu,id,it,ja,km,ko,ku,lv,nb,nl,no,pl,pt,pt-br,ru,si,sk,sl,sq,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
		icons: 'token', // %REMOVE_LINE_CORE%
		hidpi: true, // %REMOVE_LINE_CORE%

		onLoad: function() {
			// Register styles for token widget frame.
			CKEDITOR.addCss( '.cke_token{background-color:#ff0}' );
		},

		init: function( editor ) {

			var lang = editor.lang.token;

			// Register dialog.
			CKEDITOR.dialog.add( 'token', this.path + 'dialogs/token.js' );

			// Put ur init code here.
			editor.widgets.add( 'token', {
				// Widget code.
				dialog: 'token',
				pathName: lang.pathName,
				// We need to have wrapping element, otherwise there are issues in
				// add dialog.
				template: '${}',

				downcast: function() {
					return new CKEDITOR.htmlParser.text( '${' + this.data.name + '}' );
				},

				init: function() {
					// Note that token markup characters are stripped for the name.
					this.setData( 'name', this.element.getText().slice( 2, -1 ) );
				},

				data: function() {
					this.element.setText( '${' + this.data.name + '}' );
				}
			} );

			editor.ui.addButton && editor.ui.addButton( 'CreateToken', {
				label: lang.toolbar,
				command: 'token',
				toolbar: 'insert,5',
				icon: 'token'
			} );
		},

		afterInit: function( editor ) {
			var tokenReplaceRegex = /\$\{([^\$\{\}])+\}/g;

			editor.dataProcessor.dataFilter.addRules( {
				text: function( text, node ) {
					var dtd = node.parent && CKEDITOR.dtd[ node.parent.name ];

					// Skip the case when token is in elements like <title> or <textarea>
					// but upcast token in custom elements (no DTD).
					if ( dtd && !dtd.span )
						return;

					return text.replace( tokenReplaceRegex, function( match ) {
						// Creating widget code.
						var widgetWrapper = null,
							innerElement = new CKEDITOR.htmlParser.element( 'span', {
								'class': 'cke_token'
							} );

						// Adds token identifier as innertext.
						innerElement.add( new CKEDITOR.htmlParser.text( match ) );
						widgetWrapper = editor.widgets.wrapElement( innerElement, 'token' );

						// Return outerhtml of widget wrapper so it will be placed
						// as replacement.
						return widgetWrapper.getOuterHtml();
					} );
				}
			} );
		}
	} );

} )();
<commit_msg>Made the token plugin more generic so it can be used for other types of tokens.<commit_after>/**
 * @fileOverview The "token" plugin.
 *
 */

'use strict';

function escapeRegExp(string){
    return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

( function() {
	CKEDITOR.plugins.add( 'token', {
		requires: 'widget,dialog',
		lang: 'en',
		icons: 'token',
		hidpi: true,

		onLoad: function() {
			// Register styles for token widget frame.
			CKEDITOR.addCss( '.cke_token{background-color:#ff0}' );
		},

		init: function( editor ) {

			var lang = editor.lang.token;
			var tokenStart = '${';
            var tokenEnd = '}';
            if (typeof editor.config.tokenStart != 'undefined') {
                tokenStart = editor.config.tokenStart;
            }
            if (typeof editor.config.tokenEnd != 'undefined') {
                tokenEnd = editor.config.tokenEnd;
            }
            var tokenStartNum = tokenStart.length;
            var tokenEndNum = 0 - tokenEnd.length;

			// Register dialog.
			CKEDITOR.dialog.add( 'token', this.path + 'dialogs/token.js' );

			// Put ur init code here.
			editor.widgets.add( 'token', {
				// Widget code.
				dialog: 'token',
				pathName: lang.pathName,
				// We need to have wrapping element, otherwise there are issues in
				// add dialog.
				template: '' + tokenStart + tokenEnd + '',

				downcast: function() {
					return new CKEDITOR.htmlParser.text( tokenStart + this.data.name + tokenEnd );
				},

				init: function() {
					// Note that token markup characters are stripped for the name.
					this.setData( 'name', this.element.getText().slice( tokenStartNum, tokenEndNum ) );
				},

				data: function() {
					this.element.setText( tokenStart + this.data.name + tokenEnd );
				}
			} );

			editor.ui.addButton && editor.ui.addButton( 'CreateToken', {
				label: lang.toolbar,
				command: 'token',
				toolbar: 'insert,5',
				icon: 'token'
			} );
		},

		afterInit: function( editor ) {

            var tokenStart = '${';
            var tokenEnd = '}';
            if (typeof editor.config.tokenStart != 'undefined') {
                tokenStart = editor.config.tokenStart;
            }
            if (typeof editor.config.tokenEnd != 'undefined') {
                tokenEnd = editor.config.tokenEnd;
            }
            var tokenStartRegex = escapeRegExp(tokenStart);
            var tokenEndRegex = escapeRegExp(tokenEnd);
			var tokenReplaceRegex = new RegExp(tokenStartRegex + '([^' + tokenStartRegex + tokenEndRegex +'])+' + tokenEndRegex, 'g');

			editor.dataProcessor.dataFilter.addRules( {
				text: function( text, node ) {
					var dtd = node.parent && CKEDITOR.dtd[ node.parent.name ];

					// Skip the case when token is in elements like <title> or <textarea>
					// but upcast token in custom elements (no DTD).
					if ( dtd && !dtd.span )
						return;

					return text.replace( tokenReplaceRegex, function( match ) {
						// Creating widget code.
						var widgetWrapper = null,
							innerElement = new CKEDITOR.htmlParser.element( 'span', {
								'class': 'cke_token'
							} );

						// Adds token identifier as innertext.
						innerElement.add( new CKEDITOR.htmlParser.text( match ) );
						widgetWrapper = editor.widgets.wrapElement( innerElement, 'token' );

						// Return outerhtml of widget wrapper so it will be placed
						// as replacement.
						return widgetWrapper.getOuterHtml();
					} );
				}
			} );
		}
	} );

} )();
<|endoftext|>