<commit_before>  /**************************************************************************
   * GridSphere Object Functions
   **************************************************************************/

  /**
   * Checks if an object with given name exists in form
   */
  function GridSphere_Object_existsInForm(form, name) {

    // alert("Testing whether object [" + name + "] exists in form [" + form.name + "]");

    for (var i = 0; i < form.elements.length; ++i) {

      if (form.elements[i].name == name) {

        // alert("Object " + name + " exists");

        return true;
      }
    }

    // alert("Object does not exist");

    return false;
  }

  /**************************************************************************
   * GridSphere Form Functions
   **************************************************************************/

  /**
   * Submits the given action for the given form
   */
  function GridSphere_Form_submitAction(form, action) {
    form.action=action;
    form.submit();
  }

  /**************************************************************************
   * GridSpehre Check Box List Functions
   **************************************************************************/

  function GridSphere_CheckBoxList_checkAll(list) {

      if (list[0].checked == true) {

        // alert("GridSphere CheckBoxList Check All True");

        for (i = 1; i < list.length; i++) {

          list[i].checked = true;
        }

        // Select first list value if none selected yet
        if (list[0].value == "") {

          if (list.length > 1) {

            list[0].value = list[1].value;
          }
        }

      } else {

        // alert("GridSphere CheckBoxList Check All False");

        GridSphere_CheckBoxList_clear(list);
      }
  }

  function GridSphere_CheckBoxList_clear(list) {

    // alert("GridSphere CheckBoxList Clear");

      for (i = 0; i < list.length; i++) {

        list[i].checked = false;
      }

      // Clear selected value
      list[0].value = "";
  }

  function GridSphere_CheckBoxList_checkOne(list)
  {
    // alert("GridSphere CheckBoxList Check One");

      // Uncheck "all" option
      list[0].checked = false;

      // Uncheck those that don't match selection
      for (i = 1; i < list.length; i++) {

        if (list[i].value != list[0].value) {

          list[i].checked = false;
        }
      }
  }

  function GridSphere_CheckBoxList_onClick(list, newSelection)
  {
    // alert("GridSphere CheckBoxList On Click");

      if (newSelection.checked == true) {

        // Save selection only if none made yet
        if (list[0].value == "") {

          list[0].value = newSelection.value;
        }

      } else {

        // If saved selection was this one
        if (list[0].value == newSelection.value) {

          var found = false;

          // Set selection to first checked item other than this
          for (i = 1; i < list.length && !found; i++) {

            if (list[i].checked == true) {

              if (list[i].value != item.value) {

                list[0].value = list[i].value;

                found = true;
              }
            }
          }

          // If we didn't find a checked value
          if (!found) {

            // Set selection to none
            list[0].value = "";
          }
        }
      }

      // alert("GridSphere CheckBoxList new selection: " + selection.value);
  }

  function GridSphere_CheckBoxList_validateCheckOneOrMore(list)
  {
    // alert("GridSphere CheckBoxList Validate Check One Or More");

      // alert("Performing validate check one or more on " + list.name);

      return (list[0].value != "");
  }

 function GridSphere_SelectSubmit( aform ) {
    aform.submit();
 }<commit_msg>added sortable.js to existing javascript functions<commit_after>  /**************************************************************************
   * GridSphere Object Functions
   **************************************************************************/

  /**
   * Checks if an object with given name exists in form
   */
  function GridSphere_Object_existsInForm(form, name) {

    // alert("Testing whether object [" + name + "] exists in form [" + form.name + "]");

    for (var i = 0; i < form.elements.length; ++i) {

      if (form.elements[i].name == name) {

        // alert("Object " + name + " exists");

        return true;
      }
    }

    // alert("Object does not exist");

    return false;
  }

  /**************************************************************************
   * GridSphere Form Functions
   **************************************************************************/

  /**
   * Submits the given action for the given form
   */
  function GridSphere_Form_submitAction(form, action) {
    form.action=action;
    form.submit();
  }

  /**************************************************************************
   * GridSpehre Check Box List Functions
   **************************************************************************/

  function GridSphere_CheckBoxList_checkAll(list) {

      if (list[0].checked == true) {

        // alert("GridSphere CheckBoxList Check All True");

        for (i = 1; i < list.length; i++) {

          list[i].checked = true;
        }

        // Select first list value if none selected yet
        if (list[0].value == "") {

          if (list.length > 1) {

            list[0].value = list[1].value;
          }
        }

      } else {

        // alert("GridSphere CheckBoxList Check All False");

        GridSphere_CheckBoxList_clear(list);
      }
  }

  function GridSphere_CheckBoxList_clear(list) {

    // alert("GridSphere CheckBoxList Clear");

      for (i = 0; i < list.length; i++) {

        list[i].checked = false;
      }

      // Clear selected value
      list[0].value = "";
  }

  function GridSphere_CheckBoxList_checkOne(list)
  {
    // alert("GridSphere CheckBoxList Check One");

      // Uncheck "all" option
      list[0].checked = false;

      // Uncheck those that don't match selection
      for (i = 1; i < list.length; i++) {

        if (list[i].value != list[0].value) {

          list[i].checked = false;
        }
      }
  }

  function GridSphere_CheckBoxList_onClick(list, newSelection)
  {
    // alert("GridSphere CheckBoxList On Click");

      if (newSelection.checked == true) {

        // Save selection only if none made yet
        if (list[0].value == "") {

          list[0].value = newSelection.value;
        }

      } else {

        // If saved selection was this one
        if (list[0].value == newSelection.value) {

          var found = false;

          // Set selection to first checked item other than this
          for (i = 1; i < list.length && !found; i++) {

            if (list[i].checked == true) {

              if (list[i].value != item.value) {

                list[0].value = list[i].value;

                found = true;
              }
            }
          }

          // If we didn't find a checked value
          if (!found) {

            // Set selection to none
            list[0].value = "";
          }
        }
      }

      // alert("GridSphere CheckBoxList new selection: " + selection.value);
  }

  function GridSphere_CheckBoxList_validateCheckOneOrMore(list)
  {
    // alert("GridSphere CheckBoxList Validate Check One Or More");

      // alert("Performing validate check one or more on " + list.name);

      return (list[0].value != "");
  }

 function GridSphere_SelectSubmit( aform ) {
    aform.submit();
 }

// This code made publicly available from
// http://www.kryogenix.org/code/browser/sorttable/sorttable.js
// under MIT license - JN Mar 14 2004
/* Copyright (c) <year> <copyright holders>

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.
*/

addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            //initTable(thisTbl.id);
            ts_makeSortable(thisTbl);
        }
    }
}

function ts_makeSortable(table) {
    if (table.rows && table.rows.length > 0) {
        var firstRow = table.rows[0];
    }
    if (!firstRow) return;

    // We have a first row: assume it's the header, and make its contents clickable links
    for (var i=0;i<firstRow.cells.length;i++) {
        var cell = firstRow.cells[i];
        var txt = ts_getInnerText(cell);
        cell.innerHTML = ''+txt+'   ';
    }
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";

	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk) {
    // get the span
    var span;
    for (var ci=0;ci<lnk.childNodes.length;ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    var column = td.cellIndex;
    var table = getParent(td,'TABLE');

    // Work out a type for the column
    if (table.rows.length <= 1) return;
    var itm = ts_getInnerText(table.rows[1].cells[column]);
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^[$]/)) sortfn = ts_sort_currency;
    if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
    for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }

    newRows.sort(sortfn);

    if (span.getAttribute("sortdir") == 'down') {
        ARROW = '  ↑';
        newRows.reverse();
        span.setAttribute('sortdir','up');
    } else {
        ARROW = '  ↓';
        span.setAttribute('sortdir','down');
    }

    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
    // do sortbottom rows only
    for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}

    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci=0;ci<allspans.length;ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
                allspans[ci].innerHTML = '   ';
            }
        }
    }

    span.innerHTML = ARROW;
}

function getParent(el, pTagName) {
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
		return el;
	else
		return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
    } else {
        yr = aa.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
    } else {
        yr = bb.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
    }
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_currency(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    return parseFloat(aa) - parseFloat(bb);
}

function ts_sort_numeric(a,b) {
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
    if (isNaN(bb)) bb = 0;
    return aa-bb;
}

function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
}
<|endoftext|>


<commit_before>import React from 'react'
import _ from 'underscore'
import Client from 'electron-rpc/client'
import StoryList from './story_list.js'
import Menu from './menu.js'
import StoryType from '../model/story_type'

export default class StoryBox extends React.Component {
  constructor (props) {
    super(props)

    this.client = new Client()
    this.state = {
      stories: [],
      selected: StoryType.TOP_TYPE,
      status: '',
      version: '',
      upgradeVersion: ''
    }
  }

  componentDidMount () {
    var self = this

    self.client.on('update-available', function (err, releaseVersion) {
      if (err) {
        console.error(err)
        return
      }

      self.setState({ status: 'update-available', upgradeVersion: releaseVersion })
    })

    self.client.request('current-version', function (err, version) {
      if (err) {
        console.error(err)
        return
      }

      self.setState({ version: version })
    })

    self.onNavbarClick(self.state.selected)
  }

  onQuitClick () {
    this.client.request('terminate')
  }

  onUrlClick (url) {
    this.client.request('open-url', { url: url })
  }

  onMarkAsRead (id) {
    this.client.request('mark-as-read', { id: id }, function () {
      var story = _.findWhere(this.state.stories, { id: id })
      story.hasRead = true
      this.setState({ stories: this.state.stories })
    }.bind(this))
  }

  onNavbarClick (selected) {
    var self = this

    if (self.storycb) {
      self.client.removeListener(selected, self.storycb)
    }

    self.setState({ stories: [], selected: selected })
    self.storycb = function (err, stories) {
      if (err) {
        return
      }

      // console.log(JSON.stringify(stories, null, 2))
      self.setState({stories: stories})
    }
    self.client.request(selected, self.storycb)
    self.client.on(selected, self.storycb)
  }

  render () {
    var navNodes = _.map(StoryType.ALL, function (selection) {
      var className = 'control-item'
      if (this.state.selected === selection) {
        className = className + ' active'
      }
      return (
        {selection}
      )
    }, this)
    return (

            {navNodes}

        <StoryList stories={this.state.stories} onUrlClick={this.onUrlClick.bind(this)} onMarkAsRead={this.onMarkAsRead.bind(this)} />
        <Menu onQuitClick={this.onQuitClick.bind(this)} status={this.state.status} version={this.state.version} upgradeVersion={this.state.upgradeVersion} />

    )
  }
}
<commit_msg>Init `storycb` to null<commit_after>import React from 'react'
import _ from 'underscore'
import Client from 'electron-rpc/client'
import StoryList from './story_list.js'
import Menu from './menu.js'
import StoryType from '../model/story_type'

export default class StoryBox extends React.Component {
  constructor (props) {
    super(props)

    this.client = new Client()
    this.state = {
      stories: [],
      selected: StoryType.TOP_TYPE,
      status: '',
      version: '',
      upgradeVersion: ''
    }
    this.storycb = null
  }

  componentDidMount () {
    var self = this

    self.client.on('update-available', function (err, releaseVersion) {
      if (err) {
        console.error(err)
        return
      }

      self.setState({ status: 'update-available', upgradeVersion: releaseVersion })
    })

    self.client.request('current-version', function (err, version) {
      if (err) {
        console.error(err)
        return
      }

      self.setState({ version: version })
    })

    self.onNavbarClick(self.state.selected)
  }

  onQuitClick () {
    this.client.request('terminate')
  }

  onUrlClick (url) {
    this.client.request('open-url', { url: url })
  }

  onMarkAsRead (id) {
    this.client.request('mark-as-read', { id: id }, function () {
      var story = _.findWhere(this.state.stories, { id: id })
      story.hasRead = true
      this.setState({ stories: this.state.stories })
    }.bind(this))
  }

  onNavbarClick (selected) {
    var self = this

    if (self.storycb) {
      self.client.removeListener(selected, self.storycb)
    }

    self.setState({ stories: [], selected: selected })
    self.storycb = function (err, stories) {
      if (err) {
        return
      }

      // console.log(JSON.stringify(stories, null, 2))
      self.setState({stories: stories})
    }
    self.client.request(selected, self.storycb)
    self.client.on(selected, self.storycb)
  }

  render () {
    var navNodes = _.map(StoryType.ALL, function (selection) {
      var className = 'control-item'
      if (this.state.selected === selection) {
        className = className + ' active'
      }
      return (
        {selection}
      )
    }, this)
    return (

            {navNodes}

        <StoryList stories={this.state.stories} onUrlClick={this.onUrlClick.bind(this)} onMarkAsRead={this.onMarkAsRead.bind(this)} />
        <Menu onQuitClick={this.onQuitClick.bind(this)} status={this.state.status} version={this.state.version} upgradeVersion={this.state.upgradeVersion} />

    )
  }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 *  Code contributed to the webinos project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	 http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright 2011 Alexander Futasz, Fraunhofer FOKUS
 ******************************************************************************/

describe('common.RPC', function() {
	var webinos = require('webinos')(__dirname);

	var RPCHandler = webinos.global.require(webinos.global.rpc.location).RPCHandler;
	var rpcHandler;

	beforeEach(function() {
		rpcHandler = new RPCHandler();
	});

	it('RPCHandler is exported from node module', function() {
		expect(RPCHandler).toEqual(jasmine.any(Function));
	});

	it('RPCHandler object instantiated', function() {
		expect(rpcHandler).toBeDefined();
	});

	it('has createRPC function', function() {
		expect(rpcHandler.createRPC).toEqual(jasmine.any(Function));
	});

	it('has executeRPC function', function() {
		expect(rpcHandler.executeRPC).toEqual(jasmine.any(Function));
	});

	it('has registerObject function', function() {
		expect(rpcHandler.registerObject).toEqual(jasmine.any(Function));
	});

	it('has unregisterObject function', function() {
		expect(rpcHandler.unregisterObject).toEqual(jasmine.any(Function));
	});

	it('has registerCallbackObject function', function() {
		expect(rpcHandler.registerCallbackObject).toEqual(jasmine.any(Function));
	});

	it('createRPC with service as string type', function() {
		var rpc = rpcHandler.createRPC('Service', 'functionName', [1]);
		expect(rpc).toEqual(jasmine.any(Object));

		expect(rpc.jsonrpc).toBeDefined();
		expect(rpc.jsonrpc).toEqual('2.0');

		expect(rpc.id).toBeDefined();
		expect(rpc.id).toEqual(jasmine.any(String));

		expect(rpc.method).toBeDefined();
		expect(rpc.method).toEqual(jasmine.any(String));

		expect(rpc.params).toBeDefined();
		expect(rpc.params).toEqual(jasmine.any(Object));
	});

	it('createRPC with service as RPCWebinosService', function() {
		var service = new RPCWebinosService();
		var rpc = rpcHandler.createRPC(service, 'functionName', [1]);
		expect(rpc).toEqual(jasmine.any(Object));

		expect(rpc.jsonrpc).toBeDefined();
		expect(rpc.jsonrpc).toEqual('2.0');

		expect(rpc.id).toBeDefined();
		expect(rpc.id).toEqual(jasmine.any(String));

		expect(rpc.method).toBeDefined();
		expect(rpc.method).toEqual(jasmine.any(String));

		expect(rpc.serviceAddress).toBeDefined();

		expect(rpc.params).toBeDefined();
		expect(rpc.params).toEqual(jasmine.any(Object));
	});

	describe('RPC service registration', function() {
		var service;
		var rpc;

		beforeEach(function() {
			service = new RPCWebinosService();
			service.api = 'prop-api';
			service.displayName = 'prop-displayName';
			service.description = 'prop-description';
			rpc = rpcHandler.createRPC(service, 'functionName', [1]);
		});

		it('has no registered services initially', function() {
			expect(Object.keys(rpcHandler.objects).length).toEqual(0);
		});

		it('has exactly one registered service after registering', function() {
			rpcHandler.registerObject(service);
			expect(Object.keys(rpcHandler.objects).length).toEqual(1);
		});

		it('has no registered services after unregistering', function() {
			rpcHandler.registerObject(service);
			rpcHandler.unregisterObject(service);
			expect(Object.keys(rpcHandler.objects).length).toEqual(0);
		});
	});

	describe('RPC service request and response', function() {
		var service;

		beforeEach(function() {
			// create and register mock service
			var MockService = function(privRpcHandler, params) {
				this.base = RPCWebinosService;
				this.base({
					api: 'prop-api',
					displayName: 'prop-displayName',
					description: 'prop-description'
				});
				this.testListen = function(params, success, error, objRef) {
					var rpc = rpcHandler.createRPC(objRef, 'onEvent', {testProp: 42});
					rpcHandler.executeRPC(rpc);
				};
			};
			MockService.prototype = new RPCWebinosService();
			MockService.prototype.testSuccess = function(params, success, error, objRef) {
				// tests success callback provided by rpc.js
				success();
			};
			MockService.prototype.testError = function(params, success, error, objRef) {
				// tests error callback provided by rpc.js
				error();
			};
			service = new MockService();
			rpcHandler.registerObject(service);

			// use our own message handler write function, usually this would
			// write the request out to the remote peer
			var msgHandler = {
					write: function(rpc) {
						rpcHandler.handleMessage(rpc);
					}
			};
			rpcHandler.setMessageHandler(msgHandler);
		});

		it('with successfull response', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testSuccess', [1]);
			rpcHandler.executeRPC(rpc);

			// request
			expect(rpcHandler.handleMessage).toHaveBeenCalled();
			expect(rpcHandler.handleMessage.calls[0].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[0].args[0].method).toBeDefined();
			expect(rpcHandler.handleMessage.calls[0].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[0].args[0].params).toBeDefined();

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].result).toBeDefined();

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);
		});

		it('with error response', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testError', [1]);
			rpcHandler.executeRPC(rpc);

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].error).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].error.code).toEqual(32000);

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);
		});

		it('with successful responce for client side listener pattern', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testListen', [1]);
			rpc.fromObjectRef = 2342; // this is totally a unique id

			// create a temporary webinos service for our callback onEvent
			var callback = new RPCWebinosService({api:rpc.fromObjectRef});
			callback.onEvent = function (){}; // empty, using spyOn instead
			spyOn(callback, 'onEvent');
			rpcHandler.registerCallbackObject(callback);
			rpcHandler.executeRPC(rpc);

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);

			expect(callback.onEvent).toHaveBeenCalled();
			expect(callback.onEvent.calls[0].args[0].testProp).toEqual(42);
		});
	});
});<commit_msg>Update rpc/registry tests<commit_after>/*******************************************************************************
 *  Code contributed to the webinos project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	 http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright 2011 Alexander Futasz, Fraunhofer FOKUS
 ******************************************************************************/

describe('common.RPC', function() {
	var webinos = require('webinos')(__dirname);

	var Registry = webinos.global.require(webinos.global.rpc.location, "lib/registry").Registry;
	var registry;
	var RPCHandler = webinos.global.require(webinos.global.rpc.location).RPCHandler;
	var rpcHandler;

	beforeEach(function() {
		registry = new Registry();
		rpcHandler = new RPCHandler(undefined, registry);
	});

	describe('rpcHandler', function() {

		it('RPCHandler is exported from node module', function() {
			expect(RPCHandler).toEqual(jasmine.any(Function));
		});

		it('RPCHandler object instantiated', function() {
			expect(rpcHandler).toBeDefined();
		});

		it('has createRPC function', function() {
			expect(rpcHandler.createRPC).toEqual(jasmine.any(Function));
		});

		it('has executeRPC function', function() {
			expect(rpcHandler.executeRPC).toEqual(jasmine.any(Function));
		});

		it('has registerCallbackObject function', function() {
			expect(rpcHandler.registerCallbackObject).toEqual(jasmine.any(Function));
		});

		it('has registerCallbackObject function', function() {
			expect(rpcHandler.registerCallbackObject).toEqual(jasmine.any(Function));
		});

		it('createRPC with service as string type', function() {
			var rpc = rpcHandler.createRPC('Service', 'functionName', [1]);
			expect(rpc).toEqual(jasmine.any(Object));

			expect(rpc.jsonrpc).toBeDefined();
			expect(rpc.jsonrpc).toEqual('2.0');

			expect(rpc.id).toBeDefined();
			expect(rpc.id).toEqual(jasmine.any(String));

			expect(rpc.method).toBeDefined();
			expect(rpc.method).toEqual(jasmine.any(String));

			expect(rpc.params).toBeDefined();
			expect(rpc.params).toEqual(jasmine.any(Object));
		});

		it('createRPC with service as RPCWebinosService', function() {
			var service = new RPCWebinosService();
			var rpc = rpcHandler.createRPC(service, 'functionName', [1]);
			expect(rpc).toEqual(jasmine.any(Object));

			expect(rpc.jsonrpc).toBeDefined();
			expect(rpc.jsonrpc).toEqual('2.0');

			expect(rpc.id).toBeDefined();
			expect(rpc.id).toEqual(jasmine.any(String));

			expect(rpc.method).toBeDefined();
			expect(rpc.method).toEqual(jasmine.any(String));

			expect(rpc.serviceAddress).toBeDefined();

			expect(rpc.params).toBeDefined();
			expect(rpc.params).toEqual(jasmine.any(Object));
		});

	});

	describe('RPC service registration', function() {
		var service;
		var rpc;

		beforeEach(function() {
			service = new RPCWebinosService();
			service.api = 'prop-api';
			service.displayName = 'prop-displayName';
			service.description = 'prop-description';
			rpc = rpcHandler.createRPC(service, 'functionName', [1]);
		});

		it('Registry is exported from node module', function() {
			expect(Registry).toEqual(jasmine.any(Function));
		});

		it('has registerObject function', function() {
			expect(registry.registerObject).toEqual(jasmine.any(Function));
		});

		it('has unregisterObject function', function() {
			expect(registry.unregisterObject).toEqual(jasmine.any(Function));
		});

		it('has no registered services initially', function() {
			expect(Object.keys(registry.objects).length).toEqual(0);
		});

		it('has exactly one registered service after registering', function() {
			registry.registerObject(service);
			expect(Object.keys(registry.objects).length).toEqual(1);
		});

		it('has no registered services after unregistering', function() {
			registry.registerObject(service);
			registry.unregisterObject(service);
			expect(Object.keys(registry.objects).length).toEqual(0);
		});
	});

	describe('RPC service request and response', function() {
		var service;

		beforeEach(function() {
			// create and register mock service
			var MockService = function(privRpcHandler, params) {
				this.base = RPCWebinosService;
				this.base({
					api: 'prop-api',
					displayName: 'prop-displayName',
					description: 'prop-description'
				});
				this.testListen = function(params, success, error, objRef) {
					var rpc = rpcHandler.createRPC(objRef, 'onEvent', {testProp: 42});
					rpcHandler.executeRPC(rpc);
				};
			};
			MockService.prototype = new RPCWebinosService();
			MockService.prototype.testSuccess = function(params, success, error, objRef) {
				// tests success callback provided by rpc.js
				success();
			};
			MockService.prototype.testError = function(params, success, error, objRef) {
				// tests error callback provided by rpc.js
				error();
			};
			service = new MockService();
			registry.registerObject(service);

			// use our own message handler write function, usually this would
			// write the request out to the remote peer
			var msgHandler = {
					write: function(rpc) {
						rpcHandler.handleMessage(rpc);
					}
			};
			rpcHandler.setMessageHandler(msgHandler);
		});

		it('with successfull response', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testSuccess', [1]);
			rpcHandler.executeRPC(rpc);

			// request
			expect(rpcHandler.handleMessage).toHaveBeenCalled();
			expect(rpcHandler.handleMessage.calls[0].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[0].args[0].method).toBeDefined();
			expect(rpcHandler.handleMessage.calls[0].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[0].args[0].params).toBeDefined();

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].result).toBeDefined();

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);
		});

		it('with error response', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testError', [1]);
			rpcHandler.executeRPC(rpc);

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].error).toBeDefined();
			expect(rpcHandler.handleMessage.calls[1].args[0].error.code).toEqual(32000);

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);
		});

		it('with successful responce for client side listener pattern', function() {
			spyOn(rpcHandler, 'handleMessage').andCallThrough();
			spyOn(rpcHandler, 'executeRPC').andCallThrough();

			var rpc = rpcHandler.createRPC(service, 'testListen', [1]);
			rpc.fromObjectRef = 2342; // this is totally a unique id

			// create a temporary webinos service for our callback onEvent
			var callback = new RPCWebinosService({api:rpc.fromObjectRef});
			callback.onEvent = function (){}; // empty, using spyOn instead
			spyOn(callback, 'onEvent');
			rpcHandler.registerCallbackObject(callback);
			rpcHandler.executeRPC(rpc);

			// response
			expect(rpcHandler.handleMessage.calls[1].args.length).toEqual(1);
			expect(rpcHandler.handleMessage.calls[1].args[0].id).toBeDefined();

			// called once for request and once for response
			expect(rpcHandler.executeRPC.calls.length).toEqual(2);

			expect(callback.onEvent).toHaveBeenCalled();
			expect(callback.onEvent.calls[0].args[0].testProp).toEqual(42);
		});
	});
});<|endoftext|>


<commit_before>// @flow
/**
 * All About Olaf
 * Calendar page
 */

import React from 'react'
import {EventList} from './event-list'
import {tracker} from '../../analytics'
import type {PresenceEventType, EventType} from './types'
import moment from 'moment-timezone'
import delay from 'delay'
import LoadingView from '../components/loading'
const TIMEZONE = 'America/Winnipeg'

export class PresenceCalendarView extends React.Component {
  state: {
    events: EventType[],
    loaded: boolean,
    refreshing: boolean,
    error: ?Error,
    now: moment,
  } = {
    events: [],
    loaded: false,
    refreshing: true,
    error: null,
    now: moment.tz(TIMEZONE),
  };

  componentWillMount() {
    this.refresh()
  }

  props: {
    url: string,
  };

  convertEvents(data: PresenceEventType[], now: moment): EventType[] {
    return data
      .map(event => {
        const startTime = moment(event.startDateTimeUtc)
        const endTime = moment(event.endDateTimeUtc)
        return {
          startTime,
          endTime,
          summary: event.eventName,
          location: `Where: ${event.location}\nOrg: ${event.organizationName}`,
          isOngoing: startTime.isBefore(now, 'day'),
          extra: {type: 'presence', data: event},
        }
      })
      .filter(event => event.endTime.isSameOrAfter(now))
  }

  getEvents = async (now: moment = moment.tz(TIMEZONE)) => {
    let url = this.props.url

    let data: PresenceEventType[] = []
    try {
      data = await fetchJson(url)
    } catch (error) {
      tracker.trackException(error.message)
      this.setState({error: error.message})
      console.warn(error)
    }

    this.setState({
      now,
      loaded: true,
      events: this.convertEvents(data, now),
    })
  };

  refresh = async () => {
    let start = Date.now()
    this.setState({refreshing: true})

    await this.getEvents()

    // wait 0.5 seconds – if we let it go at normal speed, it feels broken.
    let elapsed = start - Date.now()
    if (elapsed < 500) {
      await delay(500 - elapsed)
    }

    this.setState({refreshing: false})
  };

  render() {
    if (!this.state.loaded) {
      return <LoadingView />
    }

    return (
      <EventList
        events={this.state.events}
        refreshing={this.state.refreshing}
        onRefresh={this.refresh}
        now={this.state.now}
        message={this.state.error ? this.state.error.message : null}
      />
    )
  }
}
<commit_msg>sort presence events by starttime (#869)<commit_after>// @flow
/**
 * All About Olaf
 * Calendar page
 */

import React from 'react'
import {EventList} from './event-list'
import {tracker} from '../../analytics'
import type {PresenceEventType, EventType} from './types'
import moment from 'moment-timezone'
import delay from 'delay'
import sortBy from 'lodash/sortBy'
import LoadingView from '../components/loading'
const TIMEZONE = 'America/Winnipeg'

export class PresenceCalendarView extends React.Component {
  state: {
    events: EventType[],
    loaded: boolean,
    refreshing: boolean,
    error: ?Error,
    now: moment,
  } = {
    events: [],
    loaded: false,
    refreshing: true,
    error: null,
    now: moment.tz(TIMEZONE),
  };

  componentWillMount() {
    this.refresh()
  }

  props: {
    url: string,
  };

  convertEvents(data: PresenceEventType[], now: moment): EventType[] {
    const events = data
      .map(event => {
        const startTime = moment(event.startDateTimeUtc)
        const endTime = moment(event.endDateTimeUtc)
        return {
          startTime,
          endTime,
          summary: event.eventName,
          location: `Where: ${event.location}\nOrg: ${event.organizationName}`,
          isOngoing: startTime.isBefore(now, 'day'),
          extra: {type: 'presence', data: event},
        }
      })
      .filter(event => event.endTime.isSameOrAfter(now))

    return sortBy(events, event => event.startTime.toISOString())
  }

  getEvents = async (now: moment = moment.tz(TIMEZONE)) => {
    let url = this.props.url

    let data: PresenceEventType[] = []
    try {
      data = await fetchJson(url)
    } catch (error) {
      tracker.trackException(error.message)
      this.setState({error: error.message})
      console.warn(error)
    }

    this.setState({
      now,
      loaded: true,
      events: this.convertEvents(data, now),
    })
  };

  refresh = async () => {
    let start = Date.now()
    this.setState({refreshing: true})

    await this.getEvents()

    // wait 0.5 seconds – if we let it go at normal speed, it feels broken.
    let elapsed = start - Date.now()
    if (elapsed < 500) {
      await delay(500 - elapsed)
    }

    this.setState({refreshing: false})
  };

  render() {
    if (!this.state.loaded) {
      return <LoadingView />
    }

    return (
      <EventList
        events={this.state.events}
        refreshing={this.state.refreshing}
        onRefresh={this.refresh}
        now={this.state.now}
        message={this.state.error ? this.state.error.message : null}
      />
    )
  }
}
<|endoftext|>


<commit_before>var path = require("path");
var cppMakeJsPath = require("./makeCpp.js");
var bpMakeJsPath = require("./makebp.js");

// Making resharper less noisy - These are defined in Generate.js
if (typeof (generateApiSummaryLines) === "undefined") generateApiSummaryLines = function () { };
if (typeof (getCompiledTemplate) === "undefined") getCompiledTemplate = function () { };
if (typeof (templatizeTree) === "undefined") templatizeTree = function () { };

var copyright =
`//////////////////////////////////////////////////////
// Copyright (C) Microsoft. 2018. All rights reserved.
//////////////////////////////////////////////////////
`;

exports.makeCombinedAPI = function (apis, sourceDir, baseApiOutputDir) {
    class TargetVersion {
        constructor(inMajor, inMinor, inPatch) {
            this.major = inMajor;
            this.minor = inMinor;
            this.patch = inPatch;
        }
        get targetVersionShort() {
            return `${this.major}.${this.minor}`;
        }

        get targetVersionLong() {
            return `${this.major}.${this.minor}.${this.patch}`;
        }
    }

    // The list of current supported UE versions - Intended to be the latest 3
    const ueTargetVersions = [
        new TargetVersion(4, 18, 0),
        new TargetVersion(4, 19, 0),
        new TargetVersion(4, 20, 0),
        new TargetVersion(4, 21, 0)
    ];

    var ueWhitelistPlatforms = '[ "Win64", "Win32", "Mac", "IOS", "Android" ]'; // TODO: Add PS4, Switch, and XBox once the testing stories are done

    for (var v = 0; v < ueTargetVersions.length; v++) {
        var ueTargetVersion = ueTargetVersions[v];
        var apiOutputDir = path.resolve(baseApiOutputDir, ueTargetVersion.targetVersionShort); // Break multiple versions into separate top level folders

        console.log("Generating Unreal Plugin to " + apiOutputDir);

        // Create the Source folder in the plugin with all the modules
        bpMakeJsPath.makeBpCombinedAPI(apis, copyright, sourceDir, apiOutputDir, ueTargetVersion.targetVersionShort, sdkGlobals.sdkVersion, sdkGlobals.buildIdentifier);
        cppMakeJsPath.makeCppCombinedAPI(apis, copyright, sourceDir, apiOutputDir, ueTargetVersion.targetVersionShort, sdkGlobals.sdkVersion, sdkGlobals.buildIdentifier);

        var authMechanisms = getAuthMechanisms(apis);
        var locals = {
            apis: apis,
            buildIdentifier: sdkGlobals.buildIdentifier,
            copyright: copyright,
            enumTypes: collectEnumsFromApis(apis),
            errorList: apis[0].errorList,
            errors: apis[0].errors,
            generateBpApiSummary: bpMakeJsPath.generateApiSummary,
            getDataTypeSafeName: bpMakeJsPath.getDataTypeSafeName,
            getDefaultVerticalName: getDefaultVerticalName,
            hasClientOptions: authMechanisms.includes("SessionTicket"),
            hasServerOptions: authMechanisms.includes("SecretKey"),
            sdkVersion: sdkGlobals.sdkVersion,
            ueTargetVersionMinor: ueTargetVersion.minor, // This is actually used
            ueTargetVersion: ueTargetVersion.targetVersionShort,
            ueTargetVersionLong: ueTargetVersion.targetVersionLong,
            ueWhitelistPlatforms: ueWhitelistPlatforms
        };

        // Copy the resources, content and the .uplugin file
        templatizeTree(locals, path.resolve(sourceDir, "source"), path.resolve(apiOutputDir, "PlayFabPlugin"));

        // Create the Example project folder
        templatizeTree(locals, path.resolve(sourceDir, "examplesource"), apiOutputDir);

        // Copy the PlayFabPlugin folder just created into the ExampleProject
        // TODO: It causes very confusing problems to copy from an output subdir to another output subdir. Let's fix this
        templatizeTree(locals, path.resolve(apiOutputDir, "PlayFabPlugin"), path.resolve(apiOutputDir, "ExampleProject/Plugins"));
    }
}

// BP Module: Pull all the enums out of all the apis, and collect them into a single collection of just the enum types and filter duplicates
function collectEnumsFromApis(apis) {
    var enumTypes = {};
    for (var a = 0; a < apis.length; a++)
        for (var d in apis[a].datatypes)
            if (apis[a].datatypes[d].isenum && apis[a].datatypes[d].enumvalues.length <= 255)
                enumTypes[d] = apis[a].datatypes[d];
    return enumTypes;
}

function getDefaultVerticalName() {
    if (exports.verticalName) {
        return exports.verticalName;
    }
    return "";
}
<commit_msg>Removing 4.18... again. (#453)<commit_after>var path = require("path");
var cppMakeJsPath = require("./makeCpp.js");
var bpMakeJsPath = require("./makebp.js");

// Making resharper less noisy - These are defined in Generate.js
if (typeof (generateApiSummaryLines) === "undefined") generateApiSummaryLines = function () { };
if (typeof (getCompiledTemplate) === "undefined") getCompiledTemplate = function () { };
if (typeof (templatizeTree) === "undefined") templatizeTree = function () { };

var copyright =
`//////////////////////////////////////////////////////
// Copyright (C) Microsoft. 2018. All rights reserved.
//////////////////////////////////////////////////////
`;

exports.makeCombinedAPI = function (apis, sourceDir, baseApiOutputDir) {
    class TargetVersion {
        constructor(inMajor, inMinor, inPatch) {
            this.major = inMajor;
            this.minor = inMinor;
            this.patch = inPatch;
        }
        get targetVersionShort() {
            return `${this.major}.${this.minor}`;
        }

        get targetVersionLong() {
            return `${this.major}.${this.minor}.${this.patch}`;
        }
    }

    // The list of current supported UE versions - Intended to be the latest 3
    const ueTargetVersions = [
        new TargetVersion(4, 19, 0),
        new TargetVersion(4, 20, 0),
        new TargetVersion(4, 21, 0)
    ];

    var ueWhitelistPlatforms = '[ "Win64", "Win32", "Mac", "IOS", "Android" ]'; // TODO: Add PS4, Switch, and XBox once the testing stories are done

    for (var v = 0; v < ueTargetVersions.length; v++) {
        var ueTargetVersion = ueTargetVersions[v];
        var apiOutputDir = path.resolve(baseApiOutputDir, ueTargetVersion.targetVersionShort); // Break multiple versions into separate top level folders

        console.log("Generating Unreal Plugin to " + apiOutputDir);

        // Create the Source folder in the plugin with all the modules
        bpMakeJsPath.makeBpCombinedAPI(apis, copyright, sourceDir, apiOutputDir, ueTargetVersion.targetVersionShort, sdkGlobals.sdkVersion, sdkGlobals.buildIdentifier);
        cppMakeJsPath.makeCppCombinedAPI(apis, copyright, sourceDir, apiOutputDir, ueTargetVersion.targetVersionShort, sdkGlobals.sdkVersion, sdkGlobals.buildIdentifier);

        var authMechanisms = getAuthMechanisms(apis);
        var locals = {
            apis: apis,
            buildIdentifier: sdkGlobals.buildIdentifier,
            copyright: copyright,
            enumTypes: collectEnumsFromApis(apis),
            errorList: apis[0].errorList,
            errors: apis[0].errors,
            generateBpApiSummary: bpMakeJsPath.generateApiSummary,
            getDataTypeSafeName: bpMakeJsPath.getDataTypeSafeName,
            getDefaultVerticalName: getDefaultVerticalName,
            hasClientOptions: authMechanisms.includes("SessionTicket"),
            hasServerOptions: authMechanisms.includes("SecretKey"),
            sdkVersion: sdkGlobals.sdkVersion,
            ueTargetVersionMinor: ueTargetVersion.minor, // This is actually used
            ueTargetVersion: ueTargetVersion.targetVersionShort,
            ueTargetVersionLong: ueTargetVersion.targetVersionLong,
            ueWhitelistPlatforms: ueWhitelistPlatforms
        };

        // Copy the resources, content and the .uplugin file
        templatizeTree(locals, path.resolve(sourceDir, "source"), path.resolve(apiOutputDir, "PlayFabPlugin"));

        // Create the Example project folder
        templatizeTree(locals, path.resolve(sourceDir, "examplesource"), apiOutputDir);

        // Copy the PlayFabPlugin folder just created into the ExampleProject
        // TODO: It causes very confusing problems to copy from an output subdir to another output subdir. Let's fix this
        templatizeTree(locals, path.resolve(apiOutputDir, "PlayFabPlugin"), path.resolve(apiOutputDir, "ExampleProject/Plugins"));
    }
}

// BP Module: Pull all the enums out of all the apis, and collect them into a single collection of just the enum types and filter duplicates
function collectEnumsFromApis(apis) {
    var enumTypes = {};
    for (var a = 0; a < apis.length; a++)
        for (var d in apis[a].datatypes)
            if (apis[a].datatypes[d].isenum && apis[a].datatypes[d].enumvalues.length <= 255)
                enumTypes[d] = apis[a].datatypes[d];
    return enumTypes;
}

function getDefaultVerticalName() {
    if (exports.verticalName) {
        return exports.verticalName;
    }
    return "";
}
<|endoftext|>


<commit_before>import {map} from 'event-stream';
import {argv} from 'yargs';
import promisify from 'es6-promisify';
import path from 'path';
import through from 'through2';

import {getNewVersion} from './version-helper';
import {getLastTag, isBlank, gitDiffMixinsAndVariables,
  getChangedComponents, getAllComponents} from './git-helper';

const exec = promisify(require('child_process').exec);
const read = promisify(require('vinyl-file').read);

export async function componentsWithChanges() {
  const lastTag = await getLastTag();
  const mixinsAndVariablesChanged = !isBlank(await gitDiffMixinsAndVariables(lastTag));
  let components;
  if (argv.updateAll || mixinsAndVariablesChanged) {
    components = await getAllComponents();
  }
  else {
    components = await getChangedComponents(lastTag);
  }
  return components;
}

function packageNameOf(componentPath) {
  if (componentPath.match(/src\/pivotal-ui\/components\//)) {
    return `pui-css-${path.basename(componentPath)}`;
  }
  else if (componentPath.match(/src\/pivotal-ui-react\//)) {
    return `pui-react-${path.basename(componentPath)}`;
  }
  else if (componentPath === './') {
    return 'pivotal-ui-root-package';
  }
  else {
    console.error(`Unknown componentPath ${componentPath}`);
    throw new Error(`Unknown componentPath ${componentPath}`);
  }
}

async function componentsDependentOn(componentPath) {
  const command = `git grep --files-with-matches ${packageNameOf(componentPath)} src/pivotal-ui-react/*/package.json src/pivotal-ui/components/*/package.json package.json`;
  try {
    return (await exec(command)).trim().split('\n')
      .map((filename) => path.dirname(filename) + path.sep);
  }
  catch(error) {
    if (error.code === 1) { // git grep returns no results
      return [];
    }
    throw error;
  }
}

export function componentsToUpdate() {
  const componentsToLookThrough = [];
  const componentsToUpdate = {};

  return through.obj(
    function(componentWithChanges, encoding, callback) {
      componentsToLookThrough.push(componentWithChanges.toString());
      componentsToUpdate[componentWithChanges] = [];
      callback();
    },

    async function(callback) {
      try {
        let component;
        while (Boolean(component = componentsToLookThrough.shift())) {
          for (const dependentComponent of (await componentsDependentOn(component))) {
            if (!componentsToUpdate[dependentComponent]) {
              componentsToLookThrough.push(dependentComponent);
              componentsToUpdate[dependentComponent] = [];
            }
            componentsToUpdate[dependentComponent].push(packageNameOf(component));
          }
        }

        for (component of Object.keys(componentsToUpdate)) {
          this.push({
            component: component,
            dependencies: componentsToUpdate[component]
          });
        }
        callback();
      }
      catch(error) {
        console.error(error.stack);
        callback(error);
      }
    }
  );
}

export function updatePackageJsons() {
  return map(async ({component, dependencies}, callback) => {
    try {
      const packageJsonPath = path.join(component, 'package.json');
      const packageJsonFile = await read(packageJsonPath);
      const packageJsonContents = JSON.parse(packageJsonFile.contents.toString());

      const version = getNewVersion();
      packageJsonContents.version = version;
      for (let dependency of dependencies) {
        packageJsonContents.dependencies[dependency] = version;
      }

      packageJsonFile.contents = new Buffer(JSON.stringify(packageJsonContents, null, 2));
      callback(null, packageJsonFile);
    } catch(error) {
      console.error(error.stack);
      callback(error);
    }
  });
}
<commit_msg>chore(tasks): updates org scope for publishes<commit_after>import { map } from 'event-stream';
import { argv } from 'yargs';
import promisify from 'es6-promisify';
import path from 'path';
import through from 'through2';

import { getNewVersion } from './version-helper';
import { getLastTag, isBlank, gitDiffMixinsAndVariables, getChangedComponents, getAllComponents } from './git-helper';

const exec = promisify(require('child_process').exec);
const read = promisify(require('vinyl-file').read);

export async function componentsWithChanges() {
  const lastTag = await getLastTag();
  const mixinsAndVariablesChanged = !isBlank(await gitDiffMixinsAndVariables(lastTag));
  let components;
  if (argv.updateAll || mixinsAndVariablesChanged) {
    components = await getAllComponents();
  } else {
    components = await getChangedComponents(lastTag);
  }
  return components;
}

function packageNameOf(componentPath) {
  if (componentPath.match(/src\/pivotal-ui\/components\//)) {
    return `@npmcorp/pui-css-${path.basename(componentPath)}`;
  } else if (componentPath.match(/src\/pivotal-ui-react\//)) {
    return `@npmcorp/pui-react-${path.basename(componentPath)}`;
  } else if (componentPath === './') {
    return 'pivotal-ui-root-package';
  } else {
    console.error(`Unknown componentPath ${componentPath}`);
    throw new Error(`Unknown componentPath ${componentPath}`);
  }
}

async function componentsDependentOn(componentPath) {
  const command = `git grep --files-with-matches ${packageNameOf(componentPath)} src/pivotal-ui-react/*/package.json src/pivotal-ui/components/*/package.json package.json`;
  try {
    return (await exec(command)).trim().split('\n')
      .map((filename) => path.dirname(filename) + path.sep);
  } catch (error) {
    if (error.code === 1) { // git grep returns no results
      return [];
    }
    throw error;
  }
}

export function componentsToUpdate() {
  const componentsToLookThrough = [];
  const componentsToUpdate = {};

  return through.obj(
    function(componentWithChanges, encoding, callback) {
      componentsToLookThrough.push(componentWithChanges.toString());
      componentsToUpdate[componentWithChanges] = [];
      callback();
    },

    async function(callback) {
      try {
        let component;
        while (Boolean(component = componentsToLookThrough.shift())) {
          for (const dependentComponent of ( await componentsDependentOn(component))) {
            if (!componentsToUpdate[dependentComponent]) {
              componentsToLookThrough.push(dependentComponent);
              componentsToUpdate[dependentComponent] = [];
            }
            componentsToUpdate[dependentComponent].push(packageNameOf(component));
          }
        }

        for (component of Object.keys(componentsToUpdate)) {
          this.push({
            component: component,
            dependencies: componentsToUpdate[component]
          });
        }
        callback();
      } catch (error) {
        console.error(error.stack);
        callback(error);
      }
    }
  );
}

export function updatePackageJsons() {
  return map(async ({component, dependencies}, callback) => {
    try {
      const packageJsonPath = path.join(component, 'package.json');
      const packageJsonFile = await read(packageJsonPath);
      const packageJsonContents = JSON.parse(packageJsonFile.contents.toString());

      const version = getNewVersion();
      packageJsonContents.version = version;
      for (let dependency of dependencies) {
        packageJsonContents.dependencies[dependency] = version;
      }

      packageJsonFile.contents = new Buffer(JSON.stringify(packageJsonContents, null, 2));
      callback(null, packageJsonFile);
    } catch (error) {
      console.error(error.stack);
      callback(error);
    }
  });
}
<|endoftext|>


<commit_before>'use strict';
labApp.controller("HomeCtrl", ['$rootScope', '$scope', 'middleService', 'blockUI', 'initData', function ($rootScope, $scope, middleService, blockUI, initData) {

    var self = this;

    self.findOnTreeById = function (id) {
        var nodeFound = $scope.root.first(function (iterNode) {
            return iterNode.model.id === id;
        });
        return nodeFound.model;
    };

    self.initializeCodeEditor = function () {
        const CRIMSON_THEME = "ace/theme/crimson_editor";
        const JAVA_MODE = "ace/mode/java";
        $scope.codeEditor = ace.edit("code-editor");
        $scope.codeEditor.$blockScrolling = Infinity;
        $scope.codeEditor.setTheme(CRIMSON_THEME);
        $scope.codeEditor.getSession().setMode(JAVA_MODE);
        $scope.codeEditor.getSession().setValue($scope.selected.code);
    };

    $scope.appModel = initData.data;

    $scope.$on('$routeChangeSuccess', function () {// initialization of main model
        $scope.root = new TreeModel().parse({"id": 0, "children": $scope.appModel.treedata});

        //tree data initialization
        $scope.treedata = $scope.appModel.treedata;
        $scope.expandedNodes = [self.findOnTreeById(1), self.findOnTreeById(11), self.findOnTreeById(2), self.findOnTreeById(21)];
        $scope.selected = self.findOnTreeById(111);

        //AutoCompletion
        $scope.javaClasses = [
            {name: 'HelloWorld.java', path: 'com.company.project.HelloWorld.java', id: 111},
            {name: 'HelloWorldTest.java', path: 'com.company.project.HelloWorldTest.java', id: 211}
        ];
        $scope.initialValue = $scope.javaClasses[0];

        $rootScope.$broadcast('resize', {});

        self.initializeCodeEditor();
    });

    $scope.formatCode = function () {
        function formatCodeFor(editor) {
            editor.getSession().setUseWrapMode(false);
            var oldFormat = editor.getValue();
            if (oldFormat.trim().length > 0) {
                var newFormat = js_beautify(oldFormat, {
                    'indent_size': 1,
                    'indent_char': '\t'
                });
                editor.setValue(newFormat);
            }
        }

        formatCodeFor(ace.edit("code-editor"));
    };

    $scope.runCode = function () {
        if ($scope.appModel.runnableNode.id == undefined) {
            $scope.appModel.console = "Please select a class to run";
            return;
        }

        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.runnableNode.mainClass = true;
        $scope.appModel.runnableNode.testClass = false;
        $scope.appModel.console = middleService.runCode($scope.appModel);
        blockUI.stop();
    };

    $scope.runTests = function () {
        if ($scope.appModel.runnableNode.id == undefined) {
            $scope.appModel.console = "Please select a test class";
            return;
        }

        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.runnableNode.mainClass = false;
        $scope.appModel.runnableNode.testClass = true;
        $scope.appModel.console = middleService.runTest($scope.appModel);
        blockUI.stop();
    };

    $scope.save = function () {
        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.console = middleService.saveWorkspace($scope.appModel);
        blockUI.stop();
    };

    $scope.new = function () {
        blockUI.start();
        $scope.appModel.console = middleService.newWorkspace($scope.appModel);
        blockUI.stop();
    };

    /**
     * Tree manager
     */
    $scope.showSelected = function (node) {
        var oldNode = $scope.selected;
        if (oldNode !== undefined) {
            oldNode.code = $scope.codeEditor.getValue();
            oldNode.cursor = $scope.codeEditor.getCursorPosition();
        }

        $scope.selected = node;
        if (node.type === "file") {
            $scope.codeEditor.setValue(node.code, 1); // moves cursor to the end
            var cursor = node.cursor == undefined ? {column: 0, row: 0} : node.cursor;
            $scope.codeEditor.moveCursorToPosition(cursor);
            $scope.codeEditor.focus();
        }
    };

    self.pathAsString = function (node) {
        var path = "";
        var pathArray = node.getPath();
        for (var index = 2; index < pathArray.length; ++index) {
            if (pathArray[index].model.name != undefined) {

                if (index === (pathArray.length - 1)) {
                    path += ".";
                }

                path += pathArray[index].model.name;
            }
        }
        return path;
    };

    $scope.addNode = function (typeToCreate, node) {
        var nodeName = prompt("Enter " + typeToCreate + " name", typeToCreate + " name");
        if (nodeName == null || nodeName.trim() === "") {
            return;
        }

        var nodeFound = $scope.root.first(function (iterNode) {
            return iterNode.model.id === node.id;
        });

        function newNodeUUID() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        function createNewNode() {
            var newNode = new TreeModel().parse({id: newNodeUUID(), name: nodeName, type: typeToCreate, children: []});
            if (typeToCreate === "file") {
                newNode.model.code = "";
            }
            return newNode;
        }

        var newNode = createNewNode();
        if (newNode.model.type === "file") {
            nodeFound.parent.addChild(newNode);
            if (nodeName.indexOf(".java") > -1) {
                $scope.javaClasses.push({
                    id: newNode.model.id,
                    name: newNode.model.name,
                    path: self.pathAsString(newNode)
                })
            }

        } else if (newNode.model.type === "folder") {
            nodeFound.addChild(newNode);
        }
    };

    $scope.editNode = function (node) {
        if (node.id === 1 || node.id === 2) {
            return;
        }

        var nodeName = prompt("Change name", node.name);
        if (nodeName == null || nodeName.trim() === "") {
            return;
        }

        var nodeFound = $scope.root.first(function (iterNode) {
            return iterNode.model.id === node.id;
        });

        nodeFound.model.name = nodeName;

        function updatePaths(node) {
            if (node.model.type === "file" && node.model.name.indexOf(".java") > -1) {
                var classesArray = $scope.javaClasses;
                for (var i = 0; i < classesArray.length; ++i) {
                    if (classesArray[i].id == node.model.id) {
                        classesArray[i].name = node.model.name;
                        classesArray[i].path = self.pathAsString(node);
                    }
                }

            } else if (node.model.type === "folder") {
                for (var j = 0; j < node.children.length; ++j) {
                    updatePaths(node.children[j]);
                }
            }
        }

        updatePaths(nodeFound);

    };

    $scope.removeNode = function (node) {
        if (node.id === 1 || node.id === 2) {
            return;
        }

        var confirmed = confirm("Delete " + node.type + " '" + node.name + "' ?");
        if (!confirmed) {
            return;
        }

        var nodeFound = $scope.root.first(function (iterNode) {
            return iterNode.model.id === node.id;
        });

        $scope.selected = $scope.treedata[0];//root selected

        if (nodeFound.model.name.indexOf(".java") > -1) {
            var classesArray = $scope.javaClasses;
            for (var index = 0; index < classesArray.length; ++index) {
                if (classesArray[index].id == nodeFound.model.id) {
                    classesArray.splice(index, 1);
                }
            }
        }

        nodeFound.drop();
    };

    $scope.treeOptions = {
        nodeChildren: "children",
        dirSelectable: true,
        allowDeselect: false,
        isLeaf: function (node) {
            return node.type === "file";
        },
        equality: function (node1, node2) {
            return (node1 === node2) && (angular.equals(node1, node2));
        }
    };

    /**
     * Autocompletion
     */
    $scope.selectedFile = function (selected) {
        if (selected == undefined) {
            $scope.appModel.runnableNode.id = undefined;
            return;
        }

        var nodeFound = $scope.root.first(function (iterNode) {
            return iterNode.model.id === selected.originalObject.id;
        });

        $scope.appModel.runnableNode.id = nodeFound.model.id;
    };

}]);<commit_msg>removed treedata references<commit_after>'use strict';
labApp.controller("HomeCtrl", ['$rootScope', '$scope', 'middleService', 'blockUI', 'initData', function ($rootScope, $scope, middleService, blockUI, initData) {

    var self = this;

    self.findById = function (id) {
        return $scope.root.first(function (iterNode) {
            return iterNode.model.id === id;
        });
    };

    self.initializeCodeEditor = function () {
        const CRIMSON_THEME = "ace/theme/crimson_editor";
        const JAVA_MODE = "ace/mode/java";
        $scope.codeEditor = ace.edit("code-editor");
        $scope.codeEditor.$blockScrolling = Infinity;
        $scope.codeEditor.setTheme(CRIMSON_THEME);
        $scope.codeEditor.getSession().setMode(JAVA_MODE);
        $scope.codeEditor.getSession().setValue($scope.selected.code);
    };

    $scope.appModel = initData.data;

    $scope.$on('$routeChangeSuccess', function () {// initialization of main model
        $scope.root = new TreeModel().parse({"id": 0, "children": $scope.appModel.treedata});

        //tree data initialization
        $scope.treedata = $scope.appModel.treedata;
        $scope.expandedNodes = [self.findById(1).model, self.findById(11).model, self.findById(2).model, self.findById(21).model];
        $scope.selected = self.findById(111).model;

        //AutoCompletion
        $scope.javaClasses = [
            {name: 'HelloWorld.java', path: 'com.company.project.HelloWorld.java', id: 111},
            {name: 'HelloWorldTest.java', path: 'com.company.project.HelloWorldTest.java', id: 211}
        ];
        $scope.initialValue = $scope.javaClasses[0];

        $rootScope.$broadcast('resize', {});

        self.initializeCodeEditor();
    });

    $scope.formatCode = function () {
        function formatCodeFor(editor) {
            editor.getSession().setUseWrapMode(false);
            var oldFormat = editor.getValue();
            if (oldFormat.trim().length > 0) {
                var newFormat = js_beautify(oldFormat, {
                    'indent_size': 1,
                    'indent_char': '\t'
                });
                editor.setValue(newFormat);
            }
        }

        formatCodeFor(ace.edit("code-editor"));
    };

    $scope.runCode = function () {
        if ($scope.appModel.runnableNode.id == undefined) {
            $scope.appModel.console = "Please select a class to run";
            return;
        }

        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.runnableNode.mainClass = true;
        $scope.appModel.runnableNode.testClass = false;
        $scope.appModel.console = middleService.runCode($scope.appModel);
        blockUI.stop();
    };

    $scope.runTests = function () {
        if ($scope.appModel.runnableNode.id == undefined) {
            $scope.appModel.console = "Please select a test class";
            return;
        }

        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.runnableNode.mainClass = false;
        $scope.appModel.runnableNode.testClass = true;
        $scope.appModel.console = middleService.runTest($scope.appModel);
        blockUI.stop();
    };

    $scope.save = function () {
        blockUI.start();
        $scope.selected.code = $scope.codeEditor.getValue();
        $scope.selected.cursor = $scope.codeEditor.getCursorPosition();
        $scope.appModel.console = middleService.saveWorkspace($scope.appModel);
        blockUI.stop();
    };

    $scope.new = function () {
        blockUI.start();
        $scope.appModel.console = middleService.newWorkspace($scope.appModel);
        blockUI.stop();
    };

    /**
     * Tree manager
     */
    $scope.showSelected = function (node) {
        var oldNode = $scope.selected;
        if (oldNode !== undefined) {
            oldNode.code = $scope.codeEditor.getValue();
            oldNode.cursor = $scope.codeEditor.getCursorPosition();
        }

        $scope.selected = node;
        if (node.type === "file") {
            $scope.codeEditor.setValue(node.code, 1); // moves cursor to the end
            var cursor = node.cursor == undefined ? {column: 0, row: 0} : node.cursor;
            $scope.codeEditor.moveCursorToPosition(cursor);
            $scope.codeEditor.focus();
        }
    };

    self.pathAsString = function (node) {
        var path = "";
        var pathArray = node.getPath();
        for (var index = 2; index < pathArray.length; ++index) {
            if (pathArray[index].model.name != undefined) {

                if (index === (pathArray.length - 1)) {
                    path += ".";
                }

                path += pathArray[index].model.name;
            }
        }
        return path;
    };

    $scope.addNode = function (typeToCreate, node) {
        var nodeName = prompt("Enter " + typeToCreate + " name", typeToCreate + " name");
        if (nodeName == null || nodeName.trim() === "") {
            return;
        }

        function newNodeUUID() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        function createNewNode() {
            var newNode = new TreeModel().parse({id: newNodeUUID(), name: nodeName, type: typeToCreate, children: []});
            if (typeToCreate === "file") {
                newNode.model.code = "";
            }
            return newNode;
        }

        var nodeFound = self.findById(node.id);
        var newNode = createNewNode();

        if (newNode.model.type === "file") {
            nodeFound.parent.addChild(newNode);
            if (nodeName.indexOf(".java") > -1) {
                $scope.javaClasses.push({
                    id: newNode.model.id,
                    name: newNode.model.name,
                    path: self.pathAsString(newNode)
                })
            }
        } else if (newNode.model.type === "folder") {
            nodeFound.addChild(newNode);
        }
    };

    $scope.editNode = function (node) {
        if (node.id === 1 || node.id === 2) {
            return;
        }

        var nodeName = prompt("Change name", node.name);
        if (nodeName == null || nodeName.trim() === "") {
            return;
        }

        var nodeFound = self.findById(node.id);
        nodeFound.model.name = nodeName;

        function updatePaths(node) {
            if (node.model.type === "file" && node.model.name.indexOf(".java") > -1) {
                var classesArray = $scope.javaClasses;
                for (var i = 0; i < classesArray.length; ++i) {
                    if (classesArray[i].id == node.model.id) {
                        classesArray[i].name = node.model.name;
                        classesArray[i].path = self.pathAsString(node);
                    }
                }

            } else if (node.model.type === "folder") {
                for (var j = 0; j < node.children.length; ++j) {
                    updatePaths(node.children[j]);
                }
            }
        }

        updatePaths(nodeFound);

    };

    $scope.removeNode = function (node) {
        if (node.id === 1 || node.id === 2) {
            return;
        }

        var confirmed = confirm("Delete " + node.type + " '" + node.name + "' ?");
        if (!confirmed) {
            return;
        }

        $scope.selected = self.findById(1).model;//select root

        var nodeFound = self.findById(node.id);
        if (nodeFound.model.name.indexOf(".java") > -1) {
            var classesArray = $scope.javaClasses;
            for (var index = 0; index < classesArray.length; ++index) {
                if (classesArray[index].id == nodeFound.model.id) {
                    classesArray.splice(index, 1);
                }
            }
        }

        nodeFound.drop();
    };

    $scope.treeOptions = {
        nodeChildren: "children",
        dirSelectable: true,
        allowDeselect: false,
        isLeaf: function (node) {
            return node.type === "file";
        },
        equality: function (node1, node2) {
            return (node1 === node2) && (angular.equals(node1, node2));
        }
    };

    /**
     * Autocompletion
     */
    $scope.selectedFile = function (selected) {
        if (selected == undefined) {
            $scope.appModel.runnableNode.id = undefined;
            return;
        }

        var nodeFound = self.findById(selected.originalObject.id);
        $scope.appModel.runnableNode.id = nodeFound.model.id;
    };

}]);<|endoftext|>


<commit_before>var CM = require('codemirror');
require('codemirror/addon/display/panel');
require('codemirror/addon/search/search.js');
require('codemirror/addon/search/searchcursor.js');
require('codemirror/addon/dialog/dialog.js');

require('./automarkup.js');
var milestones=require("./milestones");
//require('codemirror/addon/selection/active-line');
var React = require('react');
var ReactDOM = require('react-dom');
var E=React.createElement;

var applyMarkups=require("./markups").applyMarkups;

var randomKey=function() {
	return 'm'+Math.random().toString().substr(2,5);
}
var CodeMirrorComponent = React.createClass({
	displayName :"CodeMirror"
	,propTypes: {
		onChange: React.PropTypes.func,
		onFocusChange: React.PropTypes.func,
		onCursorActivity: React.PropTypes.func,
		options: React.PropTypes.object,
		path: React.PropTypes.string,
		value: React.PropTypes.string,
		onBeforeCopy:React.PropTypes.func
	}
	,getInitialState:function () {
		return {
			isFocused: false
		};
	}
	,cursorActivity:function(cm) {
		this.props.onCursorActivity&&this.props.onCursorActivity(cm);
	}
	,componentDidMount:function () {
		var textareaNode = ReactDOM.findDOMNode(this.refs.editor);
		this.codeMirror = CM(textareaNode, {
  		value: this.props.value
  		//,mode:  "javascript"
  		//inputStyle:"contenteditable",
  		,styleActiveLine:true
  		,undoDepth: Infinity
  		,lineWrapping:true
  		,readOnly:!!this.props.readOnly
  		,lineNumbers: true
  		,theme:"ambiance"
  		,gutters: ["CodeMirror-linenumbers"]

		});

		this.codeMirror.setOption("lineNumberFormatter",milestones.lineNumberFormatter.bind(this));

		//CM.fromTextArea(textareaNode, this.props.options);
		if (this.props.onBeforeCopy) this.codeMirror.on('beforeCopyToClipboard', this.props.onBeforeCopy);
		this.codeMirror.getDoc().on('change', this.props.onChange);
		if (this.props.onBeforeChange) this.codeMirror.on('beforeChange', this.props.onBeforeChange);
		this.codeMirror.on('focus', this.focusChanged.bind(this, true));
		this.codeMirror.on('blur', this.focusChanged.bind(this, false));
		this.codeMirror.on('cursorActivity',this.cursorActivity);
		this.codeMirror.on('mousedown',this.onMouseDown);

		setTimeout(function(){
			this.props.markups&&applyMarkups(this.codeMirror,this.props.markups,true);
			this.props.onMarkupReady&&this.props.onMarkupReady(this.codeMirror);
		}.bind(this),30);//need to wait for this.codeMirror.react ready (dirty hack)
	}

	,componentWillUnmount:function () {
		// todo: is there a lighter-weight way to remove the cm instance?
		if (this.codeMirror&& this.codeMirror.toTextArea) {
			this.codeMirror.toTextArea();
		}
	}

	,onMouseDown:function(cm,e) {
		this.props.onMouseDown&&this.props.onMouseDown(cm,e);
	}

	,shouldComponentUpdate:function(nextProps) {
		var update= (nextProps.value!==this.props.value || nextProps.history!==this.props.history
				||nextProps.markups!==this.props.markups);
		return update;
	}

	,componentWillReceiveProps:function (nextProps) {
		if (this.codeMirror) {

			if (this.props.history !== nextProps.history) {
				//this.codeMirror.setHistory(nextProps.history);
			}

			if (this.props.markups !== nextProps.markups) {
				nextProps.markups&&applyMarkups(this.codeMirror,nextProps.markups);
			}
		}
	}

	,getCodeMirror:function () {
		return this.codeMirror;
	}

	,markText:function(opts) {
		var doc=this.codeMirror.getDoc();
		var selections=doc.listSelections();

		for (var i=0;i<selections.length;i++) {
			var sel=selections[i];
			if (sel.anchor===sel.head) continue; //empty
			if (typeof opts.key!=="string") {
				opts.key=randomKey();
			}
			this.codeMirror.markText(sel.anchor,sel.head, opts );
		}
	}

	,focus:function () {
		if (this.codeMirror) {
			this.codeMirror.focus();
		}
	}

	,focusChanged:function (focused) {
		this.setState({isFocused: focused});
		this.props.onFocusChange && this.props.onFocusChange(focused);
	}

	,render:function () {
		return E("span",{ref:"editor"});
	}

});

module.exports = CodeMirrorComponent;<commit_msg>cnanot setState in focusCHanged after unmount<commit_after>var CM = require('codemirror');
require('codemirror/addon/display/panel');
require('codemirror/addon/search/search.js');
require('codemirror/addon/search/searchcursor.js');
require('codemirror/addon/dialog/dialog.js');

require('./automarkup.js');
var milestones=require("./milestones");
//require('codemirror/addon/selection/active-line');
var React = require('react');
var ReactDOM = require('react-dom');
var E=React.createElement;

var applyMarkups=require("./markups").applyMarkups;

var randomKey=function() {
	return 'm'+Math.random().toString().substr(2,5);
}
var CodeMirrorComponent = React.createClass({
	displayName :"CodeMirror"
	,propTypes: {
		onChange: React.PropTypes.func,
		onFocusChange: React.PropTypes.func,
		onCursorActivity: React.PropTypes.func,
		options: React.PropTypes.object,
		path: React.PropTypes.string,
		value: React.PropTypes.string,
		onBeforeCopy:React.PropTypes.func
	}
	,getInitialState:function () {
		return {
			isFocused: false
		};
	}
	,cursorActivity:function(cm) {
		this.props.onCursorActivity&&this.props.onCursorActivity(cm);
	}
	,componentDidMount:function () {
		var textareaNode = ReactDOM.findDOMNode(this.refs.editor);
		this.codeMirror = CM(textareaNode, {
  		value: this.props.value
  		//,mode:  "javascript"
  		//inputStyle:"contenteditable",
  		,styleActiveLine:true
  		,undoDepth: Infinity
  		,lineWrapping:true
  		,readOnly:!!this.props.readOnly
  		,lineNumbers: true
  		,theme:"ambiance"
  		,gutters: ["CodeMirror-linenumbers"]

		});

		this.codeMirror.setOption("lineNumberFormatter",milestones.lineNumberFormatter.bind(this));

		//CM.fromTextArea(textareaNode, this.props.options);
		if (this.props.onBeforeCopy) this.codeMirror.on('beforeCopyToClipboard', this.props.onBeforeCopy);
		this.codeMirror.getDoc().on('change', this.props.onChange);
		if (this.props.onBeforeChange) this.codeMirror.on('beforeChange', this.props.onBeforeChange);
		this.codeMirror.on('focus', this.focusChanged.bind(this, true));
		this.codeMirror.on('blur', this.focusChanged.bind(this, false));
		this.codeMirror.on('cursorActivity',this.cursorActivity);
		this.codeMirror.on('mousedown',this.onMouseDown);

		setTimeout(function(){
			this.props.markups&&applyMarkups(this.codeMirror,this.props.markups,true);
			this.props.onMarkupReady&&this.props.onMarkupReady(this.codeMirror);
		}.bind(this),30);//need to wait for this.codeMirror.react ready (dirty hack)
	}

	,componentWillUnmount:function () {
		// todo: is there a lighter-weight way to remove the cm instance?
		if (this.codeMirror&& this.codeMirror.toTextArea) {
			this.codeMirror.toTextArea();
		}
	}

	,onMouseDown:function(cm,e) {
		this.props.onMouseDown&&this.props.onMouseDown(cm,e);
	}

	,shouldComponentUpdate:function(nextProps) {
		var update= (nextProps.value!==this.props.value || nextProps.history!==this.props.history
				||nextProps.markups!==this.props.markups);
		return update;
	}

	,componentWillReceiveProps:function (nextProps) {
		if (this.codeMirror) {

			if (this.props.history !== nextProps.history) {
				//this.codeMirror.setHistory(nextProps.history);
			}

			if (this.props.markups !== nextProps.markups) {
				nextProps.markups&&applyMarkups(this.codeMirror,nextProps.markups);
			}
		}
	}

	,getCodeMirror:function () {
		return this.codeMirror;
	}

	,markText:function(opts) {
		var doc=this.codeMirror.getDoc();
		var selections=doc.listSelections();

		for (var i=0;i<selections.length;i++) {
			var sel=selections[i];
			if (sel.anchor===sel.head) continue; //empty
			if (typeof opts.key!=="string") {
				opts.key=randomKey();
			}
			this.codeMirror.markText(sel.anchor,sel.head, opts );
		}
	}

	,focus:function () {
		if (this.codeMirror) {
			this.codeMirror.focus();
		}
	}

	,focusChanged:function (focused) {
		if (!this.isMounted())return;//no longer available
		this.setState({isFocused: focused});
		this.props.onFocusChange && this.props.onFocusChange(focused);
	}

	,render:function () {
		return E("span",{ref:"editor"});
	}

});

module.exports = CodeMirrorComponent;<|endoftext|>