<commit_before>/*global angular, Promise, debug, $, noUiSlider, Fuse*/

//3rd party dependencies
angular.module('phoenixeye-deps', [
	'LocalStorageModule',
	'ui.router',
	'ui.bootstrap',
	'ngFileUpload',
	'ngToast',
	'ngMap',
	'angular-loading-bar',
	'angular.filter'
]);

//module
var module = angular.module('phoenixeye', [
	'phoenixeye-deps',
	'templates'
]);

//constants
module
.constant('Promise', Promise)
.constant('debug', debug)
.constant('$', $)
.constant('noUiSlider', noUiSlider)
.constant('Fuse', Fuse)
;<commit_msg>THREE.js as constant<commit_after>/*global angular, Promise, debug, $, noUiSlider, Fuse, THREE*/

//3rd party dependencies
angular.module('phoenixeye-deps', [
	'LocalStorageModule',
	'ui.router',
	'ui.bootstrap',
	'ngFileUpload',
	'ngToast',
	'ngMap',
	'angular-loading-bar',
	'angular.filter'
]);

//module
var module = angular.module('phoenixeye', [
	'phoenixeye-deps',
	'templates'
]);

//constants
module
.constant('Promise', Promise)
.constant('debug', debug)
.constant('$', $)
.constant('noUiSlider', noUiSlider)
.constant('Fuse', Fuse)
.constant('THREE', THREE)
;<|endoftext|>


<commit_before>var currentTab;

function showTab(strID, objTrigger) {
// Displays the tab with ID strID
	var objTab = document.getElementById(strID);
	if(objTab) {
		show(strID);
		if(currentTab && (currentTab != objTab)) {
			hide(currentTab.id);
			currentTab.style.display = "none";
		}
	}
	currentTab = objTab; // Remember which is the currently displayed tab

	// Set the clicked tab to look current
	var objTabs = document.getElementById("tabs");
	var arrTabs = objTabs.getElementsByTagName("li");
	if(objTrigger) {
		for(var i=0; i<arrTabs.length; i++) {
			arrTabs[i].className="";
		}
		var objTriggerTab = objTrigger.parentNode;
		if(objTriggerTab) {
			objTriggerTab.className="active";
		}
	}

	// fake resize event in case tab body was resized while hidden
  if (document.createEvent) {
    var e = document.createEvent('HTMLEvents');
    e.initEvent('resize', true, true);
    window.dispatchEvent(e);

  } else if( document.createEventObject ) {
    var e = document.createEventObject();
    document.documentElement.fireEvent('onresize', e);
  }

	onDOMChange();
}

function rotateScreen() {
  // Switch stylesheet and viewport based on screen orientation
  var width = document.documentElement.clientWidth || document.body.clientWidth;
  var height = document.documentElement.clientHeight || document.body.clientHeight;

  if (width > height) {
    setOrientation('landscape');
  } else {
    setOrientation('portrait');
  }

  setTimeout(scrollToTop, 500);
}

function setOrientation(orientation) {
    var body = document.getElementsByTagName("body")[0];

 //remove existing portrait/landscape class if there
    if (body.className.match(new RegExp("(^|\\s)(portrait|landscape)(\\s|$)"))) {
        body.className = body.className.replace(
          new RegExp("(^|\\s+)(portrait|landscape)(\\s+|$)"), ' ');
    }

    body.className += ' ' + orientation;
}

function showLoadingMsg(strID) {
// Show a temporary loading message in the element with ID strID
	var objToStuff = document.getElementById(strID);
	if(objToStuff) {
		objToStuff.style.height = objToStuff.offsetHeight + "px";
		objToStuff.innerHTML = "
Loading data...
";
	}
	onDOMChange();
}

function hide(strID) {
// Hides the object with ID strID
	var objToHide = document.getElementById(strID);
	if(objToHide) {
		objToHide.style.display = "none";
	}

	onDOMChange();
}

function show(strID) {
// Displays the object with ID strID
	var objToHide = document.getElementById(strID);
	if(objToHide) {
		objToHide.style.display = "block";
	}

	onDOMChange();
}

function showHideFull(objContainer) {
	var strClass = objContainer.className;
	if(strClass.indexOf("collapsed") > -1) {
		strClass = strClass.replace("collapsed","expanded");
	} else {
		strClass = strClass.replace("expanded","collapsed");
	}
	objContainer.className = strClass;
	objContainer.blur();

	onDOMChange();
}

function clearField(objField,strDefault) {
// Clears the placeholder text in an input field if it matches the default string - fixes a bug in Android
	if((objField.value==strDefault) || (objField.value=="")) {
		objField.value="";
	}
}

// Android doesn't respond to onfocus="clearField(...)" until the
// input field loses focus
function androidPlaceholderFix(searchbox) {
    // this forces the search box to display the empty string
    // instead of the place holder when the search box takes focus
    if (searchbox.value == "") {
        searchbox.value = "";
    }
}

function getCookie(name) {
  var cookie = document.cookie;
  var result = "";
  var start = cookie.indexOf(name + "=");
  if (start > -1) {
    start += name.length + 1;
    var end = cookie.indexOf(";", start);
    if (end < 0) {
      end = cookie.length;
    }
    result = unescape(cookie.substring(start, end));
  }
  return result;
}

function setCookie(name, value, expireseconds, path) {
  var exdate = new Date();
  exdate.setTime(exdate.getTime() + (expireseconds * 1000));
  var exdateclause = (expireseconds == 0) ? "" : "; expires=" + exdate.toGMTString();
  var pathclause = (path == null) ? "" : "; path=" + path;
  document.cookie = name + "=" + escape(value) + exdateclause + pathclause;
}

function getCookieArrayValue(name) {
  var value = getCookie(name);
  if (value && value.length) {
    return value.split('@@');
  } else {
    return new Array();
  }
}

function setCookieArrayValue(name, values, expireseconds, path) {
  var value = '';
  if (values && values.length) {
    value = values.join('@@');
  }
  setCookie(name, value, expireseconds, path);
}

function hasClass(ele,cls) {
    return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
    if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
    if (hasClass(ele,cls)) {
        var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
        ele.className=ele.className.replace(reg,' ');
    }
}

function toggleClass(ele, cls) {
    if (hasClass(ele, cls)) {
        removeClass(ele, cls);
    } else {
        addClass(ele, cls);
    }
}

// Share-related functions
function showShare() {
	document.getElementById("sharesheet").style.display="block";
	document.addEventListener('touchmove', doNotScroll, true);
	var iframes = document.getElementsByTagName('iframe');
	for (var i=0; i<iframes.length; i++) {
	    iframes[i].style.visibility = 'hidden';
	}
	window.scrollTo(0,0);
}
function hideShare() {
	document.getElementById("sharesheet").style.display="none";
	document.removeEventListener('touchmove', doNotScroll, true);
	var iframes = document.getElementsByTagName('iframe');
	for (var i=0; i<iframes.length; i++) {
	    iframes[i].style.visibility = 'visible';
	}
}
function doNotScroll( event ) {
	event.preventDefault(); event.stopPropagation();
}

// Bookmarks
function setBookmarkStates(name, item) {
  var bookmark = document.getElementById("bookmark");
  var items = getCookieArrayValue(name);
  for (var i = 0; i < items.length; i++) {
    if (items[i] == item) {
      addClass(bookmark, "on");
      break;
    }
  }
  if (bookmark.addEventListener) {
    bookmark.addEventListener("touchstart", function() {
        addClass(bookmark, "pressed");
    }, false);
    bookmark.addEventListener("touchend", function() {
        removeClass(bookmark, "pressed");
    }, false);

  } else if (bookmark.attachEvent) {
    bookmark.attachEvent("ontouchstart", function() {
        addClass(bookmark, "pressed");
    });
    bookmark.attachEvent("ontouchend", function() {
        removeClass(bookmark, "pressed");
    });
  }
}

function toggleBookmark(name, item, expireseconds, path) {
  var bookmark = document.getElementById("bookmark");
  toggleClass(bookmark, "on");
  var items = getCookieArrayValue(name);
  var newItems = new Array();
  if (items.length == 0) {
    newItems[0] = item;
  } else {
    var found = false;
    for (var i = 0; i < items.length; i++) {
      if (items[i] == item) {
        found = true;
      } else {
        newItems.push(items[i]);
      }
    }
    if (!found) {
      newItems.push(item);
    }
  }
  setCookieArrayValue(name, newItems, expireseconds, path);
}
<commit_msg>use built in class functions<commit_after>var currentTab;

String.prototype.strip = function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
}

function showTab(strID, objTrigger) {
// Displays the tab with ID strID
	var objTab = document.getElementById(strID);
	if(objTab) {
		show(strID);
		if(currentTab && (currentTab != objTab)) {
			hide(currentTab.id);
			currentTab.style.display = "none";
		}
	}
	currentTab = objTab; // Remember which is the currently displayed tab

	// Set the clicked tab to look current
	var objTabs = document.getElementById("tabs");
	var arrTabs = objTabs.getElementsByTagName("li");
	if(objTrigger) {
		for(var i=0; i<arrTabs.length; i++) {
			arrTabs[i].className="";
		}
		var objTriggerTab = objTrigger.parentNode;
		if(objTriggerTab) {
			objTriggerTab.className="active";
		}
	}

	// fake resize event in case tab body was resized while hidden
  if (document.createEvent) {
    var e = document.createEvent('HTMLEvents');
    e.initEvent('resize', true, true);
    window.dispatchEvent(e);

  } else if( document.createEventObject ) {
    var e = document.createEventObject();
    document.documentElement.fireEvent('onresize', e);
  }

	onDOMChange();
}

function rotateScreen() {
  // Switch stylesheet and viewport based on screen orientation
  var width = document.documentElement.clientWidth || document.body.clientWidth;
  var height = document.documentElement.clientHeight || document.body.clientHeight;

  if (width > height) {
    setOrientation('landscape');
  } else {
    setOrientation('portrait');
  }

  setTimeout(scrollToTop, 500);
}

function setOrientation(orientation) {
    var body = document.getElementsByTagName("body")[0];

 //remove existing portrait/landscape class if there
    removeClass(body, 'portrait');
    removeClass(body, 'landscape');
    addClass(body, orientation);
}

function showLoadingMsg(strID) {
// Show a temporary loading message in the element with ID strID
	var objToStuff = document.getElementById(strID);
	if(objToStuff) {
		objToStuff.style.height = objToStuff.offsetHeight + "px";
		objToStuff.innerHTML = "
Loading data...
";
	}
	onDOMChange();
}

function hide(strID) {
// Hides the object with ID strID
	var objToHide = document.getElementById(strID);
	if(objToHide) {
		objToHide.style.display = "none";
	}

	onDOMChange();
}

function show(strID) {
// Displays the object with ID strID
	var objToHide = document.getElementById(strID);
	if(objToHide) {
		objToHide.style.display = "block";
	}

	onDOMChange();
}

function showHideFull(objContainer) {
	var strClass = objContainer.className;
	if(strClass.indexOf("collapsed") > -1) {
		strClass = strClass.replace("collapsed","expanded");
	} else {
		strClass = strClass.replace("expanded","collapsed");
	}
	objContainer.className = strClass;
	objContainer.blur();

	onDOMChange();
}

function clearField(objField,strDefault) {
// Clears the placeholder text in an input field if it matches the default string - fixes a bug in Android
	if((objField.value==strDefault) || (objField.value=="")) {
		objField.value="";
	}
}

// Android doesn't respond to onfocus="clearField(...)" until the
// input field loses focus
function androidPlaceholderFix(searchbox) {
    // this forces the search box to display the empty string
    // instead of the place holder when the search box takes focus
    if (searchbox.value == "") {
        searchbox.value = "";
    }
}

function getCookie(name) {
  var cookie = document.cookie;
  var result = "";
  var start = cookie.indexOf(name + "=");
  if (start > -1) {
    start += name.length + 1;
    var end = cookie.indexOf(";", start);
    if (end < 0) {
      end = cookie.length;
    }
    result = unescape(cookie.substring(start, end));
  }
  return result;
}

function setCookie(name, value, expireseconds, path) {
  var exdate = new Date();
  exdate.setTime(exdate.getTime() + (expireseconds * 1000));
  var exdateclause = (expireseconds == 0) ? "" : "; expires=" + exdate.toGMTString();
  var pathclause = (path == null) ? "" : "; path=" + path;
  document.cookie = name + "=" + escape(value) + exdateclause + pathclause;
}

function getCookieArrayValue(name) {
  var value = getCookie(name);
  if (value && value.length) {
    return value.split('@@');
  } else {
    return new Array();
  }
}

function setCookieArrayValue(name, values, expireseconds, path) {
  var value = '';
  if (values && values.length) {
    value = values.join('@@');
  }
  setCookie(name, value, expireseconds, path);
}

function hasClass(ele,cls) {
    return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
    if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
    if (hasClass(ele,cls)) {
        var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
        ele.className=ele.className.replace(reg,' ').strip();
    }
}

function toggleClass(ele, cls) {
    if (hasClass(ele, cls)) {
        removeClass(ele, cls);
    } else {
        addClass(ele, cls);
    }
}

// Share-related functions
function showShare() {
	document.getElementById("sharesheet").style.display="block";
	document.addEventListener('touchmove', doNotScroll, true);
	var iframes = document.getElementsByTagName('iframe');
	for (var i=0; i<iframes.length; i++) {
	    iframes[i].style.visibility = 'hidden';
	}
	window.scrollTo(0,0);
}
function hideShare() {
	document.getElementById("sharesheet").style.display="none";
	document.removeEventListener('touchmove', doNotScroll, true);
	var iframes = document.getElementsByTagName('iframe');
	for (var i=0; i<iframes.length; i++) {
	    iframes[i].style.visibility = 'visible';
	}
}
function doNotScroll( event ) {
	event.preventDefault(); event.stopPropagation();
}

// Bookmarks
function setBookmarkStates(name, item) {
  var bookmark = document.getElementById("bookmark");
  var items = getCookieArrayValue(name);
  for (var i = 0; i < items.length; i++) {
    if (items[i] == item) {
      addClass(bookmark, "on");
      break;
    }
  }
  if (bookmark.addEventListener) {
    bookmark.addEventListener("touchstart", function() {
        addClass(bookmark, "pressed");
    }, false);
    bookmark.addEventListener("touchend", function() {
        removeClass(bookmark, "pressed");
    }, false);

  } else if (bookmark.attachEvent) {
    bookmark.attachEvent("ontouchstart", function() {
        addClass(bookmark, "pressed");
    });
    bookmark.attachEvent("ontouchend", function() {
        removeClass(bookmark, "pressed");
    });
  }
}

function toggleBookmark(name, item, expireseconds, path) {
  var bookmark = document.getElementById("bookmark");
  toggleClass(bookmark, "on");
  var items = getCookieArrayValue(name);
  var newItems = new Array();
  if (items.length == 0) {
    newItems[0] = item;
  } else {
    var found = false;
    for (var i = 0; i < items.length; i++) {
      if (items[i] == item) {
        found = true;
      } else {
        newItems.push(items[i]);
      }
    }
    if (!found) {
      newItems.push(item);
    }
  }
  setCookieArrayValue(name, newItems, expireseconds, path);
}
<|endoftext|>


<commit_before>/**
 * Renders the list of icons as IconLinks mapping their
 * href, title, className and color values accordingly.
 */
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import IconLink from './IconLink';

const Wrapper = styled.ul`
  display: flex;
  flex-flow: row nowrap;

  // Sizing
  padding: 1em 0;

  // List items
  &,
  li{
    display: inline-flex;
    list-style-type: none;
    margin: 0 1em;
  }

  li:first-child {
    margin: 0 1em 0 auto;
  }

  li:last-child{
    margin: 0 auto 0 1em;
  }
`;

const IconBar = ({ icons }) => (
  <Wrapper>
    {icons.map((icon) => (

<IconLink
        key={`icon-link-${icon.title}`}
        href={icon.href}
        title={icon.title}
        className={icon.className}
        hoverColor={icon.hoverColor}
      />
)
    )}
  </Wrapper>
);

IconBar.propTypes = {
  icons: PropTypes.array.isRequired,
};

export default IconBar;
<commit_msg>key added to li<commit_after>/**
 * Renders the list of icons as IconLinks mapping their
 * href, title, className and color values accordingly.
 */
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import IconLink from './IconLink';

const Wrapper = styled.ul`
  display: flex;
  flex-flow: row nowrap;

  // Sizing
  padding: 1em 0;

  // List items
  &,
  li{
    display: inline-flex;
    list-style-type: none;
    margin: 0 1em;
  }

  li:first-child {
    margin: 0 1em 0 auto;
  }

  li:last-child{
    margin: 0 auto 0 1em;
  }
`;

const IconBar = ({ icons }) => (
  <Wrapper>
    {icons.map((icon) => (
      <li key={`icon-link-${icon.title}`}>
        <IconLink
          href={icon.href}
          title={icon.title}
          className={icon.className}
          hoverColor={icon.hoverColor}
        />

    ))}
  </Wrapper>
);

IconBar.propTypes = {
  icons: PropTypes.array.isRequired,
};

export default IconBar;
<|endoftext|>


<commit_before>/** @flow */
import Immutable from 'immutable'
import Entry from './Entry'
import styles from './Widget.css'
import LabelWidget from './Labels'
import React, { PropTypes, Component } from 'react'
import {cleanTitle, getMaintainers, getScoreClassName} from '../../helper'
import { VirtualScroll } from 'react-virtualized'
import classNames from 'classnames'

export default class Widget extends Component {

  static propTypes = {
    generateData: PropTypes.func.isRequired,
    setFilter: PropTypes.func.isRequired,
    totalSize: PropTypes.any.isRequired,
    getVisiblePlugins: PropTypes.any.isRequired,
    getVisiblePluginsLabels: PropTypes.any.isRequired,
    searchData: PropTypes.func.isRequired,
    title: PropTypes.string.isRequired,
    labelFilter: PropTypes.any.isRequired
  };

  state = {
    clicked: false,
    view:'tiles',
    sort:'title',
    category:'all'
  };

  filterSet (search, filter) {
    this.props.setFilter(new Immutable.Record({
      searchField: 'labels',
      field: filter.title || 'title',
      search: search,
      asc: filter.asc || true
    }))

  };

  getFilter (labelFilter) {
    let filter;
    if (labelFilter instanceof Function) {
      filter = labelFilter();
    } else {
      filter = labelFilter;
    }
    return filter;
  };

  render () {

    const {
      generateData,
      setFilter,
      rowRenderer,
      searchData,
      title,
      totalSize,
      getVisiblePlugins,
      getVisiblePluginsLabels,
      labelFilter
    } = this.props;

    const filter = this.getFilter(labelFilter);

    const { clicked } = this.state;

    const filteredSize = getVisiblePlugins instanceof Immutable.Collection
      ? getVisiblePlugins.size
      : getVisiblePlugins.length

    const viewClass = styles[this.state.view]

    return (

Categories

                  {
                    {this.state.category = 'scm'}
                    {this.filterSet(['scm-related', 'scm'], labelFilter)}
                  }
                }
              >SCM connectors

                {
                  {this.state.category = 'build'}
                  {this.filterSet(['builder', 'buildwrapper'], labelFilter)}
                }
              }
              >Build and analytics

              {
                {this.state.category = 'deployment'}
                {this.filterSet(['cli', 'deployment'], labelFilter)}
              }
            }>Deployment

              Pipelines

              Containers

              {
                {this.state.category = 'security'}
                {this.filterSet(['user', 'security'], labelFilter)}
              }
            }>Users and security

              General purpose

          { totalSize > 0 && <LabelWidget
            labels={getVisiblePluginsLabels}
            onClick={(event)=>  {
              setFilter(new Immutable.Record({
                searchField: 'labels',
                field: filter.title || 'title',
                search: [event.target.innerText],
                asc: filter.asc || true
              }))}}
            /> }

Featured

New

All

                <button className="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Tags</button>
                { totalSize > 0 && <LabelWidget
                  labels={getVisiblePluginsLabels}
                  onClick={(event)=>  {
                    setFilter(new Immutable.Record({
                      searchField: 'labels',
                      field: filter.title || 'title',
                      search: [event.target.innerText],
                      asc: filter.asc || true
                    }))}}
                  /> }

Technologies

<button className="btn btn-sm" onClick={()=>  generateData()}>getPlugins</button>

                {totalSize > 0 &&

                    {filteredSize} of {totalSize}

                }

                <form className="form-inline pull-xs-right" action='#'>
                <input
                  disabled={totalSize === 0}
                  className={classNames(styles.SearchInput, "form-control nav-link")}
                  onChange={event => searchData(event.target.value)}
                  onSubmit={event => searchData(event.target.value)}
                  placeholder='Filter...'
                />
                </form>

                <button className="nav-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  sort: {this.state.sort}</button>

                   {
                    this.setState({ sort: 'name' })
                    setFilter(new Immutable.Record({
                      field: 'name',
                      asc: !filter.asc
                    }))}}>Name
                   {
                    this.setState({ sort: 'core' })
                    setFilter(new Immutable.Record({
                      field: 'requiredCore',
                      asc: !filter.asc
                    }))}}>Core version
                    {this.setState({ sort: 'rating' });}}>Ratings
                   {
                      this.setState({ sort: 'updated' })
                      setFilter(new Immutable.Record({
                        field: 'buildDate',
                        asc: !filter.asc
                      }))}}>Updated
                   {
                      this.setState({ sort: 'created' })
                      setFilter(new Immutable.Record({
                        field: 'releaseTimestamp',
                        asc: !filter.asc
                      }))}}>Created

                <button className="nav-link  dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  view: {this.state.view}
                </button>

                  {this.setState({ view: 'tiles' });}}>Tiles
                  {this.setState({ view: 'list' });}}>List
                  {this.setState({ view: 'table' });}}>Table

              {totalSize > 0 && getVisiblePlugins.valueSeq().map(plugin => {
                return <Entry
                  className="Entry"
                  key={plugin.id}
                  plugin={plugin} />
              })}

      )
  };

}
<commit_msg>white noise - formating changes<commit_after>/** @flow */
import Immutable from 'immutable'
import Entry from './Entry'
import styles from './Widget.css'
import LabelWidget from './Labels'
import React, { PropTypes, Component } from 'react'
import {cleanTitle, getMaintainers, getScoreClassName} from '../../helper'
import { VirtualScroll } from 'react-virtualized'
import classNames from 'classnames'

export default class Widget extends Component {

  static propTypes = {
    generateData: PropTypes.func.isRequired,
    setFilter: PropTypes.func.isRequired,
    totalSize: PropTypes.any.isRequired,
    getVisiblePlugins: PropTypes.any.isRequired,
    getVisiblePluginsLabels: PropTypes.any.isRequired,
    searchData: PropTypes.func.isRequired,
    title: PropTypes.string.isRequired,
    labelFilter: PropTypes.any.isRequired
  };

  state = {
    clicked: false,
    view:'tiles',
    sort:'title',
    category:'all'
  };

  filterSet (search, filter) {
    this.props.setFilter(new Immutable.Record({
      searchField: 'labels',
      field: filter.title || 'title',
      search: search,
      asc: filter.asc || true
    }))

  };

  getFilter (labelFilter) {
    let filter;
    if (labelFilter instanceof Function) {
      filter = labelFilter();
    } else {
      filter = labelFilter;
    }
    return filter;
  };

  render () {

    const {
      generateData,
      setFilter,
      rowRenderer,
      searchData,
      title,
      totalSize,
      getVisiblePlugins,
      getVisiblePluginsLabels,
      labelFilter
    } = this.props;

    const filter = this.getFilter(labelFilter);

    const { clicked } = this.state;

    const filteredSize = getVisiblePlugins instanceof Immutable.Collection
      ? getVisiblePlugins.size
      : getVisiblePlugins.length

    const viewClass = styles[this.state.view]

    return (

Categories

                  {
                    {this.state.category = 'scm'}
                    {this.filterSet(['scm-related', 'scm'], labelFilter)}
                  }
                }
              >SCM connectors

                {
                  {this.state.category = 'build'}
                  {this.filterSet(['builder', 'buildwrapper'], labelFilter)}
                }
              }
              >Build and analytics

              {
                {this.state.category = 'deployment'}
                {this.filterSet(['cli', 'deployment'], labelFilter)}
              }
            }>Deployment

              Pipelines

              Containers

              {
                {this.state.category = 'security'}
                {this.filterSet(['user', 'security'], labelFilter)}
              }
            }>Users and security

              General purpose

          { totalSize > 0 && <LabelWidget
            labels={getVisiblePluginsLabels}
            onClick={(event)=>  {
              setFilter(new Immutable.Record({
                searchField: 'labels',
                field: filter.title || 'title',
                search: [event.target.innerText],
                asc: filter.asc || true
              }))}}
            /> }

Featured

New

All

                <button className="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Tags</button>
                { totalSize > 0 && <LabelWidget
                  labels={getVisiblePluginsLabels}
                  onClick={(event)=>  {
                    setFilter(new Immutable.Record({
                      searchField: 'labels',
                      field: filter.title || 'title',
                      search: [event.target.innerText],
                      asc: filter.asc || true
                    }))}}
                  /> }

Technologies

<button className="btn btn-sm" onClick={()=>  generateData()}>getPlugins</button>

                {totalSize > 0 &&

                    {filteredSize} of {totalSize}

                }

                <form className="form-inline pull-xs-right" action='#'>
                <input
                  disabled={totalSize === 0}
                  className={classNames(styles.SearchInput, "form-control nav-link")}
                  onChange={event => searchData(event.target.value)}
                  onSubmit={event => searchData(event.target.value)}
                  placeholder='Filter...'
                />
                </form>

                <button className="nav-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  sort: {this.state.sort}</button>

                   {
                    this.setState({ sort: 'name' })
                    setFilter(new Immutable.Record({
                      field: 'name',
                      asc: !filter.asc
                    }))}}>Name
                   {
                    this.setState({ sort: 'core' })
                    setFilter(new Immutable.Record({
                      field: 'requiredCore',
                      asc: !filter.asc
                    }))}}>Core version
                    {this.setState({ sort: 'rating' });}}>Ratings
                   {
                      this.setState({ sort: 'updated' })
                      setFilter(new Immutable.Record({
                        field: 'buildDate',
                        asc: !filter.asc
                      }))}}>Updated
                   {
                      this.setState({ sort: 'created' })
                      setFilter(new Immutable.Record({
                        field: 'releaseTimestamp',
                        asc: !filter.asc
                      }))}}>Created

                <button className="nav-link  dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  view: {this.state.view}
                </button>

                  {this.setState({ view: 'tiles' });}}>Tiles
                  {this.setState({ view: 'list' });}}>List
                  {this.setState({ view: 'table' });}}>Table

              {totalSize > 0 && getVisiblePlugins.valueSeq().map(plugin => {
                return <Entry
                  className="Entry"
                  key={plugin.id}
                  plugin={plugin} />
              })}

      )
  };

}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import styled from 'styled-components';

import FriendlyTime from '../shared/FriendlyTime';
import RevealableDownChevron from '../shared/Icon/RevealableDownChevron';
import Panel from '../shared/Panel';
import Spinner from '../shared/Spinner';

const TransitionMaxHeight = styled.div`
  transition: max-height 400ms;
`;

class AuditLogRow extends React.PureComponent {
  static propTypes = {
    auditEvent: PropTypes.shape({
      uuid: PropTypes.string.isRequired,
      type: PropTypes.string.isRequired,
      occurredAt: PropTypes.string.isRequired,
      data: PropTypes.string,
      actor: PropTypes.shape({
        node: PropTypes.shape({
          name: PropTypes.string.isRequired
        }).isRequired
      }).isRequired,
      subject: PropTypes.shape({
        node: PropTypes.shape({
          __typename: PropTypes.string.isRequired,
          name: PropTypes.string.isRequired
        })
      }).isRequired,
      context: PropTypes.shape({
        __typename: PropTypes.string.isRequired,
        requestIpAddress: PropTypes.string,
        requestUserAgent: PropTypes.string,
        sessionCreatedAt: PropTypes.string
      }).isRequired
    }).isRequired,
    relay: PropTypes.object.isRequired
  };

  state = {
    isExpanded: false
  };

  getContextName() {
    return this.props.auditEvent.context.__typename.replace(/^Audit|Context$/g, '');
  }

  render() {
    return (
      <Panel.Row>

              {this.renderEventSentence()}

              <RevealableDownChevron
                className="dark-gray"
                revealed={this.state.isExpanded}
              />

          <TransitionMaxHeight
            className="mxn3 overflow-hidden"
            style={{
              maxHeight: this.state.isExpanded ? 1000 : 0
            }}
          >

            {this.renderEventDetails()}
          </TransitionMaxHeight>

      </Panel.Row>
    );
  }

  renderEventSentence() {
    const {
      type: eventTypeName,
      actor,
      subject,
      context
    } = this.props.auditEvent;

    // "ORGANIZATION_CREATED" => ["Organization", "Created"]
    const eventTypeSplit = eventTypeName
      .split("_")
      .map((word) => word.charAt(0) + word.slice(1).toLowerCase());

    const eventVerb = eventTypeSplit.pop().toLowerCase();

    const eventType = eventTypeSplit.join(' ');

    let subjectName = subject.node && subject.node.name;

    if (eventTypeName === 'ORGANIZATION_CREATED') {
      subjectName = `${subjectName} 🎉`;
    }

    const actorName = actor.node && actor.node.name;

    return (

        {actorName}
        {` ${eventVerb} ${eventType} `}
        {subjectName}
        {` via `}

          {this.getContextName()}

        {` `}
        <FriendlyTime
          capitalized={false}
          value={this.props.auditEvent.occurredAt}
        />

    );
  }

  renderEventDetails() {
    if (this.state.loading) {
      return (

          <Spinner style={{ margin: 9.5 }} />

      );
    }

    return (

Changed Data

        {this.renderEventData()}

{this.getContextName()} Context

IP Address

{this.props.auditEvent.context.requestIpAddress}

User Agent

{this.props.auditEvent.context.requestUserAgent}

Session Started

<FriendlyTime value={this.props.auditEvent.context.sessionCreatedAt} />

    );
  }

  renderEventData() {
    if (!this.props.auditEvent.data) {
      return;
    }

    const parsed = JSON.parse(this.props.auditEvent.data);

    if (parsed) {
      const rendered = JSON.stringify(parsed, null, '  ');

      // if this renders to a string longer than `{}`, show it
      if (rendered.length > 2) {
        return (

            {rendered}

        );
      }
    }

    // otherwise, looks like there weren't any captured data changes!
    return (
      No data changes were found
    );
  }

  handleHeaderClick = () => {
    const isExpanded = !this.state.isExpanded;

    this.setState({
      loading: true,
      isExpanded
    }, () => {
      this.props.relay.setVariables(
        {
          hasExpanded: true
        },
        (readyState) => {
          if (readyState.done) {
            this.setState({ loading: false });
          }
        }
      );
    });
  };
}

export default Relay.createContainer(AuditLogRow, {
  initialVariables: {
    hasExpanded: false
  },

  fragments: {
    auditEvent: () => Relay.QL`
      fragment on AuditEvent {
        uuid
        type
        occurredAt
        data @include(if: $hasExpanded)
        actor {
          node {
            ...on User {
              name
            }
          }
        }
        subject {
          node {
            __typename
            ...on Organization {
              name
            }
            ...on Pipeline {
              name
            }
          }
        }
        context {
          __typename
          ...on AuditWebContext {
            requestIpAddress
            requestUserAgent
            sessionCreatedAt
          }
        }
      }
    `
  }
});
<commit_msg>Use first-class subject and actor names if present<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import styled from 'styled-components';

import FriendlyTime from '../shared/FriendlyTime';
import RevealableDownChevron from '../shared/Icon/RevealableDownChevron';
import Panel from '../shared/Panel';
import Spinner from '../shared/Spinner';

const TransitionMaxHeight = styled.div`
  transition: max-height 400ms;
`;

class AuditLogRow extends React.PureComponent {
  static propTypes = {
    auditEvent: PropTypes.shape({
      uuid: PropTypes.string.isRequired,
      type: PropTypes.string.isRequired,
      occurredAt: PropTypes.string.isRequired,
      data: PropTypes.string,
      actor: PropTypes.shape({
        node: PropTypes.shape({
          name: PropTypes.string.isRequired
        }).isRequired
      }).isRequired,
      subject: PropTypes.shape({
        node: PropTypes.shape({
          __typename: PropTypes.string.isRequired,
          name: PropTypes.string.isRequired
        })
      }).isRequired,
      context: PropTypes.shape({
        __typename: PropTypes.string.isRequired,
        requestIpAddress: PropTypes.string,
        requestUserAgent: PropTypes.string,
        sessionCreatedAt: PropTypes.string
      }).isRequired
    }).isRequired,
    relay: PropTypes.object.isRequired
  };

  state = {
    isExpanded: false
  };

  getContextName() {
    return this.props.auditEvent.context.__typename.replace(/^Audit|Context$/g, '');
  }

  render() {
    return (
      <Panel.Row>

              {this.renderEventSentence()}

              <RevealableDownChevron
                className="dark-gray"
                revealed={this.state.isExpanded}
              />

          <TransitionMaxHeight
            className="mxn3 overflow-hidden"
            style={{
              maxHeight: this.state.isExpanded ? 1000 : 0
            }}
          >

            {this.renderEventDetails()}
          </TransitionMaxHeight>

      </Panel.Row>
    );
  }

  renderEventSentence() {
    const {
      type: eventTypeName,
      actor,
      subject,
      context
    } = this.props.auditEvent;

    // "ORGANIZATION_CREATED" => ["Organization", "Created"]
    const eventTypeSplit = eventTypeName
      .split("_")
      .map((word) => word.charAt(0) + word.slice(1).toLowerCase());

    const eventVerb = eventTypeSplit.pop().toLowerCase();

    const eventType = eventTypeSplit.join(' ');

    let subjectName = subject.name || subject.node && subject.node.name;

    if (eventTypeName === 'ORGANIZATION_CREATED') {
      subjectName = `${subjectName} 🎉`;
    }

    const actorName = actor.name || actor.node && actor.node.name;

    return (

        {actorName}
        {` ${eventVerb} ${eventType} `}
        {subjectName}
        {` via `}

          {this.getContextName()}

        {` `}
        <FriendlyTime
          capitalized={false}
          value={this.props.auditEvent.occurredAt}
        />

    );
  }

  renderEventDetails() {
    if (this.state.loading) {
      return (

          <Spinner style={{ margin: 9.5 }} />

      );
    }

    return (

Changed Data

        {this.renderEventData()}

{this.getContextName()} Context

IP Address

{this.props.auditEvent.context.requestIpAddress}

User Agent

{this.props.auditEvent.context.requestUserAgent}

Session Started

<FriendlyTime value={this.props.auditEvent.context.sessionCreatedAt} />

    );
  }

  renderEventData() {
    if (!this.props.auditEvent.data) {
      return;
    }

    const parsed = JSON.parse(this.props.auditEvent.data);

    if (parsed) {
      const rendered = JSON.stringify(parsed, null, '  ');

      // if this renders to a string longer than `{}`, show it
      if (rendered.length > 2) {
        return (

            {rendered}

        );
      }
    }

    // otherwise, looks like there weren't any captured data changes!
    return (
      No data changes were found
    );
  }

  handleHeaderClick = () => {
    const isExpanded = !this.state.isExpanded;

    this.setState({
      loading: true,
      isExpanded
    }, () => {
      this.props.relay.setVariables(
        {
          hasExpanded: true
        },
        (readyState) => {
          if (readyState.done) {
            this.setState({ loading: false });
          }
        }
      );
    });
  };
}

export default Relay.createContainer(AuditLogRow, {
  initialVariables: {
    hasExpanded: false
  },

  fragments: {
    auditEvent: () => Relay.QL`
      fragment on AuditEvent {
        uuid
        type
        occurredAt
        data @include(if: $hasExpanded)
        actor {
          node {
            ...on User {
              name
            }
          }
        }
        subject {
          node {
            __typename
            ...on Organization {
              name
            }
            ...on Pipeline {
              name
            }
          }
        }
        context {
          __typename
          ...on AuditWebContext {
            requestIpAddress
            requestUserAgent
            sessionCreatedAt
          }
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>var assert = require('assert'),
  request = require('../utils/request.server.js'),
  log = require('debug')('bshed:client:middleware')

module.exports = function ({rendererPath, assets}={}) {
  assert(rendererPath && assets)
  assets = assets()
  return function* client () {
    try {
      log(`using renderer from ${rendererPath}`)
      var renderer = require(rendererPath)
      var {body, type, status} = yield renderer({
        assets, url: this.url,
        request: request(this.app.server, {
          'cookie': this.get('cookie'), // send cookie header
          'x-csrf-token': this.csrf // send csrf header
        })
      })
      Object.assign(this, {status, body, type})
    } catch (err) {
      console.error(err)
      this.throw(500)
    }
  }

}
<commit_msg>consistent style<commit_after>var assert = require('assert'),
  request = require('../utils/request.server.js'),
  log = require('debug')('bshed:client:middleware')

module.exports = function ({rendererPath, assets}={}) {
  assert(rendererPath && assets)
  assets = assets()
  return function* client () {
    try {
      log(`using renderer from ${rendererPath}`)
      var renderer = require(rendererPath)
      var {body, type, status} = yield renderer({
        assets: assets, url: this.url,
        request: request(this.app.server, {
          'cookie': this.get('cookie'), // send cookie header
          'x-csrf-token': this.csrf // send csrf header
        })
      })
      Object.assign(this, {status, body, type})
    } catch (err) {
      console.error(err)
      this.throw(500)
    }
  }

}
<|endoftext|>


<commit_before>//
// Name:    accounts.js
// Purpose: Controller and routing for Article model
// Creator: Tom Söderlund
//

'use strict';

const mongooseCrudify = require('mongoose-crudify');
const request = require('request');
const cheerio = require('cheerio');
const _ = require('lodash');

const helpers = require('../../lib/helpers');
const Article = require('mongoose').model('Article');

// Private functions

const identifyingKey = 'reference';

const parseHtml = function (htmlString) {
	const $ = cheerio.load(htmlString);
	const title = $('head meta[property="og:title"]').attr('content') || $('head title').text();
	const description = $('head meta[property="og:description"]').attr('content') || $('head meta[property="description"]').attr('content');
	const imageUrl = $('head meta[property="og:image"]').attr('content') || $('head meta[property="twitter:image"]').attr('content');
	return {
		title: title,
		slug: helpers.toSlug(title),
		description: description,
		imageUrl: imageUrl,
	};
}

const prepareArticle = function (req, res, next) {
	request(req.body.url, function (error, response, body) {
		if (response.statusCode !== 200) {
			res.status(response.statusCode).send(`${response.statusCode}: ${response.statusMessage}`);
		}
		else if (error) {
			res.status(500).send(error);
		}
		else {
			// Merge req.body last = e.g. user-provided 'title' has priority
			const oldProps = _.clone(req.body);
			_.merge(req.body, parseHtml(body), oldProps);
			next();
		}
	});
};

// Public API

module.exports = function (app, config) {

	app.use(
		'/api/articles',
		mongooseCrudify({
			Model: Article,
			//identifyingKey: identifyingKey,
			beforeActions: [
				{ middlewares: [prepareArticle], only: ['create'] },
			],
			// endResponseInAction: false,
			// afterActions: [
			// 	{ middlewares: [helpers.sendRequestResponse] },
			// ],
		})
	);

};<commit_msg>Split keywords if string<commit_after>//
// Name:    accounts.js
// Purpose: Controller and routing for Article model
// Creator: Tom Söderlund
//

'use strict';

const mongooseCrudify = require('mongoose-crudify');
const request = require('request');
const cheerio = require('cheerio');
const _ = require('lodash');

const helpers = require('../../lib/helpers');
const Article = require('mongoose').model('Article');

// Private functions

const identifyingKey = 'reference';

const parseHtml = function (htmlString) {
	const $ = cheerio.load(htmlString);
	const title = $('head meta[property="og:title"]').attr('content') || $('head title').text();
	const description = $('head meta[property="og:description"]').attr('content') || $('head meta[property="description"]').attr('content');
	const imageUrl = $('head meta[property="og:image"]').attr('content') || $('head meta[property="twitter:image"]').attr('content');
	return {
		title: title,
		slug: helpers.toSlug(title),
		description: description,
		imageUrl: imageUrl,
	};
}

const prepareArticle = function (req, res, next) {
	request(req.body.url, function (error, response, body) {
		if (response.statusCode !== 200) {
			res.status(response.statusCode).send(`${response.statusCode}: ${response.statusMessage}`);
		}
		else if (error) {
			res.status(500).send(error);
		}
		else {
			// Merge req.body last = e.g. user-provided 'title' has priority
			let oldProps = _.clone(req.body);
			if (typeof(oldProps.keywords) === 'string') {
				oldProps.keywords = oldProps.keywords.split(',');
			}
			_.merge(req.body, parseHtml(body), oldProps);
			next();
		}
	});
};

// Public API

module.exports = function (app, config) {

	app.use(
		'/api/articles',
		mongooseCrudify({
			Model: Article,
			//identifyingKey: identifyingKey,
			beforeActions: [
				{ middlewares: [prepareArticle], only: ['create'] },
			],
			// endResponseInAction: false,
			// afterActions: [
			// 	{ middlewares: [helpers.sendRequestResponse] },
			// ],
		})
	);

};<|endoftext|>


<commit_before>"use strict";

// A macro object. Note that a macro can have no parameters but still
// be a function macro if it is defined with an empty parameter list.
var Macro = function(name, nameStart, nameEnd, parameters, parameterMap, isFunction, isVariadic, tokens)
{
    this.name = name;
    this.start = nameStart;
    this.end = nameEnd;

    // Tell the parameter its index, so when we lookup a parameter by name, we know its positional index
    for (var i = 0; i < parameters.length; ++i)
        parameters[i].index = i;

    this.parameters = parameters;
    this.parameterMap = parameterMap;
    this.isFunction = isFunction;
    this.isVariadic = isVariadic;
    this.tokens = tokens;
};

Macro.prototype.isParameter = function(name)
{
    return this.parameterMap[name] !== undefined;
};

Macro.prototype.getParameterByName = function(name)
{
    return this.parameterMap[name];
};

Macro.prototype.getName = function()
{
    return this.name;
};

module.exports = Macro;
<commit_msg>Removed unused methods<commit_after>"use strict";

// A macro object. Note that a macro can have no parameters but still
// be a function macro if it is defined with an empty parameter list.
var Macro = function(name, nameStart, nameEnd, parameters, parameterMap, isFunction, isVariadic, tokens)
{
    this.name = name;
    this.start = nameStart;
    this.end = nameEnd;

    // Tell the parameter its index, so when we lookup a parameter by name, we know its positional index
    for (var i = 0; i < parameters.length; ++i)
        parameters[i].index = i;

    this.parameters = parameters;
    this.parameterMap = parameterMap;
    this.isFunction = isFunction;
    this.isVariadic = isVariadic;
    this.tokens = tokens;
};

Macro.prototype.getParameterByName = function(name)
{
    return this.parameterMap[name];
};

module.exports = Macro;
<|endoftext|>


<commit_before>var Gilt;
if (!Gilt) {
  Gilt = {};
}

Gilt.Hummingbird = {};

Gilt.Hummingbird.track = function(env) {
  delete env.trackingServer;
  delete env.trackingServerSecure;
  env.u = document.location.href;
  env.bw = window.innerWidth;
  env.bh = window.innerHeight;
  env.guid = document.cookie.match(/guid=([^\_]*)_([^;]*)/)[2];
  env.gen = document.cookie.match(/gender=([^;]*);/)[1];
  env.uid = document.cookie.match(/user_id=([^\_]*)_([^;]*)/)[2];

  $('body').append('');
};
<commit_msg>Generalize hummingbird tracker<commit_after>HummingbirdTracker = {};

HummingbirdTracker.track = function(env) {
  delete env.trackingServer;
  delete env.trackingServerSecure;
  env.u = document.location.href;
  env.bw = window.innerWidth;
  env.bh = window.innerHeight;
  env.guid = document.cookie.match(/guid=([^\_]*)_([^;]*)/)[2];
  env.gen = document.cookie.match(/gender=([^;]*);/)[1];
  env.uid = document.cookie.match(/user_id=([^\_]*)_([^;]*)/)[2];

  $('body').append('');
};
<|endoftext|>


<commit_before>import _ from 'lodash';
import ReplConsoleHook from '../common/ReplConsoleHook';
import ReplConstants from '../constants/ReplConstants';
import vm from 'vm';
import fs from 'fs';
import {dirname, resolve} from 'path';
import timers from 'timers';
import module from 'module';
import util from 'util';

let execSync = require('child_process').execSync;
let cxt = null;
let systemVariables = [];
let npmExe = resolve(__dirname, 'node_modules', '.bin', 'npm');

let getPreferences = () => global.Mancy.preferences;
let noop = () => {};
let linkFun = noop;
let link = (context) => { (linkFun || noop)(context); };

let hookContext = (fun) => {
  linkFun = fun;
}

let createContext = () => {
  if(cxt) { return cxt; }
  // sandbox
  let context = vm.createContext();
  let defaults = [
    'process',
    'Buffer',
    'console',
    'module',
    'require',
    '__filename',
    '__dirname'
  ];

  let circulars = [ '_', 'global', 'GLOBAL', 'root'];

  _.each(defaults, (g) => {
    context[g] = global[g];
  });

  _.each(circulars, (g) => {
    context[g] = context;
  });

  context.console = require('console');
  _.each(['error', 'warn', 'info', 'log', 'debug'], (fun) => {
    context.console[fun] = ReplConsoleHook[fun];
  });

  let timerFuns = [ 'clearImmediate', 'clearInterval', 'clearTimeout',
    'setImmediate', 'setInterval', 'setTimeout' ];

  _.each(timerFuns, (fun) => {
    context[fun] = timers[fun];
  });

  context.os = require('os');

  context.process.on('uncaughtException', function (err) {
    console.error(err);
  });

  let {createScript} = vm;
  vm.createScript = (code, options) => {
    try {
      let {timeout} = getPreferences();
      let cxt = createScript(code, options);
      let runInContext = cxt.runInContext.bind(cxt);
      cxt.runInContext = (contextifiedSandbox, options) => {
        return runInContext(contextifiedSandbox, {
          displayErrors: false,
          timeout: timeout
        });
      };
      global.Mancy.REPLError = null;
      return cxt;
    } catch(e) {
      if(e instanceof SyntaxError) {
        global.Mancy.REPLError = e;
      }
      throw e;
    }
  };

  let _load = module._load;
  module._load = (request, parent, isMain) => {
    try {
      return _load(request, parent, isMain);
    } catch(e) {
      let path = dirname(parent.paths[parent.paths.length - 1]);
      try {
        let child = execSync(`npm install ${request}`,
          { cwd: `${path}`, stdio:[], timeout: global.Mancy.preferences.timeout });
        return _load(request, parent, isMain);
      } catch(ex) {
        throw e;
      }
    }
  };

  let debuglog = util.debuglog;
  util.debuglog = (name) => {
    if(name === 'repl') {
      return (fun, e, ret) => {
        if(fun === 'finish' && !e) {
          // unlink context
          link({});
        }
        else if(fun === 'line %j') {
          // link context
          link(context);
        }
      };
    }
    return debuglog(name);
  };

  systemVariables = _.keys(context);

  if(process.platform !== 'win32' && context.process.env.PATH.indexOf() == -1) {
    context.process.env.PATH += ':/usr/local/bin';
  }

  // load builtIns
  let builtins = require('repl')._builtinLibs;
  _.each(builtins, (name) => {
    Object.defineProperty(context, name, {
      get: () => (context[name] = require(name)),
      set: (val) => {
        delete context[name];
        context[name] = val;
      },
      configurable: true
    });
  });

  return (cxt = context);
};

let getContext = () => {
  return cxt ? cxt : createContext();
};

let builtIns = () => {
  return systemVariables;
};

createContext();
export default { createContext, getContext, builtIns, hookContext };
<commit_msg>Clean up: os comes from builtins<commit_after>import _ from 'lodash';
import ReplConsoleHook from '../common/ReplConsoleHook';
import ReplConstants from '../constants/ReplConstants';
import vm from 'vm';
import fs from 'fs';
import {dirname, resolve} from 'path';
import timers from 'timers';
import module from 'module';
import util from 'util';

let execSync = require('child_process').execSync;
let cxt = null;
let systemVariables = [];
let npmExe = resolve(__dirname, 'node_modules', '.bin', 'npm');

let getPreferences = () => global.Mancy.preferences;
let noop = () => {};
let linkFun = noop;
let link = (context) => { (linkFun || noop)(context); };

let hookContext = (fun) => {
  linkFun = fun;
}

let createContext = () => {
  if(cxt) { return cxt; }
  // sandbox
  let context = vm.createContext();
  let defaults = [
    'process',
    'Buffer',
    'console',
    'module',
    'require',
    '__filename',
    '__dirname'
  ];

  let circulars = [ '_', 'global', 'GLOBAL', 'root'];

  _.each(defaults, (g) => {
    context[g] = global[g];
  });

  _.each(circulars, (g) => {
    context[g] = context;
  });

  context.console = require('console');
  _.each(['error', 'warn', 'info', 'log', 'debug'], (fun) => {
    context.console[fun] = ReplConsoleHook[fun];
  });

  let timerFuns = [ 'clearImmediate', 'clearInterval', 'clearTimeout',
    'setImmediate', 'setInterval', 'setTimeout' ];

  _.each(timerFuns, (fun) => {
    context[fun] = timers[fun];
  });

  context.process.on('uncaughtException', function (err) {
    console.error(err);
  });

  let {createScript} = vm;
  vm.createScript = (code, options) => {
    try {
      let {timeout} = getPreferences();
      let cxt = createScript(code, options);
      let runInContext = cxt.runInContext.bind(cxt);
      cxt.runInContext = (contextifiedSandbox, options) => {
        return runInContext(contextifiedSandbox, {
          displayErrors: false,
          timeout: timeout
        });
      };
      global.Mancy.REPLError = null;
      return cxt;
    } catch(e) {
      if(e instanceof SyntaxError) {
        global.Mancy.REPLError = e;
      }
      throw e;
    }
  };

  let _load = module._load;
  module._load = (request, parent, isMain) => {
    try {
      return _load(request, parent, isMain);
    } catch(e) {
      let path = dirname(parent.paths[parent.paths.length - 1]);
      try {
        let child = execSync(`npm install ${request}`,
          { cwd: `${path}`, stdio:[], timeout: global.Mancy.preferences.timeout });
        return _load(request, parent, isMain);
      } catch(ex) {
        throw e;
      }
    }
  };

  let debuglog = util.debuglog;
  util.debuglog = (name) => {
    if(name === 'repl') {
      return (fun, e, ret) => {
        if(fun === 'finish' && !e) {
          // unlink context
          link({});
        }
        else if(fun === 'line %j') {
          // link context
          link(context);
        }
      };
    }
    return debuglog(name);
  };

  systemVariables = _.keys(context);

  if(process.platform !== 'win32' && context.process.env.PATH.indexOf() == -1) {
    context.process.env.PATH += ':/usr/local/bin';
  }

  // load builtIns
  let builtins = require('repl')._builtinLibs;
  _.each(builtins, (name) => {
    Object.defineProperty(context, name, {
      get: () => (context[name] = require(name)),
      set: (val) => {
        delete context[name];
        context[name] = val;
      },
      configurable: true
    });
  });

  return (cxt = context);
};

let getContext = () => {
  return cxt ? cxt : createContext();
};

let builtIns = () => {
  return systemVariables;
};

createContext();
export default { createContext, getContext, builtIns, hookContext };
<|endoftext|>


<commit_before>/*global DOMPurify, Marionette, moment */

hqDefine("cloudcare/js/formplayer/menus/views/query", function () {
    // 'hqwebapp/js/hq.helpers' is a dependency. It needs to be added
    // explicitly when webapps is migrated to requirejs
    var kissmetrics = hqImport("analytix/js/kissmetrix");
    var FormplayerFrontend = hqImport("cloudcare/js/formplayer/app");
    var separator = " to ",
        dateFormat = "YYYY-MM-DD";
    var selectDelimiter = "#,#"; // Formplayer also uses this
    var Const = hqImport("cloudcare/js/form_entry/const"),
        Utils = hqImport("cloudcare/js/form_entry/utils"),
        initialPageData = hqImport("hqwebapp/js/initial_page_data");

    // special format handled by CaseSearch API
    var encodeValue = function (model, value, searchForBlank) {
            if (value && model.get("input") === "daterange") {
                value = "__range__" + value.replace(separator, "__");
            } else if (model.get('input') === 'select') {
                value = value.join(selectDelimiter);
            }

            var queryProvided = !(value === '' || (_.isArray(value) && _.isEmpty(value)));
            if (searchForBlank && queryProvided) {
                return selectDelimiter + value;
            } else if (queryProvided) {
                return value;
            } else if (searchForBlank) {
                return "";
            }
        },
        decodeValue = function (model, value) {
            if (!_.isString(value)) {
                return [false, undefined];
            }
            var values = value.split(selectDelimiter),
                searchForBlank = _.contains(values, ""),
                values = _.without(values, "");

            if (model.get('input') === 'select') {
                value = values;
            } else if (values.length === 1) {
                value = values[0];
                if (model.get("input") === "daterange") {
                    value = value.replace("__range__", "").replace("__", separator);
                }
            } else {
                value = undefined;
            }
            return [searchForBlank, value];
        },
        geocoderItemCallback = function (addressTopic, model) {
            return function (item) {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Interaction in Case Search");
                model.set('value', item.place_name);
                initMapboxWidget(model);
                var broadcastObj = Utils.getBroadcastObject(item);
                $.publish(addressTopic, broadcastObj);
                return item.place_name;
            };
        },
        geocoderOnClearCallback = function (addressTopic) {
            return function () {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Interaction in Case Search");
                $.publish(addressTopic, Const.NO_ANSWER);
            };
        },
        updateReceiver = function (element) {
            return function (_event, broadcastObj) {
                // e.g. format is home-state, home-zipcode, home-us_state||country
                var receiveExpression = element.data().receive;
                var receiveField = receiveExpression.split("-")[1];
                var value = null;
                if (broadcastObj === undefined || broadcastObj === Const.NO_ANSWER) {
                    value = Const.NO_ANSWER;
                } else if (broadcastObj[receiveField]) {
                    value = broadcastObj[receiveField];
                } else {
                    // match home-us_state||country style
                    var fields = receiveField.split('||');
                    $.each(fields, function (i, field) {
                        if (broadcastObj[field] !== undefined) {
                            value = broadcastObj[field];
                            return false;
                        }
                    });
                }
                // lookup DOM element again, in case the element got rerendered
                var domElement = $('*[data-receive="' + receiveExpression + '"]');
                if (domElement.is('input')) {
                    domElement.val(value);
                    domElement.change();
                }
                else {
                    // Set lookup table option by label
                    var matchingOption = function (el) {
                        return el.find("option").filter(function (_) {
                            return $(this).text().trim() === value;
                        });
                    }
                    var option = matchingOption(domElement);
                    if (domElement[0].multiple === true) {
                        var val = option.val();
                        if (option.length === 1 && domElement.val().indexOf(val) === -1) {
                            domElement.val(
                                domElement.val().concat(val)
                            ).trigger("change");
                        }
                    }
                    else {
                        if (option.length === 1) {
                            domElement.val(String(option.index() - 1)).trigger("change");
                        } else {
                            domElement.val("-1").trigger('change');
                        }
                    }
                }
            };
        },
        initMapboxWidget = function (model) {
            var id = model.get('id'),
                inputId = id + "_mapbox",
                $field = $("#" + inputId);
            $(function () {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Seen in Case Search");
            });
            if ($field.find('.mapboxgl-ctrl-geocoder--input').length === 0) {
                if (!initialPageData.get("has_geocoder_privs")) {
                    $("#" + inputId).addClass('unsupported alert alert-warning');
                    $("#" + inputId).text(gettext(
                        "Sorry, this input is not supported because your project doesn't have a Geocoder privilege")
                    );
                    return true;
                }
                Utils.renderMapboxInput(
                    inputId,
                    geocoderItemCallback(id, model),
                    geocoderOnClearCallback(id),
                    initialPageData
                );
                var divEl = $field.find('.mapboxgl-ctrl-geocoder');
                divEl.css("max-width", "none");
                divEl.css("width", "100%");
            }

            if (model.get('value')) {
                $field.find('.mapboxgl-ctrl-geocoder--input').val(model.get('value'));
            }
        };

    var QueryView = Marionette.View.extend({
        tagName: "tr",
        className: "formplayer-request",
        template: _.template($("#query-view-item-template").html() || ""),

        templateContext: function () {
            var imageUri = this.options.model.get('imageUri'),
                audioUri = this.options.model.get('audioUri'),
                appId = this.model.collection.appId,
                value = this.options.model.get('value');

            return {
                imageUrl: imageUri ? FormplayerFrontend.getChannel().request('resourceMap', imageUri, appId) : "",
                audioUrl: audioUri ? FormplayerFrontend.getChannel().request('resourceMap', audioUri, appId) : "",
                value: value,
                hasError: this.hasError,
            };
        },

        initialize: function () {
            this.parentView = this.options.parentView;
            this.model = this.options.model;
            this.hasError = false;

            var allStickyValues = hqImport("cloudcare/js/formplayer/utils/util").getStickyQueryInputs(),
                stickyValue = allStickyValues[this.model.get('id')],
                [searchForBlank, value] = decodeValue(this.model, stickyValue);
            if (value && !this.model.get('value')) {
                // Set the value and blank search checkbox from the sticky
                // values if available and no default is present
                this.model.set('value', value);
            }
            this.model.set('searchForBlank', searchForBlank);
        },

        ui: {
            valueDropdown: 'select.query-field',
            hqHelp: '.hq-help',
            dateRange: 'input.daterange',
            date: 'input.date',
            queryField: '.query-field',
            searchForBlank: '.search-for-blank',
        },

        events: {
            'dp.change @ui.queryField': function (e) {
                var self = this;
                // Without this, the datepicker popup won't show, because in the datepicker's
                // `show` function, the dp.change event is emitted before the popup is shown.
                // The delay makes sure this code doesn't run until the popup is shown.
                _.delay(function () {
                    self.changeQueryField(e);
                });
            },
            'change @ui.queryField': 'changeQueryField',
            'click @ui.searchForBlank': 'toggleBlankSearch',
        },

        modelEvents: {
            'change': 'render',
        },

        _isValid: function () {
            if (!this.model.get('required')) {
                return true;
            }

            var answer = this.getEncodedValue();
            return answer !== undefined && (answer === "" || answer.replace(/\s+/, "") !== "");
        },

        isValid: function () {
            var hasError = !this._isValid();
            if (hasError !== this.hasError) {
                this.hasError = hasError;
                this.render();
            }
            return !this.hasError;
        },

        clear: function () {
            var self = this;
            self.model.set('value', '');
            self.model.set('searchForBlank', false);
            if (self.ui.date.length) {
                self.ui.date.data("DateTimePicker").clear();
            }
        },

        getEncodedValue: function () {
            if (this.model.get('input') === 'address') {
                return;  // skip geocoder address
            }
            var queryValue = $(this.ui.queryField).val(),
                searchForBlank = $(this.ui.searchForBlank).prop('checked');
            return encodeValue(this.model, queryValue, searchForBlank);
        },

        changeQueryField: function (e) {
            if (this.model.get('input') === 'select1' || this.model.get('input') === 'select') {
                this.parentView.changeDropdown(e);
            } else if (this.model.get('input') === 'address') {
                // geocoderItemCallback sets the value on the model
            } else {
                this.model.set('value', $(e.currentTarget).val());
            }
            this.parentView.setStickyQueryInputs();
        },

        toggleBlankSearch: function (e) {
            var self = this,
                searchForBlank = $(e.currentTarget).prop('checked');
            self.model.set('searchForBlank', searchForBlank);

            // When checking the blank search box for a geocoder field, toggle all its receiver fields
            if (self.model.get('input') === 'address') {
                _.each(self.model.collection.models, function (relatedModel) {
                    if (relatedModel.get('receive') && relatedModel.get('receive').split("-")[0] === self.model.get('id')) {
                        relatedModel.set('searchForBlank', searchForBlank);
                    }
                });
                initMapboxWidget(this.model);
            }
            self.parentView.setStickyQueryInputs();
        },

        onRender: function () {
            this.ui.valueDropdown.select2({
                allowClear: true,
                placeholder: " ",   // required for allowClear to work
                escapeMarkup: function (m) { return DOMPurify.sanitize(m); },
            });
            this.ui.hqHelp.hqHelp();
            this.ui.date.datetimepicker({
                format: dateFormat,
            });
            this.ui.dateRange.daterangepicker({
                locale: {
                    format: dateFormat,
                    separator: separator,
                },
                autoUpdateInput: false,
                "autoApply": true,
            });
            this.ui.dateRange.on('cancel.daterangepicker', function () {
                $(this).val('').trigger('change');
            });
            this.ui.dateRange.on('apply.daterangepicker', function(ev, picker) {
                $(this).val(picker.startDate.format(dateFormat) + separator + picker.endDate.format(dateFormat)).trigger('change');
            });
            this.ui.dateRange.on('change', function () {
                // Validate free-text input. Accept anything moment can recognize as a date, reformatting for ES.
                var $input = $(this),
                    oldValue = $input.val(),
                    parts = _.map(oldValue.split(separator), function (v) { return moment(v); }),
                    newValue = '';

                if (_.every(parts, function (part) { return part.isValid(); }))  {
                    if (parts.length === 1) { // condition where only one valid date is typed in rather than a range
                        $input.val(oldValue + separator + oldValue).trigger('change');
                    } else if (parts.length === 2) {
                        newValue = parts[0].format(dateFormat) + separator + parts[1].format(dateFormat);
                    }
                }
                if (oldValue !== newValue) {
                    $input.val(newValue).trigger('change');
                }
            });
            if (this.model.get('hidden') === 'true') {
                this.$el.hide();
            }
        },

    });

    var QueryListView = Marionette.CollectionView.extend({
        tagName: "div",
        template: _.template($("#query-view-list-template").html() || ""),
        childView: QueryView,
        childViewContainer: "tbody",
        childViewOptions: function () { return {parentView: this}; },

        initialize: function (options) {
            this.parentModel = options.collection.models;
        },

        templateContext: function () {
            return {
                title: this.options.title,
            };
        },

        ui: {
            clearButton: '#query-clear-button',
            submitButton: '#query-submit-button',
            valueInput: 'input.query-field',
        },

        events: {
            'click @ui.clearButton': 'clearAction',
            'click @ui.submitButton': 'submitAction',
        },

        getAnswers: function () {
            var answers = {};
            this.children.each(function (childView) {
                var encodedValue = childView.getEncodedValue();
                if (encodedValue !== undefined) {
                    answers[childView.model.get('id')] = encodedValue;
                }
            });
            return answers;
        },

        changeDropdown: function (e) {
            e.preventDefault();
            var self = this;
            var $fields = $(".query-field");

            // If there aren't at least two dropdowns, there are no dependencies
            if ($fields.filter("select").length < 2) {
                return;
            }

            var Util = hqImport("cloudcare/js/formplayer/utils/util");
            var urlObject = Util.currentUrlToObject();
            urlObject.setQueryData(this.getAnswers(), false);
            var fetchingPrompts = FormplayerFrontend.getChannel().request("app:select:menus", urlObject);
            $.when(fetchingPrompts).done(function (response) {
                for (var i = 0; i < response.models.length; i++) {
                    var choices = response.models[i].get('itemsetChoices');
                    if (choices) {
                        var $field = $($fields.get(i)),
                            value = response.models[i].get('value');
                        if ($field.data('select2')) {
                            // force close dropdown, the set below can interfere with this when clearing selection
                            $field.select2('close');
                        }
                        if (value !== null) {
                            value = value.split(selectDelimiter);
                            value = _.filter(value, function (val) { return val !== ''; });
                            if (!$field.attr('multiple')) {
                                value = _.isEmpty(value) ? null : value[0];
                            }
                        }
                        self.collection.models[i].set({
                            itemsetChoices: choices,
                            value: value,
                        });
                        $field.trigger('change.select2');
                    }
                }
            });
        },

        clearAction: function () {
            var self = this;
            this.children.each(function (childView) {
                childView.clear();
                if (childView.model.get('input') === 'address') {
                    initMapboxWidget(childView.model);
                }
            });
            self.setStickyQueryInputs();
        },

        submitAction: function (e) {
            e.preventDefault();
            FormplayerFrontend.trigger('clearNotifications', errorHTML, true);

            var invalidFields = [];
            this.children.each(function (childView) {
                if (!childView.isValid()) {
                    invalidFields.push(childView.model.get('text'));
                }
            });

            if (invalidFields.length) {
                var errorHTML = "Please enter values for the following fields:";
                errorHTML += "
" + _.map(invalidFields, function (f) { return "
" + f + "
"; }).join("") + "
";
                FormplayerFrontend.trigger('showError', errorHTML, true);
                return;
            }

            FormplayerFrontend.trigger("menu:query", this.getAnswers());
        },

        setStickyQueryInputs: function () {
            var Util = hqImport("cloudcare/js/formplayer/utils/util");
            Util.setStickyQueryInputs(this.getAnswers());
        },

        onAttach: function () {
            this.initGeocoders();
        },

        initGeocoders: function () {
            var self = this;
            _.each(self.collection.models, function (model, i) {
                var $field = $($(".query-field")[i]);

                // Set geocoder receivers to subscribe
                if (model.get('receive')) {
                    var topic = model.get('receive').split("-")[0];
                    $.subscribe(topic, updateReceiver($field));
                }

                // Set geocoder address publish
                if (model.get('input') === 'address') {
                    initMapboxWidget(model);
                }
            });
        },

    });

    return function (data) {
        return new QueryListView(data);
    };
});
<commit_msg>Fixed QA-4227<commit_after>/*global DOMPurify, Marionette, moment */

hqDefine("cloudcare/js/formplayer/menus/views/query", function () {
    // 'hqwebapp/js/hq.helpers' is a dependency. It needs to be added
    // explicitly when webapps is migrated to requirejs
    var kissmetrics = hqImport("analytix/js/kissmetrix");
    var FormplayerFrontend = hqImport("cloudcare/js/formplayer/app");
    var separator = " to ",
        dateFormat = "YYYY-MM-DD";
    var selectDelimiter = "#,#"; // Formplayer also uses this
    var Const = hqImport("cloudcare/js/form_entry/const"),
        Utils = hqImport("cloudcare/js/form_entry/utils"),
        initialPageData = hqImport("hqwebapp/js/initial_page_data");

    // special format handled by CaseSearch API
    var encodeValue = function (model, value, searchForBlank) {
            if (value && model.get("input") === "daterange") {
                value = "__range__" + value.replace(separator, "__");
            } else if (model.get('input') === 'select') {
                value = value.join(selectDelimiter);
            }

            var queryProvided = !(value === '' || (_.isArray(value) && _.isEmpty(value)));
            if (searchForBlank && queryProvided) {
                return selectDelimiter + value;
            } else if (queryProvided) {
                return value;
            } else if (searchForBlank) {
                return "";
            }
        },
        decodeValue = function (model, value) {
            if (!_.isString(value)) {
                return [false, undefined];
            }
            var values = value.split(selectDelimiter),
                searchForBlank = _.contains(values, ""),
                values = _.without(values, "");

            if (model.get('input') === 'select') {
                value = values;
            } else if (values.length === 1) {
                value = values[0];
                if (model.get("input") === "daterange") {
                    value = value.replace("__range__", "").replace("__", separator);
                }
            } else {
                value = undefined;
            }
            return [searchForBlank, value];
        },
        geocoderItemCallback = function (addressTopic, model) {
            return function (item) {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Interaction in Case Search");
                model.set('value', item.place_name);
                initMapboxWidget(model);
                var broadcastObj = Utils.getBroadcastObject(item);
                $.publish(addressTopic, broadcastObj);
                return item.place_name;
            };
        },
        geocoderOnClearCallback = function (addressTopic) {
            return function () {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Interaction in Case Search");
                $.publish(addressTopic, Const.NO_ANSWER);
            };
        },
        updateReceiver = function (element) {
            return function (_event, broadcastObj) {
                // e.g. format is home-state, home-zipcode, home-us_state||country
                var receiveExpression = element.data().receive;
                var receiveField = receiveExpression.split("-")[1];
                var value = null;
                if (broadcastObj === undefined || broadcastObj === Const.NO_ANSWER) {
                    value = Const.NO_ANSWER;
                } else if (broadcastObj[receiveField]) {
                    value = broadcastObj[receiveField];
                } else {
                    // match home-us_state||country style
                    var fields = receiveField.split('||');
                    $.each(fields, function (i, field) {
                        if (broadcastObj[field] !== undefined) {
                            value = broadcastObj[field];
                            return false;
                        }
                    });
                }
                // lookup DOM element again, in case the element got rerendered
                var domElement = $('*[data-receive="' + receiveExpression + '"]');
                if (domElement.is('input')) {
                    domElement.val(value);
                    domElement.change();
                }
                else {
                    // Set lookup table option by label
                    var matchingOption = function (el) {
                        return el.find("option").filter(function (_) {
                            return $(this).text().trim() === value;
                        });
                    }
                    var option = matchingOption(domElement);
                    if (domElement[0].multiple === true) {
                        var val = option.val();
                        if (option.length === 1 && domElement.val().indexOf(val) === -1) {
                            domElement.val(
                                domElement.val().concat(val)
                            ).trigger("change");
                        }
                    }
                    else {
                        if (option.length === 1) {
                            domElement.val(String(option.index() - 1)).trigger("change");
                        } else {
                            domElement.val("-1").trigger('change');
                        }
                    }
                }
            };
        },
        initMapboxWidget = function (model) {
            var id = model.get('id'),
                inputId = id + "_mapbox",
                $field = $("#" + inputId);
            $(function () {
                kissmetrics.track.event("Accessibility Tracking - Geocoder Seen in Case Search");
            });
            if ($field.find('.mapboxgl-ctrl-geocoder--input').length === 0) {
                if (!initialPageData.get("has_geocoder_privs")) {
                    $("#" + inputId).addClass('unsupported alert alert-warning');
                    $("#" + inputId).text(gettext(
                        "Sorry, this input is not supported because your project doesn't have a Geocoder privilege")
                    );
                    return true;
                }
                Utils.renderMapboxInput(
                    inputId,
                    geocoderItemCallback(id, model),
                    geocoderOnClearCallback(id),
                    initialPageData
                );
                var divEl = $field.find('.mapboxgl-ctrl-geocoder');
                divEl.css("max-width", "none");
                divEl.css("width", "100%");
            }

            if (model.get('value')) {
                $field.find('.mapboxgl-ctrl-geocoder--input').val(model.get('value'));
            }
        };

    var QueryView = Marionette.View.extend({
        tagName: "tr",
        className: "formplayer-request",
        template: _.template($("#query-view-item-template").html() || ""),

        templateContext: function () {
            var imageUri = this.options.model.get('imageUri'),
                audioUri = this.options.model.get('audioUri'),
                appId = this.model.collection.appId,
                value = this.options.model.get('value');

            return {
                imageUrl: imageUri ? FormplayerFrontend.getChannel().request('resourceMap', imageUri, appId) : "",
                audioUrl: audioUri ? FormplayerFrontend.getChannel().request('resourceMap', audioUri, appId) : "",
                value: value,
                hasError: this.hasError,
            };
        },

        initialize: function () {
            this.parentView = this.options.parentView;
            this.model = this.options.model;
            this.hasError = false;

            var allStickyValues = hqImport("cloudcare/js/formplayer/utils/util").getStickyQueryInputs(),
                stickyValue = allStickyValues[this.model.get('id')],
                [searchForBlank, value] = decodeValue(this.model, stickyValue);
            if (value && !this.model.get('value')) {
                // Set the value and blank search checkbox from the sticky
                // values if available and no default is present
                this.model.set('value', value);
            }
            this.model.set('searchForBlank', searchForBlank);
        },

        ui: {
            valueDropdown: 'select.query-field',
            hqHelp: '.hq-help',
            dateRange: 'input.daterange',
            date: 'input.date',
            queryField: '.query-field',
            searchForBlank: '.search-for-blank',
        },

        events: {
            'change @ui.queryField': 'changeQueryField',
            'dp.change @ui.queryField': 'changeDateQueryField',
            'click @ui.searchForBlank': 'toggleBlankSearch',
        },

        modelEvents: {
            'change': 'render',
        },

        _isValid: function () {
            if (!this.model.get('required')) {
                return true;
            }

            var answer = this.getEncodedValue();
            return answer !== undefined && (answer === "" || answer.replace(/\s+/, "") !== "");
        },

        isValid: function () {
            var hasError = !this._isValid();
            if (hasError !== this.hasError) {
                this.hasError = hasError;
                this.render();
            }
            return !this.hasError;
        },

        clear: function () {
            var self = this;
            self.model.set('value', '');
            self.model.set('searchForBlank', false);
            if (self.ui.date.length) {
                self.ui.date.data("DateTimePicker").clear();
            }
        },

        getEncodedValue: function () {
            if (this.model.get('input') === 'address') {
                return;  // skip geocoder address
            }
            var queryValue = $(this.ui.queryField).val(),
                searchForBlank = $(this.ui.searchForBlank).prop('checked');
            return encodeValue(this.model, queryValue, searchForBlank);
        },

        changeQueryField: function (e) {
            if (this.model.get('input') === 'date') {
                // Skip because dates get handled by changeDateQueryField
                return;
            } else if (this.model.get('input') === 'select1' || this.model.get('input') === 'select') {
                this.parentView.changeDropdown(e);
            } else if (this.model.get('input') === 'address') {
                // geocoderItemCallback sets the value on the model
            } else {
                this.model.set('value', $(e.currentTarget).val());
            }
            this.parentView.setStickyQueryInputs();
        },
        changeDateQueryField: function (e) {
            this.changeQueryField(e);
            this.parentView.setStickyQueryInputs();
        },

        toggleBlankSearch: function (e) {
            var self = this,
                searchForBlank = $(e.currentTarget).prop('checked');
            self.model.set('searchForBlank', searchForBlank);

            // When checking the blank search box for a geocoder field, toggle all its receiver fields
            if (self.model.get('input') === 'address') {
                _.each(self.model.collection.models, function (relatedModel) {
                    if (relatedModel.get('receive') && relatedModel.get('receive').split("-")[0] === self.model.get('id')) {
                        relatedModel.set('searchForBlank', searchForBlank);
                    }
                });
                initMapboxWidget(this.model);
            }
            self.parentView.setStickyQueryInputs();
        },

        onRender: function () {
            this.ui.valueDropdown.select2({
                allowClear: true,
                placeholder: " ",   // required for allowClear to work
                escapeMarkup: function (m) { return DOMPurify.sanitize(m); },
            });
            this.ui.hqHelp.hqHelp();
            this.ui.date.datetimepicker({
                format: dateFormat,
            });
            this.ui.dateRange.daterangepicker({
                locale: {
                    format: dateFormat,
                    separator: separator,
                },
                autoUpdateInput: false,
                "autoApply": true,
            });
            this.ui.dateRange.on('cancel.daterangepicker', function () {
                $(this).val('').trigger('change');
            });
            this.ui.dateRange.on('apply.daterangepicker', function(ev, picker) {
                $(this).val(picker.startDate.format(dateFormat) + separator + picker.endDate.format(dateFormat)).trigger('change');
            });
            this.ui.dateRange.on('change', function () {
                // Validate free-text input. Accept anything moment can recognize as a date, reformatting for ES.
                var $input = $(this),
                    oldValue = $input.val(),
                    parts = _.map(oldValue.split(separator), function (v) { return moment(v); }),
                    newValue = '';

                if (_.every(parts, function (part) { return part.isValid(); }))  {
                    if (parts.length === 1) { // condition where only one valid date is typed in rather than a range
                        $input.val(oldValue + separator + oldValue).trigger('change');
                    } else if (parts.length === 2) {
                        newValue = parts[0].format(dateFormat) + separator + parts[1].format(dateFormat);
                    }
                }
                if (oldValue !== newValue) {
                    $input.val(newValue).trigger('change');
                }
            });
            if (this.model.get('hidden') === 'true') {
                this.$el.hide();
            }
        },

    });

    var QueryListView = Marionette.CollectionView.extend({
        tagName: "div",
        template: _.template($("#query-view-list-template").html() || ""),
        childView: QueryView,
        childViewContainer: "tbody",
        childViewOptions: function () { return {parentView: this}; },

        initialize: function (options) {
            this.parentModel = options.collection.models;
        },

        templateContext: function () {
            return {
                title: this.options.title,
            };
        },

        ui: {
            clearButton: '#query-clear-button',
            submitButton: '#query-submit-button',
            valueInput: 'input.query-field',
        },

        events: {
            'click @ui.clearButton': 'clearAction',
            'click @ui.submitButton': 'submitAction',
        },

        getAnswers: function () {
            var answers = {};
            this.children.each(function (childView) {
                var encodedValue = childView.getEncodedValue();
                if (encodedValue !== undefined) {
                    answers[childView.model.get('id')] = encodedValue;
                }
            });
            return answers;
        },

        changeDropdown: function (e) {
            e.preventDefault();
            var self = this;
            var $fields = $(".query-field");

            // If there aren't at least two dropdowns, there are no dependencies
            if ($fields.filter("select").length < 2) {
                return;
            }

            var Util = hqImport("cloudcare/js/formplayer/utils/util");
            var urlObject = Util.currentUrlToObject();
            urlObject.setQueryData(this.getAnswers(), false);
            var fetchingPrompts = FormplayerFrontend.getChannel().request("app:select:menus", urlObject);
            $.when(fetchingPrompts).done(function (response) {
                for (var i = 0; i < response.models.length; i++) {
                    var choices = response.models[i].get('itemsetChoices');
                    if (choices) {
                        var $field = $($fields.get(i)),
                            value = response.models[i].get('value');
                        if ($field.data('select2')) {
                            // force close dropdown, the set below can interfere with this when clearing selection
                            $field.select2('close');
                        }
                        if (value !== null) {
                            value = value.split(selectDelimiter);
                            value = _.filter(value, function (val) { return val !== ''; });
                            if (!$field.attr('multiple')) {
                                value = _.isEmpty(value) ? null : value[0];
                            }
                        }
                        self.collection.models[i].set({
                            itemsetChoices: choices,
                            value: value,
                        });
                        $field.trigger('change.select2');
                    }
                }
            });
        },

        clearAction: function () {
            var self = this;
            this.children.each(function (childView) {
                childView.clear();
                if (childView.model.get('input') === 'address') {
                    initMapboxWidget(childView.model);
                }
            });
            self.setStickyQueryInputs();
        },

        submitAction: function (e) {
            e.preventDefault();
            FormplayerFrontend.trigger('clearNotifications', errorHTML, true);

            var invalidFields = [];
            this.children.each(function (childView) {
                if (!childView.isValid()) {
                    invalidFields.push(childView.model.get('text'));
                }
            });

            if (invalidFields.length) {
                var errorHTML = "Please enter values for the following fields:";
                errorHTML += "
" + _.map(invalidFields, function (f) { return "
" + f + "
"; }).join("") + "
";
                FormplayerFrontend.trigger('showError', errorHTML, true);
                return;
            }

            FormplayerFrontend.trigger("menu:query", this.getAnswers());
        },

        setStickyQueryInputs: function () {
            var Util = hqImport("cloudcare/js/formplayer/utils/util");
            Util.setStickyQueryInputs(this.getAnswers());
        },

        onAttach: function () {
            this.initGeocoders();
        },

        initGeocoders: function () {
            var self = this;
            _.each(self.collection.models, function (model, i) {
                var $field = $($(".query-field")[i]);

                // Set geocoder receivers to subscribe
                if (model.get('receive')) {
                    var topic = model.get('receive').split("-")[0];
                    $.subscribe(topic, updateReceiver($field));
                }

                // Set geocoder address publish
                if (model.get('input') === 'address') {
                    initMapboxWidget(model);
                }
            });
        },

    });

    return function (data) {
        return new QueryListView(data);
    };
});
<|endoftext|>