<commit_before>var command = {
  command: "migrate",
  description: "Run migrations to deploy contracts",
  builder: {
    "reset": {
      type: "boolean",
      default: false
    },
    "compile-all": {
      describe: "recompile all contracts",
      type: "boolean",
      default: false
    },
    "dry-run": {
      describe: "Run migrations against an in-memory fork, for testing",
      type: "boolean",
      default: false
    },
    "f": {
      describe: "Specify a migration number to run from",
      type: "number"
    },
    "from": {
      describe: "Specify a migration number to run from",
      type: "number"
    },
    "to": {
      describe: "Specify a migration number to run to",
      type: "number"
    },
    "interactive": {
      describe: "Manually authorize deployments after seeing a preview",
      type: "boolean",
      default: false
    }
  },
  help: {
    usage:
      "truffle migrate [--reset] [--f <number> | --from <number>] [--to <number>] [--network <name>] [--compile-all] [--verbose-rpc] [--interactive]",
    options: [
      {
        option: "--reset",
        description:
          "Run all migrations from the beginning, instead of running from the last " +
          "completed migration."
      },
      {
        option: "--f <number> | --from <number>",
        description:
          "Run contracts from a specific migration. The number refers to the prefix of " +
          "the migration file."
      },
      {
        option: "--to <number>",
        description:
          "Run contracts to a specific migration. The number refers to the prefix of the migration file."
      },
      {
        option: "--network <name>",
        description:
          "Specify the network to use, saving artifacts specific to that network. " +
          "Network name must exist\n                    in the configuration."
      },
      {
        option: "--compile-all",
        description:
          "Compile all contracts instead of intelligently choosing which contracts need to " +
          "be compiled."
      },
      {
        option: "--verbose-rpc",
        description:
          "Log communication between Truffle and the Ethereum client."
      },
      {
        option: "--interactive",
        description:
          "Prompt to confirm that the user wants to proceed after the dry run."
      }
    ]
  },
  run: function(options, done) {
    var Config = require("truffle-config");
    var Contracts = require("truffle-workflow-compile");
    var Resolver = require("truffle-resolver");
    var Artifactor = require("truffle-artifactor");
    var Migrate = require("truffle-migrate");
    var Environment = require("../environment");
    var temp = require("temp");
    var copy = require("../copy");

    // Source: ethereum.stackexchange.com/questions/17051
    var networkWhitelist = [
      1, // Mainnet (ETH & ETC)
      2, // Morden (ETC)
      3, // Ropsten
      4, // Rinkeby
      8, // Ubiq
      42, // Kovan (Parity)
      77, // Sokol
      99, // Core

      7762959, // Musiccoin
      61717561 // Aquachain
    ];

    function setupDryRunEnvironmentThenRunMigrations(config) {
      return new Promise((resolve, reject) => {
        Environment.fork(config, function(err) {
          if (err) return reject(err);

          // Copy artifacts to a temporary directory
          temp.mkdir("migrate-dry-run-", function(err, temporaryDirectory) {
            if (err) return reject(err);

            function cleanup() {
              var args = arguments;

              // Ensure directory cleanup.
              temp.cleanup(() => {
                args.length && args[0] !== null ? reject(args[0]) : resolve();
              });
            }

            copy(config.contracts_build_directory, temporaryDirectory, function(
              err
            ) {
              if (err) return cleanup(err);

              config.contracts_build_directory = temporaryDirectory;

              // Note: Create a new artifactor and resolver with the updated config.
              // This is because the contracts_build_directory changed.
              // Ideally we could architect them to be reactive of the config changes.
              config.artifactor = new Artifactor(temporaryDirectory);
              config.resolver = new Resolver(config);

              runMigrations(config, cleanup);
            });
          });
        });
      });
    }

    function runMigrations(config, callback) {
      Migrate.launchReporter();

      // check --f && --from flag usage
      const from = options.f || options.from;

      if (from) {
        Migrate.runFrom(from, config, done);
      } else {
        Migrate.needsMigrating(config, function(err, needsMigrating) {
          if (err) return callback(err);

          if (needsMigrating) {
            Migrate.run(config, callback);
          } else {
            config.logger.log("Network up to date.");
            callback();
          }
        });
      }
    }

    async function executePostDryRunMigration(buildDir) {
      let accept = true;

      if (options.interactive) {
        accept = await Migrate.acceptDryRun();
      }

      if (accept) {
        const environment = require("../environment");
        const NewConfig = require("truffle-config");
        const config = NewConfig.detect(options);

        config.contracts_build_directory = buildDir;
        config.artifactor = new Artifactor(buildDir);
        config.resolver = new Resolver(config);

        environment.detect(config, err => {
          if (err) return done(err);

          config.dryRun = false;
          runMigrations(config, done);
        });
      } else {
        done();
      }
    }

    const conf = Config.detect(options);

    Contracts.compile(conf, function(err) {
      if (err) return done(err);

      Environment.detect(conf, async function(err) {
        if (err) return done(err);

        var dryRun = options.dryRun === true;
        var production =
          networkWhitelist.includes(conf.network_id) || conf.production;

        // Dry run only
        if (dryRun) {
          try {
            await setupDryRunEnvironmentThenRunMigrations(conf);
            done();
          } catch (err) {
            done(err);
          }

          // Production: dry-run then real run
        } else if (production && !conf.skipDryRun) {
          const currentBuild = conf.contracts_build_directory;
          conf.dryRun = true;

          try {
            await setupDryRunEnvironmentThenRunMigrations(conf);
          } catch (err) {
            return done(err);
          }

          executePostDryRunMigration(currentBuild);

          // Development
        } else {
          runMigrations(conf, done);
        }
      });
    });
  }
};

module.exports = command;
<commit_msg>revert extending --f to --from<commit_after>var command = {
  command: "migrate",
  description: "Run migrations to deploy contracts",
  builder: {
    "reset": {
      type: "boolean",
      default: false
    },
    "compile-all": {
      describe: "recompile all contracts",
      type: "boolean",
      default: false
    },
    "dry-run": {
      describe: "Run migrations against an in-memory fork, for testing",
      type: "boolean",
      default: false
    },
    "f": {
      describe: "Specify a migration number to run from",
      type: "number"
    },
    "to": {
      describe: "Specify a migration number to run to",
      type: "number"
    },
    "interactive": {
      describe: "Manually authorize deployments after seeing a preview",
      type: "boolean",
      default: false
    }
  },
  help: {
    usage:
      "truffle migrate [--reset] [--f <number>] [--to <number>] [--network <name>] [--compile-all] [--verbose-rpc] [--interactive]",
    options: [
      {
        option: "--reset",
        description:
          "Run all migrations from the beginning, instead of running from the last " +
          "completed migration."
      },
      {
        option: "--f <number>",
        description:
          "Run contracts from a specific migration. The number refers to the prefix of " +
          "the migration file."
      },
      {
        option: "--to <number>",
        description:
          "Run contracts to a specific migration. The number refers to the prefix of the migration file."
      },
      {
        option: "--network <name>",
        description:
          "Specify the network to use, saving artifacts specific to that network. " +
          "Network name must exist\n                    in the configuration."
      },
      {
        option: "--compile-all",
        description:
          "Compile all contracts instead of intelligently choosing which contracts need to " +
          "be compiled."
      },
      {
        option: "--verbose-rpc",
        description:
          "Log communication between Truffle and the Ethereum client."
      },
      {
        option: "--interactive",
        description:
          "Prompt to confirm that the user wants to proceed after the dry run."
      }
    ]
  },
  run: function(options, done) {
    var Config = require("truffle-config");
    var Contracts = require("truffle-workflow-compile");
    var Resolver = require("truffle-resolver");
    var Artifactor = require("truffle-artifactor");
    var Migrate = require("truffle-migrate");
    var Environment = require("../environment");
    var temp = require("temp");
    var copy = require("../copy");

    // Source: ethereum.stackexchange.com/questions/17051
    var networkWhitelist = [
      1, // Mainnet (ETH & ETC)
      2, // Morden (ETC)
      3, // Ropsten
      4, // Rinkeby
      8, // Ubiq
      42, // Kovan (Parity)
      77, // Sokol
      99, // Core

      7762959, // Musiccoin
      61717561 // Aquachain
    ];

    function setupDryRunEnvironmentThenRunMigrations(config) {
      return new Promise((resolve, reject) => {
        Environment.fork(config, function(err) {
          if (err) return reject(err);

          // Copy artifacts to a temporary directory
          temp.mkdir("migrate-dry-run-", function(err, temporaryDirectory) {
            if (err) return reject(err);

            function cleanup() {
              var args = arguments;

              // Ensure directory cleanup.
              temp.cleanup(() => {
                args.length && args[0] !== null ? reject(args[0]) : resolve();
              });
            }

            copy(config.contracts_build_directory, temporaryDirectory, function(
              err
            ) {
              if (err) return cleanup(err);

              config.contracts_build_directory = temporaryDirectory;

              // Note: Create a new artifactor and resolver with the updated config.
              // This is because the contracts_build_directory changed.
              // Ideally we could architect them to be reactive of the config changes.
              config.artifactor = new Artifactor(temporaryDirectory);
              config.resolver = new Resolver(config);

              runMigrations(config, cleanup);
            });
          });
        });
      });
    }

    function runMigrations(config, callback) {
      Migrate.launchReporter();

      if (options.f) {
        Migrate.runFrom(options.f, config, done);
      } else {
        Migrate.needsMigrating(config, function(err, needsMigrating) {
          if (err) return callback(err);

          if (needsMigrating) {
            Migrate.run(config, callback);
          } else {
            config.logger.log("Network up to date.");
            callback();
          }
        });
      }
    }

    async function executePostDryRunMigration(buildDir) {
      let accept = true;

      if (options.interactive) {
        accept = await Migrate.acceptDryRun();
      }

      if (accept) {
        const environment = require("../environment");
        const NewConfig = require("truffle-config");
        const config = NewConfig.detect(options);

        config.contracts_build_directory = buildDir;
        config.artifactor = new Artifactor(buildDir);
        config.resolver = new Resolver(config);

        environment.detect(config, err => {
          if (err) return done(err);

          config.dryRun = false;
          runMigrations(config, done);
        });
      } else {
        done();
      }
    }

    const conf = Config.detect(options);

    Contracts.compile(conf, function(err) {
      if (err) return done(err);

      Environment.detect(conf, async function(err) {
        if (err) return done(err);

        var dryRun = options.dryRun === true;
        var production =
          networkWhitelist.includes(conf.network_id) || conf.production;

        // Dry run only
        if (dryRun) {
          try {
            await setupDryRunEnvironmentThenRunMigrations(conf);
            done();
          } catch (err) {
            done(err);
          }

          // Production: dry-run then real run
        } else if (production && !conf.skipDryRun) {
          const currentBuild = conf.contracts_build_directory;
          conf.dryRun = true;

          try {
            await setupDryRunEnvironmentThenRunMigrations(conf);
          } catch (err) {
            return done(err);
          }

          executePostDryRunMigration(currentBuild);

          // Development
        } else {
          runMigrations(conf, done);
        }
      });
    });
  }
};

module.exports = command;
<|endoftext|>


<commit_before>import { Seq } from 'immutable'

function defaults(env, app, cwd) {
	const config = Object.assign({}, env, app)
	const { port, assets, dest } = config
	return [
		group('default', ['serve', 'watch']),
		defTask('serve', 'serve', {
			port, root: dest, livereload: true
		}),
		group('build', ['assets', 'jade-prod', 'sass-prod', 'scripts']),
		group('watch', ['watch-assets', 'watch-jade', 'watch-sass', 'watch-scripts']),
		defTask('watch-assets', 'watch', {
			src: assets, task: 'assets', cwd
		}, ['assets']),
		defTask('watch-jade', 'watch', {
			src: '**/*.jade', task: 'jade', cwd
		}, ['jade']),
		defTask('watch-sass', 'watch', {
			src: '*.{scss,css}', task: 'sass', cwd
		}, ['sass']),
		defTask('assets', 'assets', {
			src: assets, dest, cwd
		}),
		defTask('jade-prod', 'jade', {
			src: '*.jade', plumber: false, dest, cwd
		}),
		defTask('jade', 'jade', {
			src: '*.jade', plumber: true, dest, cwd
		}),
		defTask('sass-prod', 'sass', {
			src: '*.{scss,css}', plumber: false, dest, cwd
		}),
		defTask('sass', 'sass', {
			src: '*.{scss,css}', plumber: true, dest, cwd
		})
	].concat(
		scripts('script', '', config, cwd),
		scripts('scriptWatch', 'watch-', config, cwd)
	)
}

function scripts(func, prefix, { scripts, paths, dest }, cwd) {
	return Seq(scripts)
		.mapEntries(([main, output]) => [main,
			defTask(prefix + main, func, {
				main, output, paths, dest, cwd
			})]
		).toArray().concat([
			group(prefix + 'scripts', Seq(scripts).keySeq().toArray())
		])
}

function defTask(name, func, options, depends) {
	return task(name, 'ferad-tasks', func, options, depends)
}
function task(name, modul, func, options, depends = []) {
	return { name, modul, func, options, depends }
}
function group(name, depends) {
	return {
		name, modul: 'ferad-configs', func: 'emptyTask',
		options: {}, depends
	}
}
function emptyTask(o, cb) {
	cb()
}

export default {
	defaults, scripts, defTask, task, group, emptyTask
}
<commit_msg>#21 production env<commit_after>import { Seq } from 'immutable'

function defaults(env, app, cwd) {
	const config = Object.assign({}, env, app)
	const { port, assets, dest } = config
	return [
		group('default', ['serve', 'watch']),
		defTask('serve', 'serve', {
			port, root: dest, livereload: true
		}),
		group('build', ['assets', 'jade-prod', 'sass-prod', 'scripts']),
		defTask('prod', 'env', {
			prop: 'NODE_ENV', value: 'production'
		}),
		group('watch', ['watch-assets', 'watch-jade', 'watch-sass', 'watch-scripts']),
		defTask('watch-assets', 'watch', {
			src: assets, task: 'assets', cwd
		}, ['assets']),
		defTask('watch-jade', 'watch', {
			src: '**/*.jade', task: 'jade', cwd
		}, ['jade']),
		defTask('watch-sass', 'watch', {
			src: '*.{scss,css}', task: 'sass', cwd
		}, ['sass']),
		defTask('assets', 'assets', {
			src: assets, dest, cwd
		}),
		defTask('jade-prod', 'jade', {
			src: '*.jade', plumber: false, dest, cwd
		}),
		defTask('jade', 'jade', {
			src: '*.jade', plumber: true, dest, cwd
		}),
		defTask('sass-prod', 'sass', {
			src: '*.{scss,css}', plumber: false, dest, cwd
		}),
		defTask('sass', 'sass', {
			src: '*.{scss,css}', plumber: true, dest, cwd
		})
	].concat(
		scripts('script', '', ['prod'], config, cwd),
		scripts('scriptWatch', 'watch-', [], config, cwd)
	)
}

function scripts(func, prefix, depends, { scripts, paths, dest }, cwd) {
	return Seq(scripts)
		.mapEntries(([main, output]) => [main,
			defTask(prefix + main, func, {
				main, output, paths, dest, cwd
			}, depends)]
		).toArray().concat([
			group(prefix + 'scripts', Seq(scripts).keySeq().toArray())
		])
}

function defTask(name, func, options, depends) {
	return task(name, 'ferad-tasks', func, options, depends)
}
function task(name, modul, func, options, depends = []) {
	return { name, modul, func, options, depends }
}
function group(name, depends) {
	return {
		name, modul: 'ferad-configs', func: 'emptyTask',
		options: {}, depends
	}
}
function emptyTask(o, cb) {
	cb()
}

export default {
	defaults, scripts, defTask, task, group, emptyTask
}
<|endoftext|>


<commit_before>module.exports = Renderer;

var EntityManager = require('tiny-ecs').EntityManager;
var Canvas        = require('../../lib/renderer/Canvas.js');
var Position      = require('../components/Position.js');
var Spatial       = require('../components/Spatial.js');

/**
 * @constructor
 * @param {EntityManager} entities
 * @param {Canvas} screen
 */
function Renderer(screen, entities)
{
  this.screen   = screen;
  this.entities = entities;
  global.renderer = this;
}

var FILTER = [Position, Spatial];

/**
 * @param {Number} dt
 * @param {Number} time
 */
Renderer.prototype.update = function(dt, time)
{
  var entities = this.entities.queryComponents(FILTER);
  var screen = this.screen;

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];

    if (entity.colorSpirit) {
      screen
        .save()
        .vtranslate(entity.position.location)
        .drawHwRect(entity.spatial.hwidth,
          entity.colorSpirit.style)
        .restore();
    }

  }
};

<commit_msg>Gems as circs<commit_after>module.exports = Renderer;

var EntityManager = require('tiny-ecs').EntityManager;
var Canvas        = require('../../lib/renderer/Canvas.js');
var Position      = require('../components/Position.js');
var Spatial       = require('../components/Spatial.js');
var LevelObject   = require('../components/LevelObject.js');

/**
 * @constructor
 * @param {EntityManager} entities
 * @param {Canvas} screen
 */
function Renderer(screen, entities)
{
  this.screen   = screen;
  this.entities = entities;
  global.renderer = this;
}

var FILTER = [Position, Spatial];

/**
 * @param {Number} dt
 * @param {Number} time
 */
Renderer.prototype.update = function(dt, time)
{
  var entities = this.entities.queryComponents(FILTER);
  var screen = this.screen;

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];

    if (entity.levelObject) {
      switch(entity.levelObject.type) {
        case LevelObject.types.GEM:
          this.drawGem(entity);
        break;
      }
    } else if (entity.colorSpirit) {
      this.drawWall(entity);
    }
  }
};

Renderer.prototype.drawGem = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawCircle(entity.spatial.hwidth.x, entity.colorSpirit.style)
    .restore();
};

Renderer.prototype.drawWall = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawHwRect(entity.spatial.hwidth, entity.colorSpirit.style)
    .restore();
};

<|endoftext|>


<commit_before>var sinon = require('sinon')
var ajax =      require('../../src/js/ajax')
var endpoints = require('../../src/js/api-endpoints')
var adminUrls = require('../../src/js/admin-urls')
var browser =   require('../../src/js/browser')
var cookies =   require('../../src/js/cookies')
var Model = require('../../src/js/models/charter-pledges/ListCharterPledgesModel')

describe('List Charter Pledges', function () {
  var model
  var headers = {
    'content-type': 'application/json',
    'session-token': 'stored-session-token'
  }
  var ajaxGetStub
  var browserLoadingStub
  var browserLoadedStub

  beforeEach(function () {
    var getCharterPledgesPromise = function () {
      return {
        then: function (success, error) {
          success({
            'status': 'ok',
            'data': pledgeData()
          })
        }
      }
    }

    ajaxGetStub = sinon.stub(ajax, 'get')
      .withArgs(endpoints.charterPledges, headers)
      .returns(getCharterPledgesPromise())

    sinon.stub(cookies, 'get')
      .withArgs('session-token')
      .returns('stored-session-token')

    browserLoadingStub = sinon.stub(browser, 'loading')
    browserLoadedStub = sinon.stub(browser, 'loaded')

    model = new Model()
  })

  afterEach(function () {
    ajax.get.restore()
    cookies.get.restore()
    browser.loading.restore()
    browser.loaded.restore()
  })

  it('should notify user it is loading' ,function () {
      expect(browserLoadingStub.calledOnce).toBeTruthy()
  })

  it('should get pledges from api', function () {
    expect(ajaxGetStub.calledOnce).toBeTruthy()
  })

  it('should set show all pledges to false', function () {
    expect(model.showAll()).toBeFalsy()
  })

  it('should set show all button label to show all', function () {
    expect(model.showAllButtonLabel()).toEqual('Show all')
  })

  it('should only show disapproved pledges', function () {
    expect(model.pledges().length).toEqual(1)
    expect(model.pledges()[0].isApproved()).toBeFalsy()
  })

  it('should set url to supporter full name', function () {
    expect(model.pledges()[0].fullName).toEqual('first name last name')
  })

  it('should set pledge description', function () {
    expect(model.pledges()[0].description).toEqual('pledge description')
  })

  it('should set pledge approval status', function () {
    expect(model.pledges()[0].isApproved()).toBeFalsy()
  })

  it('should show user then that is loaded', function () {
    expect(browserLoadedStub.calledAfter(ajaxGetStub)).toBeTruthy()
  })

  it('should set btn--primary class for currently disapproved', function () {
    expect(model.pledges()[0].buttonClass()).toEqual('btn btn--primary')
    expect(model.pledges()[0].buttonLabel()).toEqual('Approve Pledge')
  })

  describe('Toggle Show All', function () {
    beforeEach(function () {
      model.toggleShowAll()
    })

    it('should set show all button label to only disapproved', function () {
      expect(model.showAllButtonLabel()).toEqual('View awaiting approval')
    })

    it('should show all pledges', function () {
      expect(model.pledges().length).toEqual(2)
      expect(model.pledges()[0].isApproved()).toBeFalsy()
      expect(model.pledges()[1].isApproved()).toBeTruthy()
      expect(model.showAll()).toBeTruthy()
    })

    it('should set btn--warning class for currently approved', function () {
      expect(model.pledges()[1].buttonClass()).toEqual('btn btn--warning')
      expect(model.pledges()[1].buttonLabel()).toEqual('Disapprove Pledge')
    })

    describe('And Toggle Back', function () {
      beforeEach(function () {
        model.toggleShowAll()
      })

      it('should show only disapproved pledges', function () {
        expect(model.pledges().length).toEqual(1)
        expect(model.pledges()[0].isApproved()).toBeFalsy()
        expect(model.showAll()).toBeFalsy()
      })
    })
  })

  describe('Toggle Approval', function () {
    var ajaxPutStub
    beforeEach(function () {
      var getPutPromise = function () {
        return {
          then: function (success, error) {
            success({
              'status': 'ok'
            })
          }
        }
      }
      ajaxPutStub = sinon.stub(ajax, 'put')
        .withArgs(endpoints.charterPledges + '/' + model.pledges()[0].id, headers, { isApproved: true })
        .returns(getPutPromise())
      browser.loading.reset()
      browser.loaded.reset()

      model.pledges()[0].toggleApproval()
    })

    afterEach(function () {
      ajax.put.restore()
    })

    it('should show browser is loading', function () {
      expect(browserLoadingStub.calledOnce).toBeTruthy()
    })

    it('should put new approval status to api', function () {
      expect(ajaxPutStub.calledOnce).toBeTruthy()
    })

    it('should set new approval status of pledge', function () {
      expect(model.allPledges[0].isApproved()).toBeTruthy()
    })

    it('should show browser is loaded', function () {
      expect(browserLoadedStub.calledAfter(ajaxPutStub)).toBeTruthy()
    })

    it('should hide the newly approved pledge as we are only view disapproved', function () {
      expect(model.pledges().length).toEqual(0)
    })
  })
})

var pledgeData = function () {
  return [{
    "firstName": "first name",
    "lastName": "last name",
    "email": "test@test.com",
    "organisation": "organisation",
    "isOptedIn": true,
    "proposedPledge": {
      "description": "pledge description",
      "isApproved": false
    },
    "id": "570b84af3535ff1a8459a142",
    "documentCreationDate": "2016-04-11T11:04:15.1810000Z"
  }, {
    "firstName": "first name",
    "lastName": "last name",
    "email": "test1@test.com",
    "organisation": "organisation",
    "isOptedIn": true,
    "proposedPledge": {
      "description": "pledge description",
      "isApproved": true
    },
    "id": "570b84d73535ff1a8459a143",
    "documentCreationDate": "2016-04-11T11:04:55.8600000Z"
  }]
}
<commit_msg>tests<commit_after>var sinon = require('sinon')
var ajax =      require('../../src/js/ajax')
var endpoints = require('../../src/js/api-endpoints')
var adminUrls = require('../../src/js/admin-urls')
var browser =   require('../../src/js/browser')
var cookies =   require('../../src/js/cookies')
var Model = require('../../src/js/models/charter-pledges/ListCharterPledgesModel')

describe('List Charter Pledges', function () {
  var model
  var headers = {
    'content-type': 'application/json',
    'session-token': 'stored-session-token'
  }
  var ajaxGetStub
  var browserLoadingStub
  var browserLoadedStub

  beforeEach(function () {
    var getCharterPledgesPromise = function () {
      return {
        then: function (success, error) {
          success({
            'status': 'ok',
            'data': pledgeData()
          })
        }
      }
    }

    ajaxGetStub = sinon.stub(ajax, 'get')
      .withArgs(endpoints.charterPledges, headers)
      .returns(getCharterPledgesPromise())

    sinon.stub(cookies, 'get')
      .withArgs('session-token')
      .returns('stored-session-token')

    browserLoadingStub = sinon.stub(browser, 'loading')
    browserLoadedStub = sinon.stub(browser, 'loaded')

    model = new Model()
  })

  afterEach(function () {
    ajax.get.restore()
    cookies.get.restore()
    browser.loading.restore()
    browser.loaded.restore()
  })

  it('should notify user it is loading' ,function () {
      expect(browserLoadingStub.calledOnce).toBeTruthy()
  })

  it('should get pledges from api', function () {
    expect(ajaxGetStub.calledOnce).toBeTruthy()
  })

  it('should set show all pledges to false', function () {
    expect(model.showAll()).toBeFalsy()
  })

  it('should set show all button label to show all', function () {
    expect(model.showAllButtonLabel()).toEqual('Show all')
  })

  it('should only show disapproved pledges', function () {
    expect(model.pledges().length).toEqual(1)
    expect(model.pledges()[0].isApproved()).toBeFalsy()
  })

  it('should set url to supporter full name', function () {
    expect(model.pledges()[0].fullName).toEqual('first name last name')
  })

  it('should set pledge description', function () {
    expect(model.pledges()[0].description).toEqual('pledge description')
  })

  it('should set mail to link', function () {
    expect(model.pledges()[0].mailToLink).toEqual('mailto:test@test.com')
  })

  it('should format creation date', function () {
    expect(model.pledges()[0].creationDate).toEqual('11/04/16')
  })

  it('should set pledge approval status', function () {
    expect(model.pledges()[0].isApproved()).toBeFalsy()
  })

  it('should show user then that is loaded', function () {
    expect(browserLoadedStub.calledAfter(ajaxGetStub)).toBeTruthy()
  })

  it('should set btn--primary class for currently disapproved', function () {
    expect(model.pledges()[0].buttonClass()).toEqual('btn btn--primary')
    expect(model.pledges()[0].buttonLabel()).toEqual('Approve Pledge')
  })

  describe('Toggle Show All', function () {
    beforeEach(function () {
      model.toggleShowAll()
    })

    it('should set show all button label to only disapproved', function () {
      expect(model.showAllButtonLabel()).toEqual('View awaiting approval')
    })

    it('should show all pledges', function () {
      expect(model.pledges().length).toEqual(2)
      expect(model.pledges()[0].isApproved()).toBeFalsy()
      expect(model.pledges()[1].isApproved()).toBeTruthy()
      expect(model.showAll()).toBeTruthy()
    })

    it('should set btn--warning class for currently approved', function () {
      expect(model.pledges()[1].buttonClass()).toEqual('btn btn--warning')
      expect(model.pledges()[1].buttonLabel()).toEqual('Disapprove Pledge')
    })

    describe('And Toggle Back', function () {
      beforeEach(function () {
        model.toggleShowAll()
      })

      it('should show only disapproved pledges', function () {
        expect(model.pledges().length).toEqual(1)
        expect(model.pledges()[0].isApproved()).toBeFalsy()
        expect(model.showAll()).toBeFalsy()
      })
    })
  })

  describe('Toggle Approval', function () {
    var ajaxPutStub
    beforeEach(function () {
      var getPutPromise = function () {
        return {
          then: function (success, error) {
            success({
              'status': 'ok'
            })
          }
        }
      }
      ajaxPutStub = sinon.stub(ajax, 'put')
        .withArgs(endpoints.charterPledges + '/' + model.pledges()[0].id, headers, { isApproved: true })
        .returns(getPutPromise())
      browser.loading.reset()
      browser.loaded.reset()

      model.pledges()[0].toggleApproval()
    })

    afterEach(function () {
      ajax.put.restore()
    })

    it('should show browser is loading', function () {
      expect(browserLoadingStub.calledOnce).toBeTruthy()
    })

    it('should put new approval status to api', function () {
      expect(ajaxPutStub.calledOnce).toBeTruthy()
    })

    it('should set new approval status of pledge', function () {
      expect(model.allPledges[0].isApproved()).toBeTruthy()
    })

    it('should show browser is loaded', function () {
      expect(browserLoadedStub.calledAfter(ajaxPutStub)).toBeTruthy()
    })

    it('should hide the newly approved pledge as we are only view disapproved', function () {
      expect(model.pledges().length).toEqual(0)
    })
  })
})

var pledgeData = function () {
  return [{
    "firstName": "first name",
    "lastName": "last name",
    "email": "test@test.com",
    "organisation": "organisation",
    "isOptedIn": true,
    "proposedPledge": {
      "description": "pledge description",
      "isApproved": false
    },
    "id": "570b84af3535ff1a8459a142",
    "documentCreationDate": "2016-04-11T11:04:15.1810000Z"
  }, {
    "firstName": "first name",
    "lastName": "last name",
    "email": "test1@test.com",
    "organisation": "organisation",
    "isOptedIn": true,
    "proposedPledge": {
      "description": "pledge description",
      "isApproved": true
    },
    "id": "570b84d73535ff1a8459a143",
    "documentCreationDate": "2016-04-11T11:04:55.8600000Z"
  }]
}
<|endoftext|>


<commit_before>/* global Symbol */
// run `npm install` to install deps first, then `node ./` to execute

var fs = require('fs');
var chalk = require('chalk');
var path = require('path');
var cheerio = require('cheerio');

var page = fs.readFileSync(path.join(__dirname, String(process.argv[2] || 'es6').toLowerCase(), 'index.html')).toString().replace(/data-source="[^"]*"/g,'');
var $ = cheerio.load(page);
var results = {};
var desc = {};

global.__script_executed = {};

$('#body tbody tr').each(function (index) {
  if ($(this).find('.separator')[0]) {
    return;
  }
  var scripts = $(this).find('script');
  var i = 0;
  var scr;
  global.test = function test(expression) {
    results[index] = results[index] || expression;
  };
  global.asyncPassed = function asyncPassed() {
    results[index] = true;
  };
  global.__createIterableObject = function (arr, methods) {
    methods = methods || {};
    if (typeof Symbol !== 'function' || !Symbol.iterator)
      return {};
    arr.length++;
    var iterator = {
      next: function() {
        return { value: arr.shift(), done: arr.length <= 0 };
      },
      'return': methods['return'],
      'throw': methods['throw']
    };
    var iterable = {};
    iterable[Symbol.iterator] = function(){ return iterator; };
    return iterable;
  };

  results[index] = null;

  desc[index] = $(this).find('td>span:first-child').text();

  // can be multiple scripts
  for (; scripts[i] && scripts[i].children && scripts[i].children.length; i++) {
    scr = scripts[i].children[0].data.trim()
      .replace(/global\.__asyncPassedFn && __asyncPassedFn\(".*?"\)/g, "asyncPassed");
    eval(scr);
  }
});

setTimeout(function(){
  Object.keys(results).forEach(function(test) {
    var result = results[test];
    var name = desc[test];
    if (result === null) {
      console.log('\u25BC\t' + name.replace('§',''));
    } else {
      console.log(chalk[result === "Strict" ? 'cyan' : result ? 'green' : 'red']((result ? '\u2714' : '\u2718') + '\t' + (name[0]!== '§' ? '\t' + name : name.slice(1)) + '\t'));
    }
  });
},500);
<commit_msg>Use process.on('exit') instead of setTimeout<commit_after>/* global Symbol */
// run `npm install` to install deps first, then `node ./` to execute

var fs = require('fs');
var chalk = require('chalk');
var path = require('path');
var cheerio = require('cheerio');

var page = fs.readFileSync(path.join(__dirname, String(process.argv[2] || 'es6').toLowerCase(), 'index.html')).toString().replace(/data-source="[^"]*"/g,'');
var $ = cheerio.load(page);
var results = {};
var desc = {};

global.__script_executed = {};

$('#body tbody tr').each(function (index) {
  if ($(this).find('.separator')[0]) {
    return;
  }
  var scripts = $(this).find('script');
  var i = 0;
  var scr;
  global.test = function test(expression) {
    results[index] = results[index] || expression;
  };
  global.asyncPassed = function asyncPassed() {
    results[index] = true;
  };
  global.__createIterableObject = function (arr, methods) {
    methods = methods || {};
    if (typeof Symbol !== 'function' || !Symbol.iterator)
      return {};
    arr.length++;
    var iterator = {
      next: function() {
        return { value: arr.shift(), done: arr.length <= 0 };
      },
      'return': methods['return'],
      'throw': methods['throw']
    };
    var iterable = {};
    iterable[Symbol.iterator] = function(){ return iterator; };
    return iterable;
  };

  results[index] = null;

  desc[index] = $(this).find('td>span:first-child').text();

  // can be multiple scripts
  for (; scripts[i] && scripts[i].children && scripts[i].children.length; i++) {
    scr = scripts[i].children[0].data.trim()
      .replace(/global\.__asyncPassedFn && __asyncPassedFn\(".*?"\)/g, "asyncPassed");
    eval(scr);
  }
});

process.on('exit', function(){
  Object.keys(results).forEach(function(test) {
    var result = results[test];
    var name = desc[test];
    if (result === null) {
      console.log('\u25BC\t' + name.replace('§',''));
    } else {
      console.log(chalk[result === "Strict" ? 'cyan' : result ? 'green' : 'red']((result ? '\u2714' : '\u2718') + '\t' + (name[0]!== '§' ? '\t' + name : name.slice(1)) + '\t'));
    }
  });
});
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-crowdin',
  includedCommands: function() {
    return {
      'crowdin:check': require('./lib/commands/check'),
      'crowdin:download': require('./lib/commands/download')
    };
  }
};
<commit_msg>Downloads Crowdin translations with production builds<commit_after>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-crowdin',
  preBuild: function() {
    if (!this.app.isProduction) {
      return;
    }
    return require('./lib/commands/download').run.call(this);
  },
  includedCommands: function() {
    return {
      'crowdin:check': require('./lib/commands/check'),
      'crowdin:download': require('./lib/commands/download')
    };
  }
};
<|endoftext|>


<commit_before>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('core') ;
require('system/object');
require('system/error');
require('system/locale');

SC.IMAGE_ABORTED_ERROR = SC.$error("SC.Image.AbortedError", "Image", -100) ;

SC.IMAGE_FAILED_ERROR = SC.$error("SC.Image.FailedError", "Image", -101) ;

/**
  @class

  The image cache can be used to control the order of loading images into the browser cache.

  Images queues are necessary because browsers impose strict limits on the number of concurrent connections that can be open at any one time to any one host. By controlling the order and timing of your loads using this image queue, you can improve the percieved performance of your application by ensuring the images you need most load first.

  Note that if you use the SC.ImageView class, it will use this image cache for you automatically.

  h1. Loading Images

  When you need to display an image, simply call the loadImage() method with the URL of the image, along with a target/method callback. The signature of your callback should be:

  {{{
    imageDidLoad: function(imageUrl, imageOrError) {
      //...
    }
  }}}

  The "imageOrError" parameter will contain either an image object or an error object if the image could not be loaded for some reason.  If you receive an error object, it will be one of SC.IMAGE_ABORTED_ERROR or SC.IMAGE_FAILED_ERROR.

  You can also optionally specify that the image should be loaded in the background.  Background images are loaded with a lower priority than foreground images.

  h1. Aborting Image Loads

  If you request an image load but then no longer require the image for some reason, you should notify the imageCache by calling the releaseImage() method.  Pass the URL, target and method that you included in your original loadImage() request.

  If you have requested an image before, you should always call releaseImage() when you are finished with it, even if the image has already loaded.  This will allow the imageCache to properly manage its own internal resources.

  This method may remove the image from the queue of images that need or load or it may abort an image load in progress to make room for other images.  If the image is already loaded, this method will have no effect.

  h1. Reloading an Image

  If you have already loaded an image, the imageCache will avoid loading the image again.  However, if you need to force the imageCache to reload the image for some reason, you can do so by calling reloadImage(), passing the URL.

  This will cause the image cache to attempt to load the image again the next time you call loadImage on it.

  @extends SC.Object
  @since SproutCore 1.0
*/
SC.imageCache = SC.Object.create(/** @scipe SC.imageCache.prototype */ {

  /**
    The maximum number of images that can load from a single hostname at any
    one time.  For most browsers 4 is a reasonable number, though you may
    tweak this on a browser-by-browser basis.
  */
  loadLimit: 4,

  /**
    The number of currently active requests on the cache.
  */
  activeRequests: 0,

  /**
    Loads an image from the server, calling your target/method when complete.

    You should always pass at least a URL and optionally a target/method.  If you do not pass the target/method, the image will be loaded in background priority.  Usually, however, you will want to pass a callback to be notified when the image has loaded.  Your callback should have a signature like:

  {{{
    imageDidLoad: function(imageUrl, imageOrError) { .. }
  }}}

    If you do pass a target/method you can optionally also choose to load the image either in the foreground or in the background.  The image cache prioritizes foreground images over background images.  This does not impact how many images load at one time.

    @param {String} url
    @param {Object} target
    @param {String|Function} method
    @param {Boolean} isBackgroundFlag
    @returns {SC.imageCache} receiver
  */
  loadImage: function(url, target, method, isBackgroundFlag) {
    console.log('imageCache#loadImage() called...');
    // normalize params
    var type = SC.typeOf(target);
    if (SC.none(method) && SC.typeOf(target)===SC.T_FUNCTION) {
      target = null; method = target ;
    }
    if (SC.typeOf(method) === SC.T_STRING) {
      method = target[method];
    }
    // if no callback is passed, assume background image.  otherwise, assume
    // foreground image.
    if (SC.none(isBackgroundFlag)) {
      isBackgroundFlag = SC.none(target) && SC.none(method);
    }

    // get image entry in cache.  If entry is loaded, just invoke callback
    // and quit.
    var entry = this._imageEntryFor(url) ;
    if (entry.status === this.IMAGE_LOADED) {
      if (method) method.call(target || entry.image, entry.url, entry.image);

    // otherwise, add to list of callbacks and queue image.
    } else {
      if (target || method) this._addCallback(entry, target, method);
      entry.retainCount++; // increment retain count, regardless of callback
      this._scheduleImageEntry(entry, isBackgroundFlag);
    }
  },

  /**
    Invoke this method when you are finished with an image URL.  If you
    passed a target/method, you should also pass it here to remove it from
    the list of callbacks.

    @param {String} url
    @param {Object} target
    @param {String|Function} method
    @returns {SC.imageCache} receiver
  */
  releaseImage: function(url, target, method) {

    // get entry.  if there is no entry, just return as there is nothing to
    // do.
    var entry = this._imageEntryFor(url, NO) ;
    if (!entry) return this ;

    // there is an entry, decrement the retain count.  If <=0, delete!
    if (--entry.retainCount <= 0) {
      this._deleteEntry(entry);

    // if >0, just remove target/method if passed
    } else if (target || method) {
      // normalize
      var type = SC.typeOf(target);
      if (SC.none(method) && SC.typeOf(target)===SC.T_FUNCTION) {
        target = null; method = target ;
      }
      if (SC.typeOf(method) === SC.T_STRING) {
        method = target[method];
      }

      // and remove
      this._removeCallback(entry, target, method) ;
    }
  },

  /**
    Forces the image to reload the next time you try to load it.
  */
  reloadImage: function(url) {
    var entry = this._imageEntryFor(url, NO);
    if (entry && entry.status===this.IMAGE_LOADED) {
      entry.status = this.IMAGE_WAITING;
    }
  },

  /**
    Initiates a load of the next image in the image queue.  Normally you will
    not need to call this method yourself as it will be initiated
    automatically when the queue becomes active.
  */
  loadNextImage: function() {
    var entry = null, queue;

    // only run if we don't have too many active request...
    if (this.get('activeRequests')>=this.get('loadLimit')) return;

    // first look in foreground queue
    queue = this._foregroundQueue ;
    while(queue.length>0 && !entry) entry = queue.shift();

    // then look in background queue
    if (!entry) {
      queue = this._backgroundQueue ;
      while(queue.length>0 && !entry) entry = queue.shift();
    }
    this.set('isLoading', !!entry); // update isLoading...

    // if we have an entry, then initiate an image load with the proper
    // callbacks.
    if (entry) {
      var img = (entry.image = new Image()) ;
      img.onabort = this._imageDidAbort ;
      img.onerror = this._imageDidError ;
      img.onload = this._imageDidLoad ;
      img.src = entry.url ;

      // add to loading queue.
      this._loading.push(entry) ;
    }

    // increment active requests and start next request until queue is empty
    // or until load limit is reached.
    this.incrementProperty('activeRequests');
    this.loadNextImage();
  },

  // ..........................................................
  // SUPPORT METHODS
  //

  /** @private Find or create an entry for the URL. */
  _imageEntryFor: function(url, createIfNeeded) {
    if (createIfNeeded === undefined) createIfNeeded = YES;
    var entry = this._images[url] ;
    if (!entry && createIfNeeded) {
      entry = this._images[url] = {
        url: url, status: this.IMAGE_WAITING, callbacks: [], retainCount: 0
      };
    }
    return entry ;
  },

  /** @private deletes an entry from the image queue, descheduling also */
  _deleteEntry: function(entry) {
    this._unscheduleEntry(entry) ;
    delete this._images[entry.url];
  },

  /** @private
    Add a callback to the image entry.  First search the callbacks to make
    sure this is only added once.
  */
  _addCallback: function(entry, target, method) {
    var callbacks = entry.callbacks;

    // try to find in existing array
    var handler = callbacks.find(function(x) {
      return x[0]===target && x[1]===method;
    }, this);

    // not found, add...
    if (!handler) callbacks.push([target, method]);
    callbacks = null; // avoid memory leaks
    return this ;
  },

  /** @private
    Removes a callback from the image entry.  Removing a callback just nulls
    out that position in the array.  It will be skipped when executing.
  */
  _removeCallback: function(entry, target, method) {
    var callbacks = entry.callbacks ;
    callbacks.forEach(function(x, idx) {
      if (x[0]===target && x[1]===method) callbacks[idx] = null;
    }, this);
    callbacks = null; // avoid memory leaks
    return this ;
  },

  /** @private
    Adds an entry to the foreground or background queue to load.  If the
    loader is not already running, start it as well.  If the entry is in the
    queue, but it is in the background queue, possibly move it to the
    foreground queue.
  */
  _scheduleImageEntry: function(entry, isBackgroundFlag) {

    var background = this._backgroundQueue ;
    var foreground = this._foregroundQueue ;

    // if entry is loaded, nothing to do...
    if (entry.status === this.IMAGE_LOADED) return this;

    // if image is already in background queue, but now needs to be
    // foreground, simply remove from background queue....
    if ((entry.status===this.IMAGE_QUEUE) && !isBackgroundFlag && entry.isBackground) {
      background[background.indexOf(entry)] = null ;
      entry.status = this.IMAGE_WAITING ;
    }

    // if image is not in queue already, add to queue.
    if (entry.status!==this.IMAGE_QUEUE) {
      var queue = (isBackgroundFlag) ? background : foreground ;
      queue.push(entry);
      entry.status = this.IMAGE_QUEUE ;
      entry.isBackground = isBackgroundFlag ;
    }

    // if the image loader is not already running, start it...
    if (!this.isLoading) this.invokeLater(this.loadNextImage, 100);
    this.set('isLoading', YES);

    return this ; // done!
  },

  /** @private
    Removes an entry from the foreground or background queue.
  */
  _unscheduleImageEntry: function(entry) {
    // if entry is not queued, do nothing
    if (entry.status !== this.IMAGE_QUEUE) return this ;

    var queue = entry.isBackground ? this._backgroundQueue : this._foregroundQueue ;
    queue[queue.indexOf(entry)] = null;

    // if entry is loading, abort it also.  Call local abort method in-case
    // browser decides not to follow up.
    if (this._loading.indexOf(entry) >= 0) {
      queue.image.abort();
      this.imageStatusDidChange(entry.url, this.ABORTED);
    }

    return this ;
  },

  /** @private invoked by Image().  Note that this is the image instance */
  _imageDidAbort: function() {
    SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.ABORTED);
  },

  _imageDidError: function() {
    SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.ERROR);
  },

  _imageDidLoad: function() {
    SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.LOADED);
  },

  /** @private called whenever the image loading status changes.  Notifies
    items in the queue and then cleans up the entry.
  */
  imageStatusDidChange: function(url, status) {
    var entry = this._imageEntryFor(url, NO);
    if (!entry) return; // nothing to do...
    // notify handlers.
    var value ;
    switch(status) {
      case this.LOADED:
        value = entry.image;
        break;
      case this.ABORTED:
        value = SC.IMAGE_ABORTED_ERROR;
        break;
      case this.ERROR:
        value = SC.IMAGE_FAILED_ERROR ;
        break;
      default:
        value = SC.IMAGE_FAILED_ERROR ;
        break;
    }
    entry.callbacks.forEach(function(x){
      var target = x[0], method = x[1];
      method.call(target, url, value);
    },this);

    // now clear callbacks so they aren't called again.
    entry.callbacks = [];

    // finally, if the image loaded OK, then set the status.  Otherwise
    // set it to waiting so that further attempts will load again
    entry.status = (status === this.LOADED) ? this.IMAGE_LOADED : this.IMAGE_WAITING ;

    // now cleanup image...
    var image = entry.image ;
    if (image) {
      image.onload = image.onerror = image.onabort = null ; // no more notices
      if (status !== this.LOADED) entry.image = null;
    }

    // remove from loading queue and periodically compact
    this._loading[this._loading.indexOf(entry)]=null;
    if (this._loading.length > this.loadLimit*2) {
      this._loading = this._loading.compact();
    }

    this.decrementProperty('activeRequests');
    this.loadNextImage() ;
  },

  init: function() {
    sc_super();
    this._images = {};
    this._loading = [] ;
    this._foregroundQueue = [];
    this._backgroundQueue = [];
  },

  IMAGE_LOADED: "loaded",
  IMAGE_QUEUED: "queued",
  IMAGE_WAITING: "waiting",

  ABORTED: 'aborted',
  ERROR: 'error',
  LOADED: 'loaded'
});<commit_msg>fixed SC.imageCache bug<commit_after>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('core') ;
require('system/object');
require('system/error');
require('system/locale');

SC.IMAGE_ABORTED_ERROR = SC.$error("SC.Image.AbortedError", "Image", -100) ;

SC.IMAGE_FAILED_ERROR = SC.$error("SC.Image.FailedError", "Image", -101) ;

/**
  @class

  The image cache can be used to control the order of loading images into the
   browser cache.

  Images queues are necessary because browsers impose strict limits on the
  number of concurrent connections that can be open at any one time to any one
  host. By controlling the order and timing of your loads using this image queue,
  you can improve the percieved performance of your application by ensuring the
  images you need most load first.

  Note that if you use the SC.ImageView class, it will use this image cache for
  you automatically.

  h1. Loading Images

  When you need to display an image, simply call the loadImage() method with the
  URL of the image, along with a target/method callback. The signature of your
  callback should be:

  {{{
    imageDidLoad: function(imageUrl, imageOrError) {
      //...
    }
  }}}

  The "imageOrError" parameter will contain either an image object or an error
  object if the image could not be loaded for some reason.  If you receive an
  error object, it will be one of SC.IMAGE_ABORTED_ERROR or SC.IMAGE_FAILED_ERROR.

  You can also optionally specify that the image should be loaded in the
  background.  Background images are loaded with a lower priority than foreground
  images.

  h1. Aborting Image Loads

  If you request an image load but then no longer require the image for some
  reason, you should notify the imageCache by calling the releaseImage() method.
  Pass the URL, target and method that you included in your original loadImage()
  request.

  If you have requested an image before, you should always call releaseImage()
  when you are finished with it, even if the image has already loaded.  This
  will allow the imageCache to properly manage its own internal resources.

  This method may remove the image from the queue of images that need or load or
  it may abort an image load in progress to make room for other images.  If the
  image is already loaded, this method will have no effect.

  h1. Reloading an Image

  If you have already loaded an image, the imageCache will avoid loading the
  image again.  However, if you need to force the imageCache to reload the image
  for some reason, you can do so by calling reloadImage(), passing the URL.

  This will cause the image cache to attempt to load the image again the next
  time you call loadImage on it.

  @extends SC.Object
  @since SproutCore 1.0
*/
SC.imageCache = SC.Object.create(/** @scipe SC.imageCache.prototype */ {

  /**
    The maximum number of images that can load from a single hostname at any
    one time.  For most browsers 4 is a reasonable number, though you may
    tweak this on a browser-by-browser basis.
  */
  loadLimit: 4,

  /**
    The number of currently active requests on the cache.
  */
  activeRequests: 0,

  /**
    Loads an image from the server, calling your target/method when complete.

    You should always pass at least a URL and optionally a target/method.  If
    you do not pass the target/method, the image will be loaded in background
    priority.  Usually, however, you will want to pass a callback to be
    notified when the image has loaded.  Your callback should have a signature
    like:

    {{{
      imageDidLoad: function(imageUrl, imageOrError) { .. }
    }}}

    If you do pass a target/method you can optionally also choose to load the
    image either in the foreground or in the background.  The image cache
    prioritizes foreground images over background images.  This does not impact
    how many images load at one time.

    @param {String} url
    @param {Object} target
    @param {String|Function} method
    @param {Boolean} isBackgroundFlag
    @returns {SC.imageCache} receiver
  */
  loadImage: function(url, target, method, isBackgroundFlag) {
    console.log('imageCache#loadImage() called...');
    // normalize params
    var type = SC.typeOf(target);
    if (SC.none(method) && SC.typeOf(target)===SC.T_FUNCTION) {
      target = null; method = target ;
    }
    if (SC.typeOf(method) === SC.T_STRING) {
      method = target[method];
    }
    // if no callback is passed, assume background image.  otherwise, assume
    // foreground image.
    if (SC.none(isBackgroundFlag)) {
      isBackgroundFlag = SC.none(target) && SC.none(method);
    }

    // get image entry in cache.  If entry is loaded, just invoke callback
    // and quit.
    var entry = this._imageEntryFor(url) ;
    if (entry.status === this.IMAGE_LOADED) {
      if (method) method.call(target || entry.image, entry.url, entry.image);

    // otherwise, add to list of callbacks and queue image.
    } else {
      if (target || method) this._addCallback(entry, target, method);
      entry.retainCount++; // increment retain count, regardless of callback
      this._scheduleImageEntry(entry, isBackgroundFlag);
    }
  },

  /**
    Invoke this method when you are finished with an image URL.  If you
    passed a target/method, you should also pass it here to remove it from
    the list of callbacks.

    @param {String} url
    @param {Object} target
    @param {String|Function} method
    @returns {SC.imageCache} receiver
  */
  releaseImage: function(url, target, method) {

    // get entry.  if there is no entry, just return as there is nothing to
    // do.
    var entry = this._imageEntryFor(url, NO) ;
    if (!entry) return this ;

    // there is an entry, decrement the retain count.  If <=0, delete!
    if (--entry.retainCount <= 0) {
      this._deleteEntry(entry);

    // if >0, just remove target/method if passed
    } else if (target || method) {
      // normalize
      var type = SC.typeOf(target);
      if (SC.none(method) && SC.typeOf(target)===SC.T_FUNCTION) {
        target = null; method = target ;
      }
      if (SC.typeOf(method) === SC.T_STRING) {
        method = target[method];
      }

      // and remove
      this._removeCallback(entry, target, method) ;
    }
  },

  /**
    Forces the image to reload the next time you try to load it.
  */
  reloadImage: function(url) {
    var entry = this._imageEntryFor(url, NO);
    if (entry && entry.status===this.IMAGE_LOADED) {
      entry.status = this.IMAGE_WAITING;
    }
  },

  /**
    Initiates a load of the next image in the image queue.  Normally you will
    not need to call this method yourself as it will be initiated
    automatically when the queue becomes active.
  */
  loadNextImage: function() {
    var entry = null, queue;

    // only run if we don't have too many active request...
    if (this.get('activeRequests')>=this.get('loadLimit')) return;

    // first look in foreground queue
    queue = this._foregroundQueue ;
    while(queue.length>0 && !entry) entry = queue.shift();

    // then look in background queue
    if (!entry) {
      queue = this._backgroundQueue ;
      while(queue.length>0 && !entry) entry = queue.shift();
    }
    this.set('isLoading', !!entry); // update isLoading...

    // if we have an entry, then initiate an image load with the proper
    // callbacks.
    if (entry) {
      // var img = (entry.image = new Image()) ;
      var img = entry.image ;
      img.onabort = this._imageDidAbort ;
      img.onerror = this._imageDidError ;
      img.onload = this._imageDidLoad ;
      img.src = entry.url ;

      // add to loading queue.
      this._loading.push(entry) ;
    }

    // increment active requests and start next request until queue is empty
    // or until load limit is reached.
    this.incrementProperty('activeRequests');
    this.loadNextImage();
  },

  // ..........................................................
  // SUPPORT METHODS
  //

  /** @private Find or create an entry for the URL. */
  _imageEntryFor: function(url, createIfNeeded) {
    if (createIfNeeded === undefined) createIfNeeded = YES;
    var entry = this._images[url] ;
    if (!entry && createIfNeeded) {
      var img = new Image() ;
      entry = this._images[url] = {
        url: url, status: this.IMAGE_WAITING, callbacks: [], retainCount: 0, image: img
      };
      img.entry = entry ; // provide a link back to the image
    }
    return entry ;
  },

  /** @private deletes an entry from the image queue, descheduling also */
  _deleteEntry: function(entry) {
    this._unscheduleEntry(entry) ;
    delete this._images[entry.url];
  },

  /** @private
    Add a callback to the image entry.  First search the callbacks to make
    sure this is only added once.
  */
  _addCallback: function(entry, target, method) {
    var callbacks = entry.callbacks;

    // try to find in existing array
    var handler = callbacks.find(function(x) {
      return x[0]===target && x[1]===method;
    }, this);

    // not found, add...
    if (!handler) callbacks.push([target, method]);
    callbacks = null; // avoid memory leaks
    return this ;
  },

  /** @private
    Removes a callback from the image entry.  Removing a callback just nulls
    out that position in the array.  It will be skipped when executing.
  */
  _removeCallback: function(entry, target, method) {
    var callbacks = entry.callbacks ;
    callbacks.forEach(function(x, idx) {
      if (x[0]===target && x[1]===method) callbacks[idx] = null;
    }, this);
    callbacks = null; // avoid memory leaks
    return this ;
  },

  /** @private
    Adds an entry to the foreground or background queue to load.  If the
    loader is not already running, start it as well.  If the entry is in the
    queue, but it is in the background queue, possibly move it to the
    foreground queue.
  */
  _scheduleImageEntry: function(entry, isBackgroundFlag) {

    var background = this._backgroundQueue ;
    var foreground = this._foregroundQueue ;

    // if entry is loaded, nothing to do...
    if (entry.status === this.IMAGE_LOADED) return this;

    // if image is already in background queue, but now needs to be
    // foreground, simply remove from background queue....
    if ((entry.status===this.IMAGE_QUEUE) && !isBackgroundFlag && entry.isBackground) {
      background[background.indexOf(entry)] = null ;
      entry.status = this.IMAGE_WAITING ;
    }

    // if image is not in queue already, add to queue.
    if (entry.status!==this.IMAGE_QUEUE) {
      var queue = (isBackgroundFlag) ? background : foreground ;
      queue.push(entry);
      entry.status = this.IMAGE_QUEUE ;
      entry.isBackground = isBackgroundFlag ;
    }

    // if the image loader is not already running, start it...
    if (!this.isLoading) this.invokeLater(this.loadNextImage, 100);
    this.set('isLoading', YES);

    return this ; // done!
  },

  /** @private
    Removes an entry from the foreground or background queue.
  */
  _unscheduleImageEntry: function(entry) {
    // if entry is not queued, do nothing
    if (entry.status !== this.IMAGE_QUEUE) return this ;

    var queue = entry.isBackground ? this._backgroundQueue : this._foregroundQueue ;
    queue[queue.indexOf(entry)] = null;

    // if entry is loading, abort it also.  Call local abort method in-case
    // browser decides not to follow up.
    if (this._loading.indexOf(entry) >= 0) {
      queue.image.abort();
      // this.imageStatusDidChange(entry.url, this.ABORTED);
      this.imageStatusDidChange(entry, this.ABORTED);
    }

    return this ;
  },

  /** @private invoked by Image().  Note that this is the image instance */
  _imageDidAbort: function() {
    // SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.ABORTED);
    SC.imageCache.imageStatusDidChange(this.entry, SC.imageCache.ABORTED);
  },

  _imageDidError: function() {
    // SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.ERROR);
    SC.imageCache.imageStatusDidChange(this.entry, SC.imageCache.ERROR);
  },

  _imageDidLoad: function() {
    // SC.imageCache.imageStatusDidChange(this.src, SC.imageCache.LOADED);
    SC.imageCache.imageStatusDidChange(this.entry, SC.imageCache.LOADED);
  },

  /** @private called whenever the image loading status changes.  Notifies
    items in the queue and then cleans up the entry.
  */
  // imageStatusDidChange: function(url, status) {
  imageStatusDidChange: function(entry, status) {
    // var entry = this._imageEntryFor(url, NO);
    if (!entry) return; // nothing to do...
    // notify handlers.
    var value ;
    switch(status) {
      case this.LOADED:
        value = entry.image;
        break;
      case this.ABORTED:
        value = SC.IMAGE_ABORTED_ERROR;
        break;
      case this.ERROR:
        value = SC.IMAGE_FAILED_ERROR ;
        break;
      default:
        value = SC.IMAGE_FAILED_ERROR ;
        break;
    }
    entry.callbacks.forEach(function(x){
      var target = x[0], method = x[1];
      method.call(target, url, value);
    },this);

    // now clear callbacks so they aren't called again.
    entry.callbacks = [];

    // finally, if the image loaded OK, then set the status.  Otherwise
    // set it to waiting so that further attempts will load again
    entry.status = (status === this.LOADED) ? this.IMAGE_LOADED : this.IMAGE_WAITING ;

    // now cleanup image...
    var image = entry.image ;
    if (image) {
      image.onload = image.onerror = image.onabort = null ; // no more notices
      if (status !== this.LOADED) entry.image = null;
    }

    // remove from loading queue and periodically compact
    this._loading[this._loading.indexOf(entry)]=null;
    if (this._loading.length > this.loadLimit*2) {
      this._loading = this._loading.compact();
    }

    this.decrementProperty('activeRequests');
    this.loadNextImage() ;
  },

  init: function() {
    sc_super();
    this._images = {};
    this._loading = [] ;
    this._foregroundQueue = [];
    this._backgroundQueue = [];
  },

  IMAGE_LOADED: "loaded",
  IMAGE_QUEUED: "queued",
  IMAGE_WAITING: "waiting",

  ABORTED: 'aborted',
  ERROR: 'error',
  LOADED: 'loaded'
});<|endoftext|>


<commit_before>var express = require('express')
  , cluster = require('cluster')
  , numCpus = require('os').cpus().length
  , bodyParser = require('body-parser')
  , fs = require('fs')
  , hbs = require('hbs')
  , http = require('http')
  , mongoose = require('mongoose')
  , morgan = require('morgan')
  , compress = require('compression')
  , logger = require('logfmt')
  , routes = require('./routes')
  , reports = require('./routes/reports')
  , locations = require('./routes/locations')
  , fauxAuth = require('./middleware/staging-auth')
  ;

var app = express();
var env = app.get('env');
var config = require('./config/config')[env];

var dbCnx = process.env.MONGOLAB_URI || config.db;
var db = mongoose.connect(dbCnx);
var port = process.env.PORT || config.port || 3000;

// memjs reads appropriate env variables by default.
// zero configuration necessary

app.set('view engine','ejs');
app.engine('html', hbs.__express);
app.use(compress());
app.use(express.static('public'));

app.set('port', port)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

switch (app.get('env')) {
    case 'development':
        app.use(morgan('dev'));
        break;

    case 'staging':
        app.use(fauxAuth);
        break;

    default:
        app.use(morgan('combined'));
        break;
}

app.use(require('./routes/index.js'));
app.get('/reports/count.json', reports.count);
app.get('/reports/:id.json', reports.show);
app.get('/reports.json', reports.index);
app.post('/reports.json', reports.create);
app.get('/locations.json', locations.index);
app.get('/locations/count.json', locations.count);
app.use(require('./routes/wards.js'));

if (cluster.isMaster) {
  for (var i = 0; i < numCpus - 1; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    logger.log({worker: worker.process.pid, msg: 'died', code: code, signal: signal});
  });

} else {
  http.createServer(app).listen(port, function() {
    logger.log({status: 'info', msg: 'server listening', port: port});
  });
}

<commit_msg>fix the cluster to one master and one worker<commit_after>var express = require('express')
  , cluster = require('cluster')
  , numCpus = require('os').cpus().length
  , bodyParser = require('body-parser')
  , fs = require('fs')
  , hbs = require('hbs')
  , http = require('http')
  , mongoose = require('mongoose')
  , morgan = require('morgan')
  , compress = require('compression')
  , logger = require('logfmt')
  , routes = require('./routes')
  , reports = require('./routes/reports')
  , locations = require('./routes/locations')
  , fauxAuth = require('./middleware/staging-auth')
  ;

var app = express();
var env = app.get('env');
var config = require('./config/config')[env];

var dbCnx = process.env.MONGOLAB_URI || config.db;
var db = mongoose.connect(dbCnx);
var port = process.env.PORT || config.port || 3000;

// memjs reads appropriate env variables by default.
// zero configuration necessary

app.set('view engine','ejs');
app.engine('html', hbs.__express);
app.use(compress());
app.use(express.static('public'));

app.set('port', port)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

switch (app.get('env')) {
    case 'development':
        app.use(morgan('dev'));
        break;

    case 'staging':
        app.use(fauxAuth);
        break;

    default:
        app.use(morgan('combined'));
        break;
}

app.use(require('./routes/index.js'));
app.get('/reports/count.json', reports.count);
app.get('/reports/:id.json', reports.show);
app.get('/reports.json', reports.index);
app.post('/reports.json', reports.create);
app.get('/locations.json', locations.index);
app.get('/locations/count.json', locations.count);
app.use(require('./routes/wards.js'));

if (cluster.isMaster) {
  for (var i = 0; i < 2; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    logger.log({worker: worker.process.pid, msg: 'died', code: code, signal: signal});
  });

} else {
  http.createServer(app).listen(port, function() {
    logger.log({status: 'info', msg: 'server listening', port: port});
  });
}

<|endoftext|>


<commit_before>Debug = {
	log: function(message) {
		if (config.debug) {
			console.log(message);
		}
	}
};

Progress = {

	show: function(id) {
		// This progress bar style doesn't need a show
	},

	hide: function(id) {
		$(id).html('');
	},

	start: function(id) {
		var html = '';
		$(id).html(html);
	},

	stop: function(id) {
		Progress.hide(id);
	}

};

/**
 * Class to handle submissions form a user in a form
 */
FormErrorMessages = {

	errorClass: 'invalid',
	successClass: 'success',

	applyPartially: function(form, json, success) {
		var that = this;
		$.each(json, function(field, message) {
			var elm = $(form).find("*[name='" + field + "']").parent(".form-group");
			elm.addClass(success ? that.successClass : that.errorClass);
			elm.find('.error-message').text(message);
		});
	},

	apply: function(form, json, success) {
		this.remove(form);
		this.applyPartially(form, json, success);
	},

	remove: function(form) {
		$(form).find("." + this.errorClass).removeClass(this.errorClass);
		$(form).find("." + this.successClass).removeClass(this.successClass);
	}

};

/**
 * Class for logged in user
 */
AuthUser = {

	loggedIn: false,

	init: function() {
		var accountArea = $('#userAccountName');
		var id = accountArea.attr('data-id');
		accountArea.removeAttr('data-id');
		var user = (id && id > 0) ? accountArea.text() : null;
		this.setUser(user);
	},

	setUser: function(name) {
		this.loggedIn = (name && name.length > 0);

		// Modify register button
		$('#registerBtn').css('display', this.loggedIn ? 'none' : 'block');

		// Modify account button
		var accountBtn = $('#userAccountBtn');
		accountBtn.removeClass('disabled');
		if (!this.loggedIn) {
			accountBtn.addClass('disabled');
		}
		$('#userAccountName').text(this.loggedIn ? name : 'Gast');

		// Modify login account
		var loginIcon = $('#loginBtnIcon');
		loginIcon.removeClass('glyphicon-log-in');
		loginIcon.removeClass('glyphicon-log-out');
		loginIcon.addClass(this.loggedIn ? 'glyphicon-log-out' : 'glyphicon-log-in');
		$('#logBtnText').text(this.loggedIn ? 'Abmelden' : 'Anmelden');
		var loginBtn = $('#loginBtn');
		loginBtn.removeClass('btn-danger');
		loginBtn.removeClass('btn-primary');
		loginBtn.addClass(this.loggedIn ? 'btn-danger' : 'btn-primary');
	}

};

/**
 * Class to handle alerts for user-iteractions
 */
MessageBox = {

	dismissPermanently: function(name) {
		Debug.log("Dismissing message: " + name);
		// Remove message box
		$('#' + name).remove();
		// Cookie with the specified name contains a 1 to signal it should be hidden permanently
		document.cookie = escape(name) + "=1; expires=Mon, 30 Dec 2030 00:00:00 GMT; path=/";
	},

	addError: function(message, title) {
		this.add(message, 'danger', title);
	},

	addSuccess: function(message, title) {
		this.add(message, 'success', title);
	},

	addWarning: function(message, title) {
		this.add(message, 'warning', title);
	},

	addInfo: function(message, title) {
		this.add(message, 'info', title);
	},

	add: function (message, className, title) {
		var html = '
';
		html += '<button type="button" class="close" data-dismiss="alert">×' + Lang.t('close') + '</button>';
		if (title) {
			html += '' + title + '
';
		}
		html += message + '
';
		var element = $().add(html);
		$('#messages').append(element);
		element.delay(10000).fadeOut(2000);
	}

};

/**
 * Class to handle the language phrases.
 *
 * This code bases on an implementation from https://github.com/andywer/laravel-js-localization !
 * The code is released under the MIT license.
 *
 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
 */
Lang = {

	/*
	 * Translate a message.
	 *
	 * @method get
	 * @static
	 * @param {String} messageKey       The message key (message identifier).
	 * @param {Object} [replacements]   Associative array: { variableName: "replacement", ... }
	 * @return {String} Translated message.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	t: function(messageKey, replacements) {
		if (typeof phrases[messageKey] == "undefined") {
			/* like Lang::get(), if messageKey is the name of a lang file, return it as an array */
			var result = {};
			for (var prop in phrases) {
				if (prop.indexOf(messageKey + '.') > -1) {
					result[prop] = phrases[prop];
				}
			};
			if (!isEmpty(result)) {
				return result;
			}
			/* if there is nothing to return, return messageKey */
			return messageKey;
		}

		var message = phrases[messageKey];

		if (replacements) {
			message = applyReplacements(message, replacements);
		}

		return message;
	},

	/**
	 * Returns whether the given message is defined or not.
	 *
	 * @method has
	 * @static
	 * @param {String} messageKey   Message key.
	 * @return {Boolean} True if the given message exists.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	has : function(messageKey) {
		return typeof phrases[messageKey] != "undefined";
	},

	/**
	 * Choose one of multiple message versions, based on
	 * pluralization rules. Only English pluralization
	 * supported for now. If `count` is one then the first
	 * version of the message is retuned, otherwise the
	 * second version.
	 *
	 * @method choice
	 * @static
	 * @param {String} messageKey       Message key.
	 * @param {Integer} count           Subject count for pluralization.
	 * @param {Object} [replacements]   Associative array: { variableName: "replacement", ... }
	 * @return {String} Translated message.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	choice : function(messageKey, count, replacements) {
		if (typeof phrases[messageKey] == "undefined") {
			return messageKey;
		}

		var message;
		var messageSplitted = phrases[messageKey].split('|');

		if (count == 1) {
			message = messageSplitted[0];
		} else {
			message = messageSplitted[1];
		}

		if (replacements) {
			message = applyReplacements(message, replacements);
		}

		return message;
	},

    /**
     * Replace variables used in the message by appropriate values.
     *
     * @method applyReplacements
     * @static
     * @param {String} message      Input message.
     * @param {Object} replacements Associative array: { variableName: "replacement", ... }
     * @return {String} The input message with all replacements applied.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
     */
    applyReplacements: function (message, replacements) {
        for (var replacementName in replacements) {
            var replacement = replacements[replacementName];

            var regex = new RegExp(':'+replacementName, 'g');
            message = message.replace(regex, replacement);
        }

        return message;
    },

    /**
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
     */
    isEmpty: function (obj) {
        for(var prop in obj) {
            if(obj.hasOwnProperty(prop))
                return false;
        }

        return true;
    }

};

ViewUtils = {

	parseComment: function(text) {
		// Replacements that should be ignored by _.escape method
		var replacements = [];

		// Code bases on PHP implementation from Viscacha (viscacha.org) - Author: M. Mohr
		// See: http://en.wikipedia.org/wiki/URI_scheme
		var url_protocol = "([a-z]{3,9}:\\/\\/|www\\.)";
		var url_auth = "(?:(?:[\\w\\d\\-\\.]{1,}\\:)?[\\w\\d\\-\\._]{1,}@)?"; // Authorisation information
		var url_host = "(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|[a-z\\d\\.\\-]{2,}\\.[a-z]{2,7})(?:\\:\\d+)?"; // Host (domain, tld, ip, port)
		var url_path = "(?:\\/[\\w\\d\\/;\\-%@\\~,\\.\\+\\!&=_]*)?"; // Path
		var url_query = "(?:\\?[\\w\\d=\\&;\\.:,\\_\\-\\/%@\\+\\~\\[\\]]*)?"; // Query String
		var url_fragment = "(?:#[\\w\\d\\-\\/.]*)?"; // Fragment
		var non_url_begin = "(?:[^a-z]|^)"; // Chars that seperate the beginning of an URI from the rest of the text
		var non_url_end = "(?:[\\s\\(\\)<>\"']|$)"; // Chars that seperate the end of an URI from the rest of the text

		// URL RegExp - Four matches:
		// - First is the separating char from beginning
		// - Second is the whole url
		// - Third is the URI scheme (protocoll or www. for convenience)
		// - Fourth is the separating char from the end
		var url_regex = "(" + non_url_begin + ")(" + url_protocol + url_auth + url_host + url_path + url_query + url_fragment + ")(" + non_url_end + ")";

		// Replace the URLs finally
		text = text.replace(new RegExp(url_regex, "ig"), function($0, $1, $2, $3, $4){
			var prefix = '';
			// Append http:// if URL begins with www.
			if ($3.toLowerCase() === 'www.') {
				prefix = 'http://';
			}
			// Make link and add it to the replacements
			var num = replacements.length;
			replacements[num] = $1 + '' + $2 + '' + $4;
			return '{{PARSER_REPLACEMENT:' + num + '}}';
		});

		// Escape text (avoid HTML and XSS)
		text = _.escape(text);

		// Replace the Replacements
		text = text.replace(/{{PARSER_REPLACEMENT:(\d+)}}/g, function($0, $1){
			return replacements[$1];
		});

		return text;
	},

	join: function(sep, elements) {
		var filled = [];
		_.each(elements, function(element) {
			if (!_.isEmpty(element)) {
				filled.push(element);
			}
		});
		return filled.join(sep);
	}

};

// Onload initialisation
$(document).ready(function() {
	AuthUser.init();
});
<commit_msg>Fixed bug in Lang class<commit_after>Debug = {
	log: function(message) {
		if (config.debug) {
			console.log(message);
		}
	}
};

Progress = {

	show: function(id) {
		// This progress bar style doesn't need a show
	},

	hide: function(id) {
		$(id).html('');
	},

	start: function(id) {
		var html = '';
		$(id).html(html);
	},

	stop: function(id) {
		Progress.hide(id);
	}

};

/**
 * Class to handle submissions form a user in a form
 */
FormErrorMessages = {

	errorClass: 'invalid',
	successClass: 'success',

	applyPartially: function(form, json, success) {
		var that = this;
		$.each(json, function(field, message) {
			var elm = $(form).find("*[name='" + field + "']").parent(".form-group");
			elm.addClass(success ? that.successClass : that.errorClass);
			elm.find('.error-message').text(message);
		});
	},

	apply: function(form, json, success) {
		this.remove(form);
		this.applyPartially(form, json, success);
	},

	remove: function(form) {
		$(form).find("." + this.errorClass).removeClass(this.errorClass);
		$(form).find("." + this.successClass).removeClass(this.successClass);
	}

};

/**
 * Class for logged in user
 */
AuthUser = {

	loggedIn: false,

	init: function() {
		var accountArea = $('#userAccountName');
		var id = accountArea.attr('data-id');
		accountArea.removeAttr('data-id');
		var user = (id && id > 0) ? accountArea.text() : null;
		this.setUser(user);
	},

	setUser: function(name) {
		this.loggedIn = (name && name.length > 0);

		// Modify register button
		$('#registerBtn').css('display', this.loggedIn ? 'none' : 'block');

		// Modify account button
		var accountBtn = $('#userAccountBtn');
		accountBtn.removeClass('disabled');
		if (!this.loggedIn) {
			accountBtn.addClass('disabled');
		}
		$('#userAccountName').text(this.loggedIn ? name : 'Gast');

		// Modify login account
		var loginIcon = $('#loginBtnIcon');
		loginIcon.removeClass('glyphicon-log-in');
		loginIcon.removeClass('glyphicon-log-out');
		loginIcon.addClass(this.loggedIn ? 'glyphicon-log-out' : 'glyphicon-log-in');
		$('#logBtnText').text(this.loggedIn ? 'Abmelden' : 'Anmelden');
		var loginBtn = $('#loginBtn');
		loginBtn.removeClass('btn-danger');
		loginBtn.removeClass('btn-primary');
		loginBtn.addClass(this.loggedIn ? 'btn-danger' : 'btn-primary');
	}

};

/**
 * Class to handle alerts for user-iteractions
 */
MessageBox = {

	dismissPermanently: function(name) {
		Debug.log("Dismissing message: " + name);
		// Remove message box
		$('#' + name).remove();
		// Cookie with the specified name contains a 1 to signal it should be hidden permanently
		document.cookie = escape(name) + "=1; expires=Mon, 30 Dec 2030 00:00:00 GMT; path=/";
	},

	addError: function(message, title) {
		this.add(message, 'danger', title);
	},

	addSuccess: function(message, title) {
		this.add(message, 'success', title);
	},

	addWarning: function(message, title) {
		this.add(message, 'warning', title);
	},

	addInfo: function(message, title) {
		this.add(message, 'info', title);
	},

	add: function (message, className, title) {
		var html = '
';
		html += '<button type="button" class="close" data-dismiss="alert">×' + Lang.t('close') + '</button>';
		if (title) {
			html += '' + title + '
';
		}
		html += message + '
';
		var element = $().add(html);
		$('#messages').append(element);
		element.delay(10000).fadeOut(2000);
	}

};

/**
 * Class to handle the language phrases.
 *
 * This code bases on an implementation from https://github.com/andywer/laravel-js-localization !
 * The code is released under the MIT license.
 *
 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
 */
Lang = {

	/*
	 * Translate a message.
	 *
	 * @method get
	 * @static
	 * @param {String} messageKey       The message key (message identifier).
	 * @param {Object} [replacements]   Associative array: { variableName: "replacement", ... }
	 * @return {String} Translated message.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	t: function(messageKey, replacements) {
		if (typeof phrases[messageKey] == "undefined") {
			/* like Lang::get(), if messageKey is the name of a lang file, return it as an array */
			var result = {};
			for (var prop in phrases) {
				if (prop.indexOf(messageKey + '.') > -1) {
					result[prop] = phrases[prop];
				}
			};
			if (!_.isEmpty(result)) {
				return result;
			}
			/* if there is nothing to return, return messageKey */
			return messageKey;
		}

		var message = phrases[messageKey];

		if (replacements) {
			message = applyReplacements(message, replacements);
		}

		return message;
	},

	/**
	 * Returns whether the given message is defined or not.
	 *
	 * @method has
	 * @static
	 * @param {String} messageKey   Message key.
	 * @return {Boolean} True if the given message exists.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	has : function(messageKey) {
		return typeof phrases[messageKey] != "undefined";
	},

	/**
	 * Choose one of multiple message versions, based on
	 * pluralization rules. Only English pluralization
	 * supported for now. If `count` is one then the first
	 * version of the message is retuned, otherwise the
	 * second version.
	 *
	 * @method choice
	 * @static
	 * @param {String} messageKey       Message key.
	 * @param {Integer} count           Subject count for pluralization.
	 * @param {Object} [replacements]   Associative array: { variableName: "replacement", ... }
	 * @return {String} Translated message.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
	 */
	choice : function(messageKey, count, replacements) {
		if (typeof phrases[messageKey] == "undefined") {
			return messageKey;
		}

		var message;
		var messageSplitted = phrases[messageKey].split('|');

		if (count == 1) {
			message = messageSplitted[0];
		} else {
			message = messageSplitted[1];
		}

		if (replacements) {
			message = applyReplacements(message, replacements);
		}

		return message;
	},

    /**
     * Replace variables used in the message by appropriate values.
     *
     * @method applyReplacements
     * @static
     * @param {String} message      Input message.
     * @param {Object} replacements Associative array: { variableName: "replacement", ... }
     * @return {String} The input message with all replacements applied.
	 * @author Andy Wermke, https://github.com/andywer/laravel-js-localization
     */
    applyReplacements: function (message, replacements) {
        for (var replacementName in replacements) {
            var replacement = replacements[replacementName];

            var regex = new RegExp(':'+replacementName, 'g');
            message = message.replace(regex, replacement);
        }

        return message;
    }

};

ViewUtils = {

	parseComment: function(text) {
		// Replacements that should be ignored by _.escape method
		var replacements = [];

		// Code bases on PHP implementation from Viscacha (viscacha.org) - Author: M. Mohr
		// See: http://en.wikipedia.org/wiki/URI_scheme
		var url_protocol = "([a-z]{3,9}:\\/\\/|www\\.)";
		var url_auth = "(?:(?:[\\w\\d\\-\\.]{1,}\\:)?[\\w\\d\\-\\._]{1,}@)?"; // Authorisation information
		var url_host = "(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|[a-z\\d\\.\\-]{2,}\\.[a-z]{2,7})(?:\\:\\d+)?"; // Host (domain, tld, ip, port)
		var url_path = "(?:\\/[\\w\\d\\/;\\-%@\\~,\\.\\+\\!&=_]*)?"; // Path
		var url_query = "(?:\\?[\\w\\d=\\&;\\.:,\\_\\-\\/%@\\+\\~\\[\\]]*)?"; // Query String
		var url_fragment = "(?:#[\\w\\d\\-\\/.]*)?"; // Fragment
		var non_url_begin = "(?:[^a-z]|^)"; // Chars that seperate the beginning of an URI from the rest of the text
		var non_url_end = "(?:[\\s\\(\\)<>\"']|$)"; // Chars that seperate the end of an URI from the rest of the text

		// URL RegExp - Four matches:
		// - First is the separating char from beginning
		// - Second is the whole url
		// - Third is the URI scheme (protocoll or www. for convenience)
		// - Fourth is the separating char from the end
		var url_regex = "(" + non_url_begin + ")(" + url_protocol + url_auth + url_host + url_path + url_query + url_fragment + ")(" + non_url_end + ")";

		// Replace the URLs finally
		text = text.replace(new RegExp(url_regex, "ig"), function($0, $1, $2, $3, $4){
			var prefix = '';
			// Append http:// if URL begins with www.
			if ($3.toLowerCase() === 'www.') {
				prefix = 'http://';
			}
			// Make link and add it to the replacements
			var num = replacements.length;
			replacements[num] = $1 + '' + $2 + '' + $4;
			return '{{PARSER_REPLACEMENT:' + num + '}}';
		});

		// Escape text (avoid HTML and XSS)
		text = _.escape(text);

		// Replace the Replacements
		text = text.replace(/{{PARSER_REPLACEMENT:(\d+)}}/g, function($0, $1){
			return replacements[$1];
		});

		return text;
	},

	join: function(sep, elements) {
		var filled = [];
		_.each(elements, function(element) {
			if (!_.isEmpty(element)) {
				filled.push(element);
			}
		});
		return filled.join(sep);
	}

};

// Onload initialisation
$(document).ready(function() {
	AuthUser.init();
});
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

slapp.message('bones', ['mention', 'direct_message'], (msg) => {
  msg.say(':bones-smiley:')
}

slapp.message('heart', ['mention', 'direct_message'], (msg) => {
  msg.say(':heart-love:')
}

slapp.message('lungs', ['mention', 'direct_message'], (msg) => {
  msg.say(':lungs-happy:')
}

slapp.message('brain', ['mention', 'direct_message'], (msg) => {
  msg.say(':brain-idea:')
}

slapp.message('stomach', ['mention', 'direct_message'], (msg) => {
  msg.say(':stomach-tongue:')
}

// var HELP_TEXT = `
// I will respond to the following messages:
// \`help\` - to see this message.
// \`hi\` - to demonstrate a conversation that tracks state.
// \`thanks\` - to demonstrate a simple response.
// \`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
// \`attachment\` - to see a Slack attachment message.
// `

// //*********************************************
// // Setup different handlers for messages
// //*********************************************

// // response to the user typing "help"
// slapp.message('help', ['mention', 'direct_message'], (msg) => {
  // msg.say(HELP_TEXT)
// })

// // "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
// slapp
  // .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    // msg
      // .say(`${text}, how are you?`)
      // // sends next event from user to this route, passing along state
      // .route('how-are-you', { greeting: text })
  // })
  // .route('how-are-you', (msg, state) => {
    // var text = (msg.body.event && msg.body.event.text) || ''

    // // user may not have typed text as their next action, ask again and re-route
    // if (!text) {
      // return msg
        // .say("Whoops, I'm still waiting to hear how you're doing.")
        // .say('How are you?')
        // .route('how-are-you', state)
    // }

    // // add their response to state
    // state.status = text

    // msg
      // .say(`Ok then. What's your favorite color?`)
      // .route('color', state)
  // })
  // .route('color', (msg, state) => {
    // var text = (msg.body.event && msg.body.event.text) || ''

    // // user may not have typed text as their next action, ask again and re-route
    // if (!text) {
      // return msg
        // .say("I'm eagerly awaiting to hear your favorite color.")
        // .route('color', state)
    // }

    // // add their response to state
    // state.color = text

    // msg
      // .say('Thanks for sharing.')
      // .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // // At this point, since we don't route anywhere, the "conversation" is over
  // })

// // Can use a regex as well
// slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // // You can provide a list of responses, and a random one will be chosen
  // // You can also include slack emoji in your responses
  // msg.say([
    // "You're welcome :smile:",
    // 'You bet',
    // ':+1: Of course',
    // 'Anytime :sun_with_face: :full_moon_with_face:'
  // ])
// })

// // demonstrate returning an attachment...
// slapp.message('attachment', ['mention', 'direct_message'], (msg) => {
  // msg.say({
    // text: 'Check out this amazing attachment! :confetti_ball: ',
    // attachments: [{
      // text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      // title: 'Slapp Library - Open Source',
      // image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      // title_link: 'https://beepboophq.com/',
      // color: '#7CD197'
    // }]
  // })
// })

// // Catch-all for any other responses not handled above
// slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
  // // respond only 40% of the time
  // if (Math.random() < 0.4) {
    // msg.say([':wave:', ':pray:', ':raised_hands:'])
  // }
// })

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<commit_msg>fix parens<commit_after>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

slapp.message('bones', ['mention', 'direct_message'], (msg) => {
  msg.say(':bones-smiley:')
})

slapp.message('heart', ['mention', 'direct_message'], (msg) => {
  msg.say(':heart-love:')
})

slapp.message('lungs', ['mention', 'direct_message'], (msg) => {
  msg.say(':lungs-happy:')
})

slapp.message('brain', ['mention', 'direct_message'], (msg) => {
  msg.say(':brain-idea:')
})

slapp.message('stomach', ['mention', 'direct_message'], (msg) => {
  msg.say(':stomach-tongue:')
})

// var HELP_TEXT = `
// I will respond to the following messages:
// \`help\` - to see this message.
// \`hi\` - to demonstrate a conversation that tracks state.
// \`thanks\` - to demonstrate a simple response.
// \`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
// \`attachment\` - to see a Slack attachment message.
// `

// //*********************************************
// // Setup different handlers for messages
// //*********************************************

// // response to the user typing "help"
// slapp.message('help', ['mention', 'direct_message'], (msg) => {
  // msg.say(HELP_TEXT)
// })

// // "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
// slapp
  // .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    // msg
      // .say(`${text}, how are you?`)
      // // sends next event from user to this route, passing along state
      // .route('how-are-you', { greeting: text })
  // })
  // .route('how-are-you', (msg, state) => {
    // var text = (msg.body.event && msg.body.event.text) || ''

    // // user may not have typed text as their next action, ask again and re-route
    // if (!text) {
      // return msg
        // .say("Whoops, I'm still waiting to hear how you're doing.")
        // .say('How are you?')
        // .route('how-are-you', state)
    // }

    // // add their response to state
    // state.status = text

    // msg
      // .say(`Ok then. What's your favorite color?`)
      // .route('color', state)
  // })
  // .route('color', (msg, state) => {
    // var text = (msg.body.event && msg.body.event.text) || ''

    // // user may not have typed text as their next action, ask again and re-route
    // if (!text) {
      // return msg
        // .say("I'm eagerly awaiting to hear your favorite color.")
        // .route('color', state)
    // }

    // // add their response to state
    // state.color = text

    // msg
      // .say('Thanks for sharing.')
      // .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // // At this point, since we don't route anywhere, the "conversation" is over
  // })

// // Can use a regex as well
// slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // // You can provide a list of responses, and a random one will be chosen
  // // You can also include slack emoji in your responses
  // msg.say([
    // "You're welcome :smile:",
    // 'You bet',
    // ':+1: Of course',
    // 'Anytime :sun_with_face: :full_moon_with_face:'
  // ])
// })

// // demonstrate returning an attachment...
// slapp.message('attachment', ['mention', 'direct_message'], (msg) => {
  // msg.say({
    // text: 'Check out this amazing attachment! :confetti_ball: ',
    // attachments: [{
      // text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      // title: 'Slapp Library - Open Source',
      // image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      // title_link: 'https://beepboophq.com/',
      // color: '#7CD197'
    // }]
  // })
// })

// // Catch-all for any other responses not handled above
// slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
  // // respond only 40% of the time
  // if (Math.random() < 0.4) {
    // msg.say([':wave:', ':pray:', ':raised_hands:'])
  // }
// })

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<|endoftext|>