<commit_before>/*    Copyright 2022 Firewalla Inc
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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 Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require('../../../net2/logger.js')(__filename);
const fs = require('fs');
const Promise = require('bluebird');
Promise.promisifyAll(fs);
const exec = require('child-process-promise').exec;
const DockerBaseVPNClient = require('./DockerBaseVPNClient.js');
const YAML = require('../../../vendor_lib/yaml/dist');
const dns = require('dns');
const resolve4 = Promise.promisify(dns.resolve4);

class TrojanDockerClient extends DockerBaseVPNClient {

  async prepareDockerCompose(config) {
    log.info("Preparing docker compose file");
    const src = `${__dirname}/trojan/docker-compose.template.yaml`;
    const content = await fs.readFileAsync(src, {encoding: 'utf8'});
    const server = config.remote_addr || "";
    const yamlObj = YAML.parse(content);

    const ips = await resolve4(server);
    if(ips && ips.length > 0) {
      // must be IP for iptables rules
      yamlObj.services.trojan.environment.TROJAN_SERVER = ips[0];
    }

    const dst = `${this._getDockerConfigDirectory()}/docker-compose.yaml`;
    await fs.writeFileAsync(dst, YAML.stringify(yamlObj));
  }

  async prepareTrojanConfig(config) {
    log.info("Preparing trojan config file");
    const src = `${__dirname}/trojan/config.template.json`;
    const dst = `${this._getDockerConfigDirectory()}/config.json`;
    const template = require(src);
    const merged = Object.assign({}, template, config) ;
    await fs.writeFileAsync(dst, JSON.stringify(merged));
  }

  async __prepareAssets() {
    const config = await this.loadJSONConfig();

    if(_.isEmpty(config)) return;

    // prepare the log file in advance, otherwise, it will be created as a directory when docker container starts up
    await exec(`touch ${f.getUserHome()}/.forever/clash.log`);
    await this.prepareDockerCompose(config);
    await this.prepareTrojanConfig(config);
  }

  static getProtocol() {
    return "trojan";
  }

  static getConfigDirectory() {
    return `${f.getHiddenFolder()}/run/trojan_profile`;
  }
}

module.exports = TrojanDockerClient;
<commit_msg>Fix the import issue on Firewalla.js<commit_after>/*    Copyright 2022 Firewalla Inc
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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 Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require('../../../net2/logger.js')(__filename);
const fs = require('fs');
const Promise = require('bluebird');
Promise.promisifyAll(fs);
const exec = require('child-process-promise').exec;
const DockerBaseVPNClient = require('./DockerBaseVPNClient.js');
const YAML = require('../../../vendor_lib/yaml/dist');
const dns = require('dns');
const f = require('../../../net2/Firewalla.js');
const resolve4 = Promise.promisify(dns.resolve4);

class TrojanDockerClient extends DockerBaseVPNClient {

  async prepareDockerCompose(config) {
    log.info("Preparing docker compose file");
    const src = `${__dirname}/trojan/docker-compose.template.yaml`;
    const content = await fs.readFileAsync(src, {encoding: 'utf8'});
    const server = config.remote_addr || "";
    const yamlObj = YAML.parse(content);

    const ips = await resolve4(server);
    if(ips && ips.length > 0) {
      // must be IP for iptables rules
      yamlObj.services.trojan.environment.TROJAN_SERVER = ips[0];
    }

    const dst = `${this._getDockerConfigDirectory()}/docker-compose.yaml`;
    await fs.writeFileAsync(dst, YAML.stringify(yamlObj));
  }

  async prepareTrojanConfig(config) {
    log.info("Preparing trojan config file");
    const src = `${__dirname}/trojan/config.template.json`;
    const dst = `${this._getDockerConfigDirectory()}/config.json`;
    const template = require(src);
    const merged = Object.assign({}, template, config) ;
    await fs.writeFileAsync(dst, JSON.stringify(merged));
  }

  async __prepareAssets() {
    const config = await this.loadJSONConfig();

    if(_.isEmpty(config)) return;

    // prepare the log file in advance, otherwise, it will be created as a directory when docker container starts up
    await exec(`touch ${f.getUserHome()}/.forever/clash.log`);
    await this.prepareDockerCompose(config);
    await this.prepareTrojanConfig(config);
  }

  static getProtocol() {
    return "trojan";
  }

  static getConfigDirectory() {
    return `${f.getHiddenFolder()}/run/trojan_profile`;
  }
}

module.exports = TrojanDockerClient;
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.view1', ['ngRoute', 'ngFileUpload'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', function($scope, fileReader, pdfReader, lemma, cvTokenizer) {
    $scope.page1content = "No file opened.";
    $scope.fileNames = "";

    var education = ["(Phd.) Neuroscience, Nanyang Technological University, Singapore Jan 2014- Nov 2014 \
      MSc Biomedical Engineering Nanyang Technological University, Singapore Aug 2010- July 2012 \
      BE Biomedical Engineering Anna University, India Aug 2006 - May 2010"];
    $scope.testEducation = lemma.parse_education(education);
    var languages = ["Chinese Tamil Japanese"];
    $scope.testLanguages = lemma.parse_language(languages);
    console.log("education", $scope.testEducation);
    console.log("languages", $scope.testLanguages);

  $scope.$watch('file', function () {
    if ($scope.file != null) {
      $scope.files = [$scope.file];
    }
  });

  $scope.$on("fileProgress", function(e, progress) {
    $scope.progress = (progress.loaded / progress.total) * 100;
  });

  $scope.processFiles = function (files) {
    $scope.fileNames = "";
    if (files && files.length) {
      for (var i = 0; i < files.length; i++) {
        console.log(files[i]);
        $scope.fileNames += files[i].name + "\n";
        $scope.showProgressBar = true;
        fileReader.readAsDataUrl(files[i], $scope)
          .then(function(result) {
            pdfReader.getAllTextFromPdf(result).then(function(result) {
              console.log("final array of string", result);
              $scope.$apply(function() {
                result.forEach(function(line) {
                  $scope.page1content += line + '\n';
                });
              });
              cvTokenizer.tokenizeCv(result);
            });
          });
      }
    }
  };

  $scope.doProcess = function () {
    $scope.page1content = "";
    $scope.processFiles($scope.files);
  };
});<commit_msg>Added storage access to view1 controller<commit_after>'use strict';

angular.module('myApp.view1', ['ngRoute', 'ngFileUpload'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', function($scope, fileReader, pdfReader, lemma, cvTokenizer, storageAccess) {
    $scope.page1content = "No file opened.";
    $scope.fileNames = "";

    var education = ["(Phd.) Neuroscience, Nanyang Technological University, Singapore Jan 2014- Nov 2014 \
      MSc Biomedical Engineering Nanyang Technological University, Singapore Aug 2010- July 2012 \
      BE Biomedical Engineering Anna University, India Aug 2006 - May 2010"];
    $scope.testEducation = lemma.parse_education(education);
    var languages = ["Chinese Tamil Japanese"];
    $scope.testLanguages = lemma.parse_language(languages);
    console.log("education", $scope.testEducation);
    console.log("languages", $scope.testLanguages);

  $scope.$watch('file', function () {
    if ($scope.file != null) {
      $scope.files = [$scope.file];
    }
  });

  $scope.$on("fileProgress", function(e, progress) {
    $scope.progress = (progress.loaded / progress.total) * 100;
  });

  $scope.processFiles = function (files) {
    $scope.fileNames = "";
    if (files && files.length) {
      for (var i = 0; i < files.length; i++) {
        console.log(files[i]);
        $scope.fileNames += files[i].name + "\n";
        $scope.showProgressBar = true;
        fileReader.readAsDataUrl(files[i], $scope)
          .then(function(result) {
            pdfReader.getAllTextFromPdf(result).then(function(result) {
              console.log("final array of string", result);
              $scope.$apply(function() {
                result.forEach(function(line) {
                  $scope.page1content += line + '\n';
                });
              });
              cvTokenizer.tokenizeCv(result);
            });
          });
      }
    }
  };

  $scope.doProcess = function () {
    $scope.page1content = "";
    $scope.processFiles($scope.files);
  };
});<|endoftext|>


<commit_before>let filterTimeout;

function filterTimeoutCallback() {
  let newHistory = encodeURI(document.querySelector('#filter').value);
  history.pushState({}, '', '?filter=' + newHistory);
}

function filterHistory() {
  if (typeof filterTimeout !== 'undefined') {
    clearTimeout(filterTimeout);
  }
  filterTimeout = setTimeout(filterTimeoutCallback, 2000);
}

function filterMap(element) {
  let component = element.split('&');
  this[component[0]] = component[1];
  return this;
}

export function filterContainers() {

  // Fetch DOM elements, break each word in input filter.
  let filterValues = document.querySelector('#filter').value.trim().split(' ');
  let containers = document.querySelectorAll('.container');

  // Iterate through each container.
  for (let i = 0; i < containers.length; i++) {

    // Get container title.
    let spanText = containers[i].querySelector('span').innerHTML;

    // Define hidden by default.
    let hide = true;

    // Iterate through each word, show if any are found.
    for (let j = 0; j < filterValues.length; j++) {
      if (spanText.indexOf(filterValues[j]) >= 0) {
        hide = false;
        break;
      }
    }

    // Display or hide container, based on filter.
    if (hide) {
      containers[i].classList.add('hide');
      containers[i].classList.remove('show');
    }
    else {
      containers[i].classList.remove('hide');
      containers[i].classList.add('show');
    }
  }
  filterHistory();
}

export function filterOnLoad() {
  let filterInput = document.querySelector('#filter');
  if (!filterInput) {
    setTimeout(filterOnLoad, 1000);
    return;
  }
  let search = decodeURIComponent(location.search);
  if (!search) {
    return;
  }

  let searchObj = search
    .substring(1)
    .split('&')
    .map(filterMap, {})[0];

  if (searchObj.filter) {
    filterInput.value = search;
    console.log('about to call filterContainers');
    console.log(typeof filterContainers);
    filterContainers();
  }
}
<commit_msg>url_param: Sync filter options and URL params<commit_after>let filterTimeout;

function filterTimeoutCallback() {
  let newHistory = encodeURI(document.querySelector('#filter').value);
  history.pushState({}, '', '?filter=' + newHistory);
}

function filterHistory() {
  if (typeof filterTimeout !== 'undefined') {
    clearTimeout(filterTimeout);
  }
  filterTimeout = setTimeout(filterTimeoutCallback, 2000);
}

function filterMap(element) {
  let component = element.split('=');
  this[component[0]] = component[1];
  return this;
}

export function filterContainers() {

  // Fetch DOM elements, break each word in input filter.
  let filterValues = document.querySelector('#filter').value.trim().split(' ');
  let containers = document.querySelectorAll('.container');

  // Iterate through each container.
  for (let i = 0; i < containers.length; i++) {

    // Get container title.
    let spanText = containers[i].querySelector('span').innerHTML;

    // Define hidden by default.
    let hide = true;

    // Iterate through each word, show if any are found.
    for (let j = 0; j < filterValues.length; j++) {
      if (spanText.indexOf(filterValues[j]) >= 0) {
        hide = false;
        break;
      }
    }

    // Display or hide container, based on filter.
    if (hide) {
      containers[i].classList.add('hide');
      containers[i].classList.remove('show');
    }
    else {
      containers[i].classList.remove('hide');
      containers[i].classList.add('show');
    }
  }
  filterHistory();
}

export function filterOnLoad() {
  let filterInput = document.querySelector('#filter');
  if (!filterInput) {
    setTimeout(filterOnLoad, 1000);
    return;
  }
  let search = decodeURIComponent(location.search);
  if (!search) {
    return;
  }

  let searchObj = search
    .substring(1)
    .split('&')
    .map(filterMap, {})[0];

  if (searchObj.filter) {
    filterInput.value = searchObj.filter;
    console.log('about to call filterContainers');
    console.log(typeof filterContainers);
    filterContainers();
  }
}
<|endoftext|>


<commit_before>/*jslint browser: true, indent: 2, plusplus: true, vars: true */

(function (window) {
  "use strict";

  var debugMode = false;
  var visitTtl, visitorTtl;
  var $ = window.jQuery || window.Zepto || window.$;
  var visitToken, visitorToken;

  if (debugMode) {
    visitTtl = 0.2;
    visitorTtl = 5; // 5 minutes
  } else {
    visitTtl = 4 * 60; // 4 hours
    visitorTtl = 2 * 365 * 24 * 60; // 2 years
  }

  // cookies

  // http://www.quirksmode.org/js/cookies.html
  function setCookie(name, value, ttl) {
    var expires = "";
    if (ttl) {
      var date = new Date();
      date.setTime(date.getTime() + (ttl * 60 * 1000));
      expires = "; expires=" + date.toGMTString();
    }
    document.cookie = name + "=" + value + expires + "; path=/";
  }

  function getCookie(name) {
    var i, c;
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (i = 0; i < ca.length; i++) {
      c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1, c.length);
      }
      if (c.indexOf(nameEQ) === 0) {
        return c.substring(nameEQ.length, c.length);
      }
    }
    return null;
  }

  // ids

  // https://github.com/klughammer/node-randomstring
  function generateToken() {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
    var length = 32;
    var string = '';
    var i, randomNumber;

    for (i = 0; i < length; i++) {
      randomNumber = Math.floor(Math.random() * chars.length);
      string += chars.substring(randomNumber, randomNumber + 1);
    }

    return string;
  }

  function debug(message) {
    if (debugMode) {
      window.console.log(message, visitToken, visitorToken);
    }
  }

  // main

  visitToken = getCookie("ahoy_visit");
  visitorToken = getCookie("ahoy_visitor");

  if (visitToken && visitorToken) {
    // TODO keep visit alive?
    debug("Active visit");
  } else {
    if (!visitorToken) {
      visitorToken = generateToken();
      setCookie("ahoy_visitor", visitorToken, visitorTtl);
    }

    // always generate a new visit id here
    visitToken = generateToken();
    setCookie("ahoy_visit", visitToken, visitTtl);

    // make sure cookies are enabled
    if (getCookie("ahoy_visit")) {
      debug("Visit started");

      var data = {
        visit_token: visitToken,
        visitor_token: visitorToken,
        landing_page: window.location.href
      };

      // referrer
      if (document.referrer.length > 0) {
        data.referrer = document.referrer;
      }

      debug(data);

      $.post("/ahoy/visits", data);
    } else {
      debug("Cookies disabled");
    }
  }

}(window));
<commit_msg>Adds the ability to specify the ahoy cookie domain<commit_after>/*jslint browser: true, indent: 2, plusplus: true, vars: true */

(function (window) {
  "use strict";

  var debugMode = false;
  var visitTtl, visitorTtl;
  var $ = window.jQuery || window.Zepto || window.$;
  var visitToken, visitorToken;
  var cookieDomain;

  if (debugMode) {
    visitTtl = 0.2;
    visitorTtl = 5; // 5 minutes
  } else {
    visitTtl = 4 * 60; // 4 hours
    visitorTtl = 2 * 365 * 24 * 60; // 2 years
  }

  cookieDomain = window.ahoyCookieDomain || null;

  // cookies

  // http://www.quirksmode.org/js/cookies.html
  function setCookie(name, value, ttl, domain) {
    var expires = "";
    var cookieDomain = "";
    if (ttl) {
      var date = new Date();
      date.setTime(date.getTime() + (ttl * 60 * 1000));
      expires = "; expires=" + date.toGMTString();
    }
    if (domain) {
      cookieDomain = "; domain=" + domain;
    }
    document.cookie = name + "=" + value + expires + cookieDomain + "; path=/";
  }

  function getCookie(name) {
    var i, c;
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (i = 0; i < ca.length; i++) {
      c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1, c.length);
      }
      if (c.indexOf(nameEQ) === 0) {
        return c.substring(nameEQ.length, c.length);
      }
    }
    return null;
  }

  // ids

  // https://github.com/klughammer/node-randomstring
  function generateToken() {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
    var length = 32;
    var string = '';
    var i, randomNumber;

    for (i = 0; i < length; i++) {
      randomNumber = Math.floor(Math.random() * chars.length);
      string += chars.substring(randomNumber, randomNumber + 1);
    }

    return string;
  }

  function debug(message) {
    if (debugMode) {
      window.console.log(message, visitToken, visitorToken);
    }
  }

  // main

  visitToken = getCookie("ahoy_visit");
  visitorToken = getCookie("ahoy_visitor");

  if (visitToken && visitorToken) {
    // TODO keep visit alive?
    debug("Active visit");
  } else {
    if (!visitorToken) {
      visitorToken = generateToken();
      setCookie("ahoy_visitor", visitorToken, visitorTtl, cookieDomain);
    }

    // always generate a new visit id here
    visitToken = generateToken();
    setCookie("ahoy_visit", visitToken, visitTtl, cookieDomain);

    // make sure cookies are enabled
    if (getCookie("ahoy_visit")) {
      debug("Visit started");

      var data = {
        visit_token: visitToken,
        visitor_token: visitorToken,
        landing_page: window.location.href
      };

      // referrer
      if (document.referrer.length > 0) {
        data.referrer = document.referrer;
      }

      debug(data);

      $.post("/ahoy/visits", data);
    } else {
      debug("Cookies disabled");
    }
  }

}(window));
<|endoftext|>


<commit_before>define([
	'jquery',
	'underscore',
	'backbone',
	'backbone.marionette',
	'text!templates/main-content.html',
	'bootstrap-multiselect'
], function(
	$,
	_,
	Backbone,
	Marionette,
	mainContentTemplate
) {
	var HeaderView = Backbone.Marionette.ItemView.extend({
		template: mainContentTemplate,
		className: 'main-content-view',

		initialize: function(options) {

		},

		onShow: function() {
			this.$el.find('#multiselect-options').multiselect();
		}

	});

	return HeaderView;
});
<commit_msg>Update main-content-view.js<commit_after>define([
	'jquery',
	'underscore',
	'backbone',
	'backbone.marionette',
	'text!templates/main-content.html',
	'bootstrap-multiselect'
], function(
	$,
	_,
	Backbone,
	Marionette,
	mainContentTemplate
) {
	var MainContentView = Backbone.Marionette.ItemView.extend({
		template: mainContentTemplate,
		className: 'main-content-view',

		initialize: function(options) {

		},

		onShow: function() {
			this.$el.find('#multiselect-options').multiselect();
		}

	});

	return MainContentView;
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2006
 * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/

/**
 * Init namespaces
 */
if(!ORYX) {var ORYX = {};}
if(!ORYX.Core) {ORYX.Core = {};}

/**
 * Top Level uiobject.
 * @class ORYX.Core.AbstractShape
 * @extends ORYX.Core.UIObject
 */
ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(
/** @lends ORYX.Core.AbstractShape.prototype */
{

	/**
	 * Constructor
	 */
	construct: function(options, stencil) {

		arguments.callee.$.construct.apply(this, arguments);

		this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM

		// stencil reference
		this._stencil = stencil;
		// if the stencil defines a super stencil that should be used for its instances, set it.
		if (this._stencil._jsonStencil.superId){
			stencilId = this._stencil.id()
			superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId;
			stencilSet =  this._stencil.stencilSet();
			this._stencil = stencilSet.stencil(superStencilId);
		}

		//Hash map for all properties. Only stores the values of the properties.
		this.properties = new Hash();
		this.propertiesChanged = new Hash();

		//Initialization of property map and initial value.
		this._stencil.properties().each((function(property) {
			var key = property.prefix() + "-" + property.id();
			this.properties[key] = property.value();
			this.propertiesChanged[key] = true;
		}).bind(this));

		// if super stencil was defined, also regard stencil's properties:
		stencil.properties().each((function(property) {
			var key = property.prefix() + "-" + property.id();
			this.properties[key] = property.value();
			this.propertiesChanged[key] = true;
		}).bind(this));

	},

	layout: function() {

	},

	/**
	 * Returns the stencil object specifiing the type of the shape.
	 */
	getStencil: function() {
		return this._stencil;
	},

	/**
	 *
	 * @param {Object} resourceId
	 */
	getChildShapeByResourceId: function(resourceId) {

		resourceId = ERDF.__stripHashes(resourceId);

		return this.getChildShapes(true).find(function(shape) {
					return shape.resourceId == resourceId
				});
	},
	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildShapes: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
				if(deep) {
					result = result.concat(uiObject.getChildShapes(deep, iterator));
				}
			}
		});

		return result;
	},

    /**
     * @param {Object} shape
     * @return {boolean} true if any of shape's childs is given shape
     */
    hasChildShape: function(shape){
        return this.getChildShapes().any(function(child){
            return (child === shape) || child.hasChildShape(shape);
        });
    },

	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildNodes: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
			}
			if(uiObject instanceof ORYX.Core.Shape) {
				if(deep) {
					result = result.concat(uiObject.getChildNodes(deep, iterator));
				}
			}
		});

		return result;
	},

	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildEdges: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
			}
			if(uiObject instanceof ORYX.Core.Shape) {
				if(deep) {
					result = result.concat(uiObject.getChildEdges(deep, iterator));
				}
			}
		});

		return result;
	},

	/**
	 * Returns a sorted array of ORYX.Core.Node objects.
	 * Ordered in z Order, the last object has the highest z Order.
	 */
	//TODO deep iterator
	getAbstractShapesAtPosition: function() {
		var x, y;
		switch (arguments.length) {
			case 1:
				x = arguments[0].x;
				y = arguments[0].y;
				break;
			case 2:	//two or more arguments
				x = arguments[0];
				y = arguments[1];
				break;
			default:
				throw "getAbstractShapesAtPosition needs 1 or 2 arguments!"
		}

		if(this.isPointIncluded(x, y)) {

			var result = [];
			result.push(this);

			//check, if one child is at that position

			var childNodes = this.getChildNodes();
			var childEdges = this.getChildEdges();

			[childNodes, childEdges].each(function(ne){
				var nodesAtPosition = new Hash();

				ne.each(function(node) {
					if(!node.isVisible){ return }
					var candidates = node.getAbstractShapesAtPosition( x , y );
					if(candidates.length > 0) {
						var nodesInZOrder = $A(node.node.parentNode.childNodes);
						var zOrderIndex = nodesInZOrder.indexOf(node.node);
						nodesAtPosition[zOrderIndex] = candidates;
					}
				});

				nodesAtPosition.keys().sort().each(function(key) {
					result = result.concat(nodesAtPosition[key]);
				});
 			});

			return result;

		} else {
			return [];
		}
	},

	/**
	 *
	 * @param key {String} Must be 'prefix-id' of property
	 * @param value {Object} Can be of type String or Number according to property type.
	 */
	setProperty: function(key, value) {
		var oldValue = this.properties[key];
		if(oldValue !== value) {
			this.properties[key] = value;
			this.propertiesChanged[key] = true;
			this._changed();

			// Raise an event, to show that the property has changed
			window.setTimeout( function(){

				this._delegateEvent({
						type	: ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
						name	: key,
						value	: value,
						oldValue: oldValue
					});

			}.bind(this), 10)
		}
	},

	/**
	 * Calculate if the point is inside the Shape
	 * @param {Point}
	 */
	isPointIncluded: function(pointX, pointY, absoluteBounds) {
		var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();
		return absBounds.isIncluded(pointX, pointY);

	},

	/**
	 * Get the serialized object
	 * return Array with hash-entrees (prefix, name, value)
	 * Following values will given:
	 * 		Type
	 * 		Properties
	 */
	serialize: function() {
		var serializedObject = [];

		// Add the type
		serializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});

		// Add all properties
		this.getStencil().properties().each((function(property){

			var prefix = property.prefix();	// Get prefix
			var name = property.id();		// Get name

			//if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "")
				serializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});

		}).bind(this));

		return serializedObject;
	},

	deserialize: function(serialze){
		// Search in Serialize
		var initializedDocker = 0;
		serialze.each((function(obj){

			var name 	= obj.name;
			var prefix 	= obj.prefix;
			var value 	= obj.value;

			switch(prefix + "-" + name){
				case 'raziel-parent':
							// Set parent
							if(!this.parent) {break};

							// Set outgoing Shape
							var parent = this.getCanvas().getChildShapeByResourceId(value);
							if(parent) {
								parent.add(this);
							}

							break;
				default:
							// Set property
							if(this.properties.keys().member(prefix+"-"+name)) {
								this.setProperty(prefix+"-"+name, unescape(value));
							}

			}
		}).bind(this));
	},

	toString: function() { return "ORYX.Core.AbstractShape " + this.id },

    /**
     * Converts the shape to a JSON representation.
     * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.
     */
     toJSON: function(){
        var json = {
            resourceId: this.resourceId,
            properties: this.properties.inject({}, function(props, prop){
              //Takes "my_property" instead of "oryx-my_property" as key
              var key = prop[0].replace(/^[\w_]+-/, "");
              props[key] = prop[1];
              return props;
            }),
            stencil: {
                id: this.getStencil().idWithoutNs()
            },
            childShapes: this.getChildShapes().map(function(shape){
                return shape.toJSON()
            })
        };

        if(this.getOutgoingShapes){
            json.outgoing = this.getOutgoingShapes().map(function(shape){
                return {
                    resourceId: shape.resourceId
                };
            });
        }

        if(this.bounds){
            json.bounds = {
                lowerRight: this.bounds.lowerRight(),
                upperLeft: this.bounds.upperLeft()
            };
        }

        if(this.dockers){
            json.dockers = this.dockers.map(function(docker){
                return docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
            })
        }

        Ext.apply(json, ORYX.Core.AbstractShape.JSONHelper);

        // do not pollute the json attributes (for serialization), so put the corresponding
        // shape is encapsulated in a method
        json.getShape = function(){
            return this;
        }.bind(this);

        return json;
    }
 });

/**
 * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).
 * @example
 * Ext.apply(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);
 */
ORYX.Core.AbstractShape.JSONHelper = {
     /**
      * Iterates over each child shape.
      * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.
      * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)
      * @param {boolean} [modify=false] If true, the result of the iterator function is taken as new shape, return false to delete it. This enables modifying the object while iterating through the child shapes.
      * @example
      * // Increases the lowerRight x value of each direct child shape by one.
      * myShapeAsJson.eachChild(function(shape, parentShape){
      *     shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;
      *     return shape;
      * }, false, true);
      */
     eachChild: function(iterator, deep, modify){
         if(!this.childShapes) return;

         var newChildShapes = []; //needed if modify = true

         this.childShapes.each(function(shape){
             var res = iterator(shape, this);
             if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.

             if(deep) shape.eachChild(iterator, deep, modify);
         }.bind(this));

         if(modify) this.childShapes = newChildShapes;
     },

     getChildShapes: function(deep){
         var allShapes = this.childShapes;

         if(deep){
             this.eachChild(function(shape){
                 allShapes = allShapes.concat(shape.getChildShapes(deep));
             }, true);
         }

         return allShapes;
     },

     /**
      * @return {String} Serialized JSON object
      */
     serialize: function(){
         return Ext.encode(this);
     }
 }
<commit_msg>complex properties are now handled as json objects when saving and loading a model<commit_after>/**
 * Copyright (c) 2006
 * Martin Czuchra, Nicolas Peters, Daniel Polak, Willi Tscheschner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/

/**
 * Init namespaces
 */
if(!ORYX) {var ORYX = {};}
if(!ORYX.Core) {ORYX.Core = {};}

/**
 * Top Level uiobject.
 * @class ORYX.Core.AbstractShape
 * @extends ORYX.Core.UIObject
 */
ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend(
/** @lends ORYX.Core.AbstractShape.prototype */
{

	/**
	 * Constructor
	 */
	construct: function(options, stencil) {

		arguments.callee.$.construct.apply(this, arguments);

		this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM

		// stencil reference
		this._stencil = stencil;
		// if the stencil defines a super stencil that should be used for its instances, set it.
		if (this._stencil._jsonStencil.superId){
			stencilId = this._stencil.id()
			superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId;
			stencilSet =  this._stencil.stencilSet();
			this._stencil = stencilSet.stencil(superStencilId);
		}

		//Hash map for all properties. Only stores the values of the properties.
		this.properties = new Hash();
		this.propertiesChanged = new Hash();

		//Initialization of property map and initial value.
		this._stencil.properties().each((function(property) {
			var key = property.prefix() + "-" + property.id();
			this.properties[key] = property.value();
			this.propertiesChanged[key] = true;
		}).bind(this));

		// if super stencil was defined, also regard stencil's properties:
		stencil.properties().each((function(property) {
			var key = property.prefix() + "-" + property.id();
			this.properties[key] = property.value();
			this.propertiesChanged[key] = true;
		}).bind(this));

	},

	layout: function() {

	},

	/**
	 * Returns the stencil object specifiing the type of the shape.
	 */
	getStencil: function() {
		return this._stencil;
	},

	/**
	 *
	 * @param {Object} resourceId
	 */
	getChildShapeByResourceId: function(resourceId) {

		resourceId = ERDF.__stripHashes(resourceId);

		return this.getChildShapes(true).find(function(shape) {
					return shape.resourceId == resourceId
				});
	},
	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildShapes: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
				if(deep) {
					result = result.concat(uiObject.getChildShapes(deep, iterator));
				}
			}
		});

		return result;
	},

    /**
     * @param {Object} shape
     * @return {boolean} true if any of shape's childs is given shape
     */
    hasChildShape: function(shape){
        return this.getChildShapes().any(function(child){
            return (child === shape) || child.hasChildShape(shape);
        });
    },

	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildNodes: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
			}
			if(uiObject instanceof ORYX.Core.Shape) {
				if(deep) {
					result = result.concat(uiObject.getChildNodes(deep, iterator));
				}
			}
		});

		return result;
	},

	/**
	 *
	 * @param {Object} deep
	 * @param {Object} iterator
	 */
	getChildEdges: function(deep, iterator) {
		var result = [];

		this.children.each(function(uiObject) {
			if(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) {
				if(iterator) {
					iterator(uiObject);
				}
				result.push(uiObject);
			}
			if(uiObject instanceof ORYX.Core.Shape) {
				if(deep) {
					result = result.concat(uiObject.getChildEdges(deep, iterator));
				}
			}
		});

		return result;
	},

	/**
	 * Returns a sorted array of ORYX.Core.Node objects.
	 * Ordered in z Order, the last object has the highest z Order.
	 */
	//TODO deep iterator
	getAbstractShapesAtPosition: function() {
		var x, y;
		switch (arguments.length) {
			case 1:
				x = arguments[0].x;
				y = arguments[0].y;
				break;
			case 2:	//two or more arguments
				x = arguments[0];
				y = arguments[1];
				break;
			default:
				throw "getAbstractShapesAtPosition needs 1 or 2 arguments!"
		}

		if(this.isPointIncluded(x, y)) {

			var result = [];
			result.push(this);

			//check, if one child is at that position

			var childNodes = this.getChildNodes();
			var childEdges = this.getChildEdges();

			[childNodes, childEdges].each(function(ne){
				var nodesAtPosition = new Hash();

				ne.each(function(node) {
					if(!node.isVisible){ return }
					var candidates = node.getAbstractShapesAtPosition( x , y );
					if(candidates.length > 0) {
						var nodesInZOrder = $A(node.node.parentNode.childNodes);
						var zOrderIndex = nodesInZOrder.indexOf(node.node);
						nodesAtPosition[zOrderIndex] = candidates;
					}
				});

				nodesAtPosition.keys().sort().each(function(key) {
					result = result.concat(nodesAtPosition[key]);
				});
 			});

			return result;

		} else {
			return [];
		}
	},

	/**
	 *
	 * @param key {String} Must be 'prefix-id' of property
	 * @param value {Object} Can be of type String or Number according to property type.
	 */
	setProperty: function(key, value) {
		var oldValue = this.properties[key];
		if(oldValue !== value) {
			this.properties[key] = value;
			this.propertiesChanged[key] = true;
			this._changed();

			// Raise an event, to show that the property has changed
			window.setTimeout( function(){

				this._delegateEvent({
						type	: ORYX.CONFIG.EVENT_PROPERTY_CHANGED,
						name	: key,
						value	: value,
						oldValue: oldValue
					});

			}.bind(this), 10)
		}
	},

	/**
	 * Calculate if the point is inside the Shape
	 * @param {Point}
	 */
	isPointIncluded: function(pointX, pointY, absoluteBounds) {
		var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds();
		return absBounds.isIncluded(pointX, pointY);

	},

	/**
	 * Get the serialized object
	 * return Array with hash-entrees (prefix, name, value)
	 * Following values will given:
	 * 		Type
	 * 		Properties
	 */
	serialize: function() {
		var serializedObject = [];

		// Add the type
		serializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'});

		// Add all properties
		this.getStencil().properties().each((function(property){

			var prefix = property.prefix();	// Get prefix
			var name = property.id();		// Get name

			//if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "")
				serializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'});

		}).bind(this));

		return serializedObject;
	},

	deserialize: function(serialze){
		// Search in Serialize
		var initializedDocker = 0;
		serialze.each((function(obj){

			var name 	= obj.name;
			var prefix 	= obj.prefix;
			var value 	= obj.value;

            // Complex properties can be real json objects, encode them to a string
            if(Ext.type(value) === "object") value = Ext.encode(value);

			switch(prefix + "-" + name){
				case 'raziel-parent':
							// Set parent
							if(!this.parent) {break};

							// Set outgoing Shape
							var parent = this.getCanvas().getChildShapeByResourceId(value);
							if(parent) {
								parent.add(this);
							}

							break;
				default:
							// Set property
							if(this.properties.keys().member(prefix+"-"+name)) {
								this.setProperty(prefix+"-"+name, unescape(value));
							}

			}
		}).bind(this));
	},

	toString: function() { return "ORYX.Core.AbstractShape " + this.id },

    /**
     * Converts the shape to a JSON representation.
     * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method.
     */
     toJSON: function(){
        var json = {
            resourceId: this.resourceId,
            properties: this.properties.inject({}, function(props, prop){
              var key = prop[0];
              var value = prop[1];

              //If complex property, value should be a json object
              if(this.getStencil().property(key)
                && this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX
                && Ext.type(value) === "string"){
                  try {value = Ext.decode(value);} catch(error){}
              }

              //Takes "my_property" instead of "oryx-my_property" as key
              key = key.replace(/^[\w_]+-/, "");
              props[key] = value;

              return props;
            }.bind(this)),
            stencil: {
                id: this.getStencil().idWithoutNs()
            },
            childShapes: this.getChildShapes().map(function(shape){
                return shape.toJSON()
            })
        };

        if(this.getOutgoingShapes){
            json.outgoing = this.getOutgoingShapes().map(function(shape){
                return {
                    resourceId: shape.resourceId
                };
            });
        }

        if(this.bounds){
            json.bounds = {
                lowerRight: this.bounds.lowerRight(),
                upperLeft: this.bounds.upperLeft()
            };
        }

        if(this.dockers){
            json.dockers = this.dockers.map(function(docker){
                return docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center();
            })
        }

        Ext.apply(json, ORYX.Core.AbstractShape.JSONHelper);

        // do not pollute the json attributes (for serialization), so put the corresponding
        // shape is encapsulated in a method
        json.getShape = function(){
            return this;
        }.bind(this);

        return json;
    }
 });

/**
 * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()).
 * @example
 * Ext.apply(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper);
 */
ORYX.Core.AbstractShape.JSONHelper = {
     /**
      * Iterates over each child shape.
      * @param {Object} iterator Iterator function getting a child shape and his parent as arguments.
      * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes)
      * @param {boolean} [modify=false] If true, the result of the iterator function is taken as new shape, return false to delete it. This enables modifying the object while iterating through the child shapes.
      * @example
      * // Increases the lowerRight x value of each direct child shape by one.
      * myShapeAsJson.eachChild(function(shape, parentShape){
      *     shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1;
      *     return shape;
      * }, false, true);
      */
     eachChild: function(iterator, deep, modify){
         if(!this.childShapes) return;

         var newChildShapes = []; //needed if modify = true

         this.childShapes.each(function(shape){
             var res = iterator(shape, this);
             if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted.

             if(deep) shape.eachChild(iterator, deep, modify);
         }.bind(this));

         if(modify) this.childShapes = newChildShapes;
     },

     getChildShapes: function(deep){
         var allShapes = this.childShapes;

         if(deep){
             this.eachChild(function(shape){
                 allShapes = allShapes.concat(shape.getChildShapes(deep));
             }, true);
         }

         return allShapes;
     },

     /**
      * @return {String} Serialized JSON object
      */
     serialize: function(){
         return Ext.encode(this);
     }
 }
<|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/List.js"/>

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

(function() {
    Mobile.SalesLogix.Calendar.MonthView = Ext.extend(Sage.Platform.Mobile.List, {
        // Localization
        titleText: 'Calendar',
        todayText: 'Today',
        dayText: 'Day',
        weekText: 'Week',
        monthText: 'Month',
        monthTitleFormatText: 'MMMM yyyy',
        dayTitleFormatText: 'ddd MMM d, yyyy',
        dayStartTimeFormatText: 'h:mm',
        allDayText: 'All-Day',

        //Templates
        viewTemplate: new Simplate([
            '
',
            'fix for android issue #6059',
            '{%! $.searchTemplate %}',
            '{%! $.navigationTemplate %}',
            '

',
            '

',
            '{%! $.dayTemplate %}',
            '
'
        ]),
        navigationTemplate: new Simplate([
            '
',
                '<button data-tool="today" data-action="getTodayMonthActivities" class="button">{%: $.todayText %}</button>',
                '<button data-tool="day" data-action="navigateToDayView" class="button">{%: $.dayText %}</button>',
                '<button data-tool="week" data-action="navigateToWeekView" class="button">{%: $.weekText %}</button>',
                '<button data-tool="month" class="button">{%: $.monthText %}</button>',
            '
',
            '
',
            '

',
            '<button data-tool="next" data-action="goToNextMonth" class="button button-next"></button>',
            '<button data-tool="prev" data-action="goToPreviousMonth" class="button button-prev"></button>',
            '
'
        ]),
        dayTemplate: new Simplate([
            '
',
                '

',
                '

',
                '{%! $.moreTemplate %}',
            '
'
        ]),
        dayItemTemplate: new Simplate([
            '
',
            '

',
            '{%! $$.dayContentTemplate %}',
            '
'
        ]),
        dayContentTemplate: new Simplate([
            '
',
            '{%! $$.dayTimeTemplate %}',
            ' {%: $.Activity.Description %}',
            '
',
            '
{%= $$.dayNameTemplate.apply($) %}
'
        ]),
        dayTimeTemplate: new Simplate([
            '{% if ($.Activity.Timeless) { %}',
            '{%= $$.allDayText %}',
            '{% } else { %}',
            '{%: Mobile.SalesLogix.Format.date($.Activity.StartDate, $$.dayStartTimeFormatText) %}',
            '{%: Mobile.SalesLogix.Format.date($.Activity.StartDate, "tt") %},',
            '{% } %}'
        ]),
        dayNameTemplate: new Simplate([
            '{% if ($.Activity.ContactName) { %}',
            '{%: $.Activity.ContactName %} / {%: $.Activity.AccountName %}',
            '{% } else if ($.Activity.AccountName) { %}',
            '{%: $.Activity.AccountName %}',
            '{% } else { %}',
            '{%: $.Activity.LeadName %}',
            '{% } %}'
        ]),
        calendarStartTemplate: '
',
        calendarWeekHeaderStartTemplate: '
',
        calendarWeekHeaderTemplate: '{0}	',
        calendarWeekHeaderEndTemplate: '
',
        calendarWeekStartTemplate: '
',
        calendarEmptyDayTemplate: ' 	',
        calendarDayTemplate: '{0}	',
        calendarWeekEndTemplate: '
',
        calendarEndTemplate: '
',
        calendarActivityCountTemplate: new Simplate([
            '
{1}
'
        ]),
        attachmentPoints: Ext.apply({}, {
            contentEl: '.month-content',
            dateTextEl: '.date-text',
            dayTextEl: '.date-day-text',
            dayContentEl: '.day-content',
            selectedDateEl: '.selected'
        }, Sage.Platform.Mobile.List.prototype.attachmentPoints),

        //View Properties
        id: 'slx_calendar',
        cls: 'activities-for-month',
        activityListView: 'useractivity_list',
        activityWeekView: 'calendar_weeklist',
        insertView: 'activity_types_list',
        detailView: 'activity_detail',
        hideSearch: true,

        currentDate: Date.today(),
        queryWhere: null,
        queryOrderBy: 'Activity.StartDate asc',
        querySelect: [
            'Activity/StartDate',
            'Activity/EndDate',
            'Activity/Description',
            'Activity/Type',
            'Activity/AccountName',
            'Activity/ContactName',
            'Activity/LeadId',
            'Activity/LeadName',
            'Activity/UserId',
            'Activity/Timeless'
        ],
        pageSize: 31,
        resourceKind: 'useractivities',

        _onRefresh: function(o) {
            Mobile.SalesLogix.Calendar.MonthView.superclass._onRefresh.apply(this, arguments);
           if (o.resourceKind === 'activities'){
                this.refreshRequired = true;
            }
        },
        init: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.init.apply(this, arguments);
            this.setActivityQuery();
        },
        initEvents: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.initEvents.apply(this, arguments);
            this.el.on('swipe', this.onSwipe, this);
        },
        onSwipe: function(evt){
            switch(evt.browserEvent.direction){
                case 'right':
                    this.onSwipeRight();
                    break;
                case 'left':
                    this.onSwipeLeft();
                    break;
            }
        },
        onSwipeRight: function(){
            this.goToPreviousMonth();
        },
        onSwipeLeft: function(){
            this.goToNextMonth();
        },
        clear: function(){
            Mobile.SalesLogix.Calendar.MonthView.superclass.clear.apply(this, arguments);
            this.clearCurrentDateActivities();
        },
        render: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.render.apply(this, arguments);
            this.renderCalendar();
        },
        selectDay: function(params, evt, el) {
            if (this.selectedDateEl) this.selectedDateEl.removeClass('selected');
            this.selectedDateEl = Ext.get(el).addClass('selected');
            this.currentDate = Date.parse(params.date);
            this.showCurrentDateActivities();
        },
        getFirstDayOfCurrentMonth: function(){
            return this.currentDate.clone().moveToFirstDayOfMonth().clearTime();
        },
        getLastDayOfCurrentMonth: function(){
            return new Date(this.currentDate.getFullYear(),
                this.currentDate.getMonth(),
                this.currentDate.getDaysInMonth()-1,
                23, 59, 59);
        },
        getTodayMonthActivities: function(){
            var today = Date.today();
            if(this.currentDate.toString('yyyy-MM') === today.toString('yyyy-MM')){
                this.currentDate = today;
                this.highlightCurrentDate();
                this.showCurrentDateActivities();
            } else {
                this.currentDate = today;
                this.refresh();
            }
        },
        goToNextMonth: function() {
             this.currentDate.add({month: 1});
             this.refresh();
        },
        goToPreviousMonth: function() {
            this.currentDate.add({month: -1});
            this.refresh();
        },
        refresh: function(){
            this.renderCalendar();
            this.setActivityQuery();
            this.feed['$startIndex'] = 0;
            this.dayContentEl.update(this.loadingTemplate.apply(this));
            this.requestData();
        },
        setActivityQuery: function(){
            var startDate = this.getFirstDayOfCurrentMonth(),
                endDate = this.getLastDayOfCurrentMonth();
            this.queryWhere = String.format(
                    [
                        'UserId eq "{0}" and (',
                        '(Activity.Timeless eq false and Activity.StartDate between @{1}@ and @{2}@) or ',
                        '(Activity.Timeless eq true and Activity.StartDate between @{3}@ and @{4}@))'
                    ].join(''),
                    App.context['user'] && App.context['user']['$key'],
                    Sage.Platform.Mobile.Convert.toIsoStringFromDate(startDate),
                    Sage.Platform.Mobile.Convert.toIsoStringFromDate(endDate),
                    startDate.toString('yyyy-MM-ddT00:00:00Z'),
                    endDate.toString('yyyy-MM-ddT23:59:59Z')
                );
        },
        processFeed: function(feed) {
            var flatList = [],
                dt,
                currentMonthStart = this.getFirstDayOfCurrentMonth(),
                currentMonthEnd = this.getLastDayOfCurrentMonth(),
                r = feed['$resources'],
                startDay,
                endDay;

            for(var i=0, l=r.length; i<l; i++){
                this.entries[r[i].$key] = r[i];

                startDay = Sage.Platform.Mobile.Convert.toDateFromString(r[i].Activity.StartDate);
                endDay = Sage.Platform.Mobile.Convert.toDateFromString(r[i].Activity.EndDate);
                do { // track No. of activities for each calendar day
                    dt = startDay < currentMonthStart ? 1 : (r[i].Activity.Timeless ? startDay.getUTCDate() : startDay.getDate());
                    flatList[ dt ] = flatList[ dt ] ? 1 + flatList[ dt ] : 1;
                    startDay.add({day: 1});
                } while (startDay < endDay && startDay < currentMonthEnd);
            }
            this.feed = feed;

            this.highlightActivities(flatList);
            this.showCurrentDateActivities();
        },
        highlightActivities: function(flatList){
            var template = this.calendarActivityCountTemplate.apply(this);
            Ext.select('.calendar-day').each( function(el) {
                if (flatList[el.dom.textContent]) {
                    el.addClass("activeDay");
                    Ext.DomHelper.insertFirst(el, String.format(
                        template,
                        flatList[el.dom.textContent],
                        flatList[el.dom.textContent]
                    ));
                }
            });
        },
        dateToUTC: function(date){
            return new Date(date.getUTCFullYear(),
                date.getUTCMonth(),
                date.getUTCDate(),
                date.getUTCHours(),
                date.getUTCMinutes(),
                date.getUTCSeconds()
            );
        },
        clearCurrentDateActivities: function(){
            this.dayContentEl.update(this.loadingTemplate.apply(this));
        },
        setCurrentDateTitle: function(){
            this.dayTextEl.update(this.currentDate.toString(this.dayTitleFormatText));
        },
        showCurrentDateActivities: function(){
            this.setCurrentDateTitle();

            if(!this.feed){
                this.dayContentEl.update(this.loadingTemplate.apply(this));
                return;
            }

            var feed = this.feed['$resources'],
                feedLength = feed.length,
                i = 0,
                activity,
                activityDate,
                activityList = [];

            for(i = 0; i < feedLength; i += 1){
                activity = feed[i].Activity;
                activity.StartDate = Sage.Platform.Mobile.Convert.toDateFromString(activity.StartDate);
                activityDate = (activity.Timeless) ? this.dateToUTC(activity.StartDate) : activity.StartDate;
                if(activityDate.getDate() === this.currentDate.getDate()){
                    activityList.push(this.dayItemTemplate.apply(feed[i], this));
                }
            }
            if(activityList.length===0){
                this.dayContentEl.update(this.noDataTemplate.apply(this));
                return false;
            }

            this.dayContentEl.update(activityList.join(''));
        },
        renderCalendar: function() {
            var calHTML = [],
                startingDay = this.getFirstDayOfCurrentMonth().getDay(),
                dayClass = '',
                weekendClass = '',
                i = 0,
                j = 0,
                day = 1,
                dayDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth(), 1,0,0,0,0),
                today = Date.today().clearTime(),
                monthLength = this.currentDate.getDaysInMonth(),
                weekEnds = [0,6];

            calHTML.push(this.calendarStartTemplate);

            calHTML.push(this.calendarWeekHeaderStartTemplate);
            for(i = 0; i <= 6; i++ ){
                calHTML.push(String.format(this.calendarWeekHeaderTemplate, Date.CultureInfo.abbreviatedDayNames[i]  ));
            }
            calHTML.push(this.calendarWeekHeaderEndTemplate);

            //Weeks
            for (i = 0; i <= 6; i+=1){
                calHTML.push(this.calendarWeekStartTemplate);
                //Days
                for (j = 0; j <= 6; j+=1)
                {
                    if (day <= monthLength && (i > 0 || j >= startingDay)){
                        dayDate.set({day:day});
                        dayClass = (dayDate.equals(today)) ? 'today' : '';
                        weekendClass = (weekEnds.indexOf(j) !== -1) ? ' weekend' : '';
                        calHTML.push(String.format(this.calendarDayTemplate,
                                                    day,
                                                    (dayClass + weekendClass),
                                                    dayDate.toString('yyyy-MM-dd')
                                                   )
                                    );
                        day += 1;
                    }
                    else {
                        calHTML.push(this.calendarEmptyDayTemplate);
                    }

                }
                calHTML.push(this.calendarWeekEndTemplate);
                // stop making rows if we've run out of days
                if (day > monthLength) break;
            }
            calHTML.push(this.calendarEndTemplate);

            this.contentEl.update(calHTML.join(''));
            this.setDateTitle();
            this.highlightCurrentDate();
        },
        setDateTitle: function(){
            this.dateTextEl.update(this.currentDate.toString(this.monthTitleFormatText));
        },
        show: function(options) {
            Sage.Platform.Mobile.Calendar.superclass.show.call(this, options);
            if(options) {
                this.processShowOptions(options);
            } else {
                this.renderCalendar();
            }
        },
        processShowOptions: function(options){
            if(options.currentDate){
                this.currentDate = Date.parse(options.currentDate).clearTime() || Date.today().clearTime();
                this.refreshRequired = true;
            }
        },
        highlightCurrentDate: function(){
            var selectedDate = String.format('.calendar-day[data-date={0}]', this.currentDate.toString('yyyy-MM-dd'));
            if (this.selectedDateEl) this.selectedDateEl.removeClass('selected');
            this.selectedDateEl = this.contentEl.child(selectedDate);
            this.selectedDateEl.addClass('selected');
        },
        navigateToWeekView: function() {
            var view = App.getView(this.activityWeekView),
                options = {currentDate: this.currentDate.toString('yyyy-MM-dd') || Date.today()};
            view.show(options);
        },
        navigateToDayView: function() {
            var view = App.getView(this.activityListView),
                options = {currentDate: this.currentDate.toString('yyyy-MM-dd') || Date.today()};
            view.show(options);
        },
        navigateToDetailView: function(key, descriptor) {
            var entry = this.entries[key],
                activity = entry['Activity'],
                description = activity['Description'],
                key = activity['$key'];

            Mobile.SalesLogix.Activity.List.superclass.navigateToDetailView.call(this, key, description);
        }

    });
})();<commit_msg>Issue #2 - removed EndDate counting per talks about recurring activities until support is added server side, also upped request count to 500<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/List.js"/>

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

(function() {
    Mobile.SalesLogix.Calendar.MonthView = Ext.extend(Sage.Platform.Mobile.List, {
        // Localization
        titleText: 'Calendar',
        todayText: 'Today',
        dayText: 'Day',
        weekText: 'Week',
        monthText: 'Month',
        monthTitleFormatText: 'MMMM yyyy',
        dayTitleFormatText: 'ddd MMM d, yyyy',
        dayStartTimeFormatText: 'h:mm',
        allDayText: 'All-Day',

        //Templates
        viewTemplate: new Simplate([
            '
',
            'fix for android issue #6059',
            '{%! $.searchTemplate %}',
            '{%! $.navigationTemplate %}',
            '

',
            '

',
            '{%! $.dayTemplate %}',
            '
'
        ]),
        navigationTemplate: new Simplate([
            '
',
                '<button data-tool="today" data-action="getTodayMonthActivities" class="button">{%: $.todayText %}</button>',
                '<button data-tool="day" data-action="navigateToDayView" class="button">{%: $.dayText %}</button>',
                '<button data-tool="week" data-action="navigateToWeekView" class="button">{%: $.weekText %}</button>',
                '<button data-tool="month" class="button">{%: $.monthText %}</button>',
            '
',
            '
',
            '

',
            '<button data-tool="next" data-action="goToNextMonth" class="button button-next"></button>',
            '<button data-tool="prev" data-action="goToPreviousMonth" class="button button-prev"></button>',
            '
'
        ]),
        dayTemplate: new Simplate([
            '
',
                '

',
                '

',
                '{%! $.moreTemplate %}',
            '
'
        ]),
        dayItemTemplate: new Simplate([
            '
',
            '

',
            '{%! $$.dayContentTemplate %}',
            '
'
        ]),
        dayContentTemplate: new Simplate([
            '
',
            '{%! $$.dayTimeTemplate %}',
            ' {%: $.Activity.Description %}',
            '
',
            '
{%= $$.dayNameTemplate.apply($) %}
'
        ]),
        dayTimeTemplate: new Simplate([
            '{% if ($.Activity.Timeless) { %}',
            '{%= $$.allDayText %}',
            '{% } else { %}',
            '{%: Mobile.SalesLogix.Format.date($.Activity.StartDate, $$.dayStartTimeFormatText) %}',
            '{%: Mobile.SalesLogix.Format.date($.Activity.StartDate, "tt") %},',
            '{% } %}'
        ]),
        dayNameTemplate: new Simplate([
            '{% if ($.Activity.ContactName) { %}',
            '{%: $.Activity.ContactName %} / {%: $.Activity.AccountName %}',
            '{% } else if ($.Activity.AccountName) { %}',
            '{%: $.Activity.AccountName %}',
            '{% } else { %}',
            '{%: $.Activity.LeadName %}',
            '{% } %}'
        ]),
        calendarStartTemplate: '
',
        calendarWeekHeaderStartTemplate: '
',
        calendarWeekHeaderTemplate: '{0}	',
        calendarWeekHeaderEndTemplate: '
',
        calendarWeekStartTemplate: '
',
        calendarEmptyDayTemplate: ' 	',
        calendarDayTemplate: '{0}	',
        calendarWeekEndTemplate: '
',
        calendarEndTemplate: '
',
        calendarActivityCountTemplate: new Simplate([
            '
{1}
'
        ]),
        attachmentPoints: Ext.apply({}, {
            contentEl: '.month-content',
            dateTextEl: '.date-text',
            dayTextEl: '.date-day-text',
            dayContentEl: '.day-content',
            selectedDateEl: '.selected'
        }, Sage.Platform.Mobile.List.prototype.attachmentPoints),

        //View Properties
        id: 'slx_calendar',
        cls: 'activities-for-month',
        activityListView: 'useractivity_list',
        activityWeekView: 'calendar_weeklist',
        insertView: 'activity_types_list',
        detailView: 'activity_detail',
        hideSearch: true,

        currentDate: Date.today(),
        queryWhere: null,
        queryOrderBy: 'Activity.StartDate asc',
        querySelect: [
            'Activity/StartDate',
            'Activity/Description',
            'Activity/Type',
            'Activity/AccountName',
            'Activity/ContactName',
            'Activity/LeadId',
            'Activity/LeadName',
            'Activity/UserId',
            'Activity/Timeless'
        ],
        pageSize: 500,
        resourceKind: 'useractivities',

        _onRefresh: function(o) {
            Mobile.SalesLogix.Calendar.MonthView.superclass._onRefresh.apply(this, arguments);
           if (o.resourceKind === 'activities'){
                this.refreshRequired = true;
            }
        },
        init: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.init.apply(this, arguments);
            this.setActivityQuery();
        },
        initEvents: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.initEvents.apply(this, arguments);
            this.el.on('swipe', this.onSwipe, this);
        },
        onSwipe: function(evt){
            switch(evt.browserEvent.direction){
                case 'right':
                    this.onSwipeRight();
                    break;
                case 'left':
                    this.onSwipeLeft();
                    break;
            }
        },
        onSwipeRight: function(){
            this.goToPreviousMonth();
        },
        onSwipeLeft: function(){
            this.goToNextMonth();
        },
        clear: function(){
            Mobile.SalesLogix.Calendar.MonthView.superclass.clear.apply(this, arguments);
            this.clearCurrentDateActivities();
        },
        render: function() {
            Mobile.SalesLogix.Calendar.MonthView.superclass.render.apply(this, arguments);
            this.renderCalendar();
        },
        selectDay: function(params, evt, el) {
            if (this.selectedDateEl) this.selectedDateEl.removeClass('selected');
            this.selectedDateEl = Ext.get(el).addClass('selected');
            this.currentDate = Date.parse(params.date);
            this.showCurrentDateActivities();
        },
        getFirstDayOfCurrentMonth: function(){
            return this.currentDate.clone().moveToFirstDayOfMonth().clearTime();
        },
        getLastDayOfCurrentMonth: function(){
            return new Date(this.currentDate.getFullYear(),
                this.currentDate.getMonth(),
                this.currentDate.getDaysInMonth()-1,
                23, 59, 59);
        },
        getTodayMonthActivities: function(){
            var today = Date.today();
            if(this.currentDate.toString('yyyy-MM') === today.toString('yyyy-MM')){
                this.currentDate = today;
                this.highlightCurrentDate();
                this.showCurrentDateActivities();
            } else {
                this.currentDate = today;
                this.refresh();
            }
        },
        goToNextMonth: function() {
             this.currentDate.add({month: 1});
             this.refresh();
        },
        goToPreviousMonth: function() {
            this.currentDate.add({month: -1});
            this.refresh();
        },
        refresh: function(){
            this.renderCalendar();
            this.setActivityQuery();
            this.feed['$startIndex'] = 0;
            this.dayContentEl.update(this.loadingTemplate.apply(this));
            this.requestData();
        },
        setActivityQuery: function(){
            var startDate = this.getFirstDayOfCurrentMonth(),
                endDate = this.getLastDayOfCurrentMonth();
            this.queryWhere = String.format(
                    [
                        'UserId eq "{0}" and (',
                        '(Activity.Timeless eq false and Activity.StartDate between @{1}@ and @{2}@) or ',
                        '(Activity.Timeless eq true and Activity.StartDate between @{3}@ and @{4}@))'
                    ].join(''),
                    App.context['user'] && App.context['user']['$key'],
                    Sage.Platform.Mobile.Convert.toIsoStringFromDate(startDate),
                    Sage.Platform.Mobile.Convert.toIsoStringFromDate(endDate),
                    startDate.toString('yyyy-MM-ddT00:00:00Z'),
                    endDate.toString('yyyy-MM-ddT23:59:59Z')
                );
        },
        processFeed: function(feed) {
            var dateCounts = [],
                dateIndex,
                r = feed['$resources'],
                i,
                feedLength = r.length,
                startDay;
            this.feed = feed;

            for(i = 0; i < feedLength; i += 1){
                this.entries[r[i].$key] = r[i];
                startDay = Sage.Platform.Mobile.Convert.toDateFromString(r[i].Activity.StartDate);
                dateIndex = (r[i].Activity.Timeless)
                    ? startDay.getUTCDate()
                    : startDay.getDate();
                dateCounts[dateIndex] = (dateCounts[dateIndex])
                    ? dateCounts[dateIndex] + 1
                    : 1;
            }

            this.highlightActivities(dateCounts);
            this.showCurrentDateActivities();
        },
        highlightActivities: function(dateCounts){
            var template = this.calendarActivityCountTemplate.apply(this);
            Ext.select('.calendar-day').each( function(el) {
                if (dateCounts[el.dom.textContent]) {
                    el.addClass("activeDay");
                    Ext.DomHelper.insertFirst(el, String.format(
                        template,
                        dateCounts[el.dom.textContent],
                        dateCounts[el.dom.textContent]
                    ));
                }
            });
        },
        dateToUTC: function(date){
            return new Date(date.getUTCFullYear(),
                date.getUTCMonth(),
                date.getUTCDate(),
                date.getUTCHours(),
                date.getUTCMinutes(),
                date.getUTCSeconds()
            );
        },
        clearCurrentDateActivities: function(){
            this.dayContentEl.update(this.loadingTemplate.apply(this));
        },
        setCurrentDateTitle: function(){
            this.dayTextEl.update(this.currentDate.toString(this.dayTitleFormatText));
        },
        showCurrentDateActivities: function(){
            this.setCurrentDateTitle();

            if(!this.feed){
                this.dayContentEl.update(this.loadingTemplate.apply(this));
                return;
            }

            var feed = this.feed['$resources'],
                feedLength = feed.length,
                i = 0,
                activity,
                activityDate,
                activityList = [];

            for(i = 0; i < feedLength; i += 1){
                activity = feed[i].Activity;
                activity.StartDate = Sage.Platform.Mobile.Convert.toDateFromString(activity.StartDate);
                activityDate = (activity.Timeless) ? this.dateToUTC(activity.StartDate) : activity.StartDate;
                if(activityDate.getDate() === this.currentDate.getDate()){
                    activityList.push(this.dayItemTemplate.apply(feed[i], this));
                }
            }
            if(activityList.length===0){
                this.dayContentEl.update(this.noDataTemplate.apply(this));
                return false;
            }

            this.dayContentEl.update(activityList.join(''));
        },
        renderCalendar: function() {
            var calHTML = [],
                startingDay = this.getFirstDayOfCurrentMonth().getDay(),
                dayClass = '',
                weekendClass = '',
                i = 0,
                j = 0,
                day = 1,
                dayDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth(), 1,0,0,0,0),
                today = Date.today().clearTime(),
                monthLength = this.currentDate.getDaysInMonth(),
                weekEnds = [0,6];

            calHTML.push(this.calendarStartTemplate);

            calHTML.push(this.calendarWeekHeaderStartTemplate);
            for(i = 0; i <= 6; i++ ){
                calHTML.push(String.format(this.calendarWeekHeaderTemplate, Date.CultureInfo.abbreviatedDayNames[i]  ));
            }
            calHTML.push(this.calendarWeekHeaderEndTemplate);

            //Weeks
            for (i = 0; i <= 6; i+=1){
                calHTML.push(this.calendarWeekStartTemplate);
                //Days
                for (j = 0; j <= 6; j+=1)
                {
                    if (day <= monthLength && (i > 0 || j >= startingDay)){
                        dayDate.set({day:day});
                        dayClass = (dayDate.equals(today)) ? 'today' : '';
                        weekendClass = (weekEnds.indexOf(j) !== -1) ? ' weekend' : '';
                        calHTML.push(String.format(this.calendarDayTemplate,
                                                    day,
                                                    (dayClass + weekendClass),
                                                    dayDate.toString('yyyy-MM-dd')
                                                   )
                                    );
                        day += 1;
                    }
                    else {
                        calHTML.push(this.calendarEmptyDayTemplate);
                    }

                }
                calHTML.push(this.calendarWeekEndTemplate);
                // stop making rows if we've run out of days
                if (day > monthLength) break;
            }
            calHTML.push(this.calendarEndTemplate);

            this.contentEl.update(calHTML.join(''));
            this.setDateTitle();
            this.highlightCurrentDate();
        },
        setDateTitle: function(){
            this.dateTextEl.update(this.currentDate.toString(this.monthTitleFormatText));
        },
        show: function(options) {
            Sage.Platform.Mobile.Calendar.superclass.show.call(this, options);
            if(options) {
                this.processShowOptions(options);
            } else {
                this.renderCalendar();
            }
        },
        processShowOptions: function(options){
            if(options.currentDate){
                this.currentDate = Date.parse(options.currentDate).clearTime() || Date.today().clearTime();
                this.refreshRequired = true;
            }
        },
        highlightCurrentDate: function(){
            var selectedDate = String.format('.calendar-day[data-date={0}]', this.currentDate.toString('yyyy-MM-dd'));
            if (this.selectedDateEl) this.selectedDateEl.removeClass('selected');
            this.selectedDateEl = this.contentEl.child(selectedDate);
            this.selectedDateEl.addClass('selected');
        },
        navigateToWeekView: function() {
            var view = App.getView(this.activityWeekView),
                options = {currentDate: this.currentDate.toString('yyyy-MM-dd') || Date.today()};
            view.show(options);
        },
        navigateToDayView: function() {
            var view = App.getView(this.activityListView),
                options = {currentDate: this.currentDate.toString('yyyy-MM-dd') || Date.today()};
            view.show(options);
        },
        navigateToDetailView: function(key, descriptor) {
            var entry = this.entries[key],
                activity = entry['Activity'],
                description = activity['Description'],
                key = activity['$key'];

            Mobile.SalesLogix.Activity.List.superclass.navigateToDetailView.call(this, key, description);
        }

    });
})();<|endoftext|>


<commit_before>const log4js = require('log4js');
const clientLogger = log4js.getLogger('client');
const formidable = require('formidable');
const apiHandler = require('../../handler/APIHandler');

exports.expressCreateServer = function (hook_name, args, cb) {
  // The Etherpad client side sends information about how a disconnect happened
  args.app.post('/ep/pad/connection-diagnostic-info', (req, res) => {
    new formidable.IncomingForm().parse(req, (err, fields, files) => {
      clientLogger.info(`DIAGNOSTIC-INFO: ${fields.diagnosticInfo}`);
      res.end('OK');
    });
  });

  // The Etherpad client side sends information about client side javscript errors
  args.app.post('/jserror', (req, res) => {
    new formidable.IncomingForm().parse(req, (err, fields, files) => {
      try {
        var data = JSON.parse(fields.errorInfo);
      } catch (e) {
        return res.end();
      }
      clientLogger.warn(`${data.msg} --`, data);
      res.end('OK');
    });
  });

  // Provide a possibility to query the latest available API version
  args.app.get('/api', (req, res) => {
    res.json({currentVersion: apiHandler.latestApiVersion});
  });

  return cb();
};
<commit_msg>lint: src/node/hooks/express/apicalls.js<commit_after>'use strict';

const log4js = require('log4js');
const clientLogger = log4js.getLogger('client');
const formidable = require('formidable');
const apiHandler = require('../../handler/APIHandler');

exports.expressCreateServer = (hookName, args, cb) => {
  // The Etherpad client side sends information about how a disconnect happened
  args.app.post('/ep/pad/connection-diagnostic-info', (req, res) => {
    new formidable.IncomingForm().parse(req, (err, fields, files) => {
      clientLogger.info(`DIAGNOSTIC-INFO: ${fields.diagnosticInfo}`);
      res.end('OK');
    });
  });

  // The Etherpad client side sends information about client side javscript errors
  args.app.post('/jserror', (req, res) => {
    new formidable.IncomingForm().parse(req, (err, fields, files) => {
      let data;
      try {
        data = JSON.parse(fields.errorInfo);
      } catch (e) {
        return res.end();
      }
      clientLogger.warn(`${data.msg} --`, data);
      res.end('OK');
    });
  });

  // Provide a possibility to query the latest available API version
  args.app.get('/api', (req, res) => {
    res.json({currentVersion: apiHandler.latestApiVersion});
  });

  return cb();
};
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options.add_startup_page', function() {
  const List = cr.ui.List;
  const ListItem = cr.ui.ListItem;

  /**
   * Creates a new recent page list item.
   * @param {Object} pageInfo The page this item represents.
   * @constructor
   * @extends {cr.ui.ListItem}
   */
  function RecentPageListItem(pageInfo) {
    var el = cr.doc.createElement('div');
    el.pageInfo = pageInfo;
    RecentPageListItem.decorate(el);
    return el;
  }

  /**
   * Decorates an element as a recent page list item.
   * @param {!HTMLElement} el The element to decorate.
   */
  RecentPageListItem.decorate = function(el) {
    el.__proto__ = RecentPageListItem.prototype;
    el.decorate();
  };

  RecentPageListItem.prototype = {
    __proto__: ListItem.prototype,

    /** @inheritDoc */
    decorate: function() {
      ListItem.prototype.decorate.call(this);

      var titleEl = this.ownerDocument.createElement('span');
      titleEl.className = 'title';
      titleEl.classList.add('favicon-cell');
      titleEl.textContent = this.pageInfo['title'];
      titleEl.style.backgroundImage = url('chrome://favicon/' +
                                         this.pageInfo['url']);

      var urlEL = this.ownerDocument.createElement('span');
      urlEL.className = 'url';
      urlEL.textContent = this.pageInfo['displayURL'];

      this.appendChild(titleEl);
      this.appendChild(urlEL);
    },
  };

  var RecentPageList = cr.ui.define('list');

  RecentPageList.prototype = {
    __proto__: List.prototype,

    /** @inheritDoc */
    createItem: function(pageInfo) {
      return new RecentPageListItem(pageInfo);
    },
  };

  return {
    RecentPageList: RecentPageList
  };
});
<commit_msg>Show the URL when there's no title in the DOMUI prefs start-page dialog<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options.add_startup_page', function() {
  const List = cr.ui.List;
  const ListItem = cr.ui.ListItem;

  /**
   * Creates a new recent page list item.
   * @param {Object} pageInfo The page this item represents.
   * @constructor
   * @extends {cr.ui.ListItem}
   */
  function RecentPageListItem(pageInfo) {
    var el = cr.doc.createElement('div');
    el.pageInfo = pageInfo;
    RecentPageListItem.decorate(el);
    return el;
  }

  /**
   * Decorates an element as a recent page list item.
   * @param {!HTMLElement} el The element to decorate.
   */
  RecentPageListItem.decorate = function(el) {
    el.__proto__ = RecentPageListItem.prototype;
    el.decorate();
  };

  RecentPageListItem.prototype = {
    __proto__: ListItem.prototype,

    /** @inheritDoc */
    decorate: function() {
      ListItem.prototype.decorate.call(this);

      var titleEl = this.ownerDocument.createElement('span');
      titleEl.className = 'title';
      titleEl.classList.add('favicon-cell');
      titleEl.style.backgroundImage = url('chrome://favicon/' +
                                         this.pageInfo['url']);
      this.appendChild(titleEl);
      if (this.pageInfo['title'].length > 0) {
        titleEl.textContent = this.pageInfo['title'];

        var urlEL = this.ownerDocument.createElement('span');
        urlEL.className = 'url';
        urlEL.textContent = this.pageInfo['displayURL'];
        this.appendChild(urlEL);
      } else {
        titleEl.textContent = this.pageInfo['displayURL'];
      }
    },
  };

  var RecentPageList = cr.ui.define('list');

  RecentPageList.prototype = {
    __proto__: List.prototype,

    /** @inheritDoc */
    createItem: function(pageInfo) {
      return new RecentPageListItem(pageInfo);
    },
  };

  return {
    RecentPageList: RecentPageList
  };
});
<|endoftext|>