<commit_before>/**
 * Declares instance variables.
 *
 * @constructor
 *
 * @class A class for helping insert an anchor. Contains code
 * common to both the button and the menu item.
 */
UI.Clipboard_Helper = function ClipboardHelper()
{
	var self = this;
	Util.OOP.inherits(self, UI.Helper);

	this.is_selection_empty = function()
	{
		var sel = Util.Selection.get_selection(this._loki.window);
		return Util.Selection.is_collapsed(sel);
	};

	this.cut = function clipboard_cut()
	{
		self.copy('Cut', 'X');
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		Util.Range.delete_contents(rng);
		self._loki.focus();
	};

	this.copy = function clipboard_copy(command, accel)
	{
		// Get the HTML to copy
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		var html = Util.Range.get_html(rng);
		//var text = rng.toString();

		if (Util.Selection.is_collapsed(sel)) {
			// If nothing is actually selected; do not overwrite the clipboard.
			return;
		}

		// Unmassage and clean HTML
		var container = self._loki.document.createElement('DIV');
		container.innerHTML = html;
		self._loki.unmassage_node_descendants(container);

		// Clean the copied HTML. We pass an override to the block-level element
		// rule enforcer that specifies that inline content within paragraphs do
		// not have to be wrapped in (e.g.) paragraph tags. This prevents inline
		// content that is being copied from being treated as its own paragraph.
		UI.Clean.clean(container, self._loki.settings, false, {
			overrides: {DIV: Util.Block.BLOCK}
		});
		html = container.innerHTML;

		// Move HTML to clipboard
		try {
			if (UI.Clipboard_Helper._gecko) {
				_gecko_copy(html, command || 'Copy', accel || 'C');
			} else {
				_ie_copy(html);
			}
		} finally {
			self._loki.focus();
		}

	};

	this.paste = function clipboard_paste()
	{
		try {
			if (UI.Clipboard_Helper._gecko) {
				_gecko_paste();
			} else {
				_ie_paste();
			}
		} finally {
			self._loki.focus();
		}
	};

	this.delete_it = function() // delete is a reserved word
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		rng.deleteContents();
		self._loki.focus();
	};

	this.select_all = function()
	{
		self._loki.exec_command('SelectAll');
		self._loki.focus();
	};

	this.is_security_error = function(e)
	{
		return ( e.message != null && e.message.indexOf != null && e.message.indexOf('Clipboard_Helper') > -1 );
	};

	function _show_gecko_privileges_warning()
	{
		var message = "Your browser requires that you give explicit permission for " +
			"your clipboard to be accessed, so you may see a security warning " +
			"after dismissing this message. You are free to deny this permssion, " +
			"but if you do, you may be unable to cut, copy, or paste into this " +
			"document.";

		UI.Messenger.display_once_per_duration('gecko clipboard warning',
			message, 45);
	}

	function _verify_gecko_clipboard(command, accel)
	{
		var key;
		if (!self._loki.owner_window.GeckoClipboard) {
			key = ((Util.Browser.Mac) ? '⌘' : 'Ctrl-') + accel;
			alert('Unable to access your system\'s clipboard. Please choose ' +
				command + ' from your browser\'s Edit menu, or press ' +
				key + '.');
			throw new Util.Unsupported_Error('programmatic clipboard access');
		}
	}

	function _gecko_copy(html, command, accel)
	{
		_verify_gecko_clipboard(command, accel);
		_show_gecko_privileges_warning();
		self._loki.owner_window.GeckoClipboard.set(html);
	};

	function _ie_copy(html)
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);

		// transfer from iframe to editable div
		// select all of editable div
		// copy from editable div
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML = html;
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("SelectAll", false, null);
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("Copy", false, null);

		// Reposition cursor
		rng.select();
	};

	function _gecko_paste()
	{
		_verify_gecko_clipboard('Paste', 'V');
		_show_gecko_privileges_warning();
		var data = self._loki.owner_window.GeckoClipboard.get();

		var html = (data.type == 'text/html')
			? data.value
			: data.value.replace(/\r?\n/g, "
\n");

		// Massage and clean HTML
		var container = self._loki.document.createElement('DIV');
		container.innerHTML = html;
		// See UI.Clipboard_helper.copy() for the override rationale.
		UI.Clean.clean(container, self._loki.settings, false, {
			overrides: {DIV: Util.Block.BLOCK}
		});
		self._loki.massage_node_descendants(container);
		html = container.innerHTML;

		// Get selection and range
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);

		// Paste into temporary container
		container = rng.startContainer.ownerDocument.createElement('DIV');
		container.innerHTML = html;

		// Copy into document fragment
		var frag = rng.startContainer.ownerDocument.createDocumentFragment();
		for ( var i = 0; i < container.childNodes.length; i++ )
			frag.appendChild(container.childNodes[i].cloneNode(true));

		// Paste the document fragment
		Util.Selection.paste_node(sel, frag);
	};

	function _ie_paste()
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		var parent = rng.parentElement();

		// Ensure that the selection is within the editing document.
		// if (parent && parent.ownerDocument != self._loki.document)
		// 	return;

		// Make clipboard iframe editable
		// clear editable div
		// select all of editable div
		// paste into editable div
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.contentEditable = true;
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML = "";
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("SelectAll", false, null);
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("Paste", false, null);

		// Get HTML
		var html = UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML;

		// Massage and clean HTML
		var nodeName = 'DIV';
		if (rng.text != null && rng.text == "") {
			if (typeof(parent) == 'object' && parent.tagName)
				nodeName = parent.tagName;
		}

		function clean(nodeName) {
			var temp = self._loki.document.createElement(nodeName);
			temp.innerHTML = html;

			UI.Clean.clean(temp, self._loki.settings);
			self._loki.massage_node_descendants(temp);
			return temp.innerHTML;
		}

		var cleanedHTML;
		try {
			cleanedHTML = clean(nodeName);
		} catch (e) {
			if (nodeName != 'DIV')
				cleanedHTML = clean('DIV');
			else
				throw e;
		}

		// Actually paste HTML
		rng.pasteHTML(cleanedHTML);
		rng.select();
	};
};

UI.Clipboard_Helper._gecko = (typeof(Components) == 'object');

// We need to create this iframe as a place to put code that
// Gecko needs to run with special privileges, for which
// privileges Gecko requires that the code be signed.
// (But we don't want to sign _all_ of Loki, because the page
// that invokes the javascript has to be signed with the
// javascript, and we want to be able to use Loki on dynamic
// pages; sigining dynamic pages would be too inconvenient, not
// to mention slow.)
// We create this here, on the assumption that it will have
// loaded by the time we need it.
//
// For more information about how to sign scripts, see
// privileged/HOWTO

/** @ignore */
UI.Clipboard_Helper._setup_done = false

/** @ignore */
UI.Clipboard_Helper._setup = function setup_clipboard_helper() {
	var base_uri = (arguments[0]
	 	? Util.URI.build(Util.URI.normalize(arguments[0]))
		: null);
	var helper_src = null;

	if (UI.Clipboard_Helper._setup_done)
		return;

	function watch_onload(func)
	{
		if (Loki.is_document_ready()) {
			func();
			return;
		}

		if (document.addEventListener) {
			document.addEventListener('DOMContentLoaded', func, false);
			window.addEventListener('load', func, false);
		} else if (window.attachEvent) {
			window.attachEvent('onload', func);
		} else {
			window.onload = func;
		}
	}

	function create_hidden_iframe(src)
	{
		var called = false;
		var frame = Util.Document.create_element(document, 'iframe',
		{
			src: src,
			style: {
				position: 'absolute',
				box: [-500, -500, 2]
			}
		});

		function append_helper_iframe()
		{
			if (called)
				return;
			called = true;

			var body = (document.getElementsByTagName('BODY')[0] ||
				document.documentElement);
			body.appendChild(frame);
		}

		watch_onload(append_helper_iframe);

		return frame;
	}

	function make_uri(path)
	{
		if (base_uri.charAt(base_uri.length - 1) == '/')
			return base_uri + path;
		else
			return [base_uri, path].join('/');
	}

	if (UI.Clipboard_Helper._gecko) {
		// Gecko
		if (typeof(_gecko_clipboard_helper_src) == 'string') {
			// PHP helper is providing this for us.
			helper_src = _gecko_clipboard_helper_src;
		} else if (base_uri) {
			helper_src = 'jar:' +
				make_uri('auxil/privileged.jar!/gecko_clipboard.html');
		} else {
			return;
		}

		create_hidden_iframe(helper_src);
	} else {
		// everyone else
		if (typeof(UI__Clipboard_Helper_Editable_Iframe__src) == 'string') {
			// PHP helper is providing this for us.
			helper_src = UI__Clipboard_Helper_Editable_Iframe__src;
		} else if (base_uri) {
			helper_src = make_uri('auxil/loki_blank.html');
		} else {
			return;
		}
		UI.Clipboard_Helper_Editable_Iframe = create_hidden_iframe(helper_src);
	}

	UI.Clipboard_Helper._setup_done = true;
}

UI.Clipboard_Helper._setup();<commit_msg>Fixing issue 136.<commit_after>/**
 * Declares instance variables.
 *
 * @constructor
 *
 * @class A class for helping insert an anchor. Contains code
 * common to both the button and the menu item.
 */
UI.Clipboard_Helper = function ClipboardHelper()
{
	var self = this;
	Util.OOP.inherits(self, UI.Helper);

	this.is_selection_empty = function()
	{
		var sel = Util.Selection.get_selection(this._loki.window);
		return Util.Selection.is_collapsed(sel);
	};

	this.cut = function clipboard_cut()
	{
		self.copy('Cut', 'X');
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		Util.Range.delete_contents(rng);
		self._loki.focus();
	};

	this.copy = function clipboard_copy(command, accel)
	{
		// Get the HTML to copy
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		var html = Util.Range.get_html(rng);
		//var text = rng.toString();

		if (Util.Selection.is_collapsed(sel)) {
			// If nothing is actually selected; do not overwrite the clipboard.
			return;
		}

		// Unmassage and clean HTML
		var container = self._loki.document.createElement('DIV');
		container.innerHTML = html;
		self._loki.unmassage_node_descendants(container);

		// Clean the copied HTML. We pass an override to the block-level element
		// rule enforcer that specifies that inline content within paragraphs do
		// not have to be wrapped in (e.g.) paragraph tags. This prevents inline
		// content that is being copied from being treated as its own paragraph.
		UI.Clean.clean(container, self._loki.settings, false, {
			overrides: {DIV: Util.Block.BLOCK}
		});
		html = container.innerHTML;

		// Move HTML to clipboard
		try {
			if (UI.Clipboard_Helper._gecko) {
				_gecko_copy(html, command || 'Copy', accel || 'C');
			} else {
				_ie_copy(html);
			}
		} finally {
			self._loki.focus();
		}

	};

	this.paste = function clipboard_paste()
	{
		try {
			if (UI.Clipboard_Helper._gecko) {
				_gecko_paste();
			} else {
				_ie_paste();
			}
		} finally {
			self._loki.focus();
		}
	};

	this.delete_it = function() // delete is a reserved word
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		rng.deleteContents();
		self._loki.focus();
	};

	this.select_all = function()
	{
		self._loki.exec_command('SelectAll');
		self._loki.focus();
	};

	this.is_security_error = function(e)
	{
		return ( e.message != null && e.message.indexOf != null && e.message.indexOf('Clipboard_Helper') > -1 );
	};

	function _show_gecko_privileges_warning()
	{
		var message = "Your browser requires that you give explicit permission for " +
			"your clipboard to be accessed, so you may see a security warning " +
			"after dismissing this message. You are free to deny this permssion, " +
			"but if you do, you may be unable to cut, copy, or paste into this " +
			"document.";

		UI.Messenger.display_once_per_duration('gecko clipboard warning',
			message, 45);
	}

	function _verify_gecko_clipboard(command, accel)
	{
		var key;
		if (!self._loki.owner_window.GeckoClipboard) {
			key = ((Util.Browser.Mac) ? '⌘' : 'Ctrl-') + accel;
			alert('Unable to access your system\'s clipboard. Please choose ' +
				command + ' from your browser\'s Edit menu, or press ' +
				key + '.');
			throw new Util.Unsupported_Error('programmatic clipboard access');
		}
	}

	function _gecko_copy(html, command, accel)
	{
		_verify_gecko_clipboard(command, accel);
		_show_gecko_privileges_warning();
		self._loki.owner_window.GeckoClipboard.set(html);
	};

	function _ie_copy(html)
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);

		// transfer from iframe to editable div
		// select all of editable div
		// copy from editable div
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML = html;
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("SelectAll", false, null);
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("Copy", false, null);

		// Reposition cursor
		rng.select();
	};

	function _gecko_paste()
	{
		_verify_gecko_clipboard('Paste', 'V');
		_show_gecko_privileges_warning();
		var data = self._loki.owner_window.GeckoClipboard.get();

		var html = (data.type == 'text/html')
			? data.value
			: data.value.replace(/\r?\n/g, "
\n");

		// Massage and clean HTML
		var container = self._loki.document.createElement('DIV');
		container.innerHTML = html;
		// See UI.Clipboard_helper.copy() for the override rationale.
		UI.Clean.clean(container, self._loki.settings, false, {
			overrides: {DIV: Util.Block.BLOCK}
		});
		self._loki.massage_node_descendants(container);
		html = container.innerHTML;

		// Get selection and range
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);

		// Paste into temporary container
		container = rng.startContainer.ownerDocument.createElement('DIV');
		container.innerHTML = html;

		// Copy into document fragment
		var frag = rng.startContainer.ownerDocument.createDocumentFragment();
		for ( var i = 0; i < container.childNodes.length; i++ )
			frag.appendChild(container.childNodes[i].cloneNode(true));

		// Paste the document fragment
		Util.Selection.paste_node(sel, frag);
	};

	function _ie_paste()
	{
		var sel = Util.Selection.get_selection(self._loki.window);
		var rng = Util.Range.create_range(sel);
		var parent = rng.parentElement();

		// Ensure that the selection is within the editing document.
		// if (parent && parent.ownerDocument != self._loki.document)
		// 	return;

		// Make clipboard iframe editable
		// clear editable div
		// select all of editable div
		// paste into editable div
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.contentEditable = true;
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML = "";
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("SelectAll", false, null);
		UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.execCommand("Paste", false, null);

		// Get HTML
		var html = UI.Clipboard_Helper_Editable_Iframe.contentWindow.document.body.innerHTML;

		// Massage and clean HTML
		var nodeName = 'DIV';
		if (rng.text != null && rng.text == "") {
			if (typeof(parent) == 'object' && parent.tagName)
				nodeName = parent.tagName;
		}

		function clean(nodeName) {
			var temp = self._loki.document.createElement(nodeName);
			temp.innerHTML = html;

			UI.Clean.clean(temp, self._loki.settings);
			self._loki.massage_node_descendants(temp);
			return temp.innerHTML;
		}

		var cleanedHTML;
		try {
			cleanedHTML = clean(nodeName);
		} catch (e) {
			if (nodeName != 'DIV')
				cleanedHTML = clean('DIV');
			else
				throw e;
		}

		// Actually paste HTML
		rng.pasteHTML(cleanedHTML);
		rng.select();
	};
};

UI.Clipboard_Helper._gecko = (typeof(Components) == 'object');

// We need to create this iframe as a place to put code that
// Gecko needs to run with special privileges, for which
// privileges Gecko requires that the code be signed.
// (But we don't want to sign _all_ of Loki, because the page
// that invokes the javascript has to be signed with the
// javascript, and we want to be able to use Loki on dynamic
// pages; sigining dynamic pages would be too inconvenient, not
// to mention slow.)
// We create this here, on the assumption that it will have
// loaded by the time we need it.
//
// For more information about how to sign scripts, see
// privileged/HOWTO

/** @ignore */
UI.Clipboard_Helper._setup_done = false

/** @ignore */
UI.Clipboard_Helper._setup = function setup_clipboard_helper() {
	var base_uri = (arguments[0]
	 	? Util.URI.build(Util.URI.normalize(arguments[0]))
		: null);
	var helper_src = null;

	if (UI.Clipboard_Helper._setup_done)
		return;

	function watch_onload(func)
	{
		if (typeof(Loki) == "object" && Loki.is_document_ready()) {
			func();
			return;
		}

		if (document.addEventListener) {
			document.addEventListener('DOMContentLoaded', func, false);
			window.addEventListener('load', func, false);
		} else if (window.attachEvent) {
			window.attachEvent('onload', func);
		} else {
			window.onload = func;
		}
	}

	function create_hidden_iframe(src)
	{
		var called = false;
		var frame = Util.Document.create_element(document, 'iframe',
		{
			src: src,
			style: {
				position: 'absolute',
				box: [-500, -500, 2]
			}
		});

		function append_helper_iframe()
		{
			if (called)
				return;
			called = true;

			var body = (document.getElementsByTagName('BODY')[0] ||
				document.documentElement);
			body.appendChild(frame);
		}

		watch_onload(append_helper_iframe);

		return frame;
	}

	function make_uri(path)
	{
		if (base_uri.charAt(base_uri.length - 1) == '/')
			return base_uri + path;
		else
			return [base_uri, path].join('/');
	}

	if (UI.Clipboard_Helper._gecko) {
		// Gecko
		if (typeof(_gecko_clipboard_helper_src) == 'string') {
			// PHP helper is providing this for us.
			helper_src = _gecko_clipboard_helper_src;
		} else if (base_uri) {
			helper_src = 'jar:' +
				make_uri('auxil/privileged.jar!/gecko_clipboard.html');
		} else {
			return;
		}

		create_hidden_iframe(helper_src);
	} else {
		// everyone else
		if (typeof(UI__Clipboard_Helper_Editable_Iframe__src) == 'string') {
			// PHP helper is providing this for us.
			helper_src = UI__Clipboard_Helper_Editable_Iframe__src;
		} else if (base_uri) {
			helper_src = make_uri('auxil/loki_blank.html');
		} else {
			return;
		}
		UI.Clipboard_Helper_Editable_Iframe = create_hidden_iframe(helper_src);
	}

	UI.Clipboard_Helper._setup_done = true;
}

UI.Clipboard_Helper._setup();<|endoftext|>


<commit_before>/* global google */
import _ from "lodash";

import {
  default as React,
  Component,
} from "react";

import Helmet from "react-helmet";

import {
  withGoogleMap,
  GoogleMap,
  Marker,
} from "../../lib";

/*
 * This is the modify version of:
 * https://developers.google.com/maps/documentation/javascript/examples/event-arguments
 *
 * Add  to your HTML to provide google.maps reference
 */
const GettingStartedGoogleMap = withGoogleMap(props => (
  <GoogleMap
    ref={props.onMapLoad}
    defaultZoom={3}
    defaultCenter={{ lat: -25.363882, lng: 131.044922 }}
    onClick={props.onMapClick}
  >
    {props.markers.map(marker => (
      <Marker
        {...marker}
        onRightClick={() => props.onMarkerRightClick(marker)}
      />
    ))}
  </GoogleMap>
));

export default class GettingStartedExample extends Component {

  state = {
    markers: [{
      position: {
        lat: 25.0112183,
        lng: 121.52067570000001,
      },
      key: `Taiwan`,
      defaultAnimation: 2,
    }],
  };

  handleMapLoad = this.handleMapLoad.bind(this);
  handleMapClick = this.handleMapClick.bind(this);
  handleMarkerRightClick = this.handleMarkerRightClick.bind(this);

  handleMapLoad(map) {
    this._mapComponent = map;
    if (map) {
      console.log(map.getZoom());
    }
  }

  /*
   * This is called when you click on the map.
   * Go and try click now.
   */
  handleMapClick(event) {
    const nextMarkers = [
      ...this.state.markers,
      {
        position: event.latLng,
        defaultAnimation: 2,
        key: Date.now(), // Add a key property for: http://fb.me/react-warning-keys
      },
    ];
    this.setState({
      markers: nextMarkers,
    });

    if (nextMarkers.length === 3) {
      this.props.toast(
        `Right click on the marker to remove it`,
        `Also check the code!`
      );
    }
  }

  handleMarkerRightClick(targetMarker) {
    /*
     * All you modify is data, and the view is driven by data.
     * This is so called data-driven-development. (And yes, it's now in
     * web front end and even with google maps API.)
     */
    const nextMarkers = this.state.markers.filter(marker => marker !== targetMarker);
    this.setState({
      markers: nextMarkers,
    });
  }

  render() {
    return (
      <div style={{height: `100%`}}>
        <Helmet
          title="Getting Started"
        />
        <GettingStartedGoogleMap
          containerElement={
            <div style={{ height: `100%` }} />
          }
          mapElement={
            <div style={{ height: `100%` }} />
          }
          onMapLoad={this.handleMapLoad}
          onMapClick={this.handleMapClick}
          markers={this.state.markers}
          onMarkerRightClick={this.handleMarkerRightClick}
        />

    );
  }
}
<commit_msg>change center possition, make map component smaller<commit_after>/* global google */
import _ from "lodash";

import {
  default as React,
  Component,
} from "react";

import Helmet from "react-helmet";

import {
  withGoogleMap,
  GoogleMap,
  Marker,
} from "../../lib";

/*
 * This is the modify version of:
 * https://developers.google.com/maps/documentation/javascript/examples/event-arguments
 *
 * Add  to your HTML to provide google.maps reference
 */
const GettingStartedGoogleMap = withGoogleMap(props => (
  <GoogleMap
    ref={props.onMapLoad}
    defaultZoom={13}
    defaultCenter={{ lat: 28.144107, lng: -15.431281 }}
    onClick={props.onMapClick}
  >
    {props.markers.map(marker => (
      <Marker
        {...marker}
        onRightClick={() => props.onMarkerRightClick(marker)}
      />
    ))}
  </GoogleMap>
));

export default class GettingStartedExample extends Component {

  state = {
    markers: [{
      position: {
        lat: 25.0112183,
        lng: 121.52067570000001,
      },
      key: `Taiwan`,
      defaultAnimation: 2,
    }],
  };

  handleMapLoad = this.handleMapLoad.bind(this);
  handleMapClick = this.handleMapClick.bind(this);
  handleMarkerRightClick = this.handleMarkerRightClick.bind(this);

  handleMapLoad(map) {
    this._mapComponent = map;
    if (map) {
      console.log(map.getZoom());
    }
  }

  /*
   * This is called when you click on the map.
   * Go and try click now.
   */
  handleMapClick(event) {
    const nextMarkers = [
      ...this.state.markers,
      {
        position: event.latLng,
        defaultAnimation: 2,
        key: Date.now(), // Add a key property for: http://fb.me/react-warning-keys
      },
    ];
    this.setState({
      markers: nextMarkers,
    });

    if (nextMarkers.length === 3) {
      this.props.toast(
        `Right click on the marker to remove it`,
        `Also check the code!`
      );
    }
  }

  handleMarkerRightClick(targetMarker) {
    /*
     * All you modify is data, and the view is driven by data.
     * This is so called data-driven-development. (And yes, it's now in
     * web front end and even with google maps API.)
     */
    const nextMarkers = this.state.markers.filter(marker => marker !== targetMarker);
    this.setState({
      markers: nextMarkers,
    });
  }

  render() {
    return (
      <div style={{height: `100%`}}>
        <Helmet
          title="Getting Started"
        />
        <GettingStartedGoogleMap
          containerElement={
            <div style={{ height: `80%` }} />
          }
          mapElement={
            <div style={{ height: `100%` }} />
          }
          onMapLoad={this.handleMapLoad}
          onMapClick={this.handleMapClick}
          markers={this.state.markers}
          onMarkerRightClick={this.handleMarkerRightClick}
        />

    );
  }
}
<|endoftext|>


<commit_before>(function() {
  var accordionComponent = Object.create(HTMLElement.prototype);

  Object.defineProperty(accordionComponent, 'open', {
    value: '',
    writable: true
  });

  Object.defineProperty(accordionComponent, 'title', {
    value: '',
    writable: true
  });

  var css = `
    .title {
      color: white;
    }

    .content {
      display: none;
    }
  `;

  accordionComponent.createdCallback = function() {
    var shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML =`<style>${css}</style>`;

    this.titleElement = document.createElement('div');
    this.titleElement.className = 'title';
    this.titleElement.innerHTML = this.getAttribute('title');
    shadowRoot.appendChild(this.titleElement);

    this.contentElement = document.createElement('div');
    this.contentElement.className = 'content';
    shadowRoot.appendChild(this.contentElement);
  };

  accordionComponent.attachedCallback = function() {
    this.contentElement.innerHTML = this.innerHTML;
    this.innerHTML = null;
    this.addEventListener('click', function() {
      this.toggle();
    });
  };

  accordionComponent.attributeChangedCallback = function(attributeName, oldValue, newValue) {
    switch (attributeName) {
      case 'open':
        newValue;
        break;
      case 'title':
        newValue;
        break;
    }
  };

  accordionComponent.toggle = function() {
    if (this.getAttribute('open') != null) {
      this.removeAttribute('open');
      this.close();
    } else {
      this.setAttribute('open', '');
      this.open();
    }
  }

  accordionComponent.open = function() {
    this.shadowRoot.querySelector('.content').style.display = 'block';
  }

  accordionComponent.close = function() {
    this.shadowRoot.querySelector('.content').style.display = 'none';
  }

  document.registerElement('accordion-component', {prototype: accordionComponent});
}());
<commit_msg>Simple accordion component.<commit_after>(function() {
  var accordionComponent = Object.create(HTMLElement.prototype);

  Object.defineProperty(accordionComponent, 'open', {
    value: '',
    writable: true
  });

  Object.defineProperty(accordionComponent, 'title', {
    value: '',
    writable: true
  });

  var content;

  accordionComponent.createdCallback = function() {
    content = this.innerHTML;
    this.innerHTML = null;

    this.titleElement = document.createElement('div');
    this.titleElement.className = 'accordion-component-title';
    this.titleElement.innerHTML = this.getAttribute('title');
    this.appendChild(this.titleElement);

    this.contentElement = document.createElement('div');
    this.contentElement.className = 'content';
    this.appendChild(this.contentElement);
  };

  accordionComponent.attachedCallback = function() {
    this.contentElement.innerHTML = content;
    this.contentElement.style.display = 'none';
    this.addEventListener('click', function() {
      this.toggle();
    });
  };

  accordionComponent.attributeChangedCallback = function(attributeName, oldValue, newValue) {
    switch (attributeName) {
      case 'open':
        newValue;
        break;
      case 'title':
        newValue;
        break;
    }
  };

  accordionComponent.toggle = function() {
    if (this.getAttribute('open') != null) {
      this.removeAttribute('open');
      this.close();
    } else {
      this.setAttribute('open', '');
      this.open();
    }
  }

  accordionComponent.open = function() {
    this.querySelector('.content').style.display = 'block';
  }

  accordionComponent.close = function() {
    this.querySelector('.content').style.display = 'none';
  }

  document.registerElement('accordion-component', {prototype: accordionComponent});
}());
<|endoftext|>


<commit_before>const {BrowserWindow} = require('electron')
const EventEmitter = require('events')
const settingStore = require('../stores/settingStore')
const appStorage = require('../storage/appStorage')
const path = require('path')

class WMailWindow extends EventEmitter {

  /* ****************************************************************************/
  // Lifecycle
  /* ****************************************************************************/

  /**
  * @param analytics: the analytics object
  * @param options: object containing the following
  *                   @param screenLocationNS: the namespace to save the window state under. If not set, will not persist
  */
  constructor (analytics, options) {
    super()
    this.analytics = analytics
    this.window = null
    this.windowScreenLocationSaver = null
    this.options = Object.freeze(Object.assign({}, options))
  }

  /**
  * Starts the app
  * @param url: the start url
  */
  start (url) {
    this.createWindow(this.defaultWindowPreferences(), url)
  }

  /* ****************************************************************************/
  // Creation & Closing
  /* ****************************************************************************/

  /**
  * The default window preferences
  * @return the settings
  */
  defaultWindowPreferences () {
    return {
      title: 'WMail',
      icon: path.join(__dirname, '/../../../icons/app.png')
    }
  }

  /**
  * Creates and launches the window
  * @param settings: the settings to salt the window with
  * @param url: the start url
  */
  createWindow (settings, url) {
    const screenLocation = this.loadWindowScreenLocation()

    // Load up the window location & last state
    this.window = new BrowserWindow(Object.assign(settings, screenLocation))
    if (screenLocation.maximized) {
      this.window.maximize()
    }
    if (this.options.screenLocationNS) {
      this.window.on('resize', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('move', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('maximize', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('unmaximize', (evt) => { this.saveWindowScreenLocation() })
    }
    this[settingStore.ui.showAppMenu ? 'showAppMenu' : 'hideAppMenu']()

    // Bind to change events
    this.window.on('close', (evt) => { this.emit('close', evt) })
    settingStore.on('changed', this.updateWindowMenubar, this)
    this.window.on('closed', (evt) => this.destroyWindow(evt))

    // Fire the whole thing off
    this.window.loadURL(url)
  }

  /**
  * Destroys the window
  * @param evt: the event that caused destroy
  */
  destroyWindow (evt) {
    settingStore.off('changed', this.updateWindowMenubar)

    this.window = null
    this.emit('closed', evt)
  }

  /* ****************************************************************************/
  // Window state
  /* ****************************************************************************/

  /**
  * Saves the window state to disk
  */
  saveWindowScreenLocation () {
    clearTimeout(this.windowScreenLocationSaver)
    this.windowScreenLocationSaver = setTimeout(() => {
      const state = {
        fullscreen: this.window.isFullScreen(),
        maximized: this.window.isMaximized()
      }
      if (!this.window.isMaximized() && !this.window.isMinimized()) {
        const position = this.window.getPosition()
        const size = this.window.getSize()
        state.x = position[0]
        state.y = position[1]
        state.width = size[0]
        state.height = size[1]
      }

      appStorage.setJSONItem(this.options.screenLocationNS, state)
    }, 2000)
  }

  /**
  * Loads the window state
  * @return the state
  */
  loadWindowScreenLocation () {
    if (this.options.screenLocationNS) {
      return appStorage.getJSONItem(this.options.screenLocationNS, {})
    }

    return {}
  }

  /**
  * Updates the menubar
  */
  updateWindowMenubar (prev, next) {
    this[settingStore.ui.hasAppMenu ? 'showAppMenu' : 'hideAppMenu']()
  }

  /* ****************************************************************************/
  // Actions
  /* ****************************************************************************/

  /**
  * Closes the window respecting any behaviour modifiers that are set
  */
  close () {
    this.window.close()
  }

  /**
  * Shows the window
  */
  show () {
    this.window.show()
  }

  /**
  * Hides the window
  */
  hide () {
    this.window.hide()
  }

  /**
  * Focuses a window
  */
  focus () {
    this.window.focus()
  }

  /**
  * Toggles fullscreen mode
  */
  toggleFullscreen () {
    if (this.window.isFullScreenable()) {
      this.window.setFullScreen(!this.window.isFullScreen())
    } else {
      this.window.maximize(!this.window.isMaximized())
    }
  }

  /**
  * Reloads the webview
  */
  reload () {
    this.window.webContents.reload()
  }

  /**
  * Opens dev tools for this window
  */
  openDevTools () {
    this.window.webContents.openDevTools()
  }

	/**
	* Show the app menu
	*/
  showAppMenu () {
    this.window.setMenuBarVisibility(true)
  }

  /**
  * Hide the app menu
  */
  hideAppMenu () {
    this.window.setMenuBarVisibility(false)
  }

  /**
  * @return true if the window is focused
  */
  isFocused () {
    return this.window.isFocused()
  }

  /**
  * @return true if the window is visible
  */
  isVisible () {
    return this.window.isVisible()
  }

  /**
  * Sets the download progress
  * @param v: the download progress to set
  */
  setProgressBar (v) {
    this.window.setProgressBar(v)
  }
}

module.exports = WMailWindow
<commit_msg>Linux and windows fix for app bar disappearing all the time<commit_after>const {BrowserWindow} = require('electron')
const EventEmitter = require('events')
const settingStore = require('../stores/settingStore')
const appStorage = require('../storage/appStorage')
const path = require('path')

class WMailWindow extends EventEmitter {

  /* ****************************************************************************/
  // Lifecycle
  /* ****************************************************************************/

  /**
  * @param analytics: the analytics object
  * @param options: object containing the following
  *                   @param screenLocationNS: the namespace to save the window state under. If not set, will not persist
  */
  constructor (analytics, options) {
    super()
    this.analytics = analytics
    this.window = null
    this.windowScreenLocationSaver = null
    this.options = Object.freeze(Object.assign({}, options))
  }

  /**
  * Starts the app
  * @param url: the start url
  */
  start (url) {
    this.createWindow(this.defaultWindowPreferences(), url)
  }

  /* ****************************************************************************/
  // Creation & Closing
  /* ****************************************************************************/

  /**
  * The default window preferences
  * @return the settings
  */
  defaultWindowPreferences () {
    return {
      title: 'WMail',
      icon: path.join(__dirname, '/../../../icons/app.png')
    }
  }

  /**
  * Creates and launches the window
  * @param settings: the settings to salt the window with
  * @param url: the start url
  */
  createWindow (settings, url) {
    const screenLocation = this.loadWindowScreenLocation()

    // Load up the window location & last state
    this.window = new BrowserWindow(Object.assign(settings, screenLocation))
    if (screenLocation.maximized) {
      this.window.maximize()
    }
    if (this.options.screenLocationNS) {
      this.window.on('resize', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('move', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('maximize', (evt) => { this.saveWindowScreenLocation() })
      this.window.on('unmaximize', (evt) => { this.saveWindowScreenLocation() })
    }
    this[settingStore.ui.showAppMenu ? 'showAppMenu' : 'hideAppMenu']()

    // Bind to change events
    this.window.on('close', (evt) => { this.emit('close', evt) })
    settingStore.on('changed', this.updateWindowMenubar, this)
    this.window.on('closed', (evt) => this.destroyWindow(evt))

    // Fire the whole thing off
    this.window.loadURL(url)
  }

  /**
  * Destroys the window
  * @param evt: the event that caused destroy
  */
  destroyWindow (evt) {
    settingStore.off('changed', this.updateWindowMenubar)

    this.window = null
    this.emit('closed', evt)
  }

  /* ****************************************************************************/
  // Window state
  /* ****************************************************************************/

  /**
  * Saves the window state to disk
  */
  saveWindowScreenLocation () {
    clearTimeout(this.windowScreenLocationSaver)
    this.windowScreenLocationSaver = setTimeout(() => {
      const state = {
        fullscreen: this.window.isFullScreen(),
        maximized: this.window.isMaximized()
      }
      if (!this.window.isMaximized() && !this.window.isMinimized()) {
        const position = this.window.getPosition()
        const size = this.window.getSize()
        state.x = position[0]
        state.y = position[1]
        state.width = size[0]
        state.height = size[1]
      }

      appStorage.setJSONItem(this.options.screenLocationNS, state)
    }, 2000)
  }

  /**
  * Loads the window state
  * @return the state
  */
  loadWindowScreenLocation () {
    if (this.options.screenLocationNS) {
      return appStorage.getJSONItem(this.options.screenLocationNS, {})
    }

    return {}
  }

  /**
  * Updates the menubar
  */
  updateWindowMenubar (prev, next) {
    this[settingStore.ui.showAppMenu ? 'showAppMenu' : 'hideAppMenu']()
  }

  /* ****************************************************************************/
  // Actions
  /* ****************************************************************************/

  /**
  * Closes the window respecting any behaviour modifiers that are set
  */
  close () {
    this.window.close()
  }

  /**
  * Shows the window
  */
  show () {
    this.window.show()
  }

  /**
  * Hides the window
  */
  hide () {
    this.window.hide()
  }

  /**
  * Focuses a window
  */
  focus () {
    this.window.focus()
  }

  /**
  * Toggles fullscreen mode
  */
  toggleFullscreen () {
    if (this.window.isFullScreenable()) {
      this.window.setFullScreen(!this.window.isFullScreen())
    } else {
      this.window.maximize(!this.window.isMaximized())
    }
  }

  /**
  * Reloads the webview
  */
  reload () {
    this.window.webContents.reload()
  }

  /**
  * Opens dev tools for this window
  */
  openDevTools () {
    this.window.webContents.openDevTools()
  }

	/**
	* Show the app menu
	*/
  showAppMenu () {
    this.window.setMenuBarVisibility(true)
  }

  /**
  * Hide the app menu
  */
  hideAppMenu () {
    this.window.setMenuBarVisibility(false)
  }

  /**
  * @return true if the window is focused
  */
  isFocused () {
    return this.window.isFocused()
  }

  /**
  * @return true if the window is visible
  */
  isVisible () {
    return this.window.isVisible()
  }

  /**
  * Sets the download progress
  * @param v: the download progress to set
  */
  setProgressBar (v) {
    this.window.setProgressBar(v)
  }
}

module.exports = WMailWindow
<|endoftext|>


<commit_before>function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AdminPage");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserTitle");}, gvm);

    gvm.userName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserName");}, gvm);
    gvm.firstName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Firstname");}, gvm);
    gvm.lastName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Lastname");}, gvm);
    gvm.userStatus = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserStatus");}, gvm);
    gvm.userActions = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserActions");}, gvm);

    fetchUsersData();

    gvm.users = ko.observableArray([]);

    gvm.updateUsers = function(user)
    {
        gvm.users.push(user);
        console.log(user);
    }
}

function fetchUsersData()
{
    $.getJSON("/api/allusers/", function(data)
    {
        $.each(data, function(i, item){
            console.log(item.userName);
            viewModel.updateUsers(new User(item.id, item.userName, item.firstname, item.lastname, item.status));
        });
    });
}

function User(viewmodel, id, username, firstname, lastname, status) {
    return {
        id: ko.observable(id),
        userMail: ko.observable(username),
        firstname: ko.observable(firstname),
        lastname: ko.observable(lastname),
        status: ko.observable(status)
    };
}<commit_msg>Admin page: get All users<commit_after>function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AdminPage");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserTitle");}, gvm);

    gvm.userName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserName");}, gvm);
    gvm.firstName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Firstname");}, gvm);
    gvm.lastName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Lastname");}, gvm);
    gvm.userStatus = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserStatus");}, gvm);
    gvm.userActions = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("UserActions");}, gvm);

    fetchUsersData();

    gvm.users = ko.observableArray([]);

    gvm.updateUsers = function(user)
    {
        gvm.users.push(user);
        console.log(user);
    }
}

function fetchUsersData()
{
    $.getJSON("/api/allusers/", function(data)
    {
        $.each(data, function(i, item){
            console.log(item);
            viewModel.updateUsers(new User(item.id, item.username, item.firstname, item.lastname, item.status));
        });
    });
}

function User(viewmodel, id, username, firstname, lastname, status) {
    return {
        id: ko.observable(id),
        userMail: ko.observable(username),
        firstname: ko.observable(firstname),
        lastname: ko.observable(lastname),
        status: ko.observable(status)
    };
}<|endoftext|>


<commit_before>define(['jquery', 'underscore'], function ($, _) {

  var Utility = {
    DOM:{},
    Templates:{}
  };

  Utility.DOM.serializeObject = function (el) {
    var o = {};
    var a = $(el).serializeArray();
    $.each(a, function () {
      if (o[this.name] !== undefined) {
        if (!o[this.name].push) {
          o[this.name] = [o[this.name]];
        }
        o[this.name].push(this.value || '');
      } else {
        o[this.name] = this.value || '';
      }
    });
    return o;
  };

  Utility.Templates.TABLE_STRUCTURE = '
' +
      '
' +
      '<% _.each(columns, function(c){ %>' +
      '<th class="<%= c.value %>"><%= c.name %>	' +
      '<% }); %>' +
      '
' +
      '
' +
      '

';

  Utility.Templates.FORM_STRUCTURE = '<form action="<%= action %>" method="<%= method %>" class="<%= formClass %>"><fieldset>' +
      '<% if(legend){ %>' +
      '<legend><%= legend %></legend>' +
      '<% } %>' +
      '<% _.each(fields, function(field){ %>' +
      '<% if(field.type != "hidden"){ %>' +
      '<div class="control-group <%= field.outerClass %>">' +
      '<label class="control-label" for="<%= field.idPrefix %>-<%= recordId %>-<%= field.name%>"><%= field.humanName %>' +
      '<div class="controls <%= field.inputOuterClass %>">' +

      '<% if(field.type == "text") { %>' +
      '<input class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" value="<%= field.value %>" name="<%= field.name %>" size="<%= field.size %>" type="<%= field.type %>"/> ' +
      '<% } else if (field.type == "textarea") { %>' +
      '<textarea class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" rows="<%= field.rows %>" name="<%= field.name %>"><%= field.value %></textarea>' +
      '<% } %>' +

      '' +

      '
' +
      '
' +
      '<% } else { %>' +
      '<input class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" value="<%= field.value %>" name="<%= field.name %>" size="<%= field.size %>" type="<%= field.type %>" /> ' +
      '<% } %>' + // End the if type=='hidden'
      '<% }); %>'  +

      '
' +
      '<% _.each(buttons, function(button){ %>' +
      '<% if(button.type == "link"){ %>' +
      '<a class="btn <%= button.class %>" href="<%= button.href %>"><%= button.humanName %> ' +
      '<% } else { %>' +
      '<button class="btn <%= button.class %>" type="<%= button.type %>"><%= button.humanName %></button> ' +
      '<% }}); %>' +
      '
' +
      '</fieldset></form>';

  /**
   * Renders an underscore.js template with the provided structure data.
   * The default template is the Utility.Templates.TABLE_STRUCTURE.
   *
   * structureData example:
   * { columns: [{name: 'ID', value: 'id'},{name: 'Name', value: 'name'}] }
   *
   * @param structureData
   * @param template
   */
  Utility.Templates.renderTableStructure = function (structureData, template) {

    if (!template){
      template = Utility.Templates.TABLE_STRUCTURE;
    }

    return _.template(template, structureData);

  };

  /**
   * Renders a standard form layout given the form structure provided.
   *
   * Here is an example of a valid form structure:
   * var formStructure = {
       action: '#/prescriptions/new',
       method: 'POST',
       recordId: this.model.get('id'),
       class: 'form-horizontal',
       fields: [
         {
           idPrefix: 'field-type',
           name: 'id',
           humanName: 'Id',
           outerClass: '',
           inputOuterClass: '',
           value: this.model.get('id'),
           type: 'hidden'
         },
         {
           name: 'name',
           humanName: 'Name',
           value: this.model.get('name'),
           type: 'text'
         }
       ],
       buttons: [
         {'class': 'btn-primary', type: 'submit', humanName: 'Submit'},
         {type: 'reset', humanName: 'Reset'}
       ]
     };
   *
   * @param formStructure
   * @param template
   */
  Utility.Templates.renderForm = function(formStructure, template){

    if (!template){
      template = Utility.Templates.FORM_STRUCTURE;
    }

    // Prep the defaults for the form structure
    _.defaults(formStructure, {
      action: '',
      formClass: 'form-horizontal',
      method: 'POST',
      recordId: new Date().getTime(),
      legend: false,
      fields: [],
      buttons: []
    });

    _.each(formStructure.fields, function(field){
      _.defaults(field, {
        idPrefix: 'field-' + new Date().getTime(),
        outerClass: '',
        name: '',
        humanName: '',
        inputOuterClass: '',
        value: '',
        inputClass: '',
        type: 'text'
      });

      if (field.type == 'text' && !field.size){
        field.size = 30;
      } else if (field.type == 'textarea' && !field.rows){
        field.rows = 4;
      }
    });

    _.each(formStructure.buttons, function(button){
      _.defaults(button, {
        'class': '',
        type: 'button',
        humanName: 'Button'
      });
    });

    // Sort the fields according to their types so that the hidden ones are at the end
    formStructure.fields = _.sortBy(formStructure.fields, function(f){ return f.type == 'hidden' ? 2 : 1 });

    return _.template(template, formStructure);

  };

  return Utility;
});<commit_msg>Adding a utility method to scaffold a form based on a JSON object<commit_after>define(['jquery', 'underscore'], function ($, _) {

  var Utility = {
    DOM:{},
    String:{},
    Templates:{}
  };

  Utility.DOM.serializeObject = function (el) {
    var o = {};
    var a = $(el).serializeArray();
    $.each(a, function () {
      if (o[this.name] !== undefined) {
        if (!o[this.name].push) {
          o[this.name] = [o[this.name]];
        }
        o[this.name].push(this.value || '');
      } else {
        o[this.name] = this.value || '';
      }
    });
    return o;
  };

  Utility.Templates.TABLE_STRUCTURE = '
' +
          '
' +
          '<% _.each(columns, function(c){ %>' +
          '<th class="<%= c.value %>"><%= c.name %>	' +
          '<% }); %>' +
          '
' +
          '
' +
          '

';

  Utility.Templates.FORM_STRUCTURE = '<form action="<%= action %>" method="<%= method %>" class="<%= formClass %>"><fieldset>' +
          '<% if(legend){ %>' +
          '<legend><%= legend %></legend>' +
          '<% } %>' +
          '<% _.each(fields, function(field){ %>' +
          '<% if(field.type != "hidden"){ %>' +
          '<div class="control-group <%= field.outerClass %>">' +
          '<label class="control-label" for="<%= field.idPrefix %>-<%= recordId %>-<%= field.name%>"><%= field.humanName %>' +
          '<div class="controls <%= field.inputOuterClass %>">' +

          '<% if(field.type == "text") { %>' +
          '<input class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" value="<%= field.value %>" name="<%= field.name %>" size="<%= field.size %>" type="<%= field.type %>"/> ' +
          '<% } else if (field.type == "textarea") { %>' +
          '<textarea class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" rows="<%= field.rows %>" name="<%= field.name %>"><%= field.value %></textarea>' +
          '<% } %>' +

          '' +

          '
' +
          '
' +
          '<% } else { %>' +
          '<input class="<%= field.inputClass %>" id="<%= field.idPrefix %>-<%= recordId %>-<%= field.name %>" value="<%= field.value %>" name="<%= field.name %>" size="<%= field.size %>" type="<%= field.type %>" /> ' +
          '<% } %>' + // End the if type=='hidden'
          '<% }); %>' +

          '
' +
          '<% _.each(buttons, function(button){ %>' +
          '<% if(button.type == "link"){ %>' +
          '<a class="btn <%= button.class %>" href="<%= button.href %>"><%= button.humanName %> ' +
          '<% } else { %>' +
          '<button class="btn <%= button.class %>" type="<%= button.type %>"><%= button.humanName %></button> ' +
          '<% }}); %>' +
          '
' +
          '</fieldset></form>';

  /**
   * Renders an underscore.js template with the provided structure data.
   * The default template is the Utility.Templates.TABLE_STRUCTURE.
   *
   * structureData example:
   * { columns: [{name: 'ID', value: 'id'},{name: 'Name', value: 'name'}] }
   *
   * @param structureData
   * @param template
   */
  Utility.Templates.renderTableStructure = function (structureData, template) {

    if (!template) {
      template = Utility.Templates.TABLE_STRUCTURE;
    }

    return _.template(template, structureData);

  };

  /**
   * Renders a standard form layout given the form structure provided.
   *
   * The field's type can be one of:
   * - hidden
   * - text
   * - textarea
   *
   * Here is an example of a valid form structure:
   * var formStructure = {
   action: '#/prescriptions/new',
   method: 'POST',
   recordId: this.model.get('id'),
   class: 'form-horizontal',
   fields: [
   {
   idPrefix: 'field-type',
   name: 'id',
   humanName: 'Id',
   outerClass: '',
   inputOuterClass: '',
   value: this.model.get('id'),
   type: 'hidden'
   },
   {
   name: 'name',
   humanName: 'Name',
   value: this.model.get('name'),
   type: 'text'
   }
   ],
   buttons: [
   {'class': 'btn-primary', type: 'submit', humanName: 'Submit'},
   {type: 'reset', humanName: 'Reset'}
   ]
   };
   *
   * @param formStructure
   * @param template
   */
  Utility.Templates.renderForm = function (formStructure, template) {

    if (!template) {
      template = Utility.Templates.FORM_STRUCTURE;
    }

    // Prep the defaults for the form structure
    _.defaults(formStructure, {
      action:'',
      formClass:'form-horizontal',
      method:'POST',
      recordId:new Date().getTime(),
      legend:false,
      fields:[],
      buttons:[]
    });

    _.each(formStructure.fields, function (field) {
      _.defaults(field, {
        idPrefix:'field-' + new Date().getTime(),
        outerClass:'',
        name:'',
        humanName:'',
        inputOuterClass:'',
        value:'',
        inputClass:'',
        type:'text'
      });

      if (field.type == 'text' && !field.size) {
        field.size = 30;
      } else if (field.type == 'textarea' && !field.rows) {
        field.rows = 4;
      }
    });

    _.each(formStructure.buttons, function (button) {
      _.defaults(button, {
        'class':'',
        type:'button',
        humanName:'Button'
      });
    });

    // Sort the fields according to their types so that the hidden ones are at the end
    formStructure.fields = _.sortBy(formStructure.fields, function (f) {
      return f.type == 'hidden' ? 2 : 1
    });

    return _.template(template, formStructure);

  };

  Utility.Templates.buildFormStructureFromModel = function (jsonModel, formStructure, options) {

    var recordId = jsonModel._id || jsonModel.id;

    if (!options) {
      options = {};
    }
    _.defaults(options, {
      humanName:'document',
      capitalHumanName:'Document'
    });

    if (!formStructure) {
      formStructure = {};
    }
    _.defaults(formStructure, {
      action:'#',
      method:'POST',
      recordId:recordId,
      legend:(recordId ? ('Edit ' + options.humanName + ' ' + recordId) : 'New ' + options.humanName),
      fields:[],
      buttons:[]
    });

    for (var key in jsonModel) {
      var value = jsonModel[key];
      var type = false;

      if (_.isString(value) || _.isNumber(value) || !value) {
        type = 'text';
      } else if (_.isBoolean(value)) {
        type = 'checkbox';
      } else if (_.isDate(value)) {
        type = 'datetime';
      }

      if (type) {
        formStructure.fields.push({
          idPrefix:options.humanName,
          name:key,
          humanName:(key.charAt(0).toUpperCase() + key.substring(1)),
          outerClass:'',
          inputOuterClass:'',
          inputClass:'input-xlarge',
          value:value,
          type:type
        });
      } else {
        console.log('buildFormStructureFromModel: does not know how to handle type of "' + key + '" in jsonModel:', jsonModel);
      }
    }

    // Now add some buttons
    if (formStructure.buttons.length == 0) {
      formStructure.buttons.push({'class':'btn-primary', type:'submit', humanName:'Submit'});
      formStructure.buttons.push({type:'reset', humanName:'Reset'});
    }

    return formStructure;

  };

  return Utility;
});<|endoftext|>


<commit_before>'use strict';

const { ROUND_UP, ROUND_DOWN } = require ('./number')
const { NotSupported } = require ('./../errors')

//-------------------------------------------------------------------------
// converts timeframe to seconds
const parseTimeframe = (timeframe) => {

    const amount = timeframe.slice (0, -1)
    const unit = timeframe.slice (-1)
    let scale = undefined;

    if (unit === 'y') {
        scale = 60 * 60 * 24 * 365
    } else if (unit === 'M') {
        scale = 60 * 60 * 24 * 30
    } else if (unit === 'w') {
        scale = 60 * 60 * 24 * 7
    } else if (unit === 'd') {
        scale = 60 * 60 * 24
    } else if (unit === 'h') {
        scale = 60 * 60
    } else if (unit === 'm') {
        scale = 60
    } else if (unit === 's') {
        scale = 1
    } else {
        throw new NotSupported ('timeframe unit ' + unit + ' is not supported')
    }

    return amount * scale
}

const roundTimeframe = (timeframe, timestamp, direction = ROUND_DOWN) => {
    const ms = parseTimeframe (timeframe) * 1000
    // Get offset based on timeframe in milliseconds
    const offset = timestamp % ms
    return timestamp - offset + ((direction === ROUND_UP) ? ms : 0);
}

// given a sorted arrays of trades (recent last) and a timeframe builds an array of OHLCV candles
const buildOHLCVC = (trades, timeframe = '1m', since = -Infinity, limit = Infinity) => {
    const ms = parseTimeframe (timeframe) * 1000;
    const ohlcvs = [];
    const [ timestamp, /* open */, high, low, close, volume, count ] = [ 0, 1, 2, 3, 4, 5, 6 ];
    const oldest = Math.min (trades.length - 1, limit);

    for (let i = 0; i <= oldest; i++) {
        const trade = trades[i];
        if (trade.timestamp < since)
            continue;
        const openingTime = Math.floor (trade.timestamp / ms) * ms; // shift to the edge of m/h/d (but not M)
        const candle = ohlcvs.length - 1;

        if (candle === -1 || openingTime >= ohlcvs[candle][timestamp] + ms) {
            // moved to a new timeframe -> create a new candle from opening trade
            ohlcvs.push ([
                openingTime,  // timestamp
                trade.price,  // O
                trade.price,  // H
                trade.price,  // L
                trade.price,  // C
                trade.amount, // V
                1,            // count
            ]);
        } else {
            // still processing the same timeframe -> update opening trade
            ohlcvs[candle][high] = Math.max (ohlcvs[candle][high], trade.price);
            ohlcvs[candle][low] = Math.min (ohlcvs[candle][low], trade.price);
            ohlcvs[candle][close] = trade.price;
            ohlcvs[candle][volume] += trade.amount;
            ohlcvs[candle][count]++;
        } // if
    } // for
    return ohlcvs;
}

const extractParams = (string) => {
    const re = /{([\w-]+)}/g
    const matches = []
    let match = re.exec (string)
    while (match) {
        matches.push (match[1])
        match = re.exec (string)
    }
    return matches
}

const implodeParams = (string, params) => {
    if (!Array.isArray (params)) {
        const keys = Object.keys (params)
        for (let i = 0; i < keys.length; i++) {
            const key = keys[i]
            if (!Array.isArray (params[key])) {
                string = string.replace ('{' + key + '}', params[key])
            }
        }
    }
    return string
}

/*  ------------------------------------------------------------------------ */

module.exports = {

    aggregate (bidasks) {

        const result = {}

        for (let i = 0; i < bidasks.length; i++) {
            const [ price, volume ] = bidasks[i];
            if (volume > 0) {
                result[price] = (result[price] || 0) + volume
            }
        }

        return Object.keys (result).map (price => [parseFloat (price), parseFloat (result[price])])
    },

    parseTimeframe,
    roundTimeframe,
    buildOHLCVC,
    ROUND_UP,
    ROUND_DOWN,

    implodeParams,
    extractParams
}

/*  ------------------------------------------------------------------------ */
<commit_msg>js/base/functions/misc.js linting<commit_after>'use strict';

const { ROUND_UP, ROUND_DOWN } = require ('./number')
const { NotSupported } = require ('../errors')

//-------------------------------------------------------------------------
// converts timeframe to seconds
const parseTimeframe = (timeframe) => {

    const amount = timeframe.slice (0, -1)
    const unit = timeframe.slice (-1)
    let scale = undefined;

    if (unit === 'y') {
        scale = 60 * 60 * 24 * 365
    } else if (unit === 'M') {
        scale = 60 * 60 * 24 * 30
    } else if (unit === 'w') {
        scale = 60 * 60 * 24 * 7
    } else if (unit === 'd') {
        scale = 60 * 60 * 24
    } else if (unit === 'h') {
        scale = 60 * 60
    } else if (unit === 'm') {
        scale = 60
    } else if (unit === 's') {
        scale = 1
    } else {
        throw new NotSupported ('timeframe unit ' + unit + ' is not supported')
    }

    return amount * scale
}

const roundTimeframe = (timeframe, timestamp, direction = ROUND_DOWN) => {
    const ms = parseTimeframe (timeframe) * 1000
    // Get offset based on timeframe in milliseconds
    const offset = timestamp % ms
    return timestamp - offset + ((direction === ROUND_UP) ? ms : 0);
}

// given a sorted arrays of trades (recent last) and a timeframe builds an array of OHLCV candles
const buildOHLCVC = (trades, timeframe = '1m', since = -Infinity, limit = Infinity) => {
    const ms = parseTimeframe (timeframe) * 1000;
    const ohlcvs = [];
    const [ timestamp, /* open */, high, low, close, volume, count ] = [ 0, 1, 2, 3, 4, 5, 6 ];
    const oldest = Math.min (trades.length - 1, limit);

    for (let i = 0; i <= oldest; i++) {
        const trade = trades[i];
        if (trade.timestamp < since) {
            continue;
        }
        const openingTime = Math.floor (trade.timestamp / ms) * ms; // shift to the edge of m/h/d (but not M)
        const candle = ohlcvs.length - 1;

        if (candle === -1 || openingTime >= ohlcvs[candle][timestamp] + ms) {
            // moved to a new timeframe -> create a new candle from opening trade
            ohlcvs.push ([
                openingTime,  // timestamp
                trade.price,  // O
                trade.price,  // H
                trade.price,  // L
                trade.price,  // C
                trade.amount, // V
                1,            // count
            ]);
        } else {
            // still processing the same timeframe -> update opening trade
            ohlcvs[candle][high] = Math.max (ohlcvs[candle][high], trade.price);
            ohlcvs[candle][low] = Math.min (ohlcvs[candle][low], trade.price);
            ohlcvs[candle][close] = trade.price;
            ohlcvs[candle][volume] += trade.amount;
            ohlcvs[candle][count]++;
        } // if
    } // for
    return ohlcvs;
}

const extractParams = (string) => {
    const re = /{([\w-]+)}/g
    const matches = []
    let match = re.exec (string)
    while (match) {
        matches.push (match[1])
        match = re.exec (string)
    }
    return matches
}

const implodeParams = (string, params) => {
    if (!Array.isArray (params)) {
        const keys = Object.keys (params)
        for (let i = 0; i < keys.length; i++) {
            const key = keys[i]
            if (!Array.isArray (params[key])) {
                string = string.replace ('{' + key + '}', params[key])
            }
        }
    }
    return string
}

/*  ------------------------------------------------------------------------ */

module.exports = {

    aggregate (bidasks) {

        const result = {}

        for (let i = 0; i < bidasks.length; i++) {
            const [ price, volume ] = bidasks[i];
            if (volume > 0) {
                result[price] = (result[price] || 0) + volume
            }
        }

        return Object.keys (result).map ((price) => [parseFloat (price), parseFloat (result[price])])
    },

    parseTimeframe,
    roundTimeframe,
    buildOHLCVC,
    ROUND_UP,
    ROUND_DOWN,

    implodeParams,
    extractParams
}

/*  ------------------------------------------------------------------------ */
<|endoftext|>


<commit_before>const router = require('express').Router()

const { ENTITIES } = require('../search/constants')
const { DEFAULT_COLLECTION_QUERY, LOCAL_NAV, APP_PERMISSIONS, QUERY_FIELDS, QUERY_DATE_FIELDS } = require('./constants')

const { getRequestBody } = require('../../middleware/collection')
const { detectUserAgent } = require('../../middleware/detect-useragent')
const { getCollection, exportCollection } = require('../../modules/search/middleware/collection')

const { setLocalNav, setDefaultQuery, redirectToFirstNavItem, handleRoutePermissions } = require('../middleware')
const { shared } = require('./middleware')
const {
  getBriefInvestmentSummary,
  expandTeamMembers,
} = require('./middleware/team')

const {
  create,
  archive,
  audit,
  details,
  documents,
  edit,
  evaluation,
  team,
} = require('./controllers')

const {
  clientRelationshipManagementFormMiddleware,
  detailsFormMiddleware,
  investmentTypeFormMiddleware,
  projectManagementFormMiddleware,
  projectStageFormMiddleware,
  requirementsFormMiddleware,
  valueFormMiddleware,
} = require('./middleware/forms')

const { renderInvestmentList } = require('./controllers/list')
const { renderPropositionList } = require('./controllers/propositions')
const { renderEvidenceView } = require('./controllers/evidence')
const { renderAddEvidence } = require('./apps/evidence/controllers/create')
const { postUpload } = require('../documents/middleware/upload')

const { setInteractionsDetails, setCompanyDetails } = require('./middleware/interactions')
const { setPropositionsReturnUrl } = require('./middleware/propositions')
const { setEvidenceReturnUrl, setEvidenceDocumentsOptions, getDownloadLink, deleteEvidence } = require('./middleware/evidence')

const { renderTeamEdit } = require('./controllers/team/edit-team-members')
const { populateTeamEditForm, postTeamEdit } = require('./middleware/forms/team-members')

const {
  renderStatusPage,
  postStatus,
} = require('./controllers/status')

const {
  selectUKCompany,
  searchForUKCompany,
  renderCompanyResults,
  removeUKCompany,
} = require('./controllers/ukcompany')

const {
  selectAssociatedInvestmentProject,
  searchForAssociatedInvestmentProject,
  renderAssociatedInvestmentProjectResults,
  removeAssociatedInvestmentProject,
} = require('./controllers/associated')

const { transformInvestmentProjectToListItem } = require('./transformers')

const interactionsRouter = require('../interactions/router.sub-app')
const propositionsRouter = require('../propositions/router.sub-app')

router.use(handleRoutePermissions(APP_PERMISSIONS))

router.use('/:investmentId', setLocalNav(LOCAL_NAV))

router.param('investmentId', shared.getInvestmentDetails)
router.param('companyId', shared.getCompanyDetails)

router.get('/',
  detectUserAgent,
  setDefaultQuery(DEFAULT_COLLECTION_QUERY),
  getRequestBody(QUERY_FIELDS, QUERY_DATE_FIELDS),
  getCollection('investment_project', ENTITIES, transformInvestmentProjectToListItem),
  renderInvestmentList
)

router.get('/export',
  setDefaultQuery(DEFAULT_COLLECTION_QUERY),
  getRequestBody(QUERY_FIELDS),
  exportCollection('investment_project'),
)

router.post('/:investmentId/details', archive.archiveInvestmentProjectHandler, details.detailsGetHandler)
router.get('/:investmentId/unarchive', archive.unarchiveInvestmentProjectHandler)

router.get('/:investmentId/audit', audit.getInvestmentAudit)

router.get('/create/:companyId?', create.start.redirectHandler, create.start.renderCreatePage)

router.get('/create/investment-type/info', create.investmentType.renderInvestmentInfoPage)

router
  .route('/create/investment-type/:companyId')
  .get(investmentTypeFormMiddleware.populateForm, create.investmentType.renderInvestmentTypePage)
  .post(
    investmentTypeFormMiddleware.validateForm,
    create.investmentType.postHandler,
    investmentTypeFormMiddleware.populateForm,
    create.investmentType.renderInvestmentTypePage
  )

router
  .route('/create/equity-source/:companyId')
  .get(create.equitySource.getHandler, create.equitySource.renderEquitySourcePage)
  .post(
    create.equitySource.postHandler,
    create.equitySource.getHandler,
    create.equitySource.renderEquitySourcePage
  )

router
  .route('/create/project/:equityCompanyId')
  .get(
    detailsFormMiddleware.populateForm,
    create.project.getHandler,
    create.project.renderCreateProjectPage
  )
  .post(
    detailsFormMiddleware.populateForm,
    detailsFormMiddleware.handleFormPost,
    detailsFormMiddleware.validateForm,
    create.project.postHandler,
    create.project.getHandler,
    create.project.renderCreateProjectPage
  )

router.get('/:investmentId', redirectToFirstNavItem)
router.get('/:investmentId/details', details.detailsGetHandler)

router
  .route('/:investmentId/edit-details')
  .get(detailsFormMiddleware.populateForm, edit.editDetailsGet)
  .post(detailsFormMiddleware.populateForm, detailsFormMiddleware.handleFormPost, edit.editDetailsPost, edit.editDetailsGet)

router
  .route('/:investmentId/edit-value')
  .get(valueFormMiddleware.populateForm, edit.editValueGet)
  .post(valueFormMiddleware.populateForm, valueFormMiddleware.handleFormPost, edit.renderValueForm)

router
  .route('/:investmentId/edit-requirements')
  .get(requirementsFormMiddleware.populateForm, edit.renderRequirementsForm)
  .post(requirementsFormMiddleware.handleFormPost, requirementsFormMiddleware.populateForm, edit.renderRequirementsForm)

router.get('/:investmentId/team', expandTeamMembers, team.details.getDetailsHandler)

router
  .route('/:investmentId/edit-project-management')
  .get(getBriefInvestmentSummary, projectManagementFormMiddleware.populateForm, team.editProjectManagement.getHandler)
  .post(
    getBriefInvestmentSummary,
    projectManagementFormMiddleware.populateForm,
    projectManagementFormMiddleware.handleFormPost,
    team.editProjectManagement.postHandler,
    team.editProjectManagement.getHandler
  )

router
  .route('/:investmentId/edit-client-relationship-management')
  .get(
    clientRelationshipManagementFormMiddleware.populateForm,
    team.editClientRelationshipManagement.getHandler
  )
  .post(
    clientRelationshipManagementFormMiddleware.populateForm,
    clientRelationshipManagementFormMiddleware.handleFormPost,
    team.editClientRelationshipManagement.postHandler,
    team.editClientRelationshipManagement.getHandler
  )

router
  .route('/:investmentId/edit-team-members')
  .get(populateTeamEditForm, renderTeamEdit)
  .post(postTeamEdit, renderTeamEdit)

router.get('/:investmentId/propositions', setPropositionsReturnUrl, renderPropositionList)

router.get('/:investmentId/evaluation', evaluation.renderEvaluationPage)

router.get('/:investmentId/evidence', setEvidenceReturnUrl, renderEvidenceView)

router
  .route('/:investmentId/evidence/add-new')
  .get(
    setEvidenceReturnUrl,
    renderAddEvidence,
  )
  .post(
    setEvidenceReturnUrl,
    setEvidenceDocumentsOptions,
    postUpload,
  )

router
  .route('/:investmentId/evidence/:evidenceId/download')
  .get(
    getDownloadLink
  )

router
  .route('/:investmentId/evidence/:evidenceId/delete')
  .get(
    setEvidenceReturnUrl,
    deleteEvidence
  )

router.post('/:investmentId/change-project-stage', projectStageFormMiddleware.handleFormPost)

router.use('/:investmentId', setInteractionsDetails, setCompanyDetails, interactionsRouter)

router.use('/:investmentId', setPropositionsReturnUrl, propositionsRouter)

router
  .route('/:investmentId/status')
  .post(postStatus, renderStatusPage)
  .get(renderStatusPage)

router.get('/:investmentId/edit-ukcompany', selectUKCompany, searchForUKCompany, renderCompanyResults)
router.get('/:investmentId/remove-ukcompany', removeUKCompany)

// Todo - DH-1030
// Currently to associate the user you must click a link in the investment details page after
// indicating there is an association with a non-fdi r&d project
// Review the investment flow later to see if this can be improved.

router.get('/:investmentId/edit-associated',
  selectAssociatedInvestmentProject,
  searchForAssociatedInvestmentProject,
  renderAssociatedInvestmentProjectResults
)

router.get('/:investmentId/remove-associated', removeAssociatedInvestmentProject)

router.get('/:investmentId/documents', documents.renderDocuments)

module.exports = router
<commit_msg>Fix date filters should effect the number of projects exported<commit_after>const router = require('express').Router()

const { ENTITIES } = require('../search/constants')
const { DEFAULT_COLLECTION_QUERY, LOCAL_NAV, APP_PERMISSIONS, QUERY_FIELDS, QUERY_DATE_FIELDS } = require('./constants')

const { getRequestBody } = require('../../middleware/collection')
const { detectUserAgent } = require('../../middleware/detect-useragent')
const { getCollection, exportCollection } = require('../../modules/search/middleware/collection')

const { setLocalNav, setDefaultQuery, redirectToFirstNavItem, handleRoutePermissions } = require('../middleware')
const { shared } = require('./middleware')
const {
  getBriefInvestmentSummary,
  expandTeamMembers,
} = require('./middleware/team')

const {
  create,
  archive,
  audit,
  details,
  documents,
  edit,
  evaluation,
  team,
} = require('./controllers')

const {
  clientRelationshipManagementFormMiddleware,
  detailsFormMiddleware,
  investmentTypeFormMiddleware,
  projectManagementFormMiddleware,
  projectStageFormMiddleware,
  requirementsFormMiddleware,
  valueFormMiddleware,
} = require('./middleware/forms')

const { renderInvestmentList } = require('./controllers/list')
const { renderPropositionList } = require('./controllers/propositions')
const { renderEvidenceView } = require('./controllers/evidence')
const { renderAddEvidence } = require('./apps/evidence/controllers/create')
const { postUpload } = require('../documents/middleware/upload')

const { setInteractionsDetails, setCompanyDetails } = require('./middleware/interactions')
const { setPropositionsReturnUrl } = require('./middleware/propositions')
const { setEvidenceReturnUrl, setEvidenceDocumentsOptions, getDownloadLink, deleteEvidence } = require('./middleware/evidence')

const { renderTeamEdit } = require('./controllers/team/edit-team-members')
const { populateTeamEditForm, postTeamEdit } = require('./middleware/forms/team-members')

const {
  renderStatusPage,
  postStatus,
} = require('./controllers/status')

const {
  selectUKCompany,
  searchForUKCompany,
  renderCompanyResults,
  removeUKCompany,
} = require('./controllers/ukcompany')

const {
  selectAssociatedInvestmentProject,
  searchForAssociatedInvestmentProject,
  renderAssociatedInvestmentProjectResults,
  removeAssociatedInvestmentProject,
} = require('./controllers/associated')

const { transformInvestmentProjectToListItem } = require('./transformers')

const interactionsRouter = require('../interactions/router.sub-app')
const propositionsRouter = require('../propositions/router.sub-app')

router.use(handleRoutePermissions(APP_PERMISSIONS))

router.use('/:investmentId', setLocalNav(LOCAL_NAV))

router.param('investmentId', shared.getInvestmentDetails)
router.param('companyId', shared.getCompanyDetails)

router.get('/',
  detectUserAgent,
  setDefaultQuery(DEFAULT_COLLECTION_QUERY),
  getRequestBody(QUERY_FIELDS, QUERY_DATE_FIELDS),
  getCollection('investment_project', ENTITIES, transformInvestmentProjectToListItem),
  renderInvestmentList
)

router.get('/export',
  setDefaultQuery(DEFAULT_COLLECTION_QUERY),
  getRequestBody(QUERY_FIELDS, QUERY_DATE_FIELDS),
  exportCollection('investment_project'),
)

router.post('/:investmentId/details', archive.archiveInvestmentProjectHandler, details.detailsGetHandler)
router.get('/:investmentId/unarchive', archive.unarchiveInvestmentProjectHandler)

router.get('/:investmentId/audit', audit.getInvestmentAudit)

router.get('/create/:companyId?', create.start.redirectHandler, create.start.renderCreatePage)

router.get('/create/investment-type/info', create.investmentType.renderInvestmentInfoPage)

router
  .route('/create/investment-type/:companyId')
  .get(investmentTypeFormMiddleware.populateForm, create.investmentType.renderInvestmentTypePage)
  .post(
    investmentTypeFormMiddleware.validateForm,
    create.investmentType.postHandler,
    investmentTypeFormMiddleware.populateForm,
    create.investmentType.renderInvestmentTypePage
  )

router
  .route('/create/equity-source/:companyId')
  .get(create.equitySource.getHandler, create.equitySource.renderEquitySourcePage)
  .post(
    create.equitySource.postHandler,
    create.equitySource.getHandler,
    create.equitySource.renderEquitySourcePage
  )

router
  .route('/create/project/:equityCompanyId')
  .get(
    detailsFormMiddleware.populateForm,
    create.project.getHandler,
    create.project.renderCreateProjectPage
  )
  .post(
    detailsFormMiddleware.populateForm,
    detailsFormMiddleware.handleFormPost,
    detailsFormMiddleware.validateForm,
    create.project.postHandler,
    create.project.getHandler,
    create.project.renderCreateProjectPage
  )

router.get('/:investmentId', redirectToFirstNavItem)
router.get('/:investmentId/details', details.detailsGetHandler)

router
  .route('/:investmentId/edit-details')
  .get(detailsFormMiddleware.populateForm, edit.editDetailsGet)
  .post(detailsFormMiddleware.populateForm, detailsFormMiddleware.handleFormPost, edit.editDetailsPost, edit.editDetailsGet)

router
  .route('/:investmentId/edit-value')
  .get(valueFormMiddleware.populateForm, edit.editValueGet)
  .post(valueFormMiddleware.populateForm, valueFormMiddleware.handleFormPost, edit.renderValueForm)

router
  .route('/:investmentId/edit-requirements')
  .get(requirementsFormMiddleware.populateForm, edit.renderRequirementsForm)
  .post(requirementsFormMiddleware.handleFormPost, requirementsFormMiddleware.populateForm, edit.renderRequirementsForm)

router.get('/:investmentId/team', expandTeamMembers, team.details.getDetailsHandler)

router
  .route('/:investmentId/edit-project-management')
  .get(getBriefInvestmentSummary, projectManagementFormMiddleware.populateForm, team.editProjectManagement.getHandler)
  .post(
    getBriefInvestmentSummary,
    projectManagementFormMiddleware.populateForm,
    projectManagementFormMiddleware.handleFormPost,
    team.editProjectManagement.postHandler,
    team.editProjectManagement.getHandler
  )

router
  .route('/:investmentId/edit-client-relationship-management')
  .get(
    clientRelationshipManagementFormMiddleware.populateForm,
    team.editClientRelationshipManagement.getHandler
  )
  .post(
    clientRelationshipManagementFormMiddleware.populateForm,
    clientRelationshipManagementFormMiddleware.handleFormPost,
    team.editClientRelationshipManagement.postHandler,
    team.editClientRelationshipManagement.getHandler
  )

router
  .route('/:investmentId/edit-team-members')
  .get(populateTeamEditForm, renderTeamEdit)
  .post(postTeamEdit, renderTeamEdit)

router.get('/:investmentId/propositions', setPropositionsReturnUrl, renderPropositionList)

router.get('/:investmentId/evaluation', evaluation.renderEvaluationPage)

router.get('/:investmentId/evidence', setEvidenceReturnUrl, renderEvidenceView)

router
  .route('/:investmentId/evidence/add-new')
  .get(
    setEvidenceReturnUrl,
    renderAddEvidence,
  )
  .post(
    setEvidenceReturnUrl,
    setEvidenceDocumentsOptions,
    postUpload,
  )

router
  .route('/:investmentId/evidence/:evidenceId/download')
  .get(
    getDownloadLink
  )

router
  .route('/:investmentId/evidence/:evidenceId/delete')
  .get(
    setEvidenceReturnUrl,
    deleteEvidence
  )

router.post('/:investmentId/change-project-stage', projectStageFormMiddleware.handleFormPost)

router.use('/:investmentId', setInteractionsDetails, setCompanyDetails, interactionsRouter)

router.use('/:investmentId', setPropositionsReturnUrl, propositionsRouter)

router
  .route('/:investmentId/status')
  .post(postStatus, renderStatusPage)
  .get(renderStatusPage)

router.get('/:investmentId/edit-ukcompany', selectUKCompany, searchForUKCompany, renderCompanyResults)
router.get('/:investmentId/remove-ukcompany', removeUKCompany)

// Todo - DH-1030
// Currently to associate the user you must click a link in the investment details page after
// indicating there is an association with a non-fdi r&d project
// Review the investment flow later to see if this can be improved.

router.get('/:investmentId/edit-associated',
  selectAssociatedInvestmentProject,
  searchForAssociatedInvestmentProject,
  renderAssociatedInvestmentProjectResults
)

router.get('/:investmentId/remove-associated', removeAssociatedInvestmentProject)

router.get('/:investmentId/documents', documents.renderDocuments)

module.exports = router
<|endoftext|>