<commit_before>import { spawn } from 'child_process';
import fs from 'fs-promise';
import os from 'os';
import path from 'path';

import { expect } from 'chai';

import installDeps from '../src/util/install-dependencies';

const pSpawn = async (args = [], opts = {
  stdio: process.platform === 'win32' ? 'inherit' : 'pipe',
}) => {
  const child = spawn(process.execPath, [path.resolve(__dirname, '../dist/electron-forge.js')].concat(args), opts);
  let stdout = '';
  let stderr = '';
  if (process.platform !== 'win32') {
    child.stdout.on('data', (data) => { stdout += data; });
    child.stderr.on('data', (data) => { stderr += data; });
  }
  return new Promise((resolve, reject) => {
    child.on('exit', (code) => {
      if (code === 0) {
        return resolve(stdout);
      }
      reject(new Error(stderr));
    });
  });
};

const installer = process.argv.find(arg => arg.startsWith('--installer=')) || '--installer=system default';

describe(`electron-forge CLI (with installer=${installer.substr(12)})`, () => {
  it.skip('should output help', async () => {
    expect(await pSpawn(['--help'])).to.contain('Usage: electron-forge [options] [command]');
  });

  let dirID = Date.now();
  const forLintingMethod = (lintStyle) => {
    describe(`init (with lintStyle=${lintStyle})`, () => {
      let dir;

      before(async () => {
        dir = path.resolve(os.tmpdir(), `electron-forge-test-${dirID}`);
        dirID += 1;
        await fs.remove(dir);
        await pSpawn(['init', dir, `--lintstyle=${lintStyle}`]);
      });

      it('should create a new folder with a npm module inside', async () => {
        expect(await fs.exists(dir), 'the target dir should have been created').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'package.json')), 'the package.json file should exist').to.equal(true);
      });

      it('should have initialized a git repository', async () => {
        expect(await fs.exists(path.resolve(dir, '.git')), 'the .git folder should exist').to.equal(true);
      });

      it('should have installed the initial node_modules', async () => {
        expect(await fs.exists(path.resolve(dir, 'node_modules')), 'node_modules folder should exist').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'node_modules/electron-prebuilt-compile')), 'electron-prebuilt-compile should exist').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'node_modules/babel-core')), 'babel-core should exist').to.equal(true);
      });

      describe('lint', () => {
        it('should initially pass the linting process', () => pSpawn(['lint', dir]));
      });

      after(() => fs.remove(dir));
    });
  };
  forLintingMethod('airbnb');
  forLintingMethod('standard');

  describe('after init', () => {
    let dir;

    before(async () => {
      dir = path.resolve(os.tmpdir(), `electron-forge-test-${dirID}/electron-forge-test`);
      dirID += 1;
      await pSpawn(['init', dir]);
    });

    it('can package without errors', async () => {
      await pSpawn(['package', dir]);
    });

    it('can package without errors with native pre-gyp deps installed', async () => {
      await installDeps(dir, ['ref']);
      await pSpawn(['package', dir]);
    });

    describe('after package', () => {
      let targets = [];
      if (fs.existsSync(path.resolve(__dirname, `../src/makers/${process.platform}`))) {
        targets = fs.readdirSync(path.resolve(__dirname, `../src/makers/${process.platform}`)).map(file => path.parse(file).name);
      }
      const genericTargets = fs.readdirSync(path.resolve(__dirname, '../src/makers/generic')).map(file => path.parse(file).name);

      [].concat(targets).concat(genericTargets).forEach((target) => {
        describe(`make (with target=${target})`, () => {
          before(async () => {
            const packageJSON = JSON.parse(await fs.readFile(path.resolve(dir, 'package.json'), 'utf8'));
            packageJSON.config.forge.make_targets[process.platform] = [target];
            await fs.writeFile(path.resolve(dir, 'package.json'), JSON.stringify(packageJSON));
          });

          it('successfully makes with default config', async () => {
            await pSpawn(['make', dir, '-s']);
          });
        });
      });
    });

    after(() => fs.remove(dir));
  });
});
<commit_msg>test(generic): only skip help spec on Windows (#34)<commit_after>import { spawn } from 'child_process';
import fs from 'fs-promise';
import os from 'os';
import path from 'path';

import { expect } from 'chai';

import installDeps from '../src/util/install-dependencies';

const pSpawn = async (args = [], opts = {
  stdio: process.platform === 'win32' ? 'inherit' : 'pipe',
}) => {
  const child = spawn(process.execPath, [path.resolve(__dirname, '../dist/electron-forge.js')].concat(args), opts);
  let stdout = '';
  let stderr = '';
  if (process.platform !== 'win32') {
    child.stdout.on('data', (data) => { stdout += data; });
    child.stderr.on('data', (data) => { stderr += data; });
  }
  return new Promise((resolve, reject) => {
    child.on('exit', (code) => {
      if (code === 0) {
        return resolve(stdout);
      }
      reject(new Error(stderr));
    });
  });
};

const installer = process.argv.find(arg => arg.startsWith('--installer=')) || '--installer=system default';

describe(`electron-forge CLI (with installer=${installer.substr(12)})`, () => {
  it('should output help', async function helpSpec() {
    if (process.platform === 'win32') {
      this.skip();
    } else {
      expect(await pSpawn(['--help'])).to.contain('Usage: electron-forge [options] [command]');
    }
  });

  let dirID = Date.now();
  const forLintingMethod = (lintStyle) => {
    describe(`init (with lintStyle=${lintStyle})`, () => {
      let dir;

      before(async () => {
        dir = path.resolve(os.tmpdir(), `electron-forge-test-${dirID}`);
        dirID += 1;
        await fs.remove(dir);
        await pSpawn(['init', dir, `--lintstyle=${lintStyle}`]);
      });

      it('should create a new folder with a npm module inside', async () => {
        expect(await fs.exists(dir), 'the target dir should have been created').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'package.json')), 'the package.json file should exist').to.equal(true);
      });

      it('should have initialized a git repository', async () => {
        expect(await fs.exists(path.resolve(dir, '.git')), 'the .git folder should exist').to.equal(true);
      });

      it('should have installed the initial node_modules', async () => {
        expect(await fs.exists(path.resolve(dir, 'node_modules')), 'node_modules folder should exist').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'node_modules/electron-prebuilt-compile')), 'electron-prebuilt-compile should exist').to.equal(true);
        expect(await fs.exists(path.resolve(dir, 'node_modules/babel-core')), 'babel-core should exist').to.equal(true);
      });

      describe('lint', () => {
        it('should initially pass the linting process', () => pSpawn(['lint', dir]));
      });

      after(() => fs.remove(dir));
    });
  };
  forLintingMethod('airbnb');
  forLintingMethod('standard');

  describe('after init', () => {
    let dir;

    before(async () => {
      dir = path.resolve(os.tmpdir(), `electron-forge-test-${dirID}/electron-forge-test`);
      dirID += 1;
      await pSpawn(['init', dir]);
    });

    it('can package without errors', async () => {
      await pSpawn(['package', dir]);
    });

    it('can package without errors with native pre-gyp deps installed', async () => {
      await installDeps(dir, ['ref']);
      await pSpawn(['package', dir]);
    });

    describe('after package', () => {
      let targets = [];
      if (fs.existsSync(path.resolve(__dirname, `../src/makers/${process.platform}`))) {
        targets = fs.readdirSync(path.resolve(__dirname, `../src/makers/${process.platform}`)).map(file => path.parse(file).name);
      }
      const genericTargets = fs.readdirSync(path.resolve(__dirname, '../src/makers/generic')).map(file => path.parse(file).name);

      [].concat(targets).concat(genericTargets).forEach((target) => {
        describe(`make (with target=${target})`, () => {
          before(async () => {
            const packageJSON = JSON.parse(await fs.readFile(path.resolve(dir, 'package.json'), 'utf8'));
            packageJSON.config.forge.make_targets[process.platform] = [target];
            await fs.writeFile(path.resolve(dir, 'package.json'), JSON.stringify(packageJSON));
          });

          it('successfully makes with default config', async () => {
            await pSpawn(['make', dir, '-s']);
          });
        });
      });
    });

    after(() => fs.remove(dir));
  });
});
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2011 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

SC.RenderBuffer = function(tagName) {
  return SC._RenderBuffer.create({ elementTag: tagName });
};

SC._RenderBuffer = SC.Object.extend(
  /** @scope SC.RenderBuffer.prototype */ {

  elementClasses: null,
  elementId: null,
  elementAttributes: null,
  elementContent: null,
  elementTag: null,
  parentBuffer: null,

  init: function() {
    sc_super();

    this.set('elementClasses', []);
    this.set('elementAttributes', {});
    this.set('elementContent', []);
  },

  push: function(string) {
    this.get('elementContent').push(string);
    return this;
  },

  addClass: function(className) {
    this.get('elementClasses').pushObject(className);
    return this;
  },

  id: function(id) {
    this.set('elementId', id);
    return this;
  },

  attr: function(name, value) {
    this.get('elementAttributes')[name] = value;
    return this;
  },

  begin: function(tagName) {
    return SC._RenderBuffer.create({
      parentBuffer: this,
      elementTag: tagName
    });
  },

  end: function() {
    var parent = this.get('parentBuffer');

    if (parent) {
      var string = this.string();
      parent.push(string);
      return parent;
    } else {
      return this;
    }
  },

  element: function() {
    return SC.$(this.string())[0];
  },

  string: function() {
    var id = this.get('elementId'),
        classes = this.get('elementClasses'),
        attrs = this.get('elementAttributes'),
        content = this.get('elementContent'),
        tag = this.get('elementTag');

    var openTag = ["<" + tag];

    if (id) { openTag.push('id="' + id + '"'); }
    if (classes.length) { openTag.push('classes="' + classes.join(" ") + '"'); }

    for (var prop in attrs) {
      if (attrs.hasOwnProperty(prop)) {
        openTag.push(prop + '="' + attrs[prop] + '"');
      }
    }
    openTag.push('>');

    openTag = openTag.join(" ");

    return openTag + content.join() + "</" + tag + ">";
  }
});
<commit_msg>the HTML attribute listing classes is "class", not "classes" #wot<commit_after>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2011 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

SC.RenderBuffer = function(tagName) {
  return SC._RenderBuffer.create({ elementTag: tagName });
};

SC._RenderBuffer = SC.Object.extend(
  /** @scope SC.RenderBuffer.prototype */ {

  elementClasses: null,
  elementId: null,
  elementAttributes: null,
  elementContent: null,
  elementTag: null,
  parentBuffer: null,

  init: function() {
    sc_super();

    this.set('elementClasses', []);
    this.set('elementAttributes', {});
    this.set('elementContent', []);
  },

  push: function(string) {
    this.get('elementContent').push(string);
    return this;
  },

  addClass: function(className) {
    this.get('elementClasses').pushObject(className);
    return this;
  },

  id: function(id) {
    this.set('elementId', id);
    return this;
  },

  attr: function(name, value) {
    this.get('elementAttributes')[name] = value;
    return this;
  },

  begin: function(tagName) {
    return SC._RenderBuffer.create({
      parentBuffer: this,
      elementTag: tagName
    });
  },

  end: function() {
    var parent = this.get('parentBuffer');

    if (parent) {
      var string = this.string();
      parent.push(string);
      return parent;
    } else {
      return this;
    }
  },

  element: function() {
    return SC.$(this.string())[0];
  },

  string: function() {
    var id = this.get('elementId'),
        classes = this.get('elementClasses'),
        attrs = this.get('elementAttributes'),
        content = this.get('elementContent'),
        tag = this.get('elementTag');

    var openTag = ["<" + tag];

    if (id) { openTag.push('id="' + id + '"'); }
    if (classes.length) { openTag.push('class="' + classes.join(" ") + '"'); }

    for (var prop in attrs) {
      if (attrs.hasOwnProperty(prop)) {
        openTag.push(prop + '="' + attrs[prop] + '"');
      }
    }
    openTag.push('>');

    openTag = openTag.join(" ");

    return openTag + content.join() + "</" + tag + ">";
  }
});
<|endoftext|>


<commit_before>/*
 * FileExecutableSearch.js
 * Objective-J
 *
 * Created by Francisco Tolmasky.
 * Copyright 2010, 280 North, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

var FileExecutableSearchesForPaths = [{ }, { }];

function FileExecutableSearch(/*String*/ aPath, /*BOOL*/ isLocal)
{
    if (!FILE.isAbsolute(aPath) && isLocal)
        throw "Local searches cannot be relative: " + aPath;

    var existingSearch = FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath];

    if (existingSearch)
        return existingSearch;

    FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath] = this;

    this._UID = objj_generateObjectUID();
    this._isComplete = NO;
    this._eventDispatcher = new EventDispatcher(this);
    this._path = aPath;

    this._result = NULL;

    var self = this;

    function completed(/*String*/ aStaticResource)
    {
        if (!aStaticResource)
            throw new Error("Could not load file at " + aPath);

        self._result = new FileExecutable(aStaticResource.path());
        self._isComplete = YES;

        self._eventDispatcher.dispatchEvent(
        {
            type:"complete",
            fileExecutableSearch:self
        });
    }

    if (isLocal)
        rootResource.resolveSubPath(aPath, NO, completed);
    else
        StaticResource.resolveStandardNodeAtPath(aPath, completed);
}

exports.FileExecutableSearch = FileExecutableSearch;

FileExecutableSearch.prototype.path = function()
{
    return this._path;
}

FileExecutableSearch.prototype.result = function()
{
    return this._result;
}

FileExecutableSearch.prototype.UID = function()
{
    return this._UID;
}

FileExecutableSearch.prototype.isComplete = function()
{
    return this._isComplete;
}

FileExecutableSearch.prototype.result = function()
{
    return this._result;
}

FileExecutableSearch.prototype.addEventListener = function(/*String*/ anEventName, /*Function*/ aListener)
{
    this._eventDispatcher.addEventListener(anEventName, aListener);
}

FileExecutableSearch.prototype.removeEventListener = function(/*String*/ anEventName, /*Function*/ aListener)
{
    this._eventDispatcher.removeEventListener(anEventName, aListener);
}

#if DEPENDENCY_LOGGING
FileExecutableSearch.prototype.toString = function()
{
    return "<FileExecutableSearch: " + this.path() + ">";
}
#endif
<commit_msg>Fix for absolute paths working with <> includes.<commit_after>/*
 * FileExecutableSearch.js
 * Objective-J
 *
 * Created by Francisco Tolmasky.
 * Copyright 2010, 280 North, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

var FileExecutableSearchesForPaths = [{ }, { }];

function FileExecutableSearch(/*String*/ aPath, /*BOOL*/ isLocal)
{
    if (!FILE.isAbsolute(aPath) && isLocal)
        throw "Local searches cannot be relative: " + aPath;

    var existingSearch = FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath];

    if (existingSearch)
        return existingSearch;

    FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath] = this;

    this._UID = objj_generateObjectUID();
    this._isComplete = NO;
    this._eventDispatcher = new EventDispatcher(this);
    this._path = aPath;

    this._result = NULL;

    var self = this;

    function completed(/*String*/ aStaticResource)
    {
        if (!aStaticResource)
            throw new Error("Could not load file at " + aPath);

        self._result = new FileExecutable(aStaticResource.path());
        self._isComplete = YES;

        self._eventDispatcher.dispatchEvent(
        {
            type:"complete",
            fileExecutableSearch:self
        });
    }

    if (isLocal || FILE.isAbsolute(aPath))
        rootResource.resolveSubPath(aPath, NO, completed);
    else
        StaticResource.resolveStandardNodeAtPath(aPath, completed);
}

exports.FileExecutableSearch = FileExecutableSearch;

FileExecutableSearch.prototype.path = function()
{
    return this._path;
}

FileExecutableSearch.prototype.result = function()
{
    return this._result;
}

FileExecutableSearch.prototype.UID = function()
{
    return this._UID;
}

FileExecutableSearch.prototype.isComplete = function()
{
    return this._isComplete;
}

FileExecutableSearch.prototype.result = function()
{
    return this._result;
}

FileExecutableSearch.prototype.addEventListener = function(/*String*/ anEventName, /*Function*/ aListener)
{
    this._eventDispatcher.addEventListener(anEventName, aListener);
}

FileExecutableSearch.prototype.removeEventListener = function(/*String*/ anEventName, /*Function*/ aListener)
{
    this._eventDispatcher.removeEventListener(anEventName, aListener);
}

#if DEPENDENCY_LOGGING
FileExecutableSearch.prototype.toString = function()
{
    return "<FileExecutableSearch: " + this.path() + ">";
}
#endif
<|endoftext|>


<commit_before>/**
 * Iterates over a list of elements, yielding each in turn to an iterate function.
 */

//var arr = ['a','b','c'];
//
//each(arr, function(item, index, list) {
//    console.log('VAL >', item, index, list);
//});
//
//each(arr, {name: "John"}, function(item, index, list, params, next) {
//    console.log('ITEM >', item, index, list, params)
//    next();
//}, function(err){
//    if(err) {
//        console.log('err', err);
//        return;
//    }
//    console.log('done');
//});
define('each', function () {

    var regex = /([^\s,]+)/g;

    function getParamNames(fn) {
        var funStr = fn.toString();
        return funStr.slice(funStr.indexOf('(') + 1, funStr.indexOf(')')).match(regex);
    }

    function each(list) {
        var params, handler, done, progress;
        if(typeof arguments[1] === 'function') {
            handler = arguments[1];
            done = arguments[2];
            progress = arguments[2];
        } else {
            params = arguments[1] === null || arguments[1] === undefined ? {} : arguments[1];
            handler = arguments[2];
            done = arguments[3];
            progress = arguments[4];
        }

        if (!list) {
            if (done) {
                done(undefined, list, params);// we complete immediately if there is no list.
            }
            return;
        }

        // var fnDesc = handler.toString();
        var next;
        var index = 0;
        var returnVal;
        var paramNames = getParamNames(handler);
        var keys;
        var len;

        if (list.length === undefined) {
            keys = Object.keys(list);
            len = keys.length;
        }

        // allow params to modify the loop directly if they have a = in front of them.
        // start the loop part way through or so on.
        // Future feature: to have it set the starting index.
        //if (params && params['=index']) {
        //    index = params['=index'];
        //}

        var iterate = function () {
            // use list length. in case they remove or add items.
            len = keys ? len : list.length;
            if (index < len) {
                try {
                    if(params) {
                        returnVal = handler(keys ? list[keys[index]] : list[index], keys ? keys[index] : index, list, params, next);
                    } else {
                        returnVal = handler(keys ? list[keys[index]] : list[index], keys ? keys[index] : index, list, next);
                    }
                } catch(e) {
                    if (done) {
                        done(e, list, params);
                    } else {
                        throw e;// non async methods need to show the error.
                    }
                }
                // if return true then exit the loop.
                if (returnVal !== undefined) {
                    iterate = null;
                    if (done) {
                        done(returnVal, list, params);
                        return;
                    }
                    return returnVal;
                }
                if (!next) {
                    index += 1;// only if synchronous increment here.
                    iterate();
                }
            } else if (typeof done === 'function') {
                iterate = null;
                done(null, list, params);
            }
        };

        var now = Date.now();
        var limitIndex = 0;
        /**
         * Allow to process withing a ms threshold.
         * Example would be iterate as many as possible within a 10ms threshold.
         * This makes the async loop faster than 1 frame wait for each item with a 0 timeout.
         * @param {Number=} threshold
         * @param {Number=} max number of items to process before coming up for air.
         */
        function iter(threshold, limit) {
            var current;
            index += 1;// if asynchronous increment here.
            if (threshold || limit) {
                limit = limit || 500;
                current = Date.now();
                if (current < now + threshold && (!limit || index - limitIndex < limit)) {
                    iterate();
                    return;
                }
                if (progress) {
                    progress(index, len);
                }
                limitIndex = index;
                now = current;
            }
            setTimeout(iterate, 0);
        }

        if(params) {
            if(paramNames && paramNames.length === 5) {
                next = iter;
            }
        } else {
            if(paramNames && paramNames.length === 4) {
                next = iter;
            }
        }

        var syncReturnVal = iterate();
        if (syncReturnVal !== undefined) {
            return syncReturnVal;
        }
        if (!done && params) {
            return params;
        }
    }

    return each;
});
<commit_msg>each not returning value in correct spot<commit_after>/**
 * Iterates over a list of elements, yielding each in turn to an iterate function.
 */

//var arr = ['a','b','c'];
//
//each(arr, function(item, index, list) {
//    console.log('VAL >', item, index, list);
//});
//
//each(arr, {name: "John"}, function(item, index, list, params, next) {
//    console.log('ITEM >', item, index, list, params)
//    next();
//}, function(err){
//    if(err) {
//        console.log('err', err);
//        return;
//    }
//    console.log('done');
//});
define('each', function () {

    var regex = /([^\s,]+)/g;

    function getParamNames(fn) {
        var funStr = fn.toString();
        return funStr.slice(funStr.indexOf('(') + 1, funStr.indexOf(')')).match(regex);
    }

    function each(list) {
        var params, handler, done, progress;
        if(typeof arguments[1] === 'function') {
            handler = arguments[1];
            done = arguments[2];
            progress = arguments[2];
        } else {
            params = arguments[1] === null || arguments[1] === undefined ? {} : arguments[1];
            handler = arguments[2];
            done = arguments[3];
            progress = arguments[4];
        }

        if (!list) {
            if (done) {
                done(undefined, list, params);// we complete immediately if there is no list.
            }
            return;
        }

        // var fnDesc = handler.toString();
        var next;
        var index = 0;
        var returnVal;
        var paramNames = getParamNames(handler);
        var keys;
        var len;

        if (list.length === undefined) {
            keys = Object.keys(list);
            len = keys.length;
        }

        // allow params to modify the loop directly if they have a = in front of them.
        // start the loop part way through or so on.
        // Future feature: to have it set the starting index.
        //if (params && params['=index']) {
        //    index = params['=index'];
        //}

        var iterate = function () {
            // use list length. in case they remove or add items.
            len = keys ? len : list.length;
            if (index < len) {
                try {
                    if(params) {
                        returnVal = handler(keys ? list[keys[index]] : list[index], keys ? keys[index] : index, list, params, next);
                    } else {
                        returnVal = handler(keys ? list[keys[index]] : list[index], keys ? keys[index] : index, list, next);
                    }
                } catch(e) {
                    if (done) {
                        done(e, list, params);
                    } else {
                        throw e;// non async methods need to show the error.
                    }
                }
                // if return true then exit the loop.
                if (returnVal !== undefined) {
                    iterate = null;
                    if (done) {
                        done(returnVal, list, params);
                        return;
                    }
                    return returnVal;
                }
                if (!next) {
                    index += 1;// only if synchronous increment here.
                    iterate();
                }
            } else if (typeof done === 'function') {
                iterate = null;
                done(null, list, params);
            }
            return returnVal;
        };

        var now = Date.now();
        var limitIndex = 0;
        /**
         * Allow to process withing a ms threshold.
         * Example would be iterate as many as possible within a 10ms threshold.
         * This makes the async loop faster than 1 frame wait for each item with a 0 timeout.
         * @param {Number=} threshold
         * @param {Number=} max number of items to process before coming up for air.
         */
        function iter(threshold, limit) {
            var current;
            index += 1;// if asynchronous increment here.
            if (threshold || limit) {
                limit = limit || 500;
                current = Date.now();
                if (current < now + threshold && (!limit || index - limitIndex < limit)) {
                    iterate();
                    return;
                }
                if (progress) {
                    progress(index, len);
                }
                limitIndex = index;
                now = current;
            }
            setTimeout(iterate, 0);
        }

        if(params) {
            if(paramNames && paramNames.length === 5) {
                next = iter;
            }
        } else {
            if(paramNames && paramNames.length === 4) {
                next = iter;
            }
        }

        var syncReturnVal = iterate();
        if (syncReturnVal !== undefined) {
            return syncReturnVal;
        }
        if (!done && params) {
            return params;
        }
    }

    return each;
});
<|endoftext|>


<commit_before>(function () {

window.ProjectSettings = {};

/**
*  returns a random name from this list to use as a confirmation string
*/
function randomScientist() {
    var scientists = [
    'Anning',
    'Banneker',
    'Cannon',
    'Carver',
    'Chappelle',
    'Curie',
    'Divine',
    'Emeagwali',
    'Fahlberg',
    'Forssmann',
    'Franklin',
    'Herschel',
    'Hodgkin',
    'Hopper',
    'Horowitz',
    'Jemison',
    'Julian',
    'Kovalevsky',
    'Lamarr',
    'Lavoisier',
    'Lovelace',
    'Massie',
    'McClintock',
    'Meitner',
    'Mitchell',
    'Morgan',
    'Nosek',
    'Odum',
    'Pasteur',
    'Pauling',
    'Payne',
    'Pearce',
    'Pollack',
    'Rillieux',
    'Sanger',
    'Somerville',
    'Tesla',
    'Tyson',
    'Turing',
    ];

    return scientists[Math.floor(Math.random() * scientists.length)];
}

/**
    * Pulls a random name from the scientist list to use as confirmation string
*  Ignores case and whitespace
*/
ProjectSettings.getConfirmationCode = function(nodeType) {
    var key = randomScientist();
    function successHandler(response) {
        // Redirect to either the parent project or the dashboard
        window.location.href = response.url;
    }

    $.ajax({
        url: nodeApiUrl + 'get_contributors/?limit=10',
        type: "get",
        dataType: "json",
        success: function(result) {
            contributorsHTML = result['contributors']
            more = result['more']

            contriblist = ''
            $.each(contributorsHTML, function(i, b){
                contriblist += "
" + "" + b.fullname + "" + "
"
            });

            console.log(contriblist)

            bootbox.prompt(
                'Are you sure you want to delete this ' + nodeType + '?' +
                '

It will be permanently deleted for every contributor:
' +
                '
' + contriblist +'
' +
                '
' +
                ((more > 0) ? 'and ' + more + ' more...
' : '') +
                '
' +
                'If you want to continue, type ' + key + ' and click OK.

',
                function(result) {
                    if (result != null) {
                        result = result.toLowerCase();
                    }
                    if ($.trim(result) === key.toLowerCase()) {
                        var request = $.ajax({
                            type: 'DELETE',
                            dataType: 'json',
                            url: nodeApiUrl
                        });
                        request.done(successHandler);
                        request.fail($.osf.handleJSONError);
                    } else if (result != null) {
                        bootbox.alert({
                            title: 'Incorrect confirmation',
                            message: 'The confirmation string you provided was incorrect. Please try again.'
                        });
                    }
                }
            );
        }
    })
};

$(document).ready(function() {

    // TODO: Knockout-ify me
    $('#commentSettings').on('submit', function() {
        var $commentMsg = $('#configureCommentingMessage');

        var $this = $(this);
        var commentLevel = $this.find('input[name="commentLevel"]:checked').val();

        $.osf.postJSON(
            nodeApiUrl + 'settings/comments/',
            {commentLevel: commentLevel}
        ).done(function() {
            $commentMsg.addClass('text-success');
            $commentMsg.text('Successfully updated settings.');
            window.location.reload();
        }).fail(function() {
            bootbox.alert('Could not set commenting configuration. Please try again.');
        });

        return false;

    });

    // Set up submission for addon selection form
    $('#selectAddonsForm').on('submit', function() {

        var formData = {};
        $('#selectAddonsForm').find('input').each(function(idx, elm) {
            var $elm = $(elm);
            formData[$elm.attr('name')] = $elm.is(':checked');
        });
        var msgElm = $(this).find('.addon-settings-message');
        $.ajax({
            url: nodeApiUrl + 'settings/addons/',
            data: JSON.stringify(formData),
            type: 'POST',
            contentType: 'application/json',
            dataType: 'json',
            success: function() {
                msgElm.text('Settings updated').fadeIn();
                window.location.reload();
            }
        });

        return false;

    });

    // Show capabilities modal on selecting an addon; unselect if user
    // rejects terms
    $('.addon-select').on('change', function() {
        var that = this,
            $that = $(that);
        if ($that.is(':checked')) {
            var name = $that.attr('name');
            var capabilities = $('#capabilities-' + name).html();
            if (capabilities) {
                bootbox.confirm(
                    capabilities,
                    function(result) {
                        if (!result) {
                            $(that).attr('checked', false);
                        }
                    }
                );
            }
        }
    });

});

}());
<commit_msg>Remove profile links contributor list<commit_after>(function () {

window.ProjectSettings = {};

/**
*  returns a random name from this list to use as a confirmation string
*/
function randomScientist() {
    var scientists = [
    'Anning',
    'Banneker',
    'Cannon',
    'Carver',
    'Chappelle',
    'Curie',
    'Divine',
    'Emeagwali',
    'Fahlberg',
    'Forssmann',
    'Franklin',
    'Herschel',
    'Hodgkin',
    'Hopper',
    'Horowitz',
    'Jemison',
    'Julian',
    'Kovalevsky',
    'Lamarr',
    'Lavoisier',
    'Lovelace',
    'Massie',
    'McClintock',
    'Meitner',
    'Mitchell',
    'Morgan',
    'Nosek',
    'Odum',
    'Pasteur',
    'Pauling',
    'Payne',
    'Pearce',
    'Pollack',
    'Rillieux',
    'Sanger',
    'Somerville',
    'Tesla',
    'Tyson',
    'Turing',
    ];

    return scientists[Math.floor(Math.random() * scientists.length)];
}

/**
    * Pulls a random name from the scientist list to use as confirmation string
*  Ignores case and whitespace
*/
ProjectSettings.getConfirmationCode = function(nodeType) {
    var key = randomScientist();
    function successHandler(response) {
        // Redirect to either the parent project or the dashboard
        window.location.href = response.url;
    }

    $.ajax({
        url: nodeApiUrl + 'get_contributors/?limit=10',
        type: "get",
        dataType: "json",
        success: function(result) {
            contributorsHTML = result['contributors']
            more = result['more']

            contriblist = ''
            $.each(contributorsHTML, function(i, b){
                contriblist += "
" + b.fullname + "
"
            });

            console.log(contriblist)

            bootbox.prompt(
                'Are you sure you want to delete this ' + nodeType + '?' +
                '

It will be permanently deleted for every contributor:
' +
                '
' + contriblist +'
' +
                '
' +
                ((more > 0) ? 'and ' + more + ' more...
' : '') +
                '
' +
                'If you want to continue, type ' + key + ' and click OK.

',
                function(result) {
                    if (result != null) {
                        result = result.toLowerCase();
                    }
                    if ($.trim(result) === key.toLowerCase()) {
                        var request = $.ajax({
                            type: 'DELETE',
                            dataType: 'json',
                            url: nodeApiUrl
                        });
                        request.done(successHandler);
                        request.fail($.osf.handleJSONError);
                    } else if (result != null) {
                        bootbox.alert({
                            title: 'Incorrect confirmation',
                            message: 'The confirmation string you provided was incorrect. Please try again.'
                        });
                    }
                }
            );
        }
    })
};

$(document).ready(function() {

    // TODO: Knockout-ify me
    $('#commentSettings').on('submit', function() {
        var $commentMsg = $('#configureCommentingMessage');

        var $this = $(this);
        var commentLevel = $this.find('input[name="commentLevel"]:checked').val();

        $.osf.postJSON(
            nodeApiUrl + 'settings/comments/',
            {commentLevel: commentLevel}
        ).done(function() {
            $commentMsg.addClass('text-success');
            $commentMsg.text('Successfully updated settings.');
            window.location.reload();
        }).fail(function() {
            bootbox.alert('Could not set commenting configuration. Please try again.');
        });

        return false;

    });

    // Set up submission for addon selection form
    $('#selectAddonsForm').on('submit', function() {

        var formData = {};
        $('#selectAddonsForm').find('input').each(function(idx, elm) {
            var $elm = $(elm);
            formData[$elm.attr('name')] = $elm.is(':checked');
        });
        var msgElm = $(this).find('.addon-settings-message');
        $.ajax({
            url: nodeApiUrl + 'settings/addons/',
            data: JSON.stringify(formData),
            type: 'POST',
            contentType: 'application/json',
            dataType: 'json',
            success: function() {
                msgElm.text('Settings updated').fadeIn();
                window.location.reload();
            }
        });

        return false;

    });

    // Show capabilities modal on selecting an addon; unselect if user
    // rejects terms
    $('.addon-select').on('change', function() {
        var that = this,
            $that = $(that);
        if ($that.is(':checked')) {
            var name = $that.attr('name');
            var capabilities = $('#capabilities-' + name).html();
            if (capabilities) {
                bootbox.confirm(
                    capabilities,
                    function(result) {
                        if (!result) {
                            $(that).attr('checked', false);
                        }
                    }
                );
            }
        }
    });

});

}());
<|endoftext|>


<commit_before>(function(){
	"use strict";

	KC3StrategyTabs.mstupdate = new KC3StrategyTab("mstupdate");

	KC3StrategyTabs.mstupdate.definition = {
		tabSelf: KC3StrategyTabs.mstupdate,
		newShips: [],
		newGears: [],
		newCgs: [],
		archivedCgs: [],
		myServerIp: "",
		listedShipId: 1,
		shipsPerPage: 18,

		/* INIT
		Prepares all data needed
		---------------------------------*/
		init :function(){
			this.myServerIp = (new KC3Server()).setNum( PlayerManager.hq.server ).ip;
		},

		/* RELOAD
		Prepares latest fleets data
		---------------------------------*/
		reload :function(){
			const self = this;
			const timeNow = Date.now();
			this.newShips.length = 0;
			this.newGears.length = 0;
			this.newCgs.length = 0;
			this.archivedCgs.length = 0;
			this.listedShipId = 1;
			var masterChanged = false;
			KC3Master.load();
			const checkExpired = (masterColle, colleName, removeMethod, resolveMethod) => {
				$.each(masterColle, function(mstId, timeAdded) {
					if(timeNow - timeAdded > KC3Master.newUpdatesExpiredAfter) {
						removeMethod.call(KC3Master, mstId);
						console.debug("{0} {1} has expired from update list".format(colleName, mstId));
						masterChanged = true;
					} else {
						resolveMethod.call(self, mstId);
					}
				});
			};
			checkExpired(KC3Master.new_ships(), "Ship", KC3Master.remove_new_ship, (id) => {
				this.newShips.push(KC3Master.ship(id));
			});
			checkExpired(KC3Master.new_slotitems(), "Item", KC3Master.remove_new_slotitem, (id) => {
				this.newGears.push(KC3Master.slotitem(id));
			});
			checkExpired(KC3Master.new_graphs(), "New Graph", KC3Master.remove_new_graphs, (id) => {
				// Only seasonal IDs needed, other parts are same things with new ships
				if(KC3Master.isSeasonalShip(id)) {
					this.archivedCgs.push(id);
				}
			});
			checkExpired(KC3Master.changed_graphs(), "Updated Graph", KC3Master.remove_changed_graphs, (id) => {
				if(KC3Master.isRegularShip(id)) {
					this.newCgs.push(KC3Master.ship(id));
				} else {
					console.debug("Seasonal CG or Abyssals graph {0} version change detected".format(id));
				}
			});
			if(masterChanged){
				KC3Master.save();
			}
			console.debug("Current updates", this.newShips, this.newGears, this.newCgs, this.archivedCgs);
		},

		/* EXECUTE
		Places data onto the interface
		---------------------------------*/
		execute :function(){
			$(".tab_mstupdate .runtime_id").text(chrome.runtime.id);

			const self = this;
			const linkClickFunc = function(e){
				KC3StrategyTabs.gotoTab($(this).data("tab"), $(this).data("api_id"));
			};
			var shipBox, gearBox, shipFile, shipVersion, shipSrc, shipPng, appendToBox;

			// New Ship list
			$.each(this.newShips, function(index, shipData) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipData.api_id).api_filename;
				shipVersion = (KC3Master.graph(shipData.api_id).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;

				if (KC3Master.isSeasonalShip(shipData.api_id)) {
					// SEASONAL CG, no longer work since 2017-04-05 no seasonal item leak
					// don't handle it here even seasonal leak again since 2017-09-12
					return;
				} else if (KC3Master.isAbyssalShip(shipData.api_id)) {
					// ABYSSAL
					shipSrc += "&abyss=1" + (!shipVersion ? "" : "&ver=" + shipVersion);
					// try to fix CG coordinate offset, only battle exists for abyssal
					let [coordX, coordY] = KC3Master.graph(shipData.api_id).api_battle_n;
					coordX = Math.floor(coordX * 0.4) - 150;
					coordX = Math.floor(coordX * 0.4) - 40;
					shipSrc += "&forceX=" + coordX + "&forceY=" + coordY;
					appendToBox = ".tab_mstupdate .mstabyss";
					shipPng = KC3Master.png_file(shipData.api_id, "full", "ship");
				} else {
					// NON-SEASONAL CG
					// show default card frame, no coordinate adjustment needed
					shipSrc += "&abyss=0" + (!shipVersion ? "" : "&ver=" + shipVersion);
					appendToBox = ".tab_mstupdate .mstships";
					shipPng = KC3Master.png_file(shipData.api_id, "card", "ship");
				}

				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				if(KC3Meta.isAF() && shipData.api_id == KC3Meta.getAF(4)) {
					$(".ship_cg img", shipBox).attr("src", KC3Meta.getAF(3).format("bk"));
				} else {
					$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				}
				$(".ship_name", shipBox).text( KC3Meta.shipName( shipData.api_id ) )
					.data("tab", "mstship")
					.data("api_id", shipData.api_id)
					.attr("data-mst-id", shipData.api_id)
					.attr("data-swf", shipSrc)
					.attr("title", "[{0}]".format(shipData.api_id))
					.click(linkClickFunc);

				shipBox.appendTo(appendToBox);
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstships");

			// New Equipment List
			$.each(this.newGears, function(index, gearData) {
				gearBox = $(".tab_mstupdate .factory .mstgear").clone();

				if(!KC3Master.isAbyssalGear(gearData.api_id)) {
					const cardPng = KC3Master.png_file(gearData.api_id, "card", "slot");
					$(".gear_cg img", gearBox).attr("src",
						`http://${self.myServerIp}/kcs2/resources${cardPng}`);
				} else {
					$(".gear_cg img", gearBox).hide();
				}

				$(".gear_name", gearBox).text( KC3Meta.gearName( gearData.api_name ) )
					.data("tab", "mstgear")
					.data("api_id", gearData.api_id)
					.attr("data-mst-id", gearData.api_id)
					.attr("title", "[{0}]".format(gearData.api_id))
					.click(linkClickFunc);

				gearBox.appendTo(".tab_mstupdate .mstgears");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstgears");

			// New Ship Seasonal CG
			$.each(this.newCgs, function(index, shipData) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipData.api_id).api_filename;
				shipVersion = (KC3Master.graph(shipData.api_id).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;
				shipSrc += "&abyss=0&forceFrame=10";
				// try to fix seasonal CG coordinate offset based on battle values
				const [coordX, coordY] = KC3Master.graph(shipData.api_id).api_battle_n;
				shipSrc += "&forceX=" + (coordX - 160) + "&forceY=" + (coordY - 120);
				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				shipPng = KC3Master.png_file(shipData.api_id, "full", "ship");
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				$(".ship_name", shipBox).text( KC3Meta.shipName( shipData.api_name ) )
					.data("tab", "mstship")
					.data("api_id", shipData.api_id)
					.attr("data-mst-id", shipData.api_id)
					.attr("title", "[{0}]".format(shipData.api_id))
					.attr("data-coord", [coordX, coordY].join(','))
					.attr("data-swf", shipSrc)
					.click(linkClickFunc);

				shipBox.appendTo(".tab_mstupdate .mstgraph");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstgraph");

			// Archived (removed) Ship Seasonal CG
			$.each(this.archivedCgs, function(index, shipId) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipId).api_filename;
				shipVersion = (KC3Master.graph(shipId).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;
				shipSrc += "&abyss=0&forceFrame=8";
				shipSrc += "&forceX=-40&forceY=-30";
				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				const seasonalData = KC3Master.seasonal_ship(shipId);
				shipPng = KC3Master.png_file(shipId, "character_full", "ship");
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				$(".ship_name", shipBox).text(seasonalData && seasonalData.api_name ?
					seasonalData.api_name : "Not available")
					.data("tab", "mstship")
					.data("api_id", shipId)
					.attr("data-mst-id", shipId)
					.attr("title", "[{0}]".format(shipId))
					.attr("data-swf", shipSrc);
				if(seasonalData) {
					$(".ship_name", shipBox).click(linkClickFunc);
				} else {
					$(".ship_name", shipBox).removeClass("hover");
				}

				shipBox.appendTo(".tab_mstupdate .mstseason");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstseason");
			$(".page_padding").createChildrenTooltips();

			const toggleImageFunc = function(e) {
				const cgElm = $(this), imgElm = $("img", cgElm);
				const isFullImage = !cgElm.hasClass("char_image");
				cgElm.toggleClass("char_image", isFullImage);
				imgElm.attr("src", cgElm.data(isFullImage ? "char" : "full"));
			};
			const appendShipsByPage = (showAll = false) => {
				const addOneShip = (shipData) => {
					const shipBox = $(".tab_mstupdate .factory .mstship").clone()
						.addClass("smaller")
						.appendTo(".tab_mstupdate .allships");
					const version = (KC3Master.graph(shipData.api_id).api_version || [])[0],
						imgFileFull = KC3Master.png_file(shipData.api_id, "full", "ship")
							+ (!version ? "" : "?version=" + version),
						imgFileChar = KC3Master.png_file(shipData.api_id, "character_full", "ship")
							+ (!version ? "" : "?version=" + version),
						fullUrl = `http://${self.myServerIp}/kcs2/resources${imgFileFull}`,
						charUrl = `http://${self.myServerIp}/kcs2/resources${imgFileChar}`;
					$(".ship_cg img", shipBox).attr("src", fullUrl);
					$(".ship_cg", shipBox).addClass("hover").click(toggleImageFunc)
						.attr("data-full", fullUrl)
						.attr("data-char", charUrl);
					const shipName = "[{0}] {1}".format(shipData.api_id, KC3Meta.shipName(shipData.api_id));
					$(".ship_name", shipBox).text(shipName)
						.data("tab", "mstship")
						.data("api_id", shipData.api_id)
						.click(linkClickFunc);
				};
				if(this.listedShipId > 1 && $(".tab_mstupdate .allships > div").length === 0) {
					for(let id = 1; id < this.listedShipId; id++) {
						const ship = KC3Master.isRegularShip(id) && KC3Master.ship(id);
						if(ship) addOneShip(ship);
					}
				}
				const shipsToShown = showAll ? KC3Master.seasonalCgIdFrom : this.shipsPerPage;
				let shipsAdded = 0;
				for(let cnt = 0; cnt < shipsToShown; cnt++) {
					let shipData = false;
					while(!shipData && KC3Master.isRegularShip(this.listedShipId)) {
						shipData = KC3Master.ship(this.listedShipId);
						this.listedShipId += 1;
					}
					if(!shipData) break;
					addOneShip(shipData);
					shipsAdded += 1;
				}
				return shipsAdded;
			};
			$(".moreships_btn").on("click", (e) => {
				$(".moreships_btn, .allships_btn").toggle(appendShipsByPage() > 0);
			});
			$(".allships_btn").on("click", (e) => {
				appendShipsByPage(true);
				$(".moreships_btn, .allships_btn").hide();
			});
			if(!ConfigManager.devOnlyPages) {
				$(".dev_only").hide();
			}
		}

	};

})();
<commit_msg>Show ship nam3 by id for update page<commit_after>(function(){
	"use strict";

	KC3StrategyTabs.mstupdate = new KC3StrategyTab("mstupdate");

	KC3StrategyTabs.mstupdate.definition = {
		tabSelf: KC3StrategyTabs.mstupdate,
		newShips: [],
		newGears: [],
		newCgs: [],
		archivedCgs: [],
		myServerIp: "",
		listedShipId: 1,
		shipsPerPage: 18,

		/* INIT
		Prepares all data needed
		---------------------------------*/
		init :function(){
			this.myServerIp = (new KC3Server()).setNum( PlayerManager.hq.server ).ip;
		},

		/* RELOAD
		Prepares latest fleets data
		---------------------------------*/
		reload :function(){
			const self = this;
			const timeNow = Date.now();
			this.newShips.length = 0;
			this.newGears.length = 0;
			this.newCgs.length = 0;
			this.archivedCgs.length = 0;
			this.listedShipId = 1;
			var masterChanged = false;
			KC3Master.load();
			const checkExpired = (masterColle, colleName, removeMethod, resolveMethod) => {
				$.each(masterColle, function(mstId, timeAdded) {
					if(timeNow - timeAdded > KC3Master.newUpdatesExpiredAfter) {
						removeMethod.call(KC3Master, mstId);
						console.debug("{0} {1} has expired from update list".format(colleName, mstId));
						masterChanged = true;
					} else {
						resolveMethod.call(self, mstId);
					}
				});
			};
			checkExpired(KC3Master.new_ships(), "Ship", KC3Master.remove_new_ship, (id) => {
				this.newShips.push(KC3Master.ship(id));
			});
			checkExpired(KC3Master.new_slotitems(), "Item", KC3Master.remove_new_slotitem, (id) => {
				this.newGears.push(KC3Master.slotitem(id));
			});
			checkExpired(KC3Master.new_graphs(), "New Graph", KC3Master.remove_new_graphs, (id) => {
				// Only seasonal IDs needed, other parts are same things with new ships
				if(KC3Master.isSeasonalShip(id)) {
					this.archivedCgs.push(id);
				}
			});
			checkExpired(KC3Master.changed_graphs(), "Updated Graph", KC3Master.remove_changed_graphs, (id) => {
				if(KC3Master.isRegularShip(id)) {
					this.newCgs.push(KC3Master.ship(id));
				} else {
					console.debug("Seasonal CG or Abyssals graph {0} version change detected".format(id));
				}
			});
			if(masterChanged){
				KC3Master.save();
			}
			console.debug("Current updates", this.newShips, this.newGears, this.newCgs, this.archivedCgs);
		},

		/* EXECUTE
		Places data onto the interface
		---------------------------------*/
		execute :function(){
			$(".tab_mstupdate .runtime_id").text(chrome.runtime.id);

			const self = this;
			const linkClickFunc = function(e){
				KC3StrategyTabs.gotoTab($(this).data("tab"), $(this).data("api_id"));
			};
			var shipBox, gearBox, shipFile, shipVersion, shipSrc, shipPng, appendToBox;

			// New Ship list
			$.each(this.newShips, function(index, shipData) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipData.api_id).api_filename;
				shipVersion = (KC3Master.graph(shipData.api_id).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;

				if (KC3Master.isSeasonalShip(shipData.api_id)) {
					// SEASONAL CG, no longer work since 2017-04-05 no seasonal item leak
					// don't handle it here even seasonal leak again since 2017-09-12
					return;
				} else if (KC3Master.isAbyssalShip(shipData.api_id)) {
					// ABYSSAL
					shipSrc += "&abyss=1" + (!shipVersion ? "" : "&ver=" + shipVersion);
					// try to fix CG coordinate offset, only battle exists for abyssal
					let [coordX, coordY] = KC3Master.graph(shipData.api_id).api_battle_n;
					coordX = Math.floor(coordX * 0.4) - 150;
					coordX = Math.floor(coordX * 0.4) - 40;
					shipSrc += "&forceX=" + coordX + "&forceY=" + coordY;
					appendToBox = ".tab_mstupdate .mstabyss";
					shipPng = KC3Master.png_file(shipData.api_id, "full", "ship");
				} else {
					// NON-SEASONAL CG
					// show default card frame, no coordinate adjustment needed
					shipSrc += "&abyss=0" + (!shipVersion ? "" : "&ver=" + shipVersion);
					appendToBox = ".tab_mstupdate .mstships";
					shipPng = KC3Master.png_file(shipData.api_id, "card", "ship");
				}

				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				if(KC3Meta.isAF() && shipData.api_id == KC3Meta.getAF(4)) {
					$(".ship_cg img", shipBox).attr("src", KC3Meta.getAF(3).format("bk"));
				} else {
					$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				}
				$(".ship_name", shipBox).text( KC3Meta.shipName( shipData.api_id ) )
					.data("tab", "mstship")
					.data("api_id", shipData.api_id)
					.attr("data-mst-id", shipData.api_id)
					.attr("data-swf", shipSrc)
					.attr("title", "[{0}]".format(shipData.api_id))
					.click(linkClickFunc);

				shipBox.appendTo(appendToBox);
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstships");

			// New Equipment List
			$.each(this.newGears, function(index, gearData) {
				gearBox = $(".tab_mstupdate .factory .mstgear").clone();

				if(!KC3Master.isAbyssalGear(gearData.api_id)) {
					const cardPng = KC3Master.png_file(gearData.api_id, "card", "slot");
					$(".gear_cg img", gearBox).attr("src",
						`http://${self.myServerIp}/kcs2/resources${cardPng}`);
				} else {
					$(".gear_cg img", gearBox).hide();
				}

				$(".gear_name", gearBox).text( KC3Meta.gearName( gearData.api_name ) )
					.data("tab", "mstgear")
					.data("api_id", gearData.api_id)
					.attr("data-mst-id", gearData.api_id)
					.attr("title", "[{0}]".format(gearData.api_id))
					.click(linkClickFunc);

				gearBox.appendTo(".tab_mstupdate .mstgears");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstgears");

			// New Ship Seasonal CG
			$.each(this.newCgs, function(index, shipData) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipData.api_id).api_filename;
				shipVersion = (KC3Master.graph(shipData.api_id).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;
				shipSrc += "&abyss=0&forceFrame=10";
				// try to fix seasonal CG coordinate offset based on battle values
				const [coordX, coordY] = KC3Master.graph(shipData.api_id).api_battle_n;
				shipSrc += "&forceX=" + (coordX - 160) + "&forceY=" + (coordY - 120);
				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				shipPng = KC3Master.png_file(shipData.api_id, "full", "ship");
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				$(".ship_name", shipBox).text( KC3Meta.shipName( shipData.api_id ) )
					.data("tab", "mstship")
					.data("api_id", shipData.api_id)
					.attr("data-mst-id", shipData.api_id)
					.attr("title", "[{0}]".format(shipData.api_id))
					.attr("data-coord", [coordX, coordY].join(','))
					.attr("data-swf", shipSrc)
					.click(linkClickFunc);

				shipBox.appendTo(".tab_mstupdate .mstgraph");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstgraph");

			// Archived (removed) Ship Seasonal CG
			$.each(this.archivedCgs, function(index, shipId) {
				shipBox = $(".tab_mstupdate .factory .mstship").clone();
				shipFile = KC3Master.graph(shipId).api_filename;
				shipVersion = (KC3Master.graph(shipId).api_version || [])[0];
				shipSrc = "/assets/swf/card.swf?sip=" + self.myServerIp + "&shipFile=" + shipFile;
				shipSrc += "&abyss=0&forceFrame=8";
				shipSrc += "&forceX=-40&forceY=-30";
				shipSrc += !shipVersion ? "" : "&ver=" + shipVersion;
				const seasonalData = KC3Master.seasonal_ship(shipId);
				shipPng = KC3Master.png_file(shipId, "character_full", "ship");
				shipPng += !shipVersion ? "" : "?version=" + shipVersion;

				$(".ship_cg img", shipBox).attr("src", `http://${self.myServerIp}/kcs2/resources${shipPng}`);
				$(".ship_name", shipBox).text(seasonalData && seasonalData.api_name ?
					seasonalData.api_name : "Not available")
					.data("tab", "mstship")
					.data("api_id", shipId)
					.attr("data-mst-id", shipId)
					.attr("title", "[{0}]".format(shipId))
					.attr("data-swf", shipSrc);
				if(seasonalData) {
					$(".ship_name", shipBox).click(linkClickFunc);
				} else {
					$(".ship_name", shipBox).removeClass("hover");
				}

				shipBox.appendTo(".tab_mstupdate .mstseason");
			});
			$("<div/>").addClass("clear").appendTo(".tab_mstupdate .mstseason");
			$(".page_padding").createChildrenTooltips();

			const toggleImageFunc = function(e) {
				const cgElm = $(this), imgElm = $("img", cgElm);
				const isFullImage = !cgElm.hasClass("char_image");
				cgElm.toggleClass("char_image", isFullImage);
				imgElm.attr("src", cgElm.data(isFullImage ? "char" : "full"));
			};
			const appendShipsByPage = (showAll = false) => {
				const addOneShip = (shipData) => {
					const shipBox = $(".tab_mstupdate .factory .mstship").clone()
						.addClass("smaller")
						.appendTo(".tab_mstupdate .allships");
					const version = (KC3Master.graph(shipData.api_id).api_version || [])[0],
						imgFileFull = KC3Master.png_file(shipData.api_id, "full", "ship")
							+ (!version ? "" : "?version=" + version),
						imgFileChar = KC3Master.png_file(shipData.api_id, "character_full", "ship")
							+ (!version ? "" : "?version=" + version),
						fullUrl = `http://${self.myServerIp}/kcs2/resources${imgFileFull}`,
						charUrl = `http://${self.myServerIp}/kcs2/resources${imgFileChar}`;
					$(".ship_cg img", shipBox).attr("src", fullUrl);
					$(".ship_cg", shipBox).addClass("hover").click(toggleImageFunc)
						.attr("data-full", fullUrl)
						.attr("data-char", charUrl);
					const shipName = "[{0}] {1}".format(shipData.api_id, KC3Meta.shipName(shipData.api_id));
					$(".ship_name", shipBox).text(shipName)
						.data("tab", "mstship")
						.data("api_id", shipData.api_id)
						.click(linkClickFunc);
				};
				if(this.listedShipId > 1 && $(".tab_mstupdate .allships > div").length === 0) {
					for(let id = 1; id < this.listedShipId; id++) {
						const ship = KC3Master.isRegularShip(id) && KC3Master.ship(id);
						if(ship) addOneShip(ship);
					}
				}
				const shipsToShown = showAll ? KC3Master.seasonalCgIdFrom : this.shipsPerPage;
				let shipsAdded = 0;
				for(let cnt = 0; cnt < shipsToShown; cnt++) {
					let shipData = false;
					while(!shipData && KC3Master.isRegularShip(this.listedShipId)) {
						shipData = KC3Master.ship(this.listedShipId);
						this.listedShipId += 1;
					}
					if(!shipData) break;
					addOneShip(shipData);
					shipsAdded += 1;
				}
				return shipsAdded;
			};
			$(".moreships_btn").on("click", (e) => {
				$(".moreships_btn, .allships_btn").toggle(appendShipsByPage() > 0);
			});
			$(".allships_btn").on("click", (e) => {
				appendShipsByPage(true);
				$(".moreships_btn, .allships_btn").hide();
			});
			if(!ConfigManager.devOnlyPages) {
				$(".dev_only").hide();
			}
		}

	};

})();
<|endoftext|>


<commit_before>import styles from './index.scss'
import ReactFireMixin from 'reactfire'
import reactMixin from 'react-mixin'
import Firebase from 'firebase'
import config from 'utils/config'

import UserSettings from 'components/User/Settings/index'
import Timeline from 'components/Timeline/index'
import Loading from 'components/Loading/index'

export class UserView extends React.Component {
  static propTypes = {
    userFirebase: React.PropTypes.object,
  }

  constructor() {
    super()
    this.state = {
      postsFirebase: [],
    }
  }

  componentDidMount() {
    this._getUserPosts(this.props.userFirebase)
    this._getStars(this.props.userFirebase)
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.userFirebase && nextProps.userFirebase !== this.props.userFirebase) {
      this._getUserPosts(nextProps.userFirebase)
      this._getStars(nextProps.userFirebase)
    }
  }

  _isBinded(bindVar) {
    return typeof this.firebaseRefs[bindVar] !== 'undefined'
  }

  _getUserPosts(userFirebase) {
    if (!userFirebase || this._isBinded('starsFirebase')) return
    const refPosts = new Firebase(`${config.firebase.demoRef}posts`)
    this.bindAsArray(
      refPosts.orderByChild('user_id').equalTo(userFirebase.auth.uid).limitToLast(10),
      'postsFirebase'
    )
  }

  _getStars(userFirebase) {
    if (!userFirebase || this._isBinded('starsFirebase')) return
    const refStars = new Firebase(`${config.firebase.demoRef}stars/${userFirebase.auth.uid}`)
    this.bindAsArray(
      refStars.orderByChild('created_at').limitToLast(10),
      'starsFirebase'
    )
  }

  render() {
    return (

          <UserSettings {...this.props} />
          {this.state.postsFirebase.length === 0
            ? <Loading />
            : <Timeline items={this.state.postsFirebase} {...this.props} {...this.state} />}

    )
  }
}

export default reactMixin.decorate(ReactFireMixin)(UserView)
<commit_msg>add tutorial in userpage<commit_after>import styles from './index.scss'
import ReactFireMixin from 'reactfire'
import reactMixin from 'react-mixin'
import Firebase from 'firebase'
import { connect } from 'react-redux'

import config from 'utils/config'
import tutorialActions from 'actions/tutorial'

import UserSettings from 'components/User/Settings/index'
import Timeline from 'components/Timeline/index'
import Loading from 'components/Loading/index'
import Modal from 'components/Modal/index'
import ModalTutorial from 'components/Modal/Tutorial/index'

const mapStateToProps = (state) => ({
  tutorial: state.tutorial,
})

export class UserView extends React.Component {
  static propTypes = {
    userFirebase: React.PropTypes.object,
    tutorial: React.PropTypes.object.isRequired,
    toggleTutorialHasDone: React.PropTypes.func.isRequired,
  }

  constructor() {
    super()
    this.state = {
      postsFirebase: [],
    }
  }

  componentDidMount() {
    this._getUserPosts(this.props.userFirebase)
    this._getStars(this.props.userFirebase)
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.userFirebase && nextProps.userFirebase !== this.props.userFirebase) {
      this._getUserPosts(nextProps.userFirebase)
      this._getStars(nextProps.userFirebase)
    }
  }

  _isBinded(bindVar) {
    return typeof this.firebaseRefs[bindVar] !== 'undefined'
  }

  _getUserPosts(userFirebase) {
    if (!userFirebase || this._isBinded('starsFirebase')) return
    const refPosts = new Firebase(`${config.firebase.demoRef}posts`)
    this.bindAsArray(
      refPosts.orderByChild('user_id').equalTo(userFirebase.auth.uid).limitToLast(10),
      'postsFirebase'
    )
  }

  _getStars(userFirebase) {
    if (!userFirebase || this._isBinded('starsFirebase')) return
    const refStars = new Firebase(`${config.firebase.demoRef}stars/${userFirebase.auth.uid}`)
    this.bindAsArray(
      refStars.orderByChild('created_at').limitToLast(10),
      'starsFirebase'
    )
  }

  _toggleTutorialHasDone() {
    this.props.toggleTutorialHasDone({
      type: 'in',
      name: 'UserView',
    })
  }

  render() {
    const contentStyleMd = {
      height: '150px',
    }
    return (

        <Modal
          isShow={!this.props.tutorial.hasDone.in.UserView}
          toggleShow={::this._toggleTutorialHasDone}
          contentStyleMd={contentStyleMd}>
          <ModalTutorial {...this.props}>

              ここはあなたの情報が表示される非公開のページです。あなた以外の人はアクセスできませんのでご安心ください。

          </ModalTutorial>
        </Modal>

          <UserSettings {...this.props} />
          {this.state.postsFirebase.length === 0
            ? <Loading />
            : <Timeline items={this.state.postsFirebase} {...this.props} {...this.state} />}

    )
  }
}

const UserViewWithMixin = reactMixin.decorate(ReactFireMixin)(UserView)
export default connect(mapStateToProps, {
  ...tutorialActions,
})(UserViewWithMixin)
<|endoftext|>


<commit_before>/// <reference path="../../../../../argos-sdk/libraries/ext/ext-core-debug.js"/>
/// <reference path="../../../../../argos-sdk/libraries/sdata/sdata-client-debug"/>
/// <reference path="../../../../../argos-sdk/libraries/Simplate.js"/>
/// <reference path="../../../../../argos-sdk/src/View.js"/>
/// <reference path="../../../../../argos-sdk/src/Detail.js"/>

Ext.namespace("Mobile.SalesLogix.Account");

(function() {
    Mobile.SalesLogix.Account.Detail = Ext.extend(Sage.Platform.Mobile.Detail, {
        //Localization
        accountText: 'account',
        acctMgrText: 'acct mgr',
        addressText: 'address',
        businessDescriptionText: 'bus desc',
        createDateText: 'create date',
        createUserText: 'create user',
        faxText: 'fax',
        importSourceText: 'lead source',
        industryText: 'industry',
        notesText: 'notes',
        ownerText: 'owner',
        phoneCallHistoryTitle: 'Phone Call',
        phoneText: 'phone',
        activityTypeText: {
            'atPhoneCall': 'Phone Call'
        },
        actionsText: 'Quick Actions',
        relatedActivitiesText: 'Activities',
        relatedContactsText: 'Contacts',
        relatedHistoriesText: 'History',
        relatedItemsText: 'Related Items',
        relatedNotesText: 'Notes',
        relatedOpportunitiesText: 'Opportunities',
        relatedTicketsText: 'Tickets',
        statusText: 'status',
        subTypeText: 'subtype',
        titleText: 'Account',
        typeText: 'type',
        webText: 'web',
        callMainNumberText: 'Call main number',
        scheduleActivityText: 'Schedule activity',
        addNoteText: 'Add note',
        viewAddressText: 'View address',
        moreDetailsText: 'More Details',

        //View Properties
        id: 'account_detail',
        editView: 'account_edit',
        historyEditView: 'history_edit',
        noteEditView: 'note_edit',
        querySelect: [
            'AccountManager/UserInfo/FirstName',
            'AccountManager/UserInfo/LastName',
            'AccountName',
            'Address/*',
            'BusinessDescription',
            'CreateDate',
            'CreateUser',
            'Description',
            'Fax',
            'GlobalSyncID',
            'ImportSource',
            'Industry',
            'LeadSource/Description',
            'MainPhone',
            'Notes',
            'Owner/OwnerDescription',
            'Status',
            'SubType',
            'Type',
            'WebAddress'
        ],
        resourceKind: 'accounts',

        navigateToHistoryInsert: function(type, entry, complete) {
            var view = App.getView(this.historyEditView);
            if (view)
            {
                this.refreshRequired = true;

                view.show({
                    title: this.activityTypeText[type],
                    template: {},
                    entry: entry,
                    insert: true
                }, {
                    complete: complete
                });
            }
        },
        recordCallToHistory: function(complete) {
            var entry = {
                'Type': 'atPhoneCall',
                'AccountId': this.entry['$key'],
                'AccountName': this.entry['AccountName'],
                'Description': String.format("Called {0}", this.entry['AccountName']),
                'UserId': App.context && App.context.user['$key'],
                'UserName': App.context && App.context.user['UserName'],
                'Duration': 15,
                'CompletedDate': (new Date())
            };

            this.navigateToHistoryInsert('atPhoneCall', entry, complete);
        },
        callMainPhone: function() {
            this.recordCallToHistory(function() {
                App.initiateCall(this.entry['MainPhone']);
            }.createDelegate(this));
        },
        checkMainPhone: function(entry, value) {
            return !value;
        },
        viewAddress: function() {
            App.showMapForAddress(Mobile.SalesLogix.Format.address(this.entry['Address'], true, ' '));
        },
        checkAddress: function(entry, value) {
            return !Mobile.SalesLogix.Format.address(value, true, '');
        },
        scheduleActivity: function() {
            App.navigateToActivityInsertView();
        },
        addNote: function() {
            var view = App.getView(this.noteEditView);
            if (view)
            {
                view.show({
                    template: {},
                    insert: true
                });
            }
        },
        createLayout: function() {
            return this.layout || (this.layout = [{
                options: {
                    list: true,
                    title: this.actionsText,
                    cls: 'action-list'
                },
                as: [{
                    name: 'MainPhone',
                    label: this.callMainNumberText,
                    icon: 'content/images/icons/Dial_24x24.png',
                    action: 'callMainPhone',
                    disabled: this.checkMainPhone,
                    renderer: Mobile.SalesLogix.Format.phone.createDelegate(this, [false], true)
                },{
                    name: 'AccountName',
                    label: this.scheduleActivityText,
                    icon: 'content/images/icons/Schedule_ToDo_24x24.png',
                    action: 'scheduleActivity'
                },{
                    name: 'AccountName',
                    label: this.addNoteText,
                    icon: 'content/images/icons/New_Note_24x24.png',
                    action: 'addNote'
                },{
                    name: 'Address',
                    label: this.viewAddressText,
                    icon: 'content/images/icons/Map_24.png',
                    action: 'viewAddress',
                    disabled: this.checkAddress,
                    renderer: Mobile.SalesLogix.Format.address.createDelegate(this, [true, ' '], true)
                }]
            },{
                options: {
                    title: this.detailsText
                },
                as: [{
                    name: 'AccountName',
                    label: this.accountText
                },{
                    name: 'WebAddress',
                    label: this.webText,
                    renderer: Mobile.SalesLogix.Format.link
                },{
                    name: 'Fax',
                    label: this.faxText,
                    renderer: Mobile.SalesLogix.Format.phone
                },{
                    name: 'Type',
                    label: this.typeText
                },{
                    name: 'SubType',
                    label: this.subTypeText
                },{
                    name: 'Status',
                    label: this.statusText
                }]
            },{
                options: {
                    title: this.moreDetailsText,
                    collapsed: true
                },
                as: [{
                    name: 'Industry',
                    label: this.industryText,
                    type: 'text'
                },{
                    name: 'BusinessDescription',
                    label: this.businessDescriptionText,
                    type: 'text'
                },{
                    name: 'AccountManager.UserInfo',
                    label: this.acctMgrText,
                    tpl: Mobile.SalesLogix.Template.nameLF
                },{
                    name: 'Owner.OwnerDescription',
                    label: this.ownerText
                },{
                    name: 'LeadSource.Description',
                    label: this.importSourceText
                }]
            },{
                options: {
                    list: true,
                    title: this.relatedItemsText
                },
                as: [{
                    icon: 'content/images/icons/To_Do_24x24.png',
                    label: this.relatedActivitiesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}"'], true
                    ),
                    view: 'activity_related'
                },{
                    icon: 'content/images/icons/note_24.png',
                    label: this.relatedNotesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}" and Type eq "atNote"'], true
                    ),
                    view: 'note_related'
                },{
                    icon: 'content/images/icons/Contacts_24x24.png',
                    label: this.relatedContactsText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'contact_related'
                },{
                    icon: 'content/images/icons/opportunity_24.png',
                    label: this.relatedOpportunitiesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'opportunity_related'
                },{
                    icon: 'content/images/icons/Ticket_24x24.png',
                    label: this.relatedTicketsText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'ticket_related'
                },{
                    icon: 'content/images/icons/journal_24.png',
                    label: this.relatedHistoriesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}" and Type ne "atNote" and Type ne "atDatabaseChange"'], true
                    ),
                    view: 'history_related'
                }]
            }]);
        }
    });
})();<commit_msg>Localization.<commit_after>/// <reference path="../../../../../argos-sdk/libraries/ext/ext-core-debug.js"/>
/// <reference path="../../../../../argos-sdk/libraries/sdata/sdata-client-debug"/>
/// <reference path="../../../../../argos-sdk/libraries/Simplate.js"/>
/// <reference path="../../../../../argos-sdk/src/View.js"/>
/// <reference path="../../../../../argos-sdk/src/Detail.js"/>

Ext.namespace("Mobile.SalesLogix.Account");

(function() {
    Mobile.SalesLogix.Account.Detail = Ext.extend(Sage.Platform.Mobile.Detail, {
        //Localization
        accountText: 'account',
        acctMgrText: 'acct mgr',
        addressText: 'address',
        businessDescriptionText: 'bus desc',
        createDateText: 'create date',
        createUserText: 'create user',
        faxText: 'fax',
        importSourceText: 'lead source',
        industryText: 'industry',
        notesText: 'notes',
        ownerText: 'owner',
        phoneCallHistoryTitle: 'Phone Call',
        phoneText: 'phone',
        activityTypeText: {
            'atPhoneCall': 'Phone Call'
        },
        actionsText: 'Quick Actions',
        relatedActivitiesText: 'Activities',
        relatedContactsText: 'Contacts',
        relatedHistoriesText: 'History',
        relatedItemsText: 'Related Items',
        relatedNotesText: 'Notes',
        relatedOpportunitiesText: 'Opportunities',
        relatedTicketsText: 'Tickets',
        statusText: 'status',
        subTypeText: 'subtype',
        titleText: 'Account',
        typeText: 'type',
        webText: 'web',
        callMainNumberText: 'Call main number',
        scheduleActivityText: 'Schedule activity',
        addNoteText: 'Add note',
        viewAddressText: 'View address',
        moreDetailsText: 'More Details',
        calledText: 'Called {0}',

        //View Properties
        id: 'account_detail',
        editView: 'account_edit',
        historyEditView: 'history_edit',
        noteEditView: 'note_edit',
        querySelect: [
            'AccountManager/UserInfo/FirstName',
            'AccountManager/UserInfo/LastName',
            'AccountName',
            'Address/*',
            'BusinessDescription',
            'CreateDate',
            'CreateUser',
            'Description',
            'Fax',
            'GlobalSyncID',
            'ImportSource',
            'Industry',
            'LeadSource/Description',
            'MainPhone',
            'Notes',
            'Owner/OwnerDescription',
            'Status',
            'SubType',
            'Type',
            'WebAddress'
        ],
        resourceKind: 'accounts',

        navigateToHistoryInsert: function(type, entry, complete) {
            var view = App.getView(this.historyEditView);
            if (view)
            {
                this.refreshRequired = true;

                view.show({
                    title: this.activityTypeText[type],
                    template: {},
                    entry: entry,
                    insert: true
                }, {
                    complete: complete
                });
            }
        },
        recordCallToHistory: function(complete) {
            var entry = {
                'Type': 'atPhoneCall',
                'AccountId': this.entry['$key'],
                'AccountName': this.entry['AccountName'],
                'Description': String.format(this.calledText, this.entry['AccountName']),
                'UserId': App.context && App.context.user['$key'],
                'UserName': App.context && App.context.user['UserName'],
                'Duration': 15,
                'CompletedDate': (new Date())
            };

            this.navigateToHistoryInsert('atPhoneCall', entry, complete);
        },
        callMainPhone: function() {
            this.recordCallToHistory(function() {
                App.initiateCall(this.entry['MainPhone']);
            }.createDelegate(this));
        },
        checkMainPhone: function(entry, value) {
            return !value;
        },
        viewAddress: function() {
            App.showMapForAddress(Mobile.SalesLogix.Format.address(this.entry['Address'], true, ' '));
        },
        checkAddress: function(entry, value) {
            return !Mobile.SalesLogix.Format.address(value, true, '');
        },
        scheduleActivity: function() {
            App.navigateToActivityInsertView();
        },
        addNote: function() {
            var view = App.getView(this.noteEditView);
            if (view)
            {
                view.show({
                    template: {},
                    insert: true
                });
            }
        },
        createLayout: function() {
            return this.layout || (this.layout = [{
                options: {
                    list: true,
                    title: this.actionsText,
                    cls: 'action-list'
                },
                as: [{
                    name: 'MainPhone',
                    label: this.callMainNumberText,
                    icon: 'content/images/icons/Dial_24x24.png',
                    action: 'callMainPhone',
                    disabled: this.checkMainPhone,
                    renderer: Mobile.SalesLogix.Format.phone.createDelegate(this, [false], true)
                },{
                    name: 'AccountName',
                    label: this.scheduleActivityText,
                    icon: 'content/images/icons/Schedule_ToDo_24x24.png',
                    action: 'scheduleActivity'
                },{
                    name: 'AccountName',
                    label: this.addNoteText,
                    icon: 'content/images/icons/New_Note_24x24.png',
                    action: 'addNote'
                },{
                    name: 'Address',
                    label: this.viewAddressText,
                    icon: 'content/images/icons/Map_24.png',
                    action: 'viewAddress',
                    disabled: this.checkAddress,
                    renderer: Mobile.SalesLogix.Format.address.createDelegate(this, [true, ' '], true)
                }]
            },{
                options: {
                    title: this.detailsText
                },
                as: [{
                    name: 'AccountName',
                    label: this.accountText
                },{
                    name: 'WebAddress',
                    label: this.webText,
                    renderer: Mobile.SalesLogix.Format.link
                },{
                    name: 'Fax',
                    label: this.faxText,
                    renderer: Mobile.SalesLogix.Format.phone
                },{
                    name: 'Type',
                    label: this.typeText
                },{
                    name: 'SubType',
                    label: this.subTypeText
                },{
                    name: 'Status',
                    label: this.statusText
                }]
            },{
                options: {
                    title: this.moreDetailsText,
                    collapsed: true
                },
                as: [{
                    name: 'Industry',
                    label: this.industryText,
                    type: 'text'
                },{
                    name: 'BusinessDescription',
                    label: this.businessDescriptionText,
                    type: 'text'
                },{
                    name: 'AccountManager.UserInfo',
                    label: this.acctMgrText,
                    tpl: Mobile.SalesLogix.Template.nameLF
                },{
                    name: 'Owner.OwnerDescription',
                    label: this.ownerText
                },{
                    name: 'LeadSource.Description',
                    label: this.importSourceText
                }]
            },{
                options: {
                    list: true,
                    title: this.relatedItemsText
                },
                as: [{
                    icon: 'content/images/icons/To_Do_24x24.png',
                    label: this.relatedActivitiesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}"'], true
                    ),
                    view: 'activity_related'
                },{
                    icon: 'content/images/icons/note_24.png',
                    label: this.relatedNotesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}" and Type eq "atNote"'], true
                    ),
                    view: 'note_related'
                },{
                    icon: 'content/images/icons/Contacts_24x24.png',
                    label: this.relatedContactsText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'contact_related'
                },{
                    icon: 'content/images/icons/opportunity_24.png',
                    label: this.relatedOpportunitiesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'opportunity_related'
                },{
                    icon: 'content/images/icons/Ticket_24x24.png',
                    label: this.relatedTicketsText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['Account.id eq "{0}"'], true
                    ),
                    view: 'ticket_related'
                },{
                    icon: 'content/images/icons/journal_24.png',
                    label: this.relatedHistoriesText,
                    where: this.formatRelatedQuery.createDelegate(
                        this, ['AccountId eq "{0}" and Type ne "atNote" and Type ne "atDatabaseChange"'], true
                    ),
                    view: 'history_related'
                }]
            }]);
        }
    });
})();<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('arkclient')
    .service('timeService', ['$q', '$http', '$interval', TimeService]);

  /**
   * TimeService
   * @constructor
   */
  function TimeService($q, $http) {

    var timeServerUrl = "http://www.timeapi.org/";
    var serverLatency = 0;

    /**
     * Function gets a server timestamp as to not rely on the users local clock.
     * Fallback to users local clock on failure.
     * Always returns success.
     */
    function getTimestamp() {

      var deferred = $q.defer();

      var startTime = new Date().getTime();

      $http.get(timeServerUrl).then(
       function(success){

        var timestamp = success.headers().date;
        var processedTimestamp = new Date(timestamp).getTime();
        var endTime = new Date().getTime();

        serverLatency = endTime - startTime;

        var computedTimestamp = processedTimestamp + serverLatency;

        deferred.resolve(computedTimestamp);
       },
       function(error){
        // use the system time instead on error
        var timestamp = new Date().getTime();

        var computedTimestamp = timestamp;

        deferred.resolve(computedTimestamp);
       }
      );

      return deferred.promise;
    }

    return {
      getTimestamp: getTimestamp,
    };
  }

})();
<commit_msg>Updated to have a 2s timeout on the http call Added the local-to-server time diff so for any failing future calls to the time server, we can still get as accurate as possible to the correct time<commit_after>(function() {
  'use strict';

  angular.module('arkclient')
    .service('timeService', ['$q', '$http', '$interval', TimeService]);

  /**
   * TimeService
   * @constructor
   */
  function TimeService($q, $http) {

    var timeServerUrl = "http://www.timeapi.org/";
    var serverLatency = 0;
    var config = {
      timeout: 2000
    };

    /**
     * Function gets a server timestamp as to not rely on the users local clock.
     * Fallback to users local clock on failure.
     * Always returns success.
     */
    function getTimestamp() {

      var deferred = $q.defer();

      var startTime = new Date().getTime();

      $http.get(timeServerUrl, config).then(
       function(success){

        var timestamp = success.headers().date;
        var processedTimestamp = new Date(timestamp).getTime();
        var endTime = new Date().getTime();

        serverLatency = endTime - startTime;

        var computedTimestamp = processedTimestamp + serverLatency;

        deferred.resolve(computedTimestamp);
       },
       function(error){
        // use the system time instead on error
        var timestamp = new Date().getTime();

        var computedTimestamp = timestamp + serverLatency;

        deferred.resolve(computedTimestamp);
       }
      );

      return deferred.promise;
    }

    return {
      getTimestamp: getTimestamp,
    };
  }

})();
<|endoftext|>


<commit_before>//admin.js
(function() {
	var template = {};
	var selectedUser = {};
	var userList = [];
	var showEdition = false;
	var index = null;

	function onDeleteSucess (data) {
		userService.getUsers().then(render, common.onError);
	}

	function deleteUser() {
		userService.deleteUser(deleteId).then(onDeleteSucess ,common.onError);
	}

	function getFormData() {
		var user = {};

		user.email = $('#email-input').val();
		user.password = $('#password-input').val();
		user.passwordRepeat = $('#password-input-repeat').val();
		user.role = $('#role-select').val();
		return user;
	}

	function setFormData(user) {
	  $('#email-input').val(user.email);
	  $('#email-input').prop('disabled', true);
		$('#role-select').val(user.role);

	}

	function editUser() {
		selectedUser = userList[index];
		setFormData(selectedUser);
	}

	function getIdFromParent($element) {
		var $liItem = $element.closest('li');
		var id = $liItem.data('id');
		return id;
	}

	function getIndexFromParent($element) {
		var $liItem = $element.closest('li');
		var id = $liItem.data('index');
		return id;
	}

	function onSaveSucess(data) {
		if(data.success) {
			userService.getUsers().then(render, common.onError);
		} else {
			console.log("log error" , data );
	    onErrorSaveUser(data);
		}
	}

	function onEditSucess(data) {
		console.log(data);
		if(data._id = editId) {
			userService.getUsers().then(render, common.onError);
		} else {
			console.log("log error" , data );
	    onErrorSaveUser(data);
		}
	}

	function onErrorSaveUser(data) {
		$('.error-msg').show();
	}

	function isValidForm(data) {
		console.log(!$('#user-form').data('bs.validator').hasErrors());
		return !$('#user-form').data('bs.validator').hasErrors();
	}

	function showSaveOrUpdate() {
		if(showEdition) {
			$('.btn-save-user').hide();
			$('.btn-update-user').show();
			$('.form-legend').html('Update User: ' + selectedUser.email);
		} else {
			$('.btn-save-user').show();
			$('.btn-update-user').hide();
			$('.form-legend').html('Create User');
			$('#email-input').prop('disabled', false);
		}

	}

	function bindEvents() {
		$(document).on('click','.delete-user', function(e) {
			e.preventDefault();
			modalView.show();
			deleteId = getIdFromParent($(e.target));
		});

		$(document).on('click','.edit-user', function(e) {
			e.preventDefault();
			showEdition = true;

			editId = getIdFromParent($(e.target));
			index = getIndexFromParent($(e.target));
			editUser();
			showSaveOrUpdate();
		});

		$(document).on('click','.btn-save-user', function(e) {
			e.preventDefault();
			var user = getFormData();
			console.log(user);

			$('#user-form').validator('validate');

			if(isValidForm(user) && !$(e.target).hasClass('disabled')) {
				userService.saveUser(user).then(onSaveSucess, common.onError);
			}
		});

		$(document).on('click','#add-user-btn', function(e) {
			e.preventDefault();
			showEdition = false;
			$('#user-form')[0].reset();
			showSaveOrUpdate();

		});

		$(document).on('click','.btn-update-user', function(e) {
			e.preventDefault();
			var user = getFormData();
			console.log(user);

			$('#user-form').validator('validate');

			if(isValidForm(user) && !$(e.target).hasClass('disabled')) {
				userService.updateUser(editId, user).then(onEditSucess, common.onError);
			}
		});

	}

	function render(data) {
		userList = data;
		var navbarModel = {adminActive: true, listActive: false ,creatorActive: false, isAdmin: common.isAdmin()};
		var viewModel = { userArray : data};

		common.renderNavbar('#navbar-container', navbarModel, template.navbar);

		var templateLoaded = Handlebars.compile(template.list);
		$('#list-container').html(templateLoaded(viewModel));

		modalView.init('#js-modal-container', template.modal);
 		modalView.options({ body: 'Are you sure that you want to delete the selected user?'});
		modalView.bindConfirmAction(deleteUser);
		modalView.render();

 		$('#user-form').validator();
 		$('.btn-update-user').hide();

	}

	function loadTemplates() {
		common.loadTemplates(['admin', 'navbar', 'modal']).done(function(temp1, temp2, temp3) {
			template.list = temp1[0];
			template.navbar = temp2[0];
			template.modal = temp3[0];
			userService.getUsers().then(render, common.onError);
		});
	}

	$(document).ready(function ready(){
		common.checkLoggedIn();
		loadTemplates();
		bindEvents();
	});

})();<commit_msg>added edit user label<commit_after>//admin.js
(function() {
	var template = {};
	var selectedUser = {};
	var userList = [];
	var showEdition = false;
	var index = null;

	function onDeleteSucess (data) {
		userService.getUsers().then(render, common.onError);
	}

	function deleteUser() {
		userService.deleteUser(deleteId).then(onDeleteSucess ,common.onError);
	}

	function getFormData() {
		var user = {};

		user.email = $('#email-input').val();
		user.password = $('#password-input').val();
		user.passwordRepeat = $('#password-input-repeat').val();
		user.role = $('#role-select').val();
		return user;
	}

	function setFormData(user) {
	  $('#email-input').val(user.email);
	  $('#email-input').prop('disabled', true);
		$('#role-select').val(user.role);

	}

	function clearFormData() {
	  $('#email-input').val('');
	  $('#email-input').prop('disabled', false);
		$('#role-select').val('');

	}

	function editUser() {
		selectedUser = userList[index];
		setFormData(selectedUser);
	}

	function getIdFromParent($element) {
		var $liItem = $element.closest('li');
		var id = $liItem.data('id');
		return id;
	}

	function getIndexFromParent($element) {
		var $liItem = $element.closest('li');
		var id = $liItem.data('index');
		return id;
	}

	function onSaveSucess(data) {
		if(data.success) {
			userService.getUsers().then(render, common.onError);
		} else {
			console.log("log error" , data );
	    onErrorSaveUser(data);
		}
	}

	function onEditSucess(data) {
		console.log(data);
		if(data._id = editId) {
			userService.getUsers().then(render, common.onError);
		} else {
			console.log("log error" , data );
	    onErrorSaveUser(data);
		}
	}

	function onErrorSaveUser(data) {
		$('.error-msg').show();
	}

	function isValidForm(data) {
		console.log(!$('#user-form').data('bs.validator').hasErrors());
		return !$('#user-form').data('bs.validator').hasErrors();
	}

	function showSaveOrUpdate() {
		if(showEdition) {
			$('.btn-save-user').hide();
			$('.btn-update-user').show();
			$('.form-legend').html('Edit User: ' + selectedUser.email);
		} else {
			$('.btn-save-user').show();
			$('.btn-update-user').hide();
			$('.form-legend').html('Create User');
			$('#email-input').prop('disabled', false);
		}

	}

	function bindEvents() {
		$(document).on('click','.delete-user', function(e) {
			e.preventDefault();
			modalView.show();
			deleteId = getIdFromParent($(e.target));
		});

		$(document).on('click','.edit-user', function(e) {
			e.preventDefault();
			showEdition = true;

			editId = getIdFromParent($(e.target));
			index = getIndexFromParent($(e.target));
			editUser();
			showSaveOrUpdate();
		});

		$(document).on('click','.btn-save-user', function(e) {
			e.preventDefault();
			var user = getFormData();
			console.log(user);

			$('#user-form').validator('validate');

			if(isValidForm(user) && !$(e.target).hasClass('disabled')) {
				userService.saveUser(user).then(onSaveSucess, common.onError);
			}
		});

		$(document).on('click','#add-user-btn', function(e) {
			e.preventDefault();
			showEdition = false;
			$('#user-form')[0].reset();
			clearFormData();
			showSaveOrUpdate();

		});

		$(document).on('click','.btn-update-user', function(e) {
			e.preventDefault();
			var user = getFormData();
			console.log(user);

			$('#user-form').validator('validate');

			if(isValidForm(user) && !$(e.target).hasClass('disabled')) {
				userService.updateUser(editId, user).then(onEditSucess, common.onError);
			}
		});

	}

	function render(data) {
		userList = data;
		var navbarModel = {adminActive: true, listActive: false ,creatorActive: false, isAdmin: common.isAdmin()};
		var viewModel = { userArray : data};

		common.renderNavbar('#navbar-container', navbarModel, template.navbar);

		var templateLoaded = Handlebars.compile(template.list);
		$('#list-container').html(templateLoaded(viewModel));

		modalView.init('#js-modal-container', template.modal);
 		modalView.options({ body: 'Are you sure that you want to delete the selected user?'});
		modalView.bindConfirmAction(deleteUser);
		modalView.render();

 		$('#user-form').validator();
 		$('.btn-update-user').hide();

	}

	function loadTemplates() {
		common.loadTemplates(['admin', 'navbar', 'modal']).done(function(temp1, temp2, temp3) {
			template.list = temp1[0];
			template.navbar = temp2[0];
			template.modal = temp3[0];
			userService.getUsers().then(render, common.onError);
		});
	}

	$(document).ready(function ready(){
		common.checkLoggedIn();
		loadTemplates();
		bindEvents();
	});

})();<|endoftext|>