<commit_before>describe('haproxy:orchestrator', function () {
  'use strict';

  var request = require('request')
    , HAProxy = require('../')
    , chai = require('chai')
    , expect = chai.expect;

  //
  // The location of the fixtures directory.
  //
  var path = require('path')
    , pidFile = path.resolve(__dirname, 'haproxy.pid')
    , fixtures = path.resolve(__dirname, 'fixtures')
    , orchestrator = fixtures + '/orchestrator.cfg'
    , sock = '/tmp/haproxy.sock'
    , timeout = 5000
    , servers;

  chai.Assertion.includeStack = true;

  //
  // Make sure that every process is dead before we start so we don't get random
  // failures because we still have a haproxy running locally for testing
  // purposes.
  //
  // In addition to that
  //
  before(function (done) {
    var haproxy = new HAProxy();

    //
    // Attempt to clean up all established HAProxies that are started
    //
    haproxy.stop(true, function () {
      var online = 0;

      servers = [8083, 8084].reduce(function (set, port) {
        var app = require('http').createServer(function (req, res) {
          res.statusCode = 200;
          res.setHeader('Content-Type', 'text/html');

          var interval = setInterval(function () {
            res.write('server\n');
          }, 100);

          setTimeout(function () {
            clearInterval(interval);
            res.end('Hello from port: '+port);
          }, timeout);
        });

        set['srv'+ port] = app;

        app.listen(port, function () {
          if (++online === 2) done();
        });

        return set;
      }, {});
    });
  });

  //
  // As we generated HTTP servers, we need to close them again.
  //
  after(function () {
    Object.keys(servers).forEach(function close(id) {
      servers[id].close();
    });
  });

  it('prefixes the haproxy command', function () {
    var haproxy = new HAProxy(sock, {
        config: orchestrator
      , pidFile: pidFile
      , prefix: 'sudo'
    });

    expect(haproxy.orchestrator.which).to.contain('sudo /');
    expect(haproxy.orchestrator.which).to.contain('haproxy');
  });

  describe('#running', function () {
    it('should check if the current process is still running', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.running(function (err, running) {
        if (err) return done(err);

        expect(running).to.equal(false);

        haproxy.start(function (err) {
          if (err) return done(err);

          haproxy.running(function (err, running) {

            if (err) return done(err);

            expect(running).to.equal(true);
            haproxy.stop(done);
          });
        });
      });
    });

    it('should autodetect proxies if none was started by the process', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err) {
        if (err) return done(err);

        var proxy = new HAProxy(sock, {
          config: orchestrator
        });

        proxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(true);
          haproxy.stop(done);
        });
      });
    });
  });

  describe('#start', function () {
    it('should set a pidfile if none exists', function (done) {
      var haproxy = new HAProxy(sock, {
        config: orchestrator
      });

      expect(haproxy.orchestrator.pidFile).to.equal('');
      haproxy.start(function (err) {
        // Technically this is throwing an error, since the pidfile cannot be
        // generated without sudo-rights, however we just ignore it for now.
        expect(haproxy.orchestrator.pidFile).to.equal('/var/run/haproxy.pid');

        done();
      });
    });

    it('should verify the given configuration', function (done) {
      var haproxy = new HAProxy(sock, {
          config: fixtures +'/broken.cfg'
        , pidFile: pidFile
      });

      haproxy.start(function starting(err) {
        expect(err).to.be.instanceof(Error);
        done();
      });
    });

    it('should run the application demonized', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err, res, cmd) {
        expect(cmd).to.include('haproxy');
        expect(cmd).to.include('-D');

        done(err);
      });
    });

    it('should store the new pid', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      expect(haproxy.orchestrator.pid).to.equal('');

      haproxy.start(function (err) {
        expect(haproxy.orchestrator.pid).to.not.equal('');
        done(err);
      });
    });
  });

  describe('#stop', function () {
    it('should stop all the running processes', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      var another = new HAProxy('/tmp/another.sock', {
          config: fixtures +'/another.cfg'
        , pidFile: '/tmp/another.pid'
      });

      //
      // start both servers, ensure they are both running, killall ensure that
      // they are all not running.
      //
      function running(value, fn) {
        haproxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(value);
          another.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(value);
            fn();
          });
        });
      }

      function stop(fn) {
        haproxy.stop(true, function (err) {
          if (err) return done(err);

          running(false, fn);
        });
      }

      haproxy.start(function (err) {
        if (err) return done(err);

        another.start(function (err) {
          if (err) return done(err);

          running(true, stop.bind(undefined, done));
        });
      });
    });

    it('should only stop the current running process', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      var another = new HAProxy('/tmp/another.sock', {
          config: fixtures +'/another.cfg'
        , pidFile: '/tmp/another.pid'
      });

      //
      // start both servers, ensure they are both running, killall ensure that
      // they are all not running.
      //
      function running(value, fn) {
        haproxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(value);
          another.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(value);
            fn();
          });
        });
      }

      function stop(fn) {
        haproxy.stop(function (err) {
          if (err) return done(err);

          haproxy.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(false);

            another.running(function (err, running) {
              if (err) return done(err);

              expect(running).to.equal(true);
              another.stop(fn);
            });
          });
        });
      }

      haproxy.start(function (err) {
        if (err) return done(err);

        another.start(function (err) {
          if (err) return done(err);

          running(true, stop.bind(undefined, done));
        });
      });
    });
  });

  describe('#softstop', function () {
    this.timeout(timeout + 500);

    it('killing me softly (with his song)', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res, body) {
          if (err) return done(err);

          expect(body).to.include('server');
          expect(body).to.include('ello from port');

          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.softstop(function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.above(timeout);
            expect(haproxy.orchestrator.pid).to.equal('');
            finish();
          });
        }, 100);
      });
    });
  });

  describe('#reload', function (done) {
    this.timeout(timeout + 500);

    it('should gracefully reload the server', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res, body) {
          if (err) return done(err);

          expect(body).to.include('server');
          expect(body).to.include('ello from port');

          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.reload(function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.below(timeout);
            finish();
          });
        }, 100);
      });
    });

    it('should reload the server instantly', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res) {
          if (err) expect(err.message).to.include('hang up');
          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.reload(true, function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.below(timeout);
            finish();
          });
        }, 100);
      });
    });

    it('set a new pid', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err) {
        if (err) return done(err);

        var pid = haproxy.orchestrator.pid;

        haproxy.reload(function (err) {
          if (err) return done(err);

          expect(haproxy.orchestrator.pid).to.not.equal(pid);
          haproxy.stop(done);
        });
      });
    });
  });

  describe('#verify', function () {
    it('should verify the correctness of the configuration', function (done) {
      var broken = new HAProxy(sock, {
        config: orchestrator
      });

      broken.verify(function (err, okay) {
        expect(okay).to.equal(true);
        done(err);
      });
    });

    it('should verify the broken configuration', function (done) {
      var broken = new HAProxy(sock, {
        config: fixtures +'/broken.cfg'
      });

      broken.verify(function (err, okay) {
        expect(okay).to.equal(false);
        done(err);
      });
    });
  });

  afterEach(function (done) {
    var haproxy = new HAProxy();

    //
    // Attempt to clean up all established HAProxies that are started
    //
    haproxy.stop(true, function () {
      done();
    });
  });
});
<commit_msg>Prepare tests for prefix changes<commit_after>describe('haproxy:orchestrator', function () {
  'use strict';

  var request = require('request')
    , HAProxy = require('../')
    , chai = require('chai')
    , expect = chai.expect;

  //
  // The location of the fixtures directory.
  //
  var path = require('path')
    , pidFile = path.resolve(__dirname, 'haproxy.pid')
    , fixtures = path.resolve(__dirname, 'fixtures')
    , orchestrator = fixtures + '/orchestrator.cfg'
    , sock = '/tmp/haproxy.sock'
    , timeout = 5000
    , servers;

  chai.Assertion.includeStack = true;

  //
  // Make sure that every process is dead before we start so we don't get random
  // failures because we still have a haproxy running locally for testing
  // purposes.
  //
  // In addition to that
  //
  before(function (done) {
    var haproxy = new HAProxy();

    //
    // Attempt to clean up all established HAProxies that are started
    //
    haproxy.stop(true, function () {
      var online = 0;

      servers = [8083, 8084].reduce(function (set, port) {
        var app = require('http').createServer(function (req, res) {
          res.statusCode = 200;
          res.setHeader('Content-Type', 'text/html');

          var interval = setInterval(function () {
            res.write('server\n');
          }, 100);

          setTimeout(function () {
            clearInterval(interval);
            res.end('Hello from port: '+port);
          }, timeout);
        });

        set['srv'+ port] = app;

        app.listen(port, function () {
          if (++online === 2) done();
        });

        return set;
      }, {});
    });
  });

  //
  // As we generated HTTP servers, we need to close them again.
  //
  after(function () {
    Object.keys(servers).forEach(function close(id) {
      servers[id].close();
    });
  });

  it('prefixes the haproxy command', function () {
    var haproxy = new HAProxy(sock, {
        config: orchestrator
      , pidFile: pidFile
      , prefix: 'sudo'
    });

    expect(haproxy.orchestrator.prefix).to.equal('sudo');
    expect(haproxy.orchestrator.which).to.contain('haproxy');
  });

  describe('#running', function () {
    it('should check if the current process is still running', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.running(function (err, running) {
        if (err) return done(err);

        expect(running).to.equal(false);

        haproxy.start(function (err) {
          if (err) return done(err);

          haproxy.running(function (err, running) {

            if (err) return done(err);

            expect(running).to.equal(true);
            haproxy.stop(done);
          });
        });
      });
    });

    it('should autodetect proxies if none was started by the process', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err) {
        if (err) return done(err);

        var proxy = new HAProxy(sock, {
          config: orchestrator
        });

        proxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(true);
          haproxy.stop(done);
        });
      });
    });
  });

  describe('#start', function () {
    it('should set a pidfile if none exists', function (done) {
      var haproxy = new HAProxy(sock, {
        config: orchestrator
      });

      expect(haproxy.orchestrator.pidFile).to.equal('');
      haproxy.start(function (err) {
        // Technically this is throwing an error, since the pidfile cannot be
        // generated without sudo-rights, however we just ignore it for now.
        expect(haproxy.orchestrator.pidFile).to.equal('/var/run/haproxy.pid');

        done();
      });
    });

    it('should verify the given configuration', function (done) {
      var haproxy = new HAProxy(sock, {
          config: fixtures +'/broken.cfg'
        , pidFile: pidFile
      });

      haproxy.start(function starting(err) {
        expect(err).to.be.instanceof(Error);
        done();
      });
    });

    it('should run the application demonized', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err, res, cmd) {
        expect(cmd).to.include('haproxy');
        expect(cmd).to.include('-D');

        done(err);
      });
    });

    it('should store the new pid', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      expect(haproxy.orchestrator.pid).to.equal('');

      haproxy.start(function (err) {
        expect(haproxy.orchestrator.pid).to.not.equal('');
        done(err);
      });
    });
  });

  describe('#stop', function () {
    it('should stop all the running processes', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      var another = new HAProxy('/tmp/another.sock', {
          config: fixtures +'/another.cfg'
        , pidFile: '/tmp/another.pid'
      });

      //
      // start both servers, ensure they are both running, killall ensure that
      // they are all not running.
      //
      function running(value, fn) {
        haproxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(value);
          another.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(value);
            fn();
          });
        });
      }

      function stop(fn) {
        haproxy.stop(true, function (err) {
          if (err) return done(err);

          running(false, fn);
        });
      }

      haproxy.start(function (err) {
        if (err) return done(err);

        another.start(function (err) {
          if (err) return done(err);

          running(true, stop.bind(undefined, done));
        });
      });
    });

    it('should only stop the current running process', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      var another = new HAProxy('/tmp/another.sock', {
          config: fixtures +'/another.cfg'
        , pidFile: '/tmp/another.pid'
      });

      //
      // start both servers, ensure they are both running, killall ensure that
      // they are all not running.
      //
      function running(value, fn) {
        haproxy.running(function (err, running) {
          if (err) return done(err);

          expect(running).to.equal(value);
          another.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(value);
            fn();
          });
        });
      }

      function stop(fn) {
        haproxy.stop(function (err) {
          if (err) return done(err);

          haproxy.running(function (err, running) {
            if (err) return done(err);

            expect(running).to.equal(false);

            another.running(function (err, running) {
              if (err) return done(err);

              expect(running).to.equal(true);
              another.stop(fn);
            });
          });
        });
      }

      haproxy.start(function (err) {
        if (err) return done(err);

        another.start(function (err) {
          if (err) return done(err);

          running(true, stop.bind(undefined, done));
        });
      });
    });
  });

  describe('#softstop', function () {
    this.timeout(timeout + 500);

    it('killing me softly (with his song)', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res, body) {
          if (err) return done(err);

          expect(body).to.include('server');
          expect(body).to.include('ello from port');

          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.softstop(function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.above(timeout);
            expect(haproxy.orchestrator.pid).to.equal('');
            finish();
          });
        }, 100);
      });
    });
  });

  describe('#reload', function (done) {
    this.timeout(timeout + 500);

    it('should gracefully reload the server', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res, body) {
          if (err) return done(err);

          expect(body).to.include('server');
          expect(body).to.include('ello from port');

          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.reload(function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.below(timeout);
            finish();
          });
        }, 100);
      });
    });

    it('should reload the server instantly', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      function finish() {
        if (++finish.done === 2) done();
      }
      finish.done = 0;

      //
      // The request will take at least 5 seconds to complete
      //
      haproxy.start(function (err) {
        if (err) return done(err);

        request('http://localhost:8080/foo/', function (err, res) {
          if (err) expect(err.message).to.include('hang up');
          finish();
        });

        var start = Date.now();
        setTimeout(function () {
          haproxy.reload(true, function (err) {
            if (err) return done(err);

            expect(Date.now() - start).to.be.below(timeout);
            finish();
          });
        }, 100);
      });
    });

    it('set a new pid', function (done) {
      var haproxy = new HAProxy(sock, {
          config: orchestrator
        , pidFile: pidFile
      });

      haproxy.start(function (err) {
        if (err) return done(err);

        var pid = haproxy.orchestrator.pid;

        haproxy.reload(function (err) {
          if (err) return done(err);

          expect(haproxy.orchestrator.pid).to.not.equal(pid);
          haproxy.stop(done);
        });
      });
    });
  });

  describe('#verify', function () {
    it('should verify the correctness of the configuration', function (done) {
      var broken = new HAProxy(sock, {
        config: orchestrator
      });

      broken.verify(function (err, okay) {
        expect(okay).to.equal(true);
        done(err);
      });
    });

    it('should verify the broken configuration', function (done) {
      var broken = new HAProxy(sock, {
        config: fixtures +'/broken.cfg'
      });

      broken.verify(function (err, okay) {
        expect(okay).to.equal(false);
        done(err);
      });
    });
  });

  afterEach(function (done) {
    var haproxy = new HAProxy();

    //
    // Attempt to clean up all established HAProxies that are started
    //
    haproxy.stop(true, function () {
      done();
    });
  });
});
<|endoftext|>


<commit_before>const Nomad = require('nomad-stream')
const moment = require('moment')

const credentials = require('./twilio-login.js')
const phoneNumbers = require('./phone-numbers.js')

const nomad = new Nomad()

//require the Twilio module and create a REST client
const client = require('twilio')(credentials.accountSid, credentials.authToken)

// device atomic node ids
const subscriptions = ['QmW9dVfYoGdXDdhyQqh6W5M5mAUbfhTpunwoHMjXfj2J6Z', 'QmafDr5bkK8SeSfTQnCG7e79zNSpCLQq2wteZ6fAvd8V7K']

let instance
let lastPub
let notificationBody
let lastStatus1 = false
let lastStatus2 = false
let timeCharging1
let timeCharging2

const frequency =  2 * 60 * 1000 // 2 minutes
const timeThreshold = 4 * 60 * 60 * 1000 // 4 hours
const toNumber = phoneNumbers.toNumber
const fromNumber = phoneNumbers.fromNumber

const defaultPublishData = {
  [subscriptions[0]]: {
    charging_station: {
      data: '',
      time: '',
      description: '',
      price: 5
    }
  },
  [subscriptions[1]]: {
    charging_station: {
      data: '',
      time: '',
      description: '',
      price: 4
    }
  }
}

// How we manager the data
class DataMaintainer {
  constructor(){
    this.data = defaultPublishData
  }
  setValue(id, key, value){
    let cleanedKey = this.cleanKey(key)
    if(cleanedKey in this.data[id]){
      this.data[id][cleanedKey].data = value.data
      this.data[id][cleanedKey].time = value.time
      this.data[id][cleanedKey].description = value.description
    } else {
      this.data[id][cleanedKey] = value
    }
  }
  cleanKey(key){
    let cleanedKey = key.replace(/\s+/, '\x01').split('\x01')[0]
    cleanedKey = cleanedKey.toLowerCase()
    return cleanedKey
  }
  getAll(){
    return this.data
  }
  isAllFilled(){
    return this.data[subscriptions[0]]['charging_station']["data"] && this.data[subscriptions[0]]['charging_station']["time"] && this.data[subscriptions[1]]['charging_station']["data"] && this.data[subscriptions[1]]['charging_station']["time"]
  }
  clear(){
    this.data = defaultPublishData
  }
  toString(){
    return JSON.stringify(this.data)
  }
}

function getTime() {
  return new moment()
}

//init data manager
let dataManager = new DataMaintainer()

nomad.prepareToPublish()
  .then((n) => {
    instance = n
    return instance.publishRoot('Starting up EV charging station composite')
  })
  .then(() => {
    lastPub = getTime()
    nomad.subscribe(subscriptions, function(message) {
      console.log("Receieved a message for node " + message.id)
      console.log("Message was " + message.message)
      let messageData = JSON.parse(message.message)
      try{
        dataManager.setValue(message.id, Object.keys(messageData)[0],{data: messageData[Object.keys(messageData)[0]].data, time: messageData[Object.keys(messageData)[0]].time, description: messageData[Object.keys(messageData)[0]].description})
      }
      catch(err){
        console.log("DataMaintainer failed with error of " + err)
      }
      console.log(dataManager.toString())
      let currentTime = getTime()
      let timeSince = currentTime - lastPub
      let currentRecord = dataManager.getAll()
      let sensorOneData = currentRecord[Object.keys(currentRecord)[0]]['charging_station']["data"]
      let sensorTwoData = currentRecord[Object.keys(currentRecord)[1]]['charging_station']["data"]
      // if now occupied in lot 1 start timing
      if ((sensorOneData == "occupied" && sensorOneData != lastStatus1)){
        timeCharging1 = getTime()
        console.log("set time 1" + timeCharging1)
      }
      // if now occupied in lot 2 start timing
      if ((sensorTwoData == "occupied" && sensorTwoData != lastStatus2 )){
        timeCharging2 = getTime()
          console.log("set time 2"+ timeCharging2)
      }
      if (timeSince >= frequency){
        console.log('===================================> timeSince >= timeBetween')

        try{
          let timeSinceCharging1 = currentTime - timeCharging1
          let timeSinceCharging2 = currentTime - timeCharging2
          dataManager.data[subscriptions[0]]['charging_station'].timeCharging = (timeSinceCharging1/60000) + " minutes"
          dataManager.data[subscriptions[1]]['charging_station'].timeCharging = (timeSinceCharging2/60000) + " minutes"
          console.log("time 2 " + timeSinceCharging2)
          console.log("time 1 " + timeSinceCharging1)
        }
        catch(err){
          console.log("charging time failed with error of " + err)
        }
        if ((sensorOneData == "unoccupied" && sensorOneData != lastStatus1) || (sensorTwoData == "unoccupied" && sensorTwoData != lastStatus2 )){
          console.log("***************************************************************************************")
          console.log(`we are now going to notify relevant parties since there is an unoccupied `)
          console.log("***************************************************************************************")

          if(sensorOneData == "unoccupied" && sensorTwoData == "unoccupied"){
            delete dataManager.data[subscriptions[0]]['charging_station'].timeCharging
            delete dataManager.data[subscriptions[1]]['charging_station'].timeCharging
            notificationBody = `EV Charger 1 and 2 are unoccupied. Prices are ${currentRecord[Object.keys(currentRecord)[0]]['charging_station']["price"]} and ${currentRecord[Object.keys(currentRecord)[1]]['charging_station']["price"]} respectively`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })
          } else if (sensorOneData == "unoccupied"){
            delete dataManager.data[subscriptions[0]]['charging_station'].timeCharging
            notificationBody = `EV Charger 1 is unoccupied and the price is ${currentRecord[Object.keys(currentRecord)[0]]['charging_station']["price"]}`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })

          } else if (sensorTwoData == "unoccupied"){
            delete dataManager.data[subscriptions[1]]['charging_station'].timeCharging
            notificationBody = `EV Charger 2 is unoccupied and the price is ${currentRecord[Object.keys(currentRecord)[1]]['charging_station']["price"]}`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })
          }

          console.log(dataManager.toString())
          instance.publish(dataManager.toString())
            .catch(err => console.log(`Error in publishing timeSince>=timeBetween positive state: ${JSON.stringify(err)}`))
          dataManager.clear()
          lastPub = currentTime
        } else if (dataManager.isAllFilled()) {
          instance.publish(dataManager.toString())
            .catch(err => console.log(`Error in publishing timeSince>=timeBetween negative state: ${JSON.stringify(err)}`))
        }
      }
      lastStatus1 = sensorOneData
      lastStatus2 = sensorTwoData
      if (timeSince >= timeThreshold){
        // let them know the node is still online
       console.log("===================================>   timeSince >= timeThreshold")
        console.log("***************************************************************************************")
        console.log('Heartbeat, I am alive but have not got data in a long time')
        console.log("***************************************************************************************")
        messageBody = 'Heartbeat, I am alive but have not got data in a long time'
        client.messages.create({
          to: toNumber,
          from: fromNumber,
          body: messageBody,
        }, function (err, message) {
          console.log(err)
          console.log(message)
        })
        instance.publish('Heartbeat, I am alive but have not got data in a long time')
          .catch(err => console.log(`Error in publishing timeSince>=timeBetween: ${JSON.stringify(err)}`))
        dataManager.clear()
        lastPub = currentTime
      }
    })
  })
  .catch(err => console.log(`Error in main loop: ${JSON.stringify(err)}`))<commit_msg>deletion<commit_after>const Nomad = require('nomad-stream')
const moment = require('moment')

const credentials = require('./twilio-login.js')
const phoneNumbers = require('./phone-numbers.js')

const nomad = new Nomad()

//require the Twilio module and create a REST client
const client = require('twilio')(credentials.accountSid, credentials.authToken)

// device atomic node ids
const subscriptions = ['QmW9dVfYoGdXDdhyQqh6W5M5mAUbfhTpunwoHMjXfj2J6Z', 'QmafDr5bkK8SeSfTQnCG7e79zNSpCLQq2wteZ6fAvd8V7K']

let instance
let lastPub
let notificationBody
let lastStatus1 = false
let lastStatus2 = false
let timeCharging1
let timeCharging2

const frequency =  2 * 60 * 1000 // 2 minutes
const timeThreshold = 4 * 60 * 60 * 1000 // 4 hours
const toNumber = phoneNumbers.toNumber
const fromNumber = phoneNumbers.fromNumber

const defaultPublishData = {
  [subscriptions[0]]: {
    charging_station: {
      data: '',
      time: '',
      description: '',
      price: 5
    }
  },
  [subscriptions[1]]: {
    charging_station: {
      data: '',
      time: '',
      description: '',
      price: 4
    }
  }
}

// How we manager the data
class DataMaintainer {
  constructor(){
    this.data = defaultPublishData
  }
  setValue(id, key, value){
    let cleanedKey = this.cleanKey(key)
    if(cleanedKey in this.data[id]){
      this.data[id][cleanedKey].data = value.data
      this.data[id][cleanedKey].time = value.time
      this.data[id][cleanedKey].description = value.description
    } else {
      this.data[id][cleanedKey] = value
    }
  }
  cleanKey(key){
    let cleanedKey = key.replace(/\s+/, '\x01').split('\x01')[0]
    cleanedKey = cleanedKey.toLowerCase()
    return cleanedKey
  }
  getAll(){
    return this.data
  }
  isAllFilled(){
    return this.data[subscriptions[0]]['charging_station']["data"] && this.data[subscriptions[0]]['charging_station']["time"] && this.data[subscriptions[1]]['charging_station']["data"] && this.data[subscriptions[1]]['charging_station']["time"]
  }
  clear(){
    this.data = defaultPublishData
  }
  toString(){
    return JSON.stringify(this.data)
  }
}

function getTime() {
  return new moment()
}

//init data manager
let dataManager = new DataMaintainer()

nomad.prepareToPublish()
  .then((n) => {
    instance = n
    return instance.publishRoot('Starting up EV charging station composite')
  })
  .then(() => {
    lastPub = getTime()
    nomad.subscribe(subscriptions, function(message) {
      console.log("Receieved a message for node " + message.id)
      console.log("Message was " + message.message)
      let messageData = JSON.parse(message.message)
      try{
        dataManager.setValue(message.id, Object.keys(messageData)[0],{data: messageData[Object.keys(messageData)[0]].data, time: messageData[Object.keys(messageData)[0]].time, description: messageData[Object.keys(messageData)[0]].description})
      }
      catch(err){
        console.log("DataMaintainer failed with error of " + err)
      }
      console.log(dataManager.toString())
      let currentTime = getTime()
      let timeSince = currentTime - lastPub
      let currentRecord = dataManager.getAll()
      let sensorOneData = currentRecord[Object.keys(currentRecord)[0]]['charging_station']["data"]
      let sensorTwoData = currentRecord[Object.keys(currentRecord)[1]]['charging_station']["data"]
      // if now occupied in lot 1 start timing
      if ((sensorOneData == "occupied" && sensorOneData != lastStatus1)){
        timeCharging1 = getTime()
        console.log("set time 1" + timeCharging1)
      }
      // if now occupied in lot 2 start timing
      if ((sensorTwoData == "occupied" && sensorTwoData != lastStatus2 )){
        timeCharging2 = getTime()
          console.log("set time 2"+ timeCharging2)
      }
      if (timeSince >= frequency){
        console.log('===================================> timeSince >= timeBetween')

        try{
          let timeSinceCharging1 = currentTime - timeCharging1
          let timeSinceCharging2 = currentTime - timeCharging2
          dataManager.data[subscriptions[0]]['charging_station'].timeCharging = (timeSinceCharging1/60000) + " minutes"
          dataManager.data[subscriptions[1]]['charging_station'].timeCharging = (timeSinceCharging2/60000) + " minutes"
          console.log("time 2 " + timeSinceCharging2)
          console.log("time 1 " + timeSinceCharging1)
        }
        catch(err){
          console.log("charging time failed with error of " + err)
        }
        if ((sensorOneData == "unoccupied" && sensorOneData != lastStatus1) || (sensorTwoData == "unoccupied" && sensorTwoData != lastStatus2 )){
          console.log("***************************************************************************************")
          console.log(`we are now going to notify relevant parties since there is an unoccupied `)
          console.log("***************************************************************************************")

          if(sensorOneData == "unoccupied" && sensorTwoData == "unoccupied"){
            delete dataManager.data[subscriptions[0]]['charging_station'].timeCharging
            delete dataManager.data[subscriptions[1]]['charging_station'].timeCharging
            notificationBody = `EV Charger 1 and 2 are unoccupied. Prices are ${currentRecord[Object.keys(currentRecord)[0]]['charging_station']["price"]} and ${currentRecord[Object.keys(currentRecord)[1]]['charging_station']["price"]} respectively`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })
          } else if (sensorOneData == "unoccupied"){
            delete dataManager.data[subscriptions[0]]['charging_station'].timeCharging
            notificationBody = `EV Charger 1 is unoccupied and the price is ${currentRecord[Object.keys(currentRecord)[0]]['charging_station']["price"]}`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })
          } else if (sensorTwoData == "unoccupied"){
            delete dataManager.data[subscriptions[1]]['charging_station'].timeCharging
            notificationBody = `EV Charger 2 is unoccupied and the price is ${currentRecord[Object.keys(currentRecord)[1]]['charging_station']["price"]}`
            client.messages.create({
              to: toNumber,
              from: fromNumber,
              body: notificationBody,
            }, function (err, message) {
              console.log(err)
              console.log(message)
            })
          }

          console.log(dataManager.toString())
          instance.publish(dataManager.toString())
            .catch(err => console.log(`Error in publishing timeSince>=timeBetween positive state: ${JSON.stringify(err)}`))
          dataManager.clear()
          lastPub = currentTime
        } else if (dataManager.isAllFilled()) {
          if (sensorOneData == "unoccupied"){
            delete dataManager.data[subscriptions[0]]['charging_station'].timeCharging
          } else if (sensorTwoData == "unoccupied"){
            delete dataManager.data[subscriptions[1]]['charging_station'].timeCharging
          }
          instance.publish(dataManager.toString())
            .catch(err => console.log(`Error in publishing timeSince>=timeBetween negative state: ${JSON.stringify(err)}`))
        }
      }
      lastStatus1 = sensorOneData
      lastStatus2 = sensorTwoData
      if (timeSince >= timeThreshold){
        // let them know the node is still online
       console.log("===================================>   timeSince >= timeThreshold")
        console.log("***************************************************************************************")
        console.log('Heartbeat, I am alive but have not got data in a long time')
        console.log("***************************************************************************************")
        messageBody = 'Heartbeat, I am alive but have not got data in a long time'
        client.messages.create({
          to: toNumber,
          from: fromNumber,
          body: messageBody,
        }, function (err, message) {
          console.log(err)
          console.log(message)
        })
        instance.publish('Heartbeat, I am alive but have not got data in a long time')
          .catch(err => console.log(`Error in publishing timeSince>=timeBetween: ${JSON.stringify(err)}`))
        dataManager.clear()
        lastPub = currentTime
      }
    })
  })
  .catch(err => console.log(`Error in main loop: ${JSON.stringify(err)}`))<|endoftext|>


<commit_before>/*globals freedom, console, require*/

/**
 * Bind handlers on startup
 */
function start(ChatClient) {
  var chatClient = new ChatClient(),
  // If messages are going to a specific user, store that here.
      activeBuddy,
      buddylist,
      buddytabs = {},
      input,
      publicKey;

  //

  function clearLog() {
    var log = document.getElementById('statuslog');
    log.innerHTML = '';
  }

  function append(container, elt) {
    var log = document.getElementById('statuslog'),
        br;
    //Trim old messages
    if (container.childNodes) {
      while (container.childNodes.length > 36) {
        container.removeChild(log.firstChild);
      }
    }
    container.appendChild(elt);
    br = document.createElement('br');
    container.appendChild(br);
    br.scrollIntoView();
  }

  function makeDisplayString(buddylistEntry) {
    return buddylistEntry.name &&
      buddylistEntry.name !== buddylistEntry.userId ?
      buddylistEntry.name + ' (' + buddylistEntry.userId + ')' :
      buddylistEntry.userId;
  }

  function redrawBuddylist() {
    var onClick = function (buddylistEntry, child) {
      activeBuddy = buddylistEntry.userId;
      console.log('Messages will be sent to: ' + activeBuddy);
      addOrActivateTab(activeBuddy);
      redrawBuddylist();
    },
        buddylistDiv = document.getElementById('buddylist'),
        userId,
        child;

    // Remove all elements in there now
    buddylistDiv.innerHTML = 'Buddylist';

    // Create a new element for each buddy
    for (userId in buddylist) {
      if (buddylist.hasOwnProperty(userId)) {
        child = document.createElement('div');
        if (activeBuddy === userId) {
          child.innerHTML = '' + makeDisplayString(buddylist[userId]) +
            '';
        } else {
          child.innerHTML = makeDisplayString(buddylist[userId]);
        }
        // If the user clicks on a buddy,
        // change our current destination for messages
        child.addEventListener('click',
                               onClick.bind(this, buddylist[userId], child),
                               true);
        buddylistDiv.appendChild(child);
      }
    }
  }

  // on public key generation, do stuff
  chatClient.on('export-publicKey', function (userPublicKey) {
    publicKey = userPublicKey;
    document.getElementById('pgpkey').innerHTML =
      'Your PGP Public Key is:
' + '
' + publicKey + '
';
  });

  // on changes to the buddylist, redraw entire buddylist
  chatClient.on('recv-buddylist', function (val) {
    buddylist = val;
    redrawBuddylist();
  });

  // On new messages, append it to our message log
  chatClient.on('recv-message', function (data) {
    // Show the name instead of the userId, if it's available.
    var userId = data.from.userId,
        displayName = buddylist[userId].name || userId,
        message = displayName + ": " + data.message;
    activeBuddy = userId;
    addOrActivateTab(userId);
    append(document.getElementById('msglist-' + userId),
           document.createTextNode(message));
  });

  // On new messages, append it to our message log
  chatClient.on('recv-err', function (data) {
    document.getElementById('uid').textContent = "Error: " + data.message;
  });

  // Display our own userId when we get it
  chatClient.on('recv-uid', function (data) {
    document.getElementById('uid').textContent = "Logged in as: " + data;
  });

  // Display the current status of our connection to the Social provider
  chatClient.on('recv-status', function (msg) {
    if (msg && msg === 'online') {
      //document.getElementById('msg-input').disabled = false;
      //msg += ' - click a buddy to start chatting!';
    } else {
      //document.getElementById('msg-input').disabled = true;
    }
    clearLog();
    var elt = document.createElement('b');
    elt.appendChild(document.createTextNode('Status: ' + msg));
    append(document.getElementById('statuslog'), elt);
  });

  function setupChat(uid) {
    input = document.getElementById('msginput-' + uid);
    msglist = document.getElementById('msglist-' + uid);
    input.onkeydown = function (evt) {
      if (evt.keyCode === 13) {
        var text = input.value;
        input.value = "";
        append(msglist, document.createTextNode("You: " + text));
        chatClient.send(activeBuddy, text);
      }
    };
    // Timeout for focus to work w/tab redrawing
    setTimeout(function () { input.focus(); }, 100);
  }

  // SEE: https://bitbucket.org/sparklinlabs/tab-strip/src

  var numTabs = 0;
  var tabStrip = new TabStrip(document.querySelector('.tabs-container'));

  function redrawTabs() {
    var pane, ref, tab, tabLabel, tabX;
    var onClick = function (i) {
      console.log("CLOSING: " + i);
      var tabs = document.getElementsByTagName('li');
      tabStrip.emit('closeTab', tabs[i]);
    };
    tabStrip.tabsRoot.innerHTML = '';  // reset to blank
    ref = document.querySelectorAll('.panes > div');
    numTabs = ref.length;
    for (var i = 0; i < numTabs; i++) {
      pane = ref[i];
      tab = document.createElement('li');
      tab.dataset.pane = 'pane-' + (i + 1);
      tabLabel = document.createElement('span');
      tabLabel.classList.add('label');
      tabLabel.textContent = pane.id;
      tab.appendChild(tabLabel);
      if (i > 0) {
        // Add X mark to close tabs, except first status tab
        tabX = document.createElement('span');
        tabX.classList.add('label');
        tabX.textContent = '\u2612';  // ballot box with X
        // TODO: this event isn't fired properly for some reason
        tabX.addEventListener('click', onClick.bind(this, i), true);
        tab.appendChild(tabX);
      }
      tabStrip.tabsRoot.appendChild(tab);
      if (i === 0) {
        tab.classList.add('active');
        document.querySelector('.panes .' + tab.dataset.pane)
          .classList.add('active');
      }
    }
    tabStrip.on('activateTab', function(tab) {
      tabStrip.tabsRoot.querySelector('.active').classList.remove('active');
      tab.classList.add('active');
      document.querySelector('.panes > .active').classList.remove('active');
      document.querySelector('.panes .' + tab.dataset.pane)
        .classList.add('active');
      // Need to figure out which buddy is now active
      activeBuddy = buddytabs[tab.getAttribute('data-pane')];
      redrawBuddylist();
      if (activeBuddy) {
        setupChat(activeBuddy);
      }
    });
    tabStrip.on('closeTab', function(tab) {
      console.log('Removing a tab');
      tabStrip.tabsRoot.removeChild(tab);
      // TODO activate status tab or neighbor tab
    });
  }

  function addOrActivateTab(uid) {
    // Add a tab to chat with a new user (uid)
    if (!document.getElementById(uid)) {
      var newtab = document.createElement('div');
      newtab.className = 'pane-' + (numTabs + 1);
      buddytabs[newtab.className] = uid;
      newtab.id = uid;
      // TODO - make this look nicer
      newtab.innerHTML = "

" +
        "
" +
        "

" +
        "<input id='msginput-" + uid +
        "' type='text' placeholder='Type message here'/>" +
        "
" +
        "
";
      document.getElementById('panelist').appendChild(newtab);
      redrawTabs();
    }
    // Activate the new tab
    var addedtab = document.getElementById(uid);
    var tabs = document.getElementsByTagName('li');
    for (var i = 0; i < tabs.length; i++) {
      if (tabs[i].getAttribute('data-pane') === addedtab.className) {
        tabStrip.emit('activateTab', tabs[i]);
      }
    }
  }

  redrawTabs();
}

window.onload = function () {
  freedom('securechat.json').then(start);
};
<commit_msg>tabs close, though not gracefully (prevents reopening)<commit_after>/*globals freedom, console, require*/

/**
 * Bind handlers on startup
 */
function start(ChatClient) {
  var chatClient = new ChatClient(),
  // If messages are going to a specific user, store that here.
      activeBuddy,
      buddylist,
      buddytabs = {},
      input,
      publicKey;

  //

  function clearLog() {
    var log = document.getElementById('statuslog');
    log.innerHTML = '';
  }

  function append(container, elt) {
    var log = document.getElementById('statuslog'),
        br;
    //Trim old messages
    if (container.childNodes) {
      while (container.childNodes.length > 36) {
        container.removeChild(log.firstChild);
      }
    }
    container.appendChild(elt);
    br = document.createElement('br');
    container.appendChild(br);
    br.scrollIntoView();
  }

  function makeDisplayString(buddylistEntry) {
    return buddylistEntry.name &&
      buddylistEntry.name !== buddylistEntry.userId ?
      buddylistEntry.name + ' (' + buddylistEntry.userId + ')' :
      buddylistEntry.userId;
  }

  function redrawBuddylist() {
    var onClick = function (buddylistEntry, child) {
      activeBuddy = buddylistEntry.userId;
      console.log('Messages will be sent to: ' + activeBuddy);
      addOrActivateTab(activeBuddy);
      redrawBuddylist();
    },
        buddylistDiv = document.getElementById('buddylist'),
        userId,
        child;

    // Remove all elements in there now
    buddylistDiv.innerHTML = 'Buddylist';

    // Create a new element for each buddy
    for (userId in buddylist) {
      if (buddylist.hasOwnProperty(userId)) {
        child = document.createElement('div');
        if (activeBuddy === userId) {
          child.innerHTML = '' + makeDisplayString(buddylist[userId]) +
            '';
        } else {
          child.innerHTML = makeDisplayString(buddylist[userId]);
        }
        // If the user clicks on a buddy,
        // change our current destination for messages
        child.addEventListener('click',
                               onClick.bind(this, buddylist[userId], child),
                               true);
        buddylistDiv.appendChild(child);
      }
    }
  }

  // on public key generation, do stuff
  chatClient.on('export-publicKey', function (userPublicKey) {
    publicKey = userPublicKey;
    document.getElementById('pgpkey').innerHTML =
      'Your PGP Public Key is:
' + '
' + publicKey + '
';
  });

  // on changes to the buddylist, redraw entire buddylist
  chatClient.on('recv-buddylist', function (val) {
    buddylist = val;
    redrawBuddylist();
  });

  // On new messages, append it to our message log
  chatClient.on('recv-message', function (data) {
    // Show the name instead of the userId, if it's available.
    var userId = data.from.userId,
        displayName = buddylist[userId].name || userId,
        message = displayName + ": " + data.message;
    activeBuddy = userId;
    addOrActivateTab(userId);
    append(document.getElementById('msglist-' + userId),
           document.createTextNode(message));
  });

  // On new messages, append it to our message log
  chatClient.on('recv-err', function (data) {
    document.getElementById('uid').textContent = "Error: " + data.message;
  });

  // Display our own userId when we get it
  chatClient.on('recv-uid', function (data) {
    document.getElementById('uid').textContent = "Logged in as: " + data;
  });

  // Display the current status of our connection to the Social provider
  chatClient.on('recv-status', function (msg) {
    if (msg && msg === 'online') {
      //document.getElementById('msg-input').disabled = false;
      //msg += ' - click a buddy to start chatting!';
    } else {
      //document.getElementById('msg-input').disabled = true;
    }
    clearLog();
    var elt = document.createElement('b');
    elt.appendChild(document.createTextNode('Status: ' + msg));
    append(document.getElementById('statuslog'), elt);
  });

  function setupChat(uid) {
    input = document.getElementById('msginput-' + uid);
    msglist = document.getElementById('msglist-' + uid);
    input.onkeydown = function (evt) {
      if (evt.keyCode === 13) {
        var text = input.value;
        input.value = "";
        append(msglist, document.createTextNode("You: " + text));
        chatClient.send(activeBuddy, text);
      }
    };
    // Timeout for focus to work w/tab redrawing
    setTimeout(function () { input.focus(); }, 100);
  }

  // SEE: https://bitbucket.org/sparklinlabs/tab-strip/src

  var numTabs = 0;
  var tabStrip = new TabStrip(document.querySelector('.tabs-container'));

  function redrawTabs() {
    var pane, ref, tab, tabLabel, tabX;
    var onClick = function (i) {
      console.log("CLOSING: " + i);
      var tabs = document.getElementsByTagName('li');
      tabStrip.emit('closeTab', tabs[i]);
    };
    tabStrip.tabsRoot.innerHTML = '';  // reset to blank
    ref = document.querySelectorAll('.panes > div');
    numTabs = ref.length;
    for (var i = 0; i < numTabs; i++) {
      pane = ref[i];
      tab = document.createElement('li');
      tab.dataset.pane = 'pane-' + (i + 1);
      tabLabel = document.createElement('span');
      tabLabel.classList.add('label');
      tabLabel.textContent = pane.id;
      tab.appendChild(tabLabel);
      if (i > 0) {
        // Add X mark to close tabs, except first status tab
        tabX = document.createElement('span');
        tabX.textContent = '\u2612';  // ballot box with X
        tabX.addEventListener('click', onClick.bind(this, i), true);
        tab.appendChild(tabX);
      }
      tabStrip.tabsRoot.appendChild(tab);
      if (i === 0) {
        tab.classList.add('active');
        document.querySelector('.panes .' + tab.dataset.pane)
          .classList.add('active');
      }
    }
    tabStrip.on('activateTab', function(tab) {
      tabStrip.tabsRoot.querySelector('.active').classList.remove('active');
      tab.classList.add('active');
      document.querySelector('.panes > .active').classList.remove('active');
      document.querySelector('.panes .' + tab.dataset.pane)
        .classList.add('active');
      // Need to figure out which buddy is now active
      activeBuddy = buddytabs[tab.getAttribute('data-pane')];
      redrawBuddylist();
      if (activeBuddy) {
        setupChat(activeBuddy);
      }
    });
    tabStrip.on('closeTab', function(tab) {
      console.log('Removing a tab');
      tabStrip.tabsRoot.removeChild(tab);
      // TODO activate status tab or neighbor tab
    });
  }

  function addOrActivateTab(uid) {
    // Add a tab to chat with a new user (uid)
    if (!document.getElementById(uid)) {
      var newtab = document.createElement('div');
      newtab.className = 'pane-' + (numTabs + 1);
      buddytabs[newtab.className] = uid;
      newtab.id = uid;
      // TODO - make this look nicer
      newtab.innerHTML = "

" +
        "
" +
        "

" +
        "<input id='msginput-" + uid +
        "' type='text' placeholder='Type message here'/>" +
        "
" +
        "
";
      document.getElementById('panelist').appendChild(newtab);
      redrawTabs();
    }
    // Activate the new tab
    var addedtab = document.getElementById(uid);
    var tabs = document.getElementsByTagName('li');
    for (var i = 0; i < tabs.length; i++) {
      if (tabs[i].getAttribute('data-pane') === addedtab.className) {
        tabStrip.emit('activateTab', tabs[i]);
      }
    }
  }

  redrawTabs();
}

window.onload = function () {
  freedom('securechat.json').then(start);
};
<|endoftext|>


<commit_before>/**
 * @file Dialog component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Children, cloneElement, Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import PositionPop from '../_PositionPop';
import Paper from '../Paper';
import FlatButton from '../FlatButton';
import RaisedButton from '../RaisedButton';
import IconButton from '../IconButton';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import PopManagement from '../_vendors/PopManagement';

class Dialog extends Component {

    static ButtonTheme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    okButtonClickHandler = () => {

        const {visible, onOKButtonClick} = this.props;

        visible && onOKButtonClick && onOKButtonClick(() => {
            this.setState({
                visible: false
            }, () => {
                const {onRequestClose} = this.props;
                onRequestClose && onRequestClose();
            });
        });

    };

    cancelButtonClickHandler = () => {

        const {onCancelButtonClick, onRequestClose} = this.props;

        onCancelButtonClick && onCancelButtonClick();

        this.setState({
            visible: false
        }, () => {
            onRequestClose && onRequestClose();
        });

    };

    closeButtonClickHandler = () => {

        const {onCloseButtonClick, onRequestClose} = this.props;

        onCloseButtonClick && onCloseButtonClick();

        this.setState({
            visible: false
        }, () => {
            onRequestClose && onRequestClose();
        });

    };

    renderHandler = (...args) => {

        PopManagement.push(this, {
            shouldLockBody: this.props.showModal
        });

        const {onRender} = this.props;
        onRender && onRender(...args);

    };

    destroyHandler = (...args) => {

        PopManagement.pop(this);

        const {onDestroy} = this.props;
        onDestroy && onDestroy(...args);

    };

    componentWillUnmount() {
        PopManagement.pop(this);
    }

    render() {

        const {

                children,

                className, modalClassName, position, disabled, showModal,
                title, buttons, isLoading, visible,

                okButtonVisible, okButtonText, okButtonIconCls, okButtonTheme, okButtonDisabled, okButtonIsLoading,
                cancelButtonVisible, cancelButtonText, cancelButtonIconCls, cancelButtonDisabled, cancelButtonIsLoading,
                cancelButtonTheme, closeButtonVisible, closeIconCls,

                // not passing down these props
                isBlurClose, isEscClose,
                onRequestClose, onOKButtonClick, onCloseButtonClick, onCancelButtonClick,

                ...restProps

            } = this.props,

            dialogClassName = classNames('dialog', {
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         className={dialogClassName}
                         position={position}
                         visible={visible}
                         container={<Paper depth={6}></Paper>}
                         showModal={showModal}
                         modalClassName={modalClassName}
                         onRender={this.renderHandler}
                         onDestroy={this.destroyHandler}>

                    {title}

                    {
                        closeButtonVisible ?
                            <IconButton className="dialog-title-close-button"
                                        iconCls={closeIconCls}
                                        disabled={disabled}
                                        onClick={this.closeButtonClickHandler}/>
                            :
                            null
                    }

                    {children}

                    {
                        buttons ?
                            Children.map(buttons, button => cloneElement(button, {
                                isLoading,
                                disabled
                            }))
                            :
                            null
                    }

                    {
                        !buttons && okButtonVisible ?
                            <RaisedButton className="ok-button"
                                          value={okButtonText}
                                          iconCls={okButtonIconCls}
                                          theme={okButtonTheme}
                                          disabled={okButtonDisabled}
                                          isLoading={isLoading || okButtonIsLoading}
                                          disableTouchRipple={true}
                                          onClick={this.okButtonClickHandler}/>
                            :
                            null
                    }

                    {
                        !buttons && cancelButtonVisible ?
                            <FlatButton className="cancel-button"
                                        value={cancelButtonText}
                                        iconCls={cancelButtonIconCls}
                                        theme={cancelButtonTheme}
                                        disabled={cancelButtonDisabled}
                                        isLoading={isLoading || cancelButtonIsLoading}
                                        disableTouchRipple={true}
                                        onClick={this.cancelButtonClickHandler}/>
                            :
                            null
                    }

            </PositionPop>
        );

    }

}

Dialog.propTypes = {

    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The css class name of the modal.
     */
    modalClassName: PropTypes.string,

    /**
     * The styles of the root element.
     */
    style: PropTypes.object,

    parentEl: PropTypes.object,

    /**
     * The dialog alignment.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,the element will disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true,dialog box will display.
     */
    visible: PropTypes.bool,

    /**
     * If true,the pop-up box will be displayed in the mask layer, or the pop-up box will appear below the element.
     */
    showModal: PropTypes.bool,

    /**
     * Set the title of dialog.
     */
    title: PropTypes.any,

    /**
     * If true,when press down mouse the pop-up box will closed.
     */
    isBlurClose: PropTypes.bool,

    isLoading: PropTypes.bool,

    /**
     * If true, the OK button will display.
     */
    okButtonVisible: PropTypes.bool,

    /**
     * Set the text value of the OK button.
     */
    okButtonText: PropTypes.string,

    /**
     * Set the icon class of the OK button.
     */
    okButtonIconCls: PropTypes.string,

    /**
     * If true, the OK button will disabled.
     */
    okButtonDisabled: PropTypes.bool,

    /**
     * If true, the ok button will have loading effect.
     */
    okButtonIsLoading: PropTypes.bool,

    /**
     * Set theme of OK button.
     */
    okButtonTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * If true, the cancel button will display.
     */
    cancelButtonVisible: PropTypes.bool,

    /**
     * Set the text value of the cancel button.
     */
    cancelButtonText: PropTypes.string,

    /**
     * Set the icon class of the cancel button.
     */
    cancelButtonIconCls: PropTypes.string,

    /**
     * If true, the cancel button will disabled.
     */
    cancelButtonDisabled: PropTypes.bool,

    /**
     * If true, the cancel button will have loading effect.
     */
    cancelButtonIsLoading: PropTypes.bool,

    /**
     * Set theme of cancel button.
     */
    cancelButtonTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * If true, the close button in title will display.
     */
    closeButtonVisible: PropTypes.bool,

    closeIconCls: PropTypes.string,

    isEscClose: PropTypes.bool,

    /**
     * The buttons of Dialog.
     */
    buttons: PropTypes.any,

    /**
     * The function of dialog render.
     */
    onRender: PropTypes.func,

    /**
     * The function that trigger when click submit.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when click the ok button.
     */
    onOKButtonClick: PropTypes.func,

    /**
     * Callback function fired when click the cancel button.
     */
    onCancelButtonClick: PropTypes.func,

    /**
     * Callback function fired when click the close button.
     */
    onCloseButtonClick: PropTypes.func

};

Dialog.defaultProps = {

    parentEl: document.body,

    position: Position.CENTER,
    disabled: false,
    visible: false,
    showModal: true,

    isBlurClose: false,
    isLoading: false,

    okButtonVisible: true,
    okButtonText: 'OK',
    okButtonDisabled: false,
    okButtonIsLoading: false,
    okButtonTheme: Theme.SUCCESS,

    cancelButtonVisible: true,
    cancelButtonText: 'Cancel',
    cancelButtonDisabled: false,
    cancelButtonIsLoading: false,
    cancelButtonTheme: Theme.DEFAULT,

    closeButtonVisible: true,
    closeIconCls: 'fas fa-times',

    isEscClose: true

};

export default Dialog;
<commit_msg>update Dialog<commit_after>/**
 * @file Dialog component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Children, cloneElement, Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import PositionPop from '../_PositionPop';
import Paper from '../Paper';
import FlatButton from '../FlatButton';
import RaisedButton from '../RaisedButton';
import IconButton from '../IconButton';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import PopManagement from '../_vendors/PopManagement';

class Dialog extends Component {

    static ButtonTheme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    /**
     * public
     */
    getEl = () => {
        return this.refs.pop && this.refs.pop.getEl();
    };

    okButtonClickHandler = () => {

        const {visible, onOKButtonClick} = this.props;

        visible && onOKButtonClick && onOKButtonClick(() => {
            this.setState({
                visible: false
            }, () => {
                const {onRequestClose} = this.props;
                onRequestClose && onRequestClose();
            });
        });

    };

    cancelButtonClickHandler = () => {

        const {onCancelButtonClick, onRequestClose} = this.props;

        onCancelButtonClick && onCancelButtonClick();

        this.setState({
            visible: false
        }, () => {
            onRequestClose && onRequestClose();
        });

    };

    closeButtonClickHandler = () => {

        const {onCloseButtonClick, onRequestClose} = this.props;

        onCloseButtonClick && onCloseButtonClick();

        this.setState({
            visible: false
        }, () => {
            onRequestClose && onRequestClose();
        });

    };

    renderHandler = (...args) => {

        PopManagement.push(this, {
            shouldLockBody: this.props.showModal
        });

        const {onRender} = this.props;
        onRender && onRender(...args);

    };

    destroyHandler = (...args) => {

        PopManagement.pop(this);

        const {onDestroy} = this.props;
        onDestroy && onDestroy(...args);

    };

    componentWillUnmount() {
        PopManagement.pop(this);
    }

    render() {

        const {

                children,

                className, modalClassName, position, disabled, showModal,
                title, buttons, isLoading, visible,

                okButtonVisible, okButtonText, okButtonIconCls, okButtonTheme, okButtonDisabled, okButtonIsLoading,
                cancelButtonVisible, cancelButtonText, cancelButtonIconCls, cancelButtonDisabled, cancelButtonIsLoading,
                cancelButtonTheme, closeButtonVisible, closeIconCls,

                // not passing down these props
                isBlurClose, isEscClose,
                onRequestClose, onOKButtonClick, onCloseButtonClick, onCancelButtonClick,

                ...restProps

            } = this.props,

            dialogClassName = classNames('dialog', {
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         ref="pop"
                         className={dialogClassName}
                         position={position}
                         visible={visible}
                         container={<Paper depth={6}></Paper>}
                         showModal={showModal}
                         modalClassName={modalClassName}
                         onRender={this.renderHandler}
                         onDestroy={this.destroyHandler}>

                    {title}

                    {
                        closeButtonVisible ?
                            <IconButton className="dialog-title-close-button"
                                        iconCls={closeIconCls}
                                        disabled={disabled}
                                        onClick={this.closeButtonClickHandler}/>
                            :
                            null
                    }

                    {children}

                    {
                        buttons ?
                            Children.map(buttons, button => cloneElement(button, {
                                isLoading,
                                disabled
                            }))
                            :
                            null
                    }

                    {
                        !buttons && okButtonVisible ?
                            <RaisedButton className="ok-button"
                                          value={okButtonText}
                                          iconCls={okButtonIconCls}
                                          theme={okButtonTheme}
                                          disabled={okButtonDisabled}
                                          isLoading={isLoading || okButtonIsLoading}
                                          disableTouchRipple={true}
                                          onClick={this.okButtonClickHandler}/>
                            :
                            null
                    }

                    {
                        !buttons && cancelButtonVisible ?
                            <FlatButton className="cancel-button"
                                        value={cancelButtonText}
                                        iconCls={cancelButtonIconCls}
                                        theme={cancelButtonTheme}
                                        disabled={cancelButtonDisabled}
                                        isLoading={isLoading || cancelButtonIsLoading}
                                        disableTouchRipple={true}
                                        onClick={this.cancelButtonClickHandler}/>
                            :
                            null
                    }

            </PositionPop>
        );

    }

}

Dialog.propTypes = {

    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The css class name of the modal.
     */
    modalClassName: PropTypes.string,

    /**
     * The styles of the root element.
     */
    style: PropTypes.object,

    parentEl: PropTypes.object,

    /**
     * The dialog alignment.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,the element will disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true,dialog box will display.
     */
    visible: PropTypes.bool,

    /**
     * If true,the pop-up box will be displayed in the mask layer, or the pop-up box will appear below the element.
     */
    showModal: PropTypes.bool,

    /**
     * Set the title of dialog.
     */
    title: PropTypes.any,

    /**
     * If true,when press down mouse the pop-up box will closed.
     */
    isBlurClose: PropTypes.bool,

    isLoading: PropTypes.bool,

    /**
     * If true, the OK button will display.
     */
    okButtonVisible: PropTypes.bool,

    /**
     * Set the text value of the OK button.
     */
    okButtonText: PropTypes.string,

    /**
     * Set the icon class of the OK button.
     */
    okButtonIconCls: PropTypes.string,

    /**
     * If true, the OK button will disabled.
     */
    okButtonDisabled: PropTypes.bool,

    /**
     * If true, the ok button will have loading effect.
     */
    okButtonIsLoading: PropTypes.bool,

    /**
     * Set theme of OK button.
     */
    okButtonTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * If true, the cancel button will display.
     */
    cancelButtonVisible: PropTypes.bool,

    /**
     * Set the text value of the cancel button.
     */
    cancelButtonText: PropTypes.string,

    /**
     * Set the icon class of the cancel button.
     */
    cancelButtonIconCls: PropTypes.string,

    /**
     * If true, the cancel button will disabled.
     */
    cancelButtonDisabled: PropTypes.bool,

    /**
     * If true, the cancel button will have loading effect.
     */
    cancelButtonIsLoading: PropTypes.bool,

    /**
     * Set theme of cancel button.
     */
    cancelButtonTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * If true, the close button in title will display.
     */
    closeButtonVisible: PropTypes.bool,

    closeIconCls: PropTypes.string,

    isEscClose: PropTypes.bool,

    /**
     * The buttons of Dialog.
     */
    buttons: PropTypes.any,

    /**
     * The function of dialog render.
     */
    onRender: PropTypes.func,

    /**
     * The function that trigger when click submit.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when click the ok button.
     */
    onOKButtonClick: PropTypes.func,

    /**
     * Callback function fired when click the cancel button.
     */
    onCancelButtonClick: PropTypes.func,

    /**
     * Callback function fired when click the close button.
     */
    onCloseButtonClick: PropTypes.func

};

Dialog.defaultProps = {

    parentEl: document.body,

    position: Position.CENTER,
    disabled: false,
    visible: false,
    showModal: true,

    isBlurClose: false,
    isLoading: false,

    okButtonVisible: true,
    okButtonText: 'OK',
    okButtonDisabled: false,
    okButtonIsLoading: false,
    okButtonTheme: Theme.SUCCESS,

    cancelButtonVisible: true,
    cancelButtonText: 'Cancel',
    cancelButtonDisabled: false,
    cancelButtonIsLoading: false,
    cancelButtonTheme: Theme.DEFAULT,

    closeButtonVisible: true,
    closeIconCls: 'fas fa-times',

    isEscClose: true

};

export default Dialog;
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commi<commit_msg>Re-commiting last<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit<|endoftext|>


<commit_before>function pobierzZakładki(sel, url) {
  // $(sel).html('')
  $.ajax({
    url: url,
    cache: false,
    success: function(html) {
      wczytajZakładki(sel, html)
    },
    error: function(xhr, status, error) {
      $(sel).html(' ' + status + ' ' + error + "")
    }
  })
}

function wczytajZakładki(sel, html) {
  var listy = $('dl', html)
  for(var i = 0; i < listy.length; i++) {
    var bieżąca_lista = listy.eq(i)
    var bieżące_pozycje = bieżąca_lista.children('dt')

    $('#bk' + i % 4).append('
' + bieżąca_lista.prev().html() + '
')
    $('#bk' + i % 4).append('

')

    for(var j = 0; j < bieżące_pozycje.length; j++) {

      var bieżąca_pozycja = bieżące_pozycje.eq(j)
      var bieżący_link = bieżąca_pozycja.children().first()

      if (bieżący_link.prop('tagName') == 'A') {
        $('#bk' + i % 4).append('
' + bieżący_link[0].outerHTML + '
')
      }

    }

    $('#bk' + i % 4).append('

')

  }
}

$(document).ready(function() {
  pobierzZakładki('#bk1', 'https://jkpluta.github.io/bookmarks.html')
})
<commit_msg>Porządki<commit_after>let LICZBA_KOLUMN = 4

function pobierzZakładki(sel, url) {
  $(sel).html('')
  $.ajax({
    url: url,
    cache: false,
    success: function(html) {
      wczytajZakładki(sel, html)
    },
    error: function(xhr, status, error) {
      $(sel).html(' ' + status + ' ' + error + "")
    }
  })
}

function wczytajZakładki(sel, html) {
  $('#bks').html('')
  for(var i = 0; i < LICZBA_KOLUMN; i++) {
    $('#bks').append('

')
  }

  var listy = $('dl', html)
  for (var i = 0; i < listy.length; i++) {
    var bieżąca_lista = listy.eq(i)
    var bieżące_pozycje = bieżąca_lista.children('dt')

    $('#bk' + i % LICZBA_KOLUMN).append('
' + bieżąca_lista.prev().html() + '
')
    $('#bk' + i % LICZBA_KOLUMN).append('

')

    for (var j = 0; j < bieżące_pozycje.length; j++) {

      var bieżąca_pozycja = bieżące_pozycje.eq(j)
      var bieżące_linki = bieżąca_pozycja.children('a')

      if (bieżące_linki.length > 0) {
        var bieżący_link = bieżące_linki.first()
        $('#bk' + i % LICZBA_KOLUMN).append('
' + bieżący_link[0].outerHTML + '
')
      }

    }

    $('#bk' + i % LICZBA_KOLUMN).append('

')

  }
}

$(document).ready(function() {
  pobierzZakładki('#bks', 'https://jkpluta.github.io/bookmarks.html')
})
<|endoftext|>


<commit_before>const gulp = require('gulp');
const template = require('gulp-template');
const rename = require('gulp-rename');
const fs = require('fs')

const parse5 = require('parse5');

gulp.task('default', () => {
    gulp.start('updateContent');
    gulp.start('updateEssentials');
});

gulp.task('updateEssentials', () => {
    gulp.src('src/css/*').pipe(gulp.dest('dist/css'));
    gulp.src('src/font/*').pipe(gulp.dest('dist/font'));
    gulp.src('src/js/*').pipe(gulp.dest('dist/js'));
    gulp.src('src/img/*').pipe(gulp.dest('dist/img'));
})

gulp.task('updateContent', () => {
    fs.readdir('src/elements/', (err, files) => {
      files.forEach(file => {
        var fileContent = fs.readFileSync('src/elements/'+file, "utf8");

        const doc = parse5.parse(fileContent);

        var body = []
        var styledef = ""

        doc.childNodes[1].childNodes.forEach(function(element) {
          if (element.tagName === "body") {
            body = parse5.serialize(element);
            element.attrs.forEach(function (attr) {
              if (attr.name === "style") {
                styledef = attr.value
              }
            });
          }
        })

        gulp.src('src/template.html')
          .pipe(template(
            {content: body,
             style : styledef}
          ))
          .pipe(rename(file))
          .pipe(gulp.dest('dist/'))
      });
    })
})

var watcher = gulp.watch('src/*/*');

watcher.on('change', function(path, stats) {
    gulp.start('updateContent');
    gulp.start('updateEssentials');
});
<commit_msg>also update on template changes<commit_after>const gulp = require('gulp');
const template = require('gulp-template');
const rename = require('gulp-rename');
const fs = require('fs')

const parse5 = require('parse5');

gulp.task('default', () => {
    gulp.start('updateContent');
    gulp.start('updateEssentials');
});

gulp.task('updateEssentials', () => {
    gulp.src('src/css/*').pipe(gulp.dest('dist/css'));
    gulp.src('src/font/*').pipe(gulp.dest('dist/font'));
    gulp.src('src/js/*').pipe(gulp.dest('dist/js'));
    gulp.src('src/img/*').pipe(gulp.dest('dist/img'));
})

gulp.task('updateContent', () => {
    fs.readdir('src/elements/', (err, files) => {
      files.forEach(file => {
        var fileContent = fs.readFileSync('src/elements/'+file, "utf8");

        const doc = parse5.parse(fileContent);

        var body = []
        var styledef = ""

        doc.childNodes[1].childNodes.forEach(function(element) {
          if (element.tagName === "body") {
            body = parse5.serialize(element);
            element.attrs.forEach(function (attr) {
              if (attr.name === "style") {
                styledef = attr.value
              }
            });
          }
        })

        gulp.src('src/template.html')
          .pipe(template(
            {content: body,
             style : styledef}
          ))
          .pipe(rename(file))
          .pipe(gulp.dest('dist/'))
      });
    })
})

var watcher = gulp.watch('src/*/*');

watcher.on('change', function(path, stats) {
    gulp.start('updateContent');
    gulp.start('updateEssentials');
});

var watcher = gulp.watch('src/*.html');

watcher.on('change', function(path, stats) {
    gulp.start('updateContent');
    gulp.start('updateEssentials');
});
<|endoftext|>


<commit_before>define(['angular', 'jquery', 'jss', 'farbtastic', 'defaults'], function(angular, jquery, jss, farbtastic, defaults) {
    return {
        init: function(scope) {
            var that = this;

            jquery.each(defaults.defaultTheme.colors, function(key, value) {
                var inputFarbtastic = jquery('#' + key).farbtastic('#input-' + key);
                // Add a listener to update farbtastic and style when a color is changed.
                scope.$watch('theme.colors["' + key + '"]', function(newVal, oldVal) {
                    jquery.farbtastic('#' + key).setColor(newVal);
                    that.updateStyle(false);
                });
            });

            // Add a listener to update the page item count when the window is resized.
            jquery(window).resize(function() {
                scope.$apply(function() {
                    scope.setPageItemCount(that.getPageItemCount());
                });
            });

            scope.setPageItemCount(that.getPageItemCount());

            jquery('body').show();
        },
        /**
            Compares window height to element height to fine the number of elements per page.
            returns: The number of items to fit on a page.
        */
        getPageItemCount: function() {
            var pageHeight = jquery('body').height();
            var headerHeight = jquery('h1').outerHeight(true);
            var navBarHeight = jquery('.page-chooser').outerHeight(true);
            var footerHeight = jquery('.footer').outerHeight(true);
            var height =  pageHeight - (headerHeight + navBarHeight + footerHeight);

            jss.set('.external', {
                'height': '' + height
            });
            jss.set('.bookmark_page', {
                'height': '' + height
            });

            return Math.floor((height) / 60) - 1;
        },
        /**
            Changes the style to whatever is in the scope.
            transition: A bool indicating whether to slowly transition or immediately change.
        */
        updateStyle: function(transition) {
            var scope = angular.element(document.body).scope();

            var options_color = defaults.defaultTheme['options-color'];
            var background_color = defaults.defaultTheme['background-color'];
            var main_color = defaults.defaultTheme['main-color'];
            var title_color = defaults.defaultTheme['title-color'];

            jquery.each(defaults.defaultTheme.colors, function(key, value) {

                jquery('#' + key).farbtastic('.color-picker .' + key);
                //
                // // Add a listener to update farbtastic when a color is changed.
                // scope.$watch('theme.colors["' + key + '"]', function(newVal, oldVal) {
                //     jquery.farbtastic('#' + key).setColor(newVal);
                // });
            });
            if (scope.theme) {
                background_color = scope.theme.colors['background-color'];
                options_color = scope.theme.colors['options-color'];
                main_color = scope.theme.colors['main-color'];
                title_color = scope.theme.colors['title-color'];
            }

            if(scope.font === 0) {
                jss.set('body', {
                    'font-family': '"Segoe UI", Helvetica, Arial, sans-serif',
                });
            } else {
                jss.set('body', {
                    'font-family': 'Raleway, "Segoe UI", Helvetica, Arial, sans-serif',
                });
            }

            jss.set('*', {
                'border-color': options_color
            });

            jss.set('::-webkit-scrollbar', {
                'background': background_color
            });

            jss.set('::-webkit-scrollbar-thumb', {
                'background': options_color
            });

            jss.set('::-webkit-input-placeholder', {
                'background': main_color
            });

            // Transition the colors
            if (transition) {
                jquery('.background-color').animate({'backgroundColor': background_color}, {duration: 800, queue: false});
                jquery('.title-color').animate({'color': title_color}, {duration: 400, queue: false});
                jquery('body').animate({'color': main_color}, {duration: 400, queue: false});
                jquery('input').animate({'color': main_color}, {duration: 400, queue: false});
                jquery('.options-color').animate({'color': options_color}, {duration: 400, queue: false});
            }

            //but then we still need to add it to the DOM.
            jss.set('.background-color', {
                'background-color': background_color
            });
            jss.set('.title-color', {
                'color': title_color
            });
            jss.set('body', {
                'color': main_color
            });
            jss.set('input', {
                'color': main_color
            });
            jss.set('.options-color', {
                'color': options_color
            });
            jss.set('.bookmark-active', {
                'color': options_color
                //'border-bottom': '2px solid ' + options_color
            });
        }
    };
});
<commit_msg>Move line<commit_after>define(['angular', 'jquery', 'jss', 'farbtastic', 'defaults'], function(angular, jquery, jss, farbtastic, defaults) {
    return {
        init: function(scope) {
            var that = this;

            jquery.each(defaults.defaultTheme.colors, function(key, value) {
                var inputFarbtastic = jquery('#' + key).farbtastic('#input-' + key);
                // Add a listener to update farbtastic and style when a color is changed.
                scope.$watch('theme.colors["' + key + '"]', function(newVal, oldVal) {
                    jquery.farbtastic('#' + key).setColor(newVal);
                    that.updateStyle(false);
                });
            });

            // Add a listener to update the page item count when the window is resized.
            jquery(window).resize(function() {
                scope.$apply(function() {
                    scope.setPageItemCount(that.getPageItemCount());
                });
            });

            jquery('body').show();
            scope.setPageItemCount(that.getPageItemCount());
        },
        /**
            Compares window height to element height to fine the number of elements per page.
            returns: The number of items to fit on a page.
        */
        getPageItemCount: function() {
            var pageHeight = jquery('body').height();
            var headerHeight = jquery('h1').outerHeight(true);
            var navBarHeight = jquery('.page-chooser').outerHeight(true);
            var footerHeight = jquery('.footer').outerHeight(true);
            var height =  pageHeight - (headerHeight + navBarHeight + footerHeight);

            jss.set('.external', {
                'height': '' + height
            });
            jss.set('.bookmark_page', {
                'height': '' + height
            });

            return Math.floor((height) / 60) - 1;
        },
        /**
            Changes the style to whatever is in the scope.
            transition: A bool indicating whether to slowly transition or immediately change.
        */
        updateStyle: function(transition) {
            var scope = angular.element(document.body).scope();

            var options_color = defaults.defaultTheme['options-color'];
            var background_color = defaults.defaultTheme['background-color'];
            var main_color = defaults.defaultTheme['main-color'];
            var title_color = defaults.defaultTheme['title-color'];

            jquery.each(defaults.defaultTheme.colors, function(key, value) {

                jquery('#' + key).farbtastic('.color-picker .' + key);
                //
                // // Add a listener to update farbtastic when a color is changed.
                // scope.$watch('theme.colors["' + key + '"]', function(newVal, oldVal) {
                //     jquery.farbtastic('#' + key).setColor(newVal);
                // });
            });
            if (scope.theme) {
                background_color = scope.theme.colors['background-color'];
                options_color = scope.theme.colors['options-color'];
                main_color = scope.theme.colors['main-color'];
                title_color = scope.theme.colors['title-color'];
            }

            if(scope.font === 0) {
                jss.set('body', {
                    'font-family': '"Segoe UI", Helvetica, Arial, sans-serif',
                });
            } else {
                jss.set('body', {
                    'font-family': 'Raleway, "Segoe UI", Helvetica, Arial, sans-serif',
                });
            }

            jss.set('*', {
                'border-color': options_color
            });

            jss.set('::-webkit-scrollbar', {
                'background': background_color
            });

            jss.set('::-webkit-scrollbar-thumb', {
                'background': options_color
            });

            jss.set('::-webkit-input-placeholder', {
                'background': main_color
            });

            // Transition the colors
            if (transition) {
                jquery('.background-color').animate({'backgroundColor': background_color}, {duration: 800, queue: false});
                jquery('.title-color').animate({'color': title_color}, {duration: 400, queue: false});
                jquery('body').animate({'color': main_color}, {duration: 400, queue: false});
                jquery('input').animate({'color': main_color}, {duration: 400, queue: false});
                jquery('.options-color').animate({'color': options_color}, {duration: 400, queue: false});
            }

            //but then we still need to add it to the DOM.
            jss.set('.background-color', {
                'background-color': background_color
            });
            jss.set('.title-color', {
                'color': title_color
            });
            jss.set('body', {
                'color': main_color
            });
            jss.set('input', {
                'color': main_color
            });
            jss.set('.options-color', {
                'color': options_color
            });
            jss.set('.bookmark-active', {
                'color': options_color
                //'border-bottom': '2px solid ' + options_color
            });
        }
    };
});
<|endoftext|>