<commit_before>"use strict"
var MyCharts = (function(){
	var chartObjectParameter,
		defaultValue,
		constructor,
		validate,
		errorMessages,
		raiseError,
		chartType,
		startPreparingTheChart,
		misc,
		events,
		attributes,
		settingUpCommonAttributesNotSpecified,
		setupChartContainer;

	defaultValue = {
		chartId: "chart1",
		chartContainerId: "chart",
		chartType: "bullseye",
		height: "300px",
		width: "300px",
		dataType: "JSON",
		dataSource: []
	};

	chartType = [
		"bullseye",
		"triangle"
	];

	/**
	*	This object holds the basic attribute value
	*/
	attributes = {
		common: {
			// common attributes are applicable for all chart types
			captionSpaceWidth: 0,
			captionSpaceHeight: 0,
			xAxisWidth: 0,
			yAxisHeight: 0,
			isAnimate: 0,
			backgroundColor: ""
		},
		chartSpecific: {
			// chart specific attributes are only for specific charts
			bullseye: {
				minRadius: 0
			},
			triangle: {

			}
		}

	};

	/*
	*	Holds all the error messages
	*/
	errorMessages = {
		ivalidId: "The provided chart ID is invalid",
		invalidContainerId: "The provided container id is not valid",
		containerNotFound: "Can't find the container in page",
		chartTypeNotSupported: "Provided chartType not supported"
	},

	/**
	* Holds all the supported events
	*/
	events = {
		beforeRender: null,
		afterRender: null
	};

	raiseError = (function(message){
		console.error(message);
	});

	/**
	*	This object holds all the validation methods
	*/
	validate = {
		chartId: function(id) {
			if(id.trim()=="") {
				return false;
			}
			if(id.trim().indexOf(" ")!=-1) {
				raiseError(errorMessages.invalId);
				return false;
			}
			return true;
		},
		chartContainerId: function(id) {
			if(id.trim()=="") {
				return false;
			}
			if(id.trim().indexOf(" ") !== -1) {
				raiseError(errorMessages.invalidContainerId);
				return false;
			}

			return true;
		},
		chartType: function(type) {
			if(type.trim()=="") {
				return false;
			}
			type = type.trim().toLowerCase();
			if(chartType.indexOf(type) === -1) {
				raiseError(errorMessages.chartTypeNotSupported);
				return false;
			}
			return true;
		},
		checkWidthHeight: function(width, height) {
			return true;
		},
		checkDataType: function(dataType) {
			return true;
		},
		checkData: function(data, dataType) {
			return true;
		}
	}

	/**
	* This object holds all the miscellaneous methods which used throughout the program
	*/
	misc = {
		sort: function(data) {
			var index1, index2, tempData, length;
			length = data.length;
			for(index1=0; index1<length; index1++) {
				for(index2=0; index2<(length-index1-1); index2++) {
					if(data[index2].value > data[index2+1].value) {
						tempData = data[index2];
						data[index2+1] = data[index2];
						data[index2+1] = tempData;
					}
				}
			}
			return data;
		}
	}

	/**
	*	This object is fullfilled by constructor and holds the things needed to populate the chart
	*/
	chartObjectParameter = {
		chartId: defaultValue.chartId,
		chartContainer: document.getElementById(defaultValue.chartContainerId),
		chartType: defaultValue.chartType,
		width: defaultValue.width,
		height: defaultValue.height,
		dataType: defaultValue.dataType,
		dataSource: defaultValue.dataSource,
		attributes: {}
	};

	/**
	*	This is the constructor and it's purpose is to validate and prepare the chartObjectParameter object
	*	arguments[0][0] = chartId
	*	arguments[0][1] = chartContainerId
	*	arguments[0][2] = chartType
	*	arguments[0][3] = width
	*	arguments[0][4] = height
	*	arguments[0][5] = chartDataType
	*	arguments[0][6] = dataSource
	*	arguments[0][7] = attributesOptions
	*/
	constructor = (function(){
		var chartSpecificAttributes,
			commonAttributes,
			index;
		if(validate.chartId(arguments[0][0])){
			chartObjectParameter.chartId = arguments[0][0].trim();
		}

		if(validate.chartContainerId(arguments[0][1])){
			chartObjectParameter.chartContainer = arguments[0][1].trim();
		}

		if(validate.chartType(arguments[0][2])) {
			chartObjectParameter.chartType = arguments[0][2].trim().toLowerCase();
		}

		if(validate.checkWidthHeight(arguments[0][3], arguments[0][4])) {
			chartObjectParameter.width = arguments[0][3];
			chartObjectParameter.height = arguments[0][4];
		}

		if(validate.checkDataType(arguments[0][5])) {
			chartObjectParameter.dataType = arguments[0][5].trim().toUpperCase();
		}

		if(validate.checkData(arguments[0][6], chartObjectParameter.dataType)) {
			chartObjectParameter.dataSource = misc.sort(arguments[0][6]);
		} else {
			return false;
		}

		if(typeof arguments[0][7] !== "undefined") {
			chartObjectParameter.attributes = arguments[0][7];

			//chartObjectParameter.attributes = attributes.common;
			commonAttributes = attributes.common;
			for(index in commonAttributes) {
				if(typeof chartObjectParameter.attributes[commonAttributes[index]] === "undefined") {
					chartObjectParameter.attributes[commonAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
				}
			}

			chartSpecificAttributes = Object.keys(attributes.chartSpecific[chartObjectParameter.chartType]);
			for(index in chartSpecificAttributes) {
				if(typeof chartObjectParameter.attributes[chartSpecificAttributes[index]] === "undefined") {
					chartObjectParameter.attributes[chartSpecificAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
				}
			}
		} else {
			// merging common attributes and chart specific attributes to chartObjectParameter
			chartObjectParameter.attributes = attributes.common;
			chartSpecificAttributes = Object.keys(attributes.chartSpecific[chartObjectParameter.chartType]);
			for(index in chartSpecificAttributes) {
				chartObjectParameter.attributes[chartSpecificAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
			}
		}
	})(arguments);

	setupChartContainer = (function() {console.log(chartObjectParameter.chartContainer);
		var tempObject = document.getElementById(chartObjectParameter.chartContainer);
		if(!tempObject) {
			raiseError(errorMessages.containerNotFound);
			return false;
		} else {
			chartObjectParameter.chartContainer = tempObject;
		}
		return true;
	});

	/**
	* This function will setup the attributes which is not specified by user
	*/
	settingUpCommonAttributesNotSpecified = (function(){
		if(!chartObjectParameter.attributes.xAxisHeight) {
			chartObjectParameter.attributes.xAxisHeight = ((chartObjectParameter.width*1.67)/100);
		}
		if(!chartObjectParameter.attributes.yAxisHeight) {
			chartObjectParameter.attributes.yAxisHeight = ((chartObjectParameter.height*1.67)/100);
		}
		if(!chartObjectParameter.attributes.captionSpaceWidth) {
			chartObjectParameter.attributes.captionSpaceWidth = ((chartObjectParameter.width*1.67)/100);
		}
		if(!chartObjectParameter.attributes.captionSpaceHeight) {
			chartObjectParameter.attributes.captionSpaceHeight = ((chartObjectParameter.height*1.67)/100);
		}
		if(chartObjectParameter.attributes.backgroundColor.trim() === "") {
			chartObjectParameter.attributes.backgroundColor = "#ccffcc";
		}
	});

	startPreparingTheChart = (function() {
		console.log(chartObjectParameter);
		settingUpCommonAttributesNotSpecified();
		// if before render event is specified, firing the evenet
		if(events.beforeRender) {
			events.beforeRender();
		}
	});
	this.beforeRender = (function(fn) {
		events.beforeRender = fn;
	});
	this.afterRender = (function(fn) {
		events.afterRender = fn;
	});
	this.render = (function(){
		if(!setupChartContainer()) {
			return false;
		}

		startPreparingTheChart();

		// if after render event is specified, firing the event
		if(events.afterRender) {
			events.afterRender();
		}
	});

});<commit_msg>setting up default attribute continues<commit_after>"use strict"
var MyCharts = (function(){
	var chartObjectParameter,
		defaultValue,
		constructor,
		validate,
		errorMessages,
		raiseError,
		chartType,
		startPreparingTheChart,
		misc,
		events,
		attributes,
		settingUpCommonAttributesNotSpecified,
		setupChartContainer;

	defaultValue = {
		chartId: "chart1",
		chartContainerId: "chart",
		chartType: "bullseye",
		height: "300px",
		width: "300px",
		dataType: "JSON",
		dataSource: []
	};

	chartType = [
		"bullseye",
		"triangle"
	];

	/**
	*	This object holds the basic attribute value
	*/
	attributes = {
		common: {
			// common attributes are applicable for all chart types
			captionSpaceWidth: 0,
			captionSpaceHeight: 0,
			xAxisHeight: 0,
			yAxisWidth: 0,
			isAnimate: 0,
			backgroundColor: ""
		},
		chartSpecific: {
			// chart specific attributes are only for specific charts
			bullseye: {
				minRadius: 0
			},
			triangle: {

			}
		}

	};

	/*
	*	Holds all the error messages
	*/
	errorMessages = {
		ivalidId: "The provided chart ID is invalid",
		invalidContainerId: "The provided container id is not valid",
		containerNotFound: "Can't find the container in page",
		chartTypeNotSupported: "Provided chartType not supported"
	},

	/**
	* Holds all the supported events
	*/
	events = {
		beforeRender: null,
		afterRender: null
	};

	raiseError = (function(message){
		console.error(message);
	});

	/**
	*	This object holds all the validation methods
	*/
	validate = {
		chartId: function(id) {
			if(id.trim()=="") {
				return false;
			}
			if(id.trim().indexOf(" ")!=-1) {
				raiseError(errorMessages.invalId);
				return false;
			}
			return true;
		},
		chartContainerId: function(id) {
			if(id.trim()=="") {
				return false;
			}
			if(id.trim().indexOf(" ") !== -1) {
				raiseError(errorMessages.invalidContainerId);
				return false;
			}

			return true;
		},
		chartType: function(type) {
			if(type.trim()=="") {
				return false;
			}
			type = type.trim().toLowerCase();
			if(chartType.indexOf(type) === -1) {
				raiseError(errorMessages.chartTypeNotSupported);
				return false;
			}
			return true;
		},
		checkWidthHeight: function(width, height) {
			return true;
		},
		checkDataType: function(dataType) {
			return true;
		},
		checkData: function(data, dataType) {
			return true;
		}
	}

	/**
	* This object holds all the miscellaneous methods which used throughout the program
	*/
	misc = {
		sort: function(data) {
			var index1, index2, tempData, length;
			length = data.length;
			for(index1=0; index1<length; index1++) {
				for(index2=0; index2<(length-index1-1); index2++) {
					if(data[index2].value > data[index2+1].value) {
						tempData = data[index2];
						data[index2+1] = data[index2];
						data[index2+1] = tempData;
					}
				}
			}
			return data;
		}
	}

	/**
	*	This object is fullfilled by constructor and holds the things needed to populate the chart
	*/
	chartObjectParameter = {
		chartId: defaultValue.chartId,
		chartContainer: document.getElementById(defaultValue.chartContainerId),
		chartType: defaultValue.chartType,
		width: defaultValue.width,
		height: defaultValue.height,
		dataType: defaultValue.dataType,
		dataSource: defaultValue.dataSource,
		attributes: {}
	};

	/**
	*	This is the constructor and it's purpose is to validate and prepare the chartObjectParameter object
	*	arguments[0][0] = chartId
	*	arguments[0][1] = chartContainerId
	*	arguments[0][2] = chartType
	*	arguments[0][3] = width
	*	arguments[0][4] = height
	*	arguments[0][5] = chartDataType
	*	arguments[0][6] = dataSource
	*	arguments[0][7] = attributesOptions
	*/
	constructor = (function(){
		var chartSpecificAttributes,
			commonAttributes,
			index;
		if(validate.chartId(arguments[0][0])){
			chartObjectParameter.chartId = arguments[0][0].trim();
		}

		if(validate.chartContainerId(arguments[0][1])){
			chartObjectParameter.chartContainer = arguments[0][1].trim();
		}

		if(validate.chartType(arguments[0][2])) {
			chartObjectParameter.chartType = arguments[0][2].trim().toLowerCase();
		}

		if(validate.checkWidthHeight(arguments[0][3], arguments[0][4])) {
			chartObjectParameter.width = arguments[0][3];
			chartObjectParameter.height = arguments[0][4];
		}

		if(validate.checkDataType(arguments[0][5])) {
			chartObjectParameter.dataType = arguments[0][5].trim().toUpperCase();
		}

		if(validate.checkData(arguments[0][6], chartObjectParameter.dataType)) {
			chartObjectParameter.dataSource = misc.sort(arguments[0][6]);
		} else {
			return false;
		}

		if(typeof arguments[0][7] !== "undefined") {
			chartObjectParameter.attributes = arguments[0][7];

			//chartObjectParameter.attributes = attributes.common;
			commonAttributes = attributes.common;
			for(index in commonAttributes) {
				if(typeof chartObjectParameter.attributes[commonAttributes[index]] === "undefined") {
					chartObjectParameter.attributes[commonAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
				}
			}

			chartSpecificAttributes = Object.keys(attributes.chartSpecific[chartObjectParameter.chartType]);
			for(index in chartSpecificAttributes) {
				if(typeof chartObjectParameter.attributes[chartSpecificAttributes[index]] === "undefined") {
					chartObjectParameter.attributes[chartSpecificAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
				}
			}
		} else {
			// merging common attributes and chart specific attributes to chartObjectParameter
			chartObjectParameter.attributes = attributes.common;
			chartSpecificAttributes = Object.keys(attributes.chartSpecific[chartObjectParameter.chartType]);
			for(index in chartSpecificAttributes) {
				chartObjectParameter.attributes[chartSpecificAttributes[index]] = attributes.chartSpecific[chartObjectParameter.chartType][chartSpecificAttributes[index]];
			}
		}
	})(arguments);

	setupChartContainer = (function() {console.log(chartObjectParameter.chartContainer);
		var tempObject = document.getElementById(chartObjectParameter.chartContainer);
		if(!tempObject) {
			raiseError(errorMessages.containerNotFound);
			return false;
		} else {
			chartObjectParameter.chartContainer = tempObject;
		}
		return true;
	});

	/**
	* This function will setup the attributes which is not specified by user
	*/
	settingUpCommonAttributesNotSpecified = (function(){
		if(!chartObjectParameter.attributes.xAxisHeight) {
			chartObjectParameter.attributes.xAxisHeight = ((chartObjectParameter.width*1.67)/100);
		}
		if(!chartObjectParameter.attributes.yAxisWidth) {
			chartObjectParameter.attributes.yAxisWidth = ((chartObjectParameter.height*1.67)/100);
		}
		if(!chartObjectParameter.attributes.captionSpaceWidth) {
			chartObjectParameter.attributes.captionSpaceWidth = ((chartObjectParameter.width*1.67)/100);
		}
		if(!chartObjectParameter.attributes.captionSpaceHeight) {
			chartObjectParameter.attributes.captionSpaceHeight = ((chartObjectParameter.height*1.67)/100);
		}
		if(chartObjectParameter.attributes.backgroundColor.trim() === "") {
			chartObjectParameter.attributes.backgroundColor = "#ccffcc";
		}
	});

	startPreparingTheChart = (function() {
		console.log(chartObjectParameter);
		settingUpCommonAttributesNotSpecified();
		// if before render event is specified, firing the evenet
		if(events.beforeRender) {
			events.beforeRender();
		}
	});
	this.beforeRender = (function(fn) {
		events.beforeRender = fn;
	});
	this.afterRender = (function(fn) {
		events.afterRender = fn;
	});
	this.render = (function(){
		if(!setupChartContainer()) {
			return false;
		}

		startPreparingTheChart();

		// if after render event is specified, firing the event
		if(events.afterRender) {
			events.afterRender();
		}
	});

});<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const isProduction = process.env.NODE_ENV === 'production'

const ROOT = path.join(__dirname, '/../')

const config = {
  entry: {
    bundled: [
      'jquery',
      'bootstrap-sass',
      'inline-attachment/src/inline-attachment.js',
      'jquery.cookie',
      './client/thirdparty-js/jquery.selection.js',
      'babel-polyfill',
    ],
    app: path.join(ROOT, 'client/app.js'),
    crowi: path.join(ROOT, 'client/crowi.js'),
    presentation: path.join(ROOT, 'client/crowi-presentation.js'),
    form: path.join(ROOT, 'client/crowi-form.js'),
    admin: path.join(ROOT, 'client/crowi-admin.js'),
  },
  output: {
    path: path.join(ROOT, 'public/js'),
    filename: '[name].js',
  },
  devtool: 'inline-source-map',
  resolve: {
    modules: ['./node_modules', './client/thirdparty-js'],
  },
  module: {
    rules: [
      {
        test: /\.ya?ml$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'json-loader',
          },
          {
            loader: 'yaml-loader',
          },
        ],
      },
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.EnvironmentPlugin(['NODE_ENV']),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'bundled',
      minChunks: Infinity,
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
    new CopyWebpackPlugin([
      { from: path.join(ROOT, 'node_modules/reveal.js/css'), to: path.join(ROOT, 'public/css/reveal/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/css'), to: path.join(ROOT, 'public/js/reveal/lib/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/js'), to: path.join(ROOT, 'public/js/reveal/lib/js') },
      { from: path.join(ROOT, 'node_modules/reveal.js/plugin'), to: path.join(ROOT, 'public/js/reveal/plugin/') },
    ]),
  ],
}

if (isProduction) {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
    }),
  )
}

module.exports = config
<commit_msg>Migrate to optimization.splitChunks<commit_after>const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const isProduction = process.env.NODE_ENV === 'production'

const ROOT = path.join(__dirname, '/../')

const config = {
  entry: {
    bundled: [
      'jquery',
      'bootstrap-sass',
      'inline-attachment/src/inline-attachment.js',
      'jquery.cookie',
      './client/thirdparty-js/jquery.selection.js',
      'babel-polyfill',
    ],
    app: path.join(ROOT, 'client/app.js'),
    crowi: path.join(ROOT, 'client/crowi.js'),
    presentation: path.join(ROOT, 'client/crowi-presentation.js'),
    form: path.join(ROOT, 'client/crowi-form.js'),
    admin: path.join(ROOT, 'client/crowi-admin.js'),
  },
  output: {
    path: path.join(ROOT, 'public/js'),
    filename: '[name].js',
  },
  devtool: 'inline-source-map',
  resolve: {
    modules: ['./node_modules', './client/thirdparty-js'],
  },
  module: {
    rules: [
      {
        test: /\.ya?ml$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'json-loader',
          },
          {
            loader: 'yaml-loader',
          },
        ],
      },
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
        ],
      },
    ],
  },
  optimization: {
    splitChunks: {
      name: 'bundled',
    },
  },
  plugins: [
    new webpack.EnvironmentPlugin(['NODE_ENV']),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
    new CopyWebpackPlugin([
      { from: path.join(ROOT, 'node_modules/reveal.js/css'), to: path.join(ROOT, 'public/css/reveal/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/css'), to: path.join(ROOT, 'public/js/reveal/lib/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/js'), to: path.join(ROOT, 'public/js/reveal/lib/js') },
      { from: path.join(ROOT, 'node_modules/reveal.js/plugin'), to: path.join(ROOT, 'public/js/reveal/plugin/') },
    ]),
  ],
}

if (isProduction) {
  config.plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
    }),
  )
}

module.exports = config
<|endoftext|>


<commit_before>import init from "../_utils/plugin-init";

class #{blockname.pascalCase} {
  constructor(element, options) {
    this.element = element;
    this.name = "#{blockname.dashCase}";

    this._defaults = {};

    this.options = {
      ...this._defaults,
      ...options
    };

    this.init();
  }

  init() {
    this.buildCache();
    this.bindEvents();
  }

  buildCache() {}

  bindEvents() {}
}

export default init(#{blockname.pascalCase});
<commit_msg>Update javscript template<commit_after>import Plugin, { init } from "@/modules/_utils/Plugin";

class #{blockname.pascalCase} extends Plugin {
  defaults() {
    return {};
  }

  init() {}

  buildCache() {}

  bindEvents() {}
}

export default init(#{blockname.pascalCase}, "#{blockname.dashCase}");
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import config from 'config:@sanity/google-maps-input'
import Button from 'part:@sanity/components/buttons/default'
import Dialog from 'part:@sanity/components/dialogs/default'
import Fieldset from 'part:@sanity/components/fieldsets/default'
import {PatchEvent, set, setIfMissing, unset} from 'part:@sanity/form-builder/patch-event'
import styles from '../styles/GeopointInput.css'
import GeopointSelect from './GeopointSelect'
import GoogleMapsLoadProxy from './GoogleMapsLoadProxy'

const getLocale = context => {
  const intl = context.intl || {}
  return intl.locale || (typeof window !== 'undefined' && window.navigator.language) || 'en'
}

const getStaticImageUrl = value => {
  const loc = `${value.lat},${value.lng}`
  const params = {
    key: config.apiKey,
    center: loc,
    markers: loc,
    zoom: 13,
    scale: 2,
    size: '640x300'
  }

  const qs = Object.keys(params).reduce((res, param) => {
    return res.concat(`${param}=${encodeURIComponent(params[param])}`)
  }, [])

  return `https://maps.googleapis.com/maps/api/staticmap?${qs.join('&')}`
}

class GeopointInput extends React.Component {
  static propTypes = {
    onChange: PropTypes.func.isRequired,
    markers: PropTypes.arrayOf(
      PropTypes.shape({
        type: PropTypes.string
      })
    ),
    value: PropTypes.shape({
      lat: PropTypes.number,
      lng: PropTypes.number
    }),
    type: PropTypes.shape({
      title: PropTypes.string.isRequired,
      description: PropTypes.string
    })
  }

  static defaultProps = {
    markers: []
  }

  static contextTypes = {
    intl: PropTypes.shape({
      locale: PropTypes.string
    })
  }

  constructor() {
    super()

    this.handleToggleModal = this.handleToggleModal.bind(this)
    this.handleCloseModal = this.handleCloseModal.bind(this)

    this.state = {
      modalOpen: false
    }
  }

  handleToggleModal() {
    this.setState(prevState => ({modalOpen: !prevState.modalOpen}))
  }

  handleChange = latLng => {
    const {type, onChange} = this.props
    onChange(
      PatchEvent.from([
        setIfMissing({
          _type: type.name
        }),
        set(latLng.lat(), ['lat']),
        set(latLng.lng(), ['lng'])
      ])
    )
  }

  handleClear = () => {
    const {onChange} = this.props
    onChange(PatchEvent.from(unset()))
  }

  handleCloseModal() {
    this.setState({modalOpen: false})
  }

  render() {
    const {value, type, markers} = this.props

    if (!config || !config.apiKey) {
      return (

            The Geopoint type needs
            a Google Maps API key with access to:

Google Maps JavaScript API

Google Places API Web Service

Google Static Maps API

            Please enter the API key with access to these services in

              `<project-root>/config/@sanity/google-maps-input.json`

      )
    }

    return (
      <Fieldset
        legend={type.title}
        description={type.description}
        className={styles.root}
        markers={markers}
      >

          {value && (

          )}

            <Button onClick={this.handleToggleModal}>{value ? 'Edit' : 'Set location'}</Button>

            {value && (
              <Button type="button" onClick={this.handleClear}>
                Remove
              </Button>
            )}

          {this.state.modalOpen && (
            <Dialog
              title="Place on map"
              onClose={this.handleCloseModal}
              onCloseClick={this.handleCloseModal}
              onOpen={this.handleOpenModal}
              message="Select location by dragging the marker or search for a place"
              isOpen={this.state.modalOpen}
            >

                <GoogleMapsLoadProxy
                  value={value}
                  apiKey={config.apiKey}
                  onChange={this.handleChange}
                  defaultLocation={config.defaultLocation}
                  defaultZoom={config.defaultZoom}
                  locale={getLocale(this.context)}
                  component={GeopointSelect}
                />

            </Dialog>
          )}

      </Fieldset>
    )
  }
}

export default GeopointInput
<commit_msg>[google-maps-input] make buttons look the same as rest of studio<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import config from 'config:@sanity/google-maps-input'
import Button from 'part:@sanity/components/buttons/default'
import Dialog from 'part:@sanity/components/dialogs/default'
import Fieldset from 'part:@sanity/components/fieldsets/default'
import {PatchEvent, set, setIfMissing, unset} from 'part:@sanity/form-builder/patch-event'
import ButtonGrid from 'part:@sanity/components/buttons/button-grid'
import EditIcon from 'part:@sanity/base/edit-icon'
import styles from '../styles/GeopointInput.css'
import GeopointSelect from './GeopointSelect'
import GoogleMapsLoadProxy from './GoogleMapsLoadProxy'

const getLocale = context => {
  const intl = context.intl || {}
  return intl.locale || (typeof window !== 'undefined' && window.navigator.language) || 'en'
}

const getStaticImageUrl = value => {
  const loc = `${value.lat},${value.lng}`
  const params = {
    key: config.apiKey,
    center: loc,
    markers: loc,
    zoom: 13,
    scale: 2,
    size: '640x300'
  }

  const qs = Object.keys(params).reduce((res, param) => {
    return res.concat(`${param}=${encodeURIComponent(params[param])}`)
  }, [])

  return `https://maps.googleapis.com/maps/api/staticmap?${qs.join('&')}`
}

class GeopointInput extends React.Component {
  static propTypes = {
    onChange: PropTypes.func.isRequired,
    markers: PropTypes.arrayOf(
      PropTypes.shape({
        type: PropTypes.string
      })
    ),
    value: PropTypes.shape({
      lat: PropTypes.number,
      lng: PropTypes.number
    }),
    type: PropTypes.shape({
      title: PropTypes.string.isRequired,
      description: PropTypes.string
    })
  }

  static defaultProps = {
    markers: []
  }

  static contextTypes = {
    intl: PropTypes.shape({
      locale: PropTypes.string
    })
  }

  constructor() {
    super()

    this.handleToggleModal = this.handleToggleModal.bind(this)
    this.handleCloseModal = this.handleCloseModal.bind(this)

    this.state = {
      modalOpen: false
    }
  }

  handleToggleModal() {
    this.setState(prevState => ({modalOpen: !prevState.modalOpen}))
  }

  handleChange = latLng => {
    const {type, onChange} = this.props
    onChange(
      PatchEvent.from([
        setIfMissing({
          _type: type.name
        }),
        set(latLng.lat(), ['lat']),
        set(latLng.lng(), ['lng'])
      ])
    )
  }

  handleClear = () => {
    const {onChange} = this.props
    onChange(PatchEvent.from(unset()))
  }

  handleCloseModal() {
    this.setState({modalOpen: false})
  }

  render() {
    const {value, type, markers} = this.props

    if (!config || !config.apiKey) {
      return (

            The Geopoint type needs
            a Google Maps API key with access to:

Google Maps JavaScript API

Google Places API Web Service

Google Static Maps API

            Please enter the API key with access to these services in

              `<project-root>/config/@sanity/google-maps-input.json`

      )
    }

    return (
      <Fieldset
        legend={type.title}
        description={type.description}
        className={styles.root}
        markers={markers}
      >

          {value && (

          )}

            <ButtonGrid>
              <Button inverted onClick={this.handleToggleModal} icon={value && EditIcon}>
                {value ? 'Edit' : 'Set location'}
              </Button>

              {value && (
                <Button color="danger" inverted type="button" onClick={this.handleClear}>
                  Remove
                </Button>
              )}
            </ButtonGrid>

          {this.state.modalOpen && (
            <Dialog
              title="Place on map"
              onClose={this.handleCloseModal}
              onCloseClick={this.handleCloseModal}
              onOpen={this.handleOpenModal}
              message="Select location by dragging the marker or search for a place"
              isOpen={this.state.modalOpen}
            >

                <GoogleMapsLoadProxy
                  value={value}
                  apiKey={config.apiKey}
                  onChange={this.handleChange}
                  defaultLocation={config.defaultLocation}
                  defaultZoom={config.defaultZoom}
                  locale={getLocale(this.context)}
                  component={GeopointSelect}
                />

            </Dialog>
          )}

      </Fieldset>
    )
  }
}

export default GeopointInput
<|endoftext|>


<commit_before>/* globals BUILDCONFIG _ L*/
const availableProcessingOptions = [
    {
        label: 'Color Corrected',
        description:
            `Export with the color-corrections and false color composites configured
            for this project`,
        value: 'current',
        default: true
    }, {
        label: 'Raw',
        value: 'raw',
        exportOptions: {
            raw: true
        }
    }, {
        label: 'NDVI',
        value: 'ndvi',
        description:
            'Assess whether the target being observed contains live green vegetation or not',
        toolId: '7311e8ca-9af7-4fab-b63e-559d2e765388'
    }, {
        label: 'NDWI',
        value: 'ndwi',
        description:
            'An index that is primarily used to distinguish water bodies.',
        toolId: '2d3a351f-54b4-42a9-9db4-d027b9aac03c'
    }, {
        label: 'NDMI',
        value: 'ndmi',
        description:
            'An index that assesses the variation of the moisture content of vegetation.',
        toolId: '44fad5c9-1e0d-4631-aaa0-a61182619cb1'
    }
];

export default (app) => {
    class ProjectService {
        constructor(
            $resource, $location, $http, $q, APP_CONFIG,
            tokenService, authService, statusService
        ) {
            'ngInject';

            this.tokenService = tokenService;
            this.authService = authService;
            this.statusService = statusService;
            this.$http = $http;
            this.$location = $location;
            this.$q = $q;
            this.availableProcessingOptions = availableProcessingOptions;

            this.tileServer = `${APP_CONFIG.tileServerLocation}`;

            this.Project = $resource(
                `${BUILDCONFIG.API_HOST}/api/projects/:id/`, {
                    id: '@properties.id'
                }, {
                    query: {
                        method: 'GET',
                        cache: false
                    },
                    get: {
                        method: 'GET',
                        cache: false
                    },
                    create: {
                        method: 'POST'
                    },
                    delete: {
                        method: 'DELETE'
                    },
                    updateProject: {
                        method: 'PUT',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:id`,
                        params: {
                            id: '@id'
                        }
                    },
                    addScenes: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes/`,
                        params: {
                            projectId: '@projectId'
                        },
                        isArray: true
                    },
                    projectScenes: {
                        method: 'GET',
                        cache: false,
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes`,
                        params: {
                            projectId: '@projectId',
                            pending: '@pending'
                        }
                    },
                    projectAois: {
                        method: 'GET',
                        cache: false,
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/areas-of-interest`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    removeScenes: {
                        method: 'DELETE',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes/`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    export: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/exports/`
                    },
                    listExports: {
                        method: 'GET',
                        url: `${BUILDCONFIG.API_HOST}/api/exports?project=:project`,
                        params: {
                            project: '@project'
                        }
                    },
                    createAOI: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/areas-of-interest/`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    approveScenes: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}` +
                            '/api/projects/:projectId/scenes/accept',
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    sceneOrder: {
                        method: 'GET',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/order/`,
                        cache: false,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    updateSceneOrder: {
                        method: 'PUT',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/order/`,
                        params: {
                            projectId: '@projectId'
                        }
                    }
                }
            );
        }

        query(params = {}) {
            return this.Project.query(params).$promise;
        }

        searchQuery() {
            return this.$q((resolve, reject) => {
                let pageSize = 1000;
                let firstPageParams = {
                    pageSize: pageSize,
                    page: 0,
                    sort: 'createdAt,desc'
                };

                let firstRequest = this.query(firstPageParams);

                firstRequest.then((page) => {
                    let self = this;
                    let num = page.count;
                    let requests = [firstRequest];
                    if (page.count > pageSize) {
                        let requestMaker = function *(totalResults) {
                            let pageNum = 1;
                            while (pageNum * pageSize <= totalResults) {
                                let pageParams = {
                                    pageSize: pageSize,
                                    page: pageNum,
                                    sort: 'createdAt,desc'
                                };
                                yield self.query(pageParams);
                                pageNum += 1;
                            }
                        };

                        requests = requests.concat(Array.from(requestMaker(num)));
                    }

                    this.$q.all(requests).then(
                        (allResponses) => {
                            resolve(
                                allResponses.reduce((res, resp) => res.concat(resp.results), [])
                            );
                        },
                        () => {
                            reject('Error loading projects.');
                        }
                    );
                }, () => {
                    reject('Error loading projects.');
                });
            });
        }

        fetchProject(id) {
            return this.Project.get({id}).$promise;
        }

        listExports(params = {}) {
            return this.Project.listExports(params).$promise;
        }

        export(project, settings = {}, options = {}) {
            const defaultOptions = {
                resolution: 9,
                stitch: true,
                crop: false
            };

            const finalOptions = Object.assign(defaultOptions, options);

            const defaultSettings = {
                projectId: project.id,
                exportStatus: 'NOTEXPORTED',
                exportType: 'S3',
                visibility: 'PRIVATE',
                exportOptions: finalOptions
            };

            const finalSettings = Object.assign(defaultSettings, settings);

            const userRequest = this.authService.getCurrentUser();

            return userRequest.then(
                (user) => {
                    return this.Project.export(
                        Object.assign(finalSettings, {
                            organizationId: user.organizationId
                        })
                    ).$promise;
                },
                (error) => {
                    return error;
                }
            );
        }

        createProject(name, params = {}) {
            return this.authService.getCurrentUser().then(
                (user) => {
                    return this.Project.create({
                        organizationId: user.organizationId,
                        name: name,
                        description: params.description || '',
                        visibility: params.visibility || 'PRIVATE',
                        tileVisibility: params.tileVisibility || 'PRIVATE',
                        tags: params.tags || [],
                        isAOIProject: params.isAOIProject || false
                    }).$promise;
                },
                (error) => {
                    return error;
                }
            );
        }

        addScenes(projectId, sceneIds) {
            return this.Project.addScenes(
                {projectId: projectId},
                sceneIds
            ).$promise;
        }

        getProjectScenes(params) {
            return this.Project.projectScenes(params).$promise;
        }

        getProjectCorners(projectId) {
            return this.getAllProjectScenes({projectId: projectId}).then(({scenes}) => {
                let corners = {
                    lowerLeftLon: null,
                    lowerLeftLat: null,
                    upperRightLon: null,
                    upperRightLat: null
                };
                scenes.forEach(scene => {
                    let metadata = scene.sceneMetadata;
                    if (metadata.lowerLeftCornerLatitude < corners.lowerLeftLat ||
                        corners.lowerLeftLat === null) {
                        corners.lowerLeftLat = metadata.lowerLeftCornerLatitude;
                    }
                    if (metadata.lowerLeftCornerLongitude < corners.lowerLeftLon ||
                        corners.lowerLeftLon === null) {
                        corners.lowerLeftLon = metadata.lowerLeftCornerLongitude;
                    }
                    if (metadata.upperRightCornerLatitude < corners.upperRightLat ||
                        corners.upperRightLat === null) {
                        corners.upperRightLat = metadata.upperRightCornerLatitude;
                    }
                    if (metadata.upperRightCornerLongitude < corners.upperRightLon ||
                        corners.upperRightLon === null) {
                        corners.upperRightLon = metadata.upperRightCornerLongitude;
                    }
                });
                return corners;
            });
        }

        /** Return all scenes in a single collection, making multiple requests if necessary
         *
         * @param {object} params to pass as query params
         * @return {Promise} promise that will resolve when all scenes are available
         */
        getAllProjectScenes(params) {
            let pageSize = 30;
            let firstPageParams = Object.assign({}, params, {
                pageSize: pageSize,
                page: 0,
                sort: 'createdAt,desc'
            });
            let firstRequest = this.getProjectScenes(firstPageParams);

            return firstRequest.then((res) => {
                const count = res.count;
                const scenes = res.results;
                const requests = Array(Math.floor(count / pageSize) - 1)
                      .fill().map((x, page) => {
                          return this.getProjectScenes(Object.assign({}, params, {
                              pageSize,
                              page: page + 1,
                              sort: 'createdAt,desc'
                          })).then((pageResponse) => pageResponse.results);
                      });
                return this.$q.all(requests).then((sceneChunks) => {
                    return {count, scenes: scenes.concat(_.flatten(sceneChunks))};
                });
            });
        }

        getProjectStatus(projectId) {
            return this.getAllProjectScenes({ projectId }).then(({scenes}) => {
                if (scenes) {
                    const counts = scenes.reduce((acc, scene) => {
                        const ingestStatus = scene.statusFields.ingestStatus;
                        acc[ingestStatus] = acc[ingestStatus] + 1 || 1;
                        return acc;
                    }, {});
                    if (counts.FAILED) {
                        return 'FAILED';
                    } else if (counts.NOTINGESTING || counts.TOBEINGESTED || counts.INGESTING) {
                        return 'PARTIAL';
                    } else if (counts.INGESTED) {
                        return 'CURRENT';
                    }
                }
                return 'NOSCENES';
            });
        }

        getProjectSceneCount(params) {
            let countParams = Object.assign({}, params, {pageSize: 1, page: 0});
            return this.Project.projectScenes(countParams).$promise;
        }

        removeScenesFromProject(projectId, scenes) {
            return this.$http({
                method: 'DELETE',
                url: `${BUILDCONFIG.API_HOST}/api/projects/${projectId}/scenes/`,
                data: scenes,
                headers: {'Content-Type': 'application/json;charset=utf-8'}
            });
        }

        deleteProject(projectId) {
            return this.Project.delete({id: projectId}).$promise;
        }

        updateProject(params) {
            return this.Project.updateProject(params).$promise;
        }

        createAOI(project, params) {
            return this.$q((resolve, reject) => {
                this.authService.getCurrentUser().then(user => {
                    const paramsWithOrg =
                          Object.assign(params, { organizationId: user.organizationId });
                    this.Project.createAOI(
                        {projectId: project},
                        paramsWithOrg
                    ).$promise.then(() => resolve(), (err) => reject(err));
                });
            });
        }

        approveScenes(projectId, sceneIds) {
            return this.Project.approveScenes(
                {projectId},
                sceneIds
            ).$promise;
        }

        getProjectLayerURL(project, params) {
            let projectId = typeof project === 'object' ? project.id : project;
            let queryParams = params || {};
            queryParams.tag = new Date().getTime();
            let formattedParams = L.Util.getParamString(queryParams);

            return `${this.tileServer}/${projectId}/{z}/{x}/{y}/${formattedParams}`;
        }

        getProjectShareLayerURL(project, token) {
            let projectId = typeof project === 'object' ? project.id : project;

            let params = {
                tag: new Date().getTime()
            };

            if (token) {
                params.token = token;
            }

            let formattedParams = L.Util.getParamString(params);

            return `${this.tileServer}/${projectId}/{z}/{x}/{y}/${formattedParams}`;
        }

        getZoomLevel(bbox) {
            let diffLng = Math.abs(bbox[0] - bbox[2]);
            let diffLat = Math.abs(bbox[1] - bbox[3]);

            // Scale down if latitude is less than 55 to adjust for
            // web mercator distortion
            let lngMultiplier = bbox[0] < 55 ? 0.8 : 1;
            let maxDiff = diffLng > diffLat ? diffLng : diffLat;
            let diff = maxDiff * lngMultiplier;
            if (diff >= 0.5) {
                return 8;
            } else if (diff >= 0.01 && diff < 0.5) {
                return 11;
            } else if (diff >= 0.005 && diff < 0.01) {
                return 16;
            }
            return 18;
        }

        getProjectThumbnailURL(project, token) {
            if (project.extent) {
                let coords = project.extent.coordinates[0];
                // Lower left and upper right coordinates in extent
                let bbox = [...coords[0], ...coords[2]];
                let params = {
                    bbox: bbox,
                    zoom: this.getZoomLevel(bbox),
                    token: token
                };
                let formattedParams = L.Util.getParamString(params);
                let url = `${this.tileServer}/${project.id}/export/${formattedParams}`;
                return url;
            }
            return null;
        }

        getBaseURL() {
            let host = this.$location.host();
            let protocol = this.$location.protocol();
            let port = this.$location.port();
            let formattedPort = port !== 80 && port !== 443 ? ':' + port : '';
            return `${protocol}://${host}${formattedPort}`;
        }

        getProjectShareURL(project) {
            return this.$q((resolve, reject) => {
                let shareUrl = `${this.getBaseURL()}/share/${project.id}`;
                if (project.tileVisibility === 'PRIVATE') {
                    this.tokenService.getOrCreateProjectMapToken(project).then((token) => {
                        resolve(`${shareUrl}/?mapToken=${token.id}`);
                    }, (error) => reject(error));
                } else {
                    resolve(shareUrl);
                }
            });
        }

        getProjectAois(projectId) {
            return this.Project.projectAois({projectId: projectId}).$promise;
        }

        getSceneOrder(projectId) {
            const pageSize = 30;
            const firtPageParams = {
                pageSize,
                page: 0
            };
            return this.Project.sceneOrder({projectId: projectId})
                .$promise.then((res) => {
                    const scenes = res.results;
                    const count = res.count;
                    let promises = Array(Math.floor(count / pageSize) - 1).fill().map((x, page) => {
                        return this.Project.sceneOrder({
                            projectId,
                            pageSize,
                            page: page + 1
                        }).$promise.then((pageResponse) => pageResponse.results);
                    });
                    return this.$q.all(promises).then((sceneChunks) => {
                        const allScenes = scenes.concat(_.flatten(sceneChunks));
                        return allScenes;
                    });
                });
        }

        updateSceneOrder(projectId, sceneIds) {
            return this.Project.updateSceneOrder(
                {projectId: projectId},
                sceneIds
            ).$promise;
        }

        getAnnotationShapefile(projectId) {
            return this.$http({
                method: 'GET',
                url: `${BUILDCONFIG.API_HOST}/api/projects/${projectId}/annotations/shapefile`
            });
        }
    }

    app.service('projectService', ProjectService);
};
<commit_msg>Prevent negative array sizes when less than 30 scenes in project<commit_after>/* globals BUILDCONFIG _ L*/
const availableProcessingOptions = [
    {
        label: 'Color Corrected',
        description:
            `Export with the color-corrections and false color composites configured
            for this project`,
        value: 'current',
        default: true
    }, {
        label: 'Raw',
        value: 'raw',
        exportOptions: {
            raw: true
        }
    }, {
        label: 'NDVI',
        value: 'ndvi',
        description:
            'Assess whether the target being observed contains live green vegetation or not',
        toolId: '7311e8ca-9af7-4fab-b63e-559d2e765388'
    }, {
        label: 'NDWI',
        value: 'ndwi',
        description:
            'An index that is primarily used to distinguish water bodies.',
        toolId: '2d3a351f-54b4-42a9-9db4-d027b9aac03c'
    }, {
        label: 'NDMI',
        value: 'ndmi',
        description:
            'An index that assesses the variation of the moisture content of vegetation.',
        toolId: '44fad5c9-1e0d-4631-aaa0-a61182619cb1'
    }
];

export default (app) => {
    class ProjectService {
        constructor(
            $resource, $location, $http, $q, APP_CONFIG,
            tokenService, authService, statusService
        ) {
            'ngInject';

            this.tokenService = tokenService;
            this.authService = authService;
            this.statusService = statusService;
            this.$http = $http;
            this.$location = $location;
            this.$q = $q;
            this.availableProcessingOptions = availableProcessingOptions;

            this.tileServer = `${APP_CONFIG.tileServerLocation}`;

            this.Project = $resource(
                `${BUILDCONFIG.API_HOST}/api/projects/:id/`, {
                    id: '@properties.id'
                }, {
                    query: {
                        method: 'GET',
                        cache: false
                    },
                    get: {
                        method: 'GET',
                        cache: false
                    },
                    create: {
                        method: 'POST'
                    },
                    delete: {
                        method: 'DELETE'
                    },
                    updateProject: {
                        method: 'PUT',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:id`,
                        params: {
                            id: '@id'
                        }
                    },
                    addScenes: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes/`,
                        params: {
                            projectId: '@projectId'
                        },
                        isArray: true
                    },
                    projectScenes: {
                        method: 'GET',
                        cache: false,
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes`,
                        params: {
                            projectId: '@projectId',
                            pending: '@pending'
                        }
                    },
                    projectAois: {
                        method: 'GET',
                        cache: false,
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/areas-of-interest`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    removeScenes: {
                        method: 'DELETE',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/scenes/`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    export: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/exports/`
                    },
                    listExports: {
                        method: 'GET',
                        url: `${BUILDCONFIG.API_HOST}/api/exports?project=:project`,
                        params: {
                            project: '@project'
                        }
                    },
                    createAOI: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/areas-of-interest/`,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    approveScenes: {
                        method: 'POST',
                        url: `${BUILDCONFIG.API_HOST}` +
                            '/api/projects/:projectId/scenes/accept',
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    sceneOrder: {
                        method: 'GET',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/order/`,
                        cache: false,
                        params: {
                            projectId: '@projectId'
                        }
                    },
                    updateSceneOrder: {
                        method: 'PUT',
                        url: `${BUILDCONFIG.API_HOST}/api/projects/:projectId/order/`,
                        params: {
                            projectId: '@projectId'
                        }
                    }
                }
            );
        }

        query(params = {}) {
            return this.Project.query(params).$promise;
        }

        searchQuery() {
            return this.$q((resolve, reject) => {
                let pageSize = 1000;
                let firstPageParams = {
                    pageSize: pageSize,
                    page: 0,
                    sort: 'createdAt,desc'
                };

                let firstRequest = this.query(firstPageParams);

                firstRequest.then((page) => {
                    let self = this;
                    let num = page.count;
                    let requests = [firstRequest];
                    if (page.count > pageSize) {
                        let requestMaker = function *(totalResults) {
                            let pageNum = 1;
                            while (pageNum * pageSize <= totalResults) {
                                let pageParams = {
                                    pageSize: pageSize,
                                    page: pageNum,
                                    sort: 'createdAt,desc'
                                };
                                yield self.query(pageParams);
                                pageNum += 1;
                            }
                        };

                        requests = requests.concat(Array.from(requestMaker(num)));
                    }

                    this.$q.all(requests).then(
                        (allResponses) => {
                            resolve(
                                allResponses.reduce((res, resp) => res.concat(resp.results), [])
                            );
                        },
                        () => {
                            reject('Error loading projects.');
                        }
                    );
                }, () => {
                    reject('Error loading projects.');
                });
            });
        }

        fetchProject(id) {
            return this.Project.get({id}).$promise;
        }

        listExports(params = {}) {
            return this.Project.listExports(params).$promise;
        }

        export(project, settings = {}, options = {}) {
            const defaultOptions = {
                resolution: 9,
                stitch: true,
                crop: false
            };

            const finalOptions = Object.assign(defaultOptions, options);

            const defaultSettings = {
                projectId: project.id,
                exportStatus: 'NOTEXPORTED',
                exportType: 'S3',
                visibility: 'PRIVATE',
                exportOptions: finalOptions
            };

            const finalSettings = Object.assign(defaultSettings, settings);

            const userRequest = this.authService.getCurrentUser();

            return userRequest.then(
                (user) => {
                    return this.Project.export(
                        Object.assign(finalSettings, {
                            organizationId: user.organizationId
                        })
                    ).$promise;
                },
                (error) => {
                    return error;
                }
            );
        }

        createProject(name, params = {}) {
            return this.authService.getCurrentUser().then(
                (user) => {
                    return this.Project.create({
                        organizationId: user.organizationId,
                        name: name,
                        description: params.description || '',
                        visibility: params.visibility || 'PRIVATE',
                        tileVisibility: params.tileVisibility || 'PRIVATE',
                        tags: params.tags || [],
                        isAOIProject: params.isAOIProject || false
                    }).$promise;
                },
                (error) => {
                    return error;
                }
            );
        }

        addScenes(projectId, sceneIds) {
            return this.Project.addScenes(
                {projectId: projectId},
                sceneIds
            ).$promise;
        }

        getProjectScenes(params) {
            return this.Project.projectScenes(params).$promise;
        }

        getProjectCorners(projectId) {
            return this.getAllProjectScenes({projectId: projectId}).then(({scenes}) => {
                let corners = {
                    lowerLeftLon: null,
                    lowerLeftLat: null,
                    upperRightLon: null,
                    upperRightLat: null
                };
                scenes.forEach(scene => {
                    let metadata = scene.sceneMetadata;
                    if (metadata.lowerLeftCornerLatitude < corners.lowerLeftLat ||
                        corners.lowerLeftLat === null) {
                        corners.lowerLeftLat = metadata.lowerLeftCornerLatitude;
                    }
                    if (metadata.lowerLeftCornerLongitude < corners.lowerLeftLon ||
                        corners.lowerLeftLon === null) {
                        corners.lowerLeftLon = metadata.lowerLeftCornerLongitude;
                    }
                    if (metadata.upperRightCornerLatitude < corners.upperRightLat ||
                        corners.upperRightLat === null) {
                        corners.upperRightLat = metadata.upperRightCornerLatitude;
                    }
                    if (metadata.upperRightCornerLongitude < corners.upperRightLon ||
                        corners.upperRightLon === null) {
                        corners.upperRightLon = metadata.upperRightCornerLongitude;
                    }
                });
                return corners;
            });
        }

        /** Return all scenes in a single collection, making multiple requests if necessary
         *
         * @param {object} params to pass as query params
         * @return {Promise} promise that will resolve when all scenes are available
         */
        getAllProjectScenes(params) {
            let pageSize = 30;
            let firstPageParams = Object.assign({}, params, {
                pageSize: pageSize,
                page: 0,
                sort: 'createdAt,desc'
            });
            let firstRequest = this.getProjectScenes(firstPageParams);

            return firstRequest.then((res) => {
                const count = res.count;
                const scenes = res.results;
                let arraySize = Math.max(Math.floor(count / pageSize) - 1, 0);
                const requests = Array(arraySize)
                      .fill().map((x, page) => {
                          return this.getProjectScenes(Object.assign({}, params, {
                              pageSize,
                              page: page + 1,
                              sort: 'createdAt,desc'
                          })).then((pageResponse) => pageResponse.results);
                      });
                return this.$q.all(requests).then((sceneChunks) => {
                    return {count, scenes: scenes.concat(_.flatten(sceneChunks))};
                });
            });
        }

        getProjectStatus(projectId) {
            return this.getAllProjectScenes({ projectId }).then(({scenes}) => {
                if (scenes) {
                    const counts = scenes.reduce((acc, scene) => {
                        const ingestStatus = scene.statusFields.ingestStatus;
                        acc[ingestStatus] = acc[ingestStatus] + 1 || 1;
                        return acc;
                    }, {});
                    if (counts.FAILED) {
                        return 'FAILED';
                    } else if (counts.NOTINGESTING || counts.TOBEINGESTED || counts.INGESTING) {
                        return 'PARTIAL';
                    } else if (counts.INGESTED) {
                        return 'CURRENT';
                    }
                }
                return 'NOSCENES';
            });
        }

        getProjectSceneCount(params) {
            let countParams = Object.assign({}, params, {pageSize: 1, page: 0});
            return this.Project.projectScenes(countParams).$promise;
        }

        removeScenesFromProject(projectId, scenes) {
            return this.$http({
                method: 'DELETE',
                url: `${BUILDCONFIG.API_HOST}/api/projects/${projectId}/scenes/`,
                data: scenes,
                headers: {'Content-Type': 'application/json;charset=utf-8'}
            });
        }

        deleteProject(projectId) {
            return this.Project.delete({id: projectId}).$promise;
        }

        updateProject(params) {
            return this.Project.updateProject(params).$promise;
        }

        createAOI(project, params) {
            return this.$q((resolve, reject) => {
                this.authService.getCurrentUser().then(user => {
                    const paramsWithOrg =
                          Object.assign(params, { organizationId: user.organizationId });
                    this.Project.createAOI(
                        {projectId: project},
                        paramsWithOrg
                    ).$promise.then(() => resolve(), (err) => reject(err));
                });
            });
        }

        approveScenes(projectId, sceneIds) {
            return this.Project.approveScenes(
                {projectId},
                sceneIds
            ).$promise;
        }

        getProjectLayerURL(project, params) {
            let projectId = typeof project === 'object' ? project.id : project;
            let queryParams = params || {};
            queryParams.tag = new Date().getTime();
            let formattedParams = L.Util.getParamString(queryParams);

            return `${this.tileServer}/${projectId}/{z}/{x}/{y}/${formattedParams}`;
        }

        getProjectShareLayerURL(project, token) {
            let projectId = typeof project === 'object' ? project.id : project;

            let params = {
                tag: new Date().getTime()
            };

            if (token) {
                params.token = token;
            }

            let formattedParams = L.Util.getParamString(params);

            return `${this.tileServer}/${projectId}/{z}/{x}/{y}/${formattedParams}`;
        }

        getZoomLevel(bbox) {
            let diffLng = Math.abs(bbox[0] - bbox[2]);
            let diffLat = Math.abs(bbox[1] - bbox[3]);

            // Scale down if latitude is less than 55 to adjust for
            // web mercator distortion
            let lngMultiplier = bbox[0] < 55 ? 0.8 : 1;
            let maxDiff = diffLng > diffLat ? diffLng : diffLat;
            let diff = maxDiff * lngMultiplier;
            if (diff >= 0.5) {
                return 8;
            } else if (diff >= 0.01 && diff < 0.5) {
                return 11;
            } else if (diff >= 0.005 && diff < 0.01) {
                return 16;
            }
            return 18;
        }

        getProjectThumbnailURL(project, token) {
            if (project.extent) {
                let coords = project.extent.coordinates[0];
                // Lower left and upper right coordinates in extent
                let bbox = [...coords[0], ...coords[2]];
                let params = {
                    bbox: bbox,
                    zoom: this.getZoomLevel(bbox),
                    token: token
                };
                let formattedParams = L.Util.getParamString(params);
                let url = `${this.tileServer}/${project.id}/export/${formattedParams}`;
                return url;
            }
            return null;
        }

        getBaseURL() {
            let host = this.$location.host();
            let protocol = this.$location.protocol();
            let port = this.$location.port();
            let formattedPort = port !== 80 && port !== 443 ? ':' + port : '';
            return `${protocol}://${host}${formattedPort}`;
        }

        getProjectShareURL(project) {
            return this.$q((resolve, reject) => {
                let shareUrl = `${this.getBaseURL()}/share/${project.id}`;
                if (project.tileVisibility === 'PRIVATE') {
                    this.tokenService.getOrCreateProjectMapToken(project).then((token) => {
                        resolve(`${shareUrl}/?mapToken=${token.id}`);
                    }, (error) => reject(error));
                } else {
                    resolve(shareUrl);
                }
            });
        }

        getProjectAois(projectId) {
            return this.Project.projectAois({projectId: projectId}).$promise;
        }

        getSceneOrder(projectId) {
            const pageSize = 30;
            const firtPageParams = {
                pageSize,
                page: 0
            };
            return this.Project.sceneOrder({projectId: projectId})
                .$promise.then((res) => {
                    const scenes = res.results;
                    const count = res.count;
                    let promises = Array(Math.floor(count / pageSize) + 1).fill().map((x, page) => {
                        return this.Project.sceneOrder({
                            projectId,
                            pageSize,
                            page: page + 1
                        }).$promise.then((pageResponse) => pageResponse.results);
                    });
                    return this.$q.all(promises).then((sceneChunks) => {
                        const allScenes = scenes.concat(_.flatten(sceneChunks));
                        return allScenes;
                    });
                });
        }

        updateSceneOrder(projectId, sceneIds) {
            return this.Project.updateSceneOrder(
                {projectId: projectId},
                sceneIds
            ).$promise;
        }

        getAnnotationShapefile(projectId) {
            return this.$http({
                method: 'GET',
                url: `${BUILDCONFIG.API_HOST}/api/projects/${projectId}/annotations/shapefile`
            });
        }
    }

    app.service('projectService', ProjectService);
};
<|endoftext|>


<commit_before>import { eventResultClicked, eventTrackingReset } from "sajari";

import GA from "./ga";

import {
  resultsEvent,
  trackingResetEvent,
  resultClickedEvent
} from "../controllers";

class Analytics {
  /**
   * Constructs an analytics object that operates on the specified pipeline.
   * @param {Pipeline} pipeline
   * @param {Sajari.Tracking} tracking
   * @param {GA} [ga=GoogleAnalytics]
   */
  constructor(pipeline, tracking, ga = new GA()) {
    this.ga = ga;

    this.enabled = false;
    this.body = "";

    this.pipeline = pipeline;
    this.tracking = tracking;

    // longest values are for sending the users last intended query on reset
    this.longestNonAutocompletedBody = "";
    this.longestAutocompletedBody = "";

    // default to working with web pipeline values
    this.bodyLabel = "q";
    this.bodyAutocompletedLabel = "q.used";

    this.beforeunload = this.beforeunload.bind(this);
    this.onChange = this.onChange.bind(this);
    this.resetBody = this.resetBody.bind(this);
    this.resultClicked = this.resultClicked.bind(this);

    window.addEventListener("beforeunload", this.beforeunload);

    this.pipeline.listen(resultsEvent, this.onChange);
    this.tracking.listen(eventTrackingReset, this.resetBody);
    this.tracking.listen(eventResultClicked, this.resultClicked);
  }

  /**
   * Runs before the page is closed/navigated away from. Can trigger a ga onPageClose call.
   */
  beforeunload() {
    if (this.enabled && this.body) {
      this.ga.onPageClose(this.body);
      this.enabled = false;
    }
  }

  /**
   * Resets the currently held parameters. Can trigger a ga onBodyReset call.
   */
  resetBody() {
    if (this.enabled) {
      // Send the longest body since the last time the body was cleared.
      // Use completion if available.
      this.ga.onBodyReset(
        this.longestAutocompletedBody || this.longestNonAutocompletedBody
      );
      this.longestNonAutocompletedBody = "";
      this.longestAutocompletedBody = "";
      this.enabled = false;
    }
  }

  /**
   * Runs when the results have changed. Updates the currently held search parameters.
   */
  onChange() {
    const searchResponse = this.pipeline.getResults() || {};
    // Enable analytics once a successful search has been performed
    if (searchResponse.results) {
      this.enabled = true;
    }

    const values = this.pipeline.getQueryValues() || {};
    const originalBody = values[this.bodyLabel] || "";
    const newBody = values[this.bodyAutocompletedLabel] || originalBody;

    // Here we check the lengths of the non-autocompleted bodies.
    // We do this because while the user is backspacing their query
    // the new autocompleted body may be longer than their actual input,
    // but we want to record their input rather than a completion resulting
    // from them removing chars.
    if (originalBody.length >= this.longestNonAutocompletedBody.length) {
      this.longestNonAutocompletedBody = originalBody;
      this.longestAutocompletedBody = values[this.bodyAutocompletedLabel];
    }

    this.body = newBody;
  }

  /**
   * Runs when a result has been clicked. Can trigger a ga onResultClicked call.
   */
  resultClicked() {
    if (this.enabled && this.body) {
      this.ga.onResultClicked(this.body);
      this.longestNonAutocompletedBody = "";
      this.longestAutocompletedBody = "";
      this.enabled = false;
    }
  }
}

export default Analytics;
<commit_msg>analytics: fix edge case where clearing input wouldn't send the correct body<commit_after>import { eventResultClicked, eventTrackingReset } from "sajari";

import GA from "./ga";

import {
  resultsEvent,
  trackingResetEvent,
  resultClickedEvent
} from "../controllers";

class Analytics {
  /**
   * Constructs an analytics object that operates on the specified pipeline.
   * @param {Pipeline} pipeline
   * @param {Sajari.Tracking} tracking
   * @param {GA} [ga=GoogleAnalytics]
   */
  constructor(pipeline, tracking, ga = new GA()) {
    this.ga = ga;

    this.enabled = false;
    this.body = "";

    this.pipeline = pipeline;
    this.tracking = tracking;

    // longest values are for sending the users last intended query on reset
    this.longestNonAutocompletedBody = "";
    this.longestAutocompletedBody = "";

    // default to working with web pipeline values
    this.bodyLabel = "q";
    this.bodyAutocompletedLabel = "q.used";

    this.beforeunload = this.beforeunload.bind(this);
    this.onChange = this.onChange.bind(this);
    this.resetBody = this.resetBody.bind(this);
    this.resultClicked = this.resultClicked.bind(this);

    window.addEventListener("beforeunload", this.beforeunload);

    this.pipeline.listen(resultsEvent, this.onChange);
    this.tracking.listen(eventTrackingReset, this.resetBody);
    this.tracking.listen(eventResultClicked, this.resultClicked);
  }

  /**
   * Runs before the page is closed/navigated away from. Can trigger a ga onPageClose call.
   */
  beforeunload() {
    if (this.enabled && this.body) {
      this.ga.onPageClose(this.body);
      this.enabled = false;
    }
  }

  /**
   * Resets the currently held parameters. Can trigger a ga onBodyReset call.
   */
  resetBody() {
    if (this.enabled) {
      // Send the longest body since the last time the body was cleared.
      // Use completion if available.
      this.ga.onBodyReset(
        this.longestAutocompletedBody || this.longestNonAutocompletedBody
      );
      this.longestNonAutocompletedBody = "";
      this.longestAutocompletedBody = "";
      this.enabled = false;
    }
  }

  /**
   * Runs when the results have changed. Updates the currently held search parameters.
   */
  onChange() {
    const searchResponse = this.pipeline.getResults() || {};
    // Enable analytics once a successful search has been performed
    if (!searchResponse.time) {
      return;
    }
    this.enabled = true;

    const values = this.pipeline.getQueryValues() || {};
    const originalBody = values[this.bodyLabel] || "";
    const newBody = values[this.bodyAutocompletedLabel] || originalBody;

    // Here we check the lengths of the non-autocompleted bodies.
    // We do this because while the user is backspacing their query
    // the new autocompleted body may be longer than their actual input,
    // but we want to record their input rather than a completion resulting
    // from them removing chars.
    if (originalBody.length >= this.longestNonAutocompletedBody.length) {
      this.longestNonAutocompletedBody = originalBody;
      this.longestAutocompletedBody = values[this.bodyAutocompletedLabel];
    }

    this.body = newBody;
  }

  /**
   * Runs when a result has been clicked. Can trigger a ga onResultClicked call.
   */
  resultClicked() {
    if (this.enabled && this.body) {
      this.ga.onResultClicked(this.body);
      this.longestNonAutocompletedBody = "";
      this.longestAutocompletedBody = "";
      this.enabled = false;
    }
  }
}

export default Analytics;
<|endoftext|>


<commit_before>$(function(){
    antsmc2__aucomplete = null;
    });

function make_suggestions(elem_selector, fetch_qset_ids_url) {
    var elem = document.querySelector(elem_selector);
    if (new RegExp("^.*\{\{\s*$").test(elem.value)) {
          $.get( fetch_qset_ids_url, function( list ) {
            if(antsmc2__aucomplete){
               antsmc2__aucomplete._list = list;
               antsmc2__aucomplete.evaluate();
             }
             else
                antsmc2__aucomplete = get_autocomplete(list);
        });
     }

    get_autocomplete = function(list) {
            return new Awesomplete(elem, {
                                    list: [],
                                        filter: function(text, input) {
                                            return Awesomplete.FILTER_CONTAINS(text, input.match(/[^({{)]*$/)[0]);
                                        },

                                        replace: function(text) {
                                            var before = this.input.value.match(/^.*{{\s*|/)[0].trim();
                                            this.input.value = before +text + "}} ";
                                        }
                                });
    }

}

<commit_msg>fix random criterai during listing<commit_after>$(function(){
    antsmc2__aucomplete = null;
    });

function make_suggestions(elem_selector, fetch_qset_ids_url) {
    var elem = document.querySelector(elem_selector);
    if (new RegExp("^.*\{\{$").test(elem.value)) {
          $.get( fetch_qset_ids_url, function( list ) {
            if(antsmc2__aucomplete){
               antsmc2__aucomplete._list = list;
               antsmc2__aucomplete.evaluate();
             }
             else
                antsmc2__aucomplete = get_autocomplete(list);
        });
     }

    get_autocomplete = function(list) {
            return new Awesomplete(elem, {
                                    list: [],
                                        filter: function(text, input) {
                                            return Awesomplete.FILTER_CONTAINS(text, input.match(/[^({{)]*$/)[0]);
                                        },

                                        replace: function(text) {
                                            var before = this.input.value.match(/^.*{{\s*|/)[0].trim();
                                            this.input.value = before +text + "}} ";
                                        }
                                });
    }

}

<|endoftext|>