<commit_before>'use strict';
var LevelUtil = require('../../src/levels').LevelUtil,
  Skills = require('../../src/skills').Skills,
  CommandUtil = require('../../src/command_util').CommandUtil,
  util = require('util'),
  Commands = require('../../src/commands').Commands,
  Effects = require('../../src/effects').Effects;

exports.listeners = {

  //// Function wrappers needed to access "this" (Player obj)
  regen: function(l10n) {
      return function(bonus) {
        bonus = bonus || player.getSkills('recovery');
        const config = {
          player: this,
          bonus
        };
        this.addEffect('resting', Effects.regen(config));
    }
  },

  meditate: function(l10n) {
    return function(bonus) {
      bonus = bonus || player.getSkills('concentration');
      const config = {
        player: this,
        stat: 'sanity',
        bonus
      };
      this.addEffect('meditating', Effects.regen(config));
    }
  },

  action: function(l10n) {
    return function(cost) {

      if (cost) {
        const currentEnergy = this.getAttribute('energy');
        const newEnergy = Math.max(0, currentEnergy - cost);
        this.setAttribute('energy', newEnergy);
      }

      const recovery = ['resting', 'meditating', 'recuperating'];
      recovery.forEach(state => {
        const effect = this.getEffects(state);
        if (effect) {
          util.log(this.getName() + ' ends ' + state);
          effect.deactivate();
          this.removeEffect(state);
        }
      });
    }
  },

  experience: function(l10n) {
    return function(experience) {

      const maxLevel = 60;
      if (this.getAttribute('level') >= maxLevel) {
        return;
      }

      util.log(this.getName() + ' has gained ' + experience + ' XP.');
      this.sayL10n(l10n, 'EXPGAIN', experience);

      const tnl = LevelUtil.expToLevel(this.getAttribute('level')) - this.getAttribute('experience');

      if (experience >= tnl) {
        return this.emit('level');
      }

      this.setAttribute('experience', this.getAttribute('experience') + experience);
    }
  },

  level: function(l10n) {
    return function() {
      const name = this.getName();
      const newLevel = this.getAttribute('level') + 1;
      const healthGain = Math.ceil(this.getAttribute('max_health') * 1.10);
      const energyGain = this.getAttribute('max_energy')
                       + this.getAttribute('stamina')
                       + this.getAttribute('quickness');

      const sanityGain = this.getAttribute('max_sanity')
                       + this.getAttribute('willpower')
                       + this.getAttribute('cleverness');

      util.log(name + ' gained health ' + healthGain);
      util.log(name + ' gained energy ' + energyGain);
      util.log(name + ' gained sanity' + sanityGain);

      const gainedMutation = newLevel % 2 === 0;

      let mutationPoints = this.getAttribute('mutagens');

      util.log(name + ' is now level ' + newLevel);

      this.sayL10n(l10n, 'LEVELUP');

      if (gainedMutation) {
        this.sayL10n(l10n, 'MUTAGEN_GAIN');
        mutationPoints++;
        this.setAttribute('mutagens', mutationPoints);
      }

      this.setAttribute('level', newLevel);
      this.setAttribute('experience', 0);
      this.setAttribute('attrPoints', (this.getAttribute('attrPoints') || 0) + 1);

      // Do whatever you want to do here when a player levels up...
      const attrToLevel = {
        'health': healthGain,
        'energy': energyGain,
        'sanity:': sanityGain,
      };

      for (const attr in attrToLevel) {
        const max = 'max_' + attr;
        this.setAttribute(max, healthGain);
        this.setAttribute(attr, this.getAttribute(max));
        player.say('<blue>You have gained ' + attr + '.</blue>');
      }

      // Add points for skills
      const skillGain = LevelUtil.getTrainingTime(newLevel);
      const newTrainingTime = this.getTraining('time') + skillGain;
      util.log(name + ' can train x', newTrainingTime);
      this.setTraining('time', newTrainingTime);
    }
  },

  //TODO: Permadeath, add it.
  die: function(l10n) {
    return function() {
      const startLocation = 1;
      const playerExp = this.getAttribute('experience');
      const experiencePenalty = playerExp - Math.ceil((playerExp * 0.10));

      util.log(this.getName() + ' died.');
      Commands.player_commands.remove('all', this, true);
      Commands.player_commands.drop('all', this);

      this.setLocation(startLocation);
      this.emit('regen');
      this.setAttribute('experience', experiencePenalty);
    }
  },

  changeTime: function(l10n) {
    return function (wasDaytime, rooms) {
      const playerIsOutside = rooms.getAt(this.getLocation()).biome === 'outdoors';

      if (playerIsOutside) {
        if (wasDaytime) {
          this.sayL10n(l10n, "SUN_SETTING");
          setTimeout(() => this.sayL10n(l10n, "SUN_SET"), 5000);

        } else {
          this.sayL10n(l10n, "SUN_RISING");
          setTimeout(() => this.sayL10n(l10n, "SUN_UP"), 5000);
        }

      } else if (wasDaytime) {
        this.sayL10n(l10n, "SUN_SETTING_INDOORS");
      } else {
        this.sayL10n(l10n, "SUN_UP_INDOORS");
      }

    }
  }
};
<commit_msg>Fix invalid refs to player, use this keyword instead.<commit_after>'use strict';
var LevelUtil = require('../../src/levels').LevelUtil,
  Skills = require('../../src/skills').Skills,
  CommandUtil = require('../../src/command_util').CommandUtil,
  util = require('util'),
  Commands = require('../../src/commands').Commands,
  Effects = require('../../src/effects').Effects;

exports.listeners = {

  //// Function wrappers needed to access "this" (Player obj)
  regen: function(l10n) {
      return function(bonus) {
        bonus = bonus || this.getSkills('recovery');
        const config = {
          player: this,
          bonus
        };
        this.addEffect('resting', Effects.regen(config));
    }
  },

  meditate: function(l10n) {
    return function(bonus) {
      bonus = bonus || this.getSkills('concentration');
      const config = {
        player: this,
        stat: 'sanity',
        bonus
      };
      this.addEffect('meditating', Effects.regen(config));
    }
  },

  action: function(l10n) {
    return function(cost) {

      if (cost) {
        const currentEnergy = this.getAttribute('energy');
        const newEnergy = Math.max(0, currentEnergy - cost);
        this.setAttribute('energy', newEnergy);
      }

      const recovery = ['resting', 'meditating', 'recuperating'];
      recovery.forEach(state => {
        const effect = this.getEffects(state);
        if (effect) {
          util.log(this.getName() + ' ends ' + state);
          effect.deactivate();
          this.removeEffect(state);
        }
      });
    }
  },

  experience: function(l10n) {
    return function(experience) {

      const maxLevel = 60;
      if (this.getAttribute('level') >= maxLevel) {
        return;
      }

      util.log(this.getName() + ' has gained ' + experience + ' XP.');
      this.sayL10n(l10n, 'EXPGAIN', experience);

      const tnl = LevelUtil.expToLevel(this.getAttribute('level')) - this.getAttribute('experience');

      if (experience >= tnl) {
        return this.emit('level');
      }

      this.setAttribute('experience', this.getAttribute('experience') + experience);
    }
  },

  level: function(l10n) {
    return function() {
      const name = this.getName();
      const newLevel = this.getAttribute('level') + 1;
      const healthGain = Math.ceil(this.getAttribute('max_health') * 1.10);
      const energyGain = this.getAttribute('max_energy')
                       + this.getAttribute('stamina')
                       + this.getAttribute('quickness');

      const sanityGain = this.getAttribute('max_sanity')
                       + this.getAttribute('willpower')
                       + this.getAttribute('cleverness');

      util.log(name + ' gained health ' + healthGain);
      util.log(name + ' gained energy ' + energyGain);
      util.log(name + ' gained sanity' + sanityGain);

      const gainedMutation = newLevel % 2 === 0;

      let mutationPoints = this.getAttribute('mutagens');

      util.log(name + ' is now level ' + newLevel);

      this.sayL10n(l10n, 'LEVELUP');

      if (gainedMutation) {
        this.sayL10n(l10n, 'MUTAGEN_GAIN');
        mutationPoints++;
        this.setAttribute('mutagens', mutationPoints);
      }

      this.setAttribute('level', newLevel);
      this.setAttribute('experience', 0);
      this.setAttribute('attrPoints', (this.getAttribute('attrPoints') || 0) + 1);

      // Do whatever you want to do here when a player levels up...
      const attrToLevel = {
        'health': healthGain,
        'energy': energyGain,
        'sanity:': sanityGain,
      };

      for (const attr in attrToLevel) {
        const max = 'max_' + attr;
        this.setAttribute(max, healthGain);
        this.setAttribute(attr, this.getAttribute(max));
        this.say('<blue>You have gained ' + attr + '.</blue>');
      }

      // Add points for skills
      const skillGain = LevelUtil.getTrainingTime(newLevel);
      const newTrainingTime = this.getTraining('time') + skillGain;
      util.log(name + ' can train x', newTrainingTime);
      this.setTraining('time', newTrainingTime);
    }
  },

  //TODO: Permadeath, add it.
  die: function(l10n) {
    return function() {
      const startLocation = 1;
      const playerExp = this.getAttribute('experience');
      const experiencePenalty = playerExp - Math.ceil((playerExp * 0.10));

      util.log(this.getName() + ' died.');
      Commands.player_commands.remove('all', this, true);
      Commands.player_commands.drop('all', this);

      this.setLocation(startLocation);
      this.emit('regen');
      this.setAttribute('experience', experiencePenalty);
    }
  },

  changeTime: function(l10n) {
    return function (wasDaytime, rooms) {
      const playerIsOutside = rooms.getAt(this.getLocation()).biome === 'outdoors';

      if (playerIsOutside) {
        if (wasDaytime) {
          this.sayL10n(l10n, "SUN_SETTING");
          setTimeout(() => this.sayL10n(l10n, "SUN_SET"), 5000);

        } else {
          this.sayL10n(l10n, "SUN_RISING");
          setTimeout(() => this.sayL10n(l10n, "SUN_UP"), 5000);
        }

      } else if (wasDaytime) {
        this.sayL10n(l10n, "SUN_SETTING_INDOORS");
      } else {
        this.sayL10n(l10n, "SUN_UP_INDOORS");
      }

    }
  }
};
<|endoftext|>


<commit_before>import { remote, shell } from 'electron';
import settings from 'electron-settings';

import { SEND_TOGGLE_COMPACT } from '../channels';

export const openNewWindow = (link) => shell.openExternal(link);

export const setFullAppMode = (win) => {
  const isCompact = settings.get('system.compact');
  if (isCompact) win.webContents.send(SEND_TOGGLE_COMPACT);
};

export const setWindowSize = (win, compact) => {
  const WIDTH = 650;
  const HEIGHT = 500;
  const COMPACT_WIDTH = 150;
  const COMPACT_HEIGHT = 90;

  if (compact) {
    win.setResizable(false);
    win.setMaximizable(false);
    win.setAlwaysOnTop(true);
    win.setMinimumSize(COMPACT_WIDTH, COMPACT_HEIGHT);
    win.setSize(COMPACT_WIDTH, COMPACT_HEIGHT, true);
    settings.set('system.compact', true);
  } else {
    win.setResizable(true);
    win.setMaximizable(true);
    win.setAlwaysOnTop(false);
    win.setMinimumSize(WIDTH, HEIGHT);
    win.setSize(WIDTH, HEIGHT, true);
    settings.set('system.compact', false);
  }
};

export const showWindow = () => remote.getCurrentWindow().show();
<commit_msg>enhancement: Increase height of window<commit_after>import { remote, shell } from 'electron';
import settings from 'electron-settings';

import { SEND_TOGGLE_COMPACT } from '../channels';

export const openNewWindow = (link) => shell.openExternal(link);

export const setFullAppMode = (win) => {
  const isCompact = settings.get('system.compact');
  if (isCompact) win.webContents.send(SEND_TOGGLE_COMPACT);
};

export const setWindowSize = (win, compact) => {
  const WIDTH = 650;
  const HEIGHT = 515;
  const COMPACT_WIDTH = 150;
  const COMPACT_HEIGHT = 90;

  if (compact) {
    win.setResizable(false);
    win.setMaximizable(false);
    win.setAlwaysOnTop(true);
    win.setMinimumSize(COMPACT_WIDTH, COMPACT_HEIGHT);
    win.setSize(COMPACT_WIDTH, COMPACT_HEIGHT, true);
    settings.set('system.compact', true);
  } else {
    win.setResizable(true);
    win.setMaximizable(true);
    win.setAlwaysOnTop(false);
    win.setMinimumSize(WIDTH, HEIGHT);
    win.setSize(WIDTH, HEIGHT, true);
    settings.set('system.compact', false);
  }
};

export const showWindow = () => remote.getCurrentWindow().show();
<|endoftext|>


<commit_before>import HttpError from 'admin-on-rest/lib/util/HttpError'
import fetchJsonLd from 'api-doc-parser/lib/hydra/fetchJsonLd';
import {getDocumentationUrlFromHeaders} from  'api-doc-parser/lib/hydra/parseHydraDocumentation'
import {promises} from 'jsonld';

/**
 * Sends HTTP requests to a Hydra API.
 *
 * Adapted from AdminBuilder On Rest
 *
 * @copyright Kévin Dunglas
 * @copyright Francois Zaninotto, Marmelab
 * @see https://github.com/marmelab/admin-on-rest/blob/v0.9.2/src/util/fetch.js
 *
 * @param {string} url
 * @param {object} options
 * @return {object}
 */
export default (url, options = {}) => {
  const requestHeaders = options.headers || new Headers();

  if (options.user && options.user.authenticated && options.user.token) {
    requestHeaders.set('Authorization', options.user.token);
  }

  return fetchJsonLd(url, { ...options, headers: requestHeaders })
    .then(data => {
      if (data.response.status < 200 || data.response.status >= 300) {
        return promises
          .expand(data.body, { base: getDocumentationUrlFromHeaders(data.response.headers) })
          .then(json => {
            try {
              return Promise.reject(new Error(json[0]['http://www.w3.org/ns/hydra/core#description'][0]['@value']));
            } catch (e) {
              return Promise.reject(new HttpError(data.response.statusText, status));
            }
          })
          .catch(() => {
            return Promise.reject(new HttpError(data.response.statusText, status));
          })
      }
      return {
        'status': data.response.status,
        'headers': data.response.headers,
        'json': data.body
      };
    });
};
<commit_msg>Remove outdated copyright<commit_after>import HttpError from 'admin-on-rest/lib/util/HttpError'
import fetchJsonLd from 'api-doc-parser/lib/hydra/fetchJsonLd';
import {getDocumentationUrlFromHeaders} from  'api-doc-parser/lib/hydra/parseHydraDocumentation'
import {promises} from 'jsonld';

/**
 * Sends HTTP requests to a Hydra API.
 *
 * Adapted from AdminBuilder On Rest
 *
 * @copyright Kévin Dunglas
 *
 * @param {string} url
 * @param {object} options
 * @return {object}
 */
export default (url, options = {}) => {
  const requestHeaders = options.headers || new Headers();

  if (options.user && options.user.authenticated && options.user.token) {
    requestHeaders.set('Authorization', options.user.token);
  }

  return fetchJsonLd(url, { ...options, headers: requestHeaders })
    .then(data => {
      if (data.response.status < 200 || data.response.status >= 300) {
        return promises
          .expand(data.body, { base: getDocumentationUrlFromHeaders(data.response.headers) })
          .then(json => {
            try {
              return Promise.reject(new Error(json[0]['http://www.w3.org/ns/hydra/core#description'][0]['@value']));
            } catch (e) {
              return Promise.reject(new HttpError(data.response.statusText, status));
            }
          })
          .catch(() => {
            return Promise.reject(new HttpError(data.response.statusText, status));
          })
      }
      return {
        'status': data.response.status,
        'headers': data.response.headers,
        'json': data.body
      };
    });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
	Text,
	View,
	InteractionManager,
	ActivityIndicator,
	TextInput,
	StyleSheet,
	Alert,
	TouchableWithoutFeedback,
	TouchableOpacity,
	KeyboardAvoidingView,
	ScrollView
} from 'react-native';
import { connect } from 'react-redux';
import Icon from 'react-native-vector-icons/FontAwesome';
import Device from 'react-native-device-info';

import { hideKeyboard, getCampusPrimary } from '../util/general';
import logger from '../util/logger';
import css from '../styles/css';
import AppSettings from '../AppSettings';

class FeedbackView extends Component {

	constructor(props) {
		super(props);

		this.state = {
			commentsText: '',
			nameText: '',
			emailText: '',
			commentsHeight: 0,
			loaded: false,
			submit: false,
			labelText: 'Help us make the ' + AppSettings.APP_NAME +
				' app better. Submit your thoughts and suggestions.'
		};
	}

	componentDidMount() {
		logger.ga('View Loaded: Feedback');

		InteractionManager.runAfterInteractions(() => {
			this.setState({ loaded: true });
		});
	}

	componentWillReceiveProps(nextProps) {
		// Clear search results when navigating away
		if (nextProps.scene.key !== this.props.scene.key) {
			this.setState({
				commentsText: '',
				nameText: '',
				emailText: '',
			});
		}
	}

	/**
	 * Called after state change
	 * @return bool whether the component should re-render.
	**/
	shouldComponentUpdate(nextProps, nextState) {
		return true;
	}

	_postFeedback() {
		if (this.state.commentsText !== '') {
			this.setState({ loaded: false });

			const formData = new FormData();
			formData.append('element_1', this.state.commentsText);
			formData.append('element_2', this.state.nameText);
			formData.append('element_3', this.state.emailText);
			formData.append(
				'element_4',
				'Device Manufacturer: ' + Device.getManufacturer() + '\n' +
				'Device Brand: ' + Device.getBrand() + '\n' +
				'Device Model: ' + Device.getModel() + '\n' +
				'Device ID: ' + Device.getDeviceId() + '\n' +
				'System Name: ' + Device.getSystemName() + '\n' +
				'System Version: ' + Device.getSystemVersion() + '\n' +
				'Bundle ID: ' + Device.getBundleId() + '\n' +
				'App Version: ' + Device.getVersion() + '\n' +
				'Build Number: ' + Device.getBuildNumber() + '\n' +
				'Device Name: ' + Device.getDeviceName() + '\n' +
				'User Agent: ' + Device.getUserAgent() + '\n' +
				'Device Locale: ' + Device.getDeviceLocale() + '\n' +
				'Device Country: ' + Device.getDeviceCountry() + '\n' +
				'Timezone: ' + Device.getTimezone()
			);
			formData.append('form_id','175631');
			formData.append('submit_form','1');
			formData.append('page_number','1');
			formData.append('submit_form','Submit');

			fetch('https://eforms.ucsd.edu/view.php?id=175631', {
				method: 'POST',
				body: formData
			})
			.then((response) => {
				// Clear fields and alert user
				Alert.alert(
					'Thank you!',
					'We will take your feedback into consideration as we continue developing and improving the app.',
				);

				this.setState({
					submit: true,
					commentsText: '',
					nameText: '',
					emailText: '',
					commentsHeight: 0,
					loaded: true
				});
				return response.json();
			})
			.then((responseJson) => {
				// logger.log(responseJson);
			})
			.catch((error) => {
				logger.error('Error submitting Feedback: ' + error);
			});
		}
		else {
			return;
		}
	}

	_renderLoadingView() {
		return (
			<View style={css.main_container}>
				<ActivityIndicator
					animating={true}
					style={styles.loading_icon}
					size="large"
				/>
			</View>
		);
	}

	_renderFormView() {
		return (
			<KeyboardAvoidingView
				style={css.main_container}
				behavior="padding"
			>
				<TouchableWithoutFeedback
					onPress={() => hideKeyboard()}
				>
					<View
						style={{ flex: 1 }}
					>
						<Text style={styles.feedback_label}>
							{this.state.labelText}
						</Text>
						<TextInput
							ref={(ref) => { this._feedback = ref; }}
							multiline={true}
							blurOnSubmit={true}
							value={this.state.commentsText}
							onFocus={() => this.setState({
								labelText: ''
							})}
							onChange={(event) => {
								this.setState({
									commentsText: event.nativeEvent.text,
								});
							}}
							placeholder="Tell us what you think*"
							underlineColorAndroid={'transparent'}
							style={[styles.feedback_text]}
							returnKeyType={'done'}
							maxLength={500}
						/>
						<TextInput
							ref={(ref) => { this._email = ref; }}
							value={this.state.emailText}
							onChangeText={(text) => this.setState({ emailText: text })}
							placeholder="Email"
							underlineColorAndroid={'transparent'}
							style={styles.email_text}
							returnKeyType={'done'}
							keyboardType={'email-address'}
							maxLength={100}
						/>
						<TouchableOpacity underlayColor={'rgba(200,200,200,.1)'} onPress={() => this._postFeedback()}>
							<View style={styles.submit_container}>
								<Text style={styles.submit_text}>Submit</Text>
							</View>
						</TouchableOpacity>
					</View>
				</TouchableWithoutFeedback>
			</KeyboardAvoidingView>
		);
	}

	render() {
		// return this._renderSubmitView();
		if (!this.state.loaded) {
			return this._renderLoadingView();
		} else {
			return this._renderFormView();
		}
	}
}

const styles = StyleSheet.create({
	loading_icon: { flex: 1, alignItems: 'center', justifyContent: 'center' },
	feedback_container: { flex: 1, flexDirection: 'column', marginHorizontal: 8, marginTop: 8 },
	feedback_label: { flexWrap: 'wrap', fontSize: 18, margin: 8, lineHeight: 24 },
	feedback_text: { flex: 1, backgroundColor: '#FFF', fontSize: 18, alignItems: 'center', padding: 8, margin: 8, minHeight: 50 },
	email_text: { backgroundColor: '#FFF', fontSize: 18, alignItems: 'center', padding: 8, margin: 8, minHeight: 50 },

	submit_container: { justifyContent: 'center', alignItems: 'center', backgroundColor: getCampusPrimary(), borderRadius: 3, padding: 10, margin: 8 },
	submit_text: { fontSize: 16, color: '#FFF' },

	feedback_text_container: { flexDirection: 'row', borderColor: '#DADADA', borderBottomWidth: 1, marginBottom: 8, backgroundColor: 'white' },
	text_container: { height: 50, borderColor: '#DADADA', borderBottomWidth: 1, marginBottom: 8 },
});

const mapStateToProps = (state, props) => (
	{
		scene: state.routes.scene
	}
);

module.exports = connect(mapStateToProps)(FeedbackView);

/*
<TouchableWithoutFeedback
				onPress={() => hideKeyboard()}
			>
				<View style={css.main_container}>
					<View style={styles.feedback_container}>
						<Text style={styles.feedback_label}>
							Help us make the {AppSettings.APP_NAME} app better.{'\n'}
							Submit your thoughts and suggestions.
						</Text>

						<View style={styles.feedback_text_container}>
							<TextInput
								ref={(ref) => { this._feedback = ref; }}
								multiline={true}
								blurOnSubmit={true}
								value={this.state.commentsText}
								onChange={(event) => {
									this.setState({
										commentsText: event.nativeEvent.text,
										// commentsHeight: event.nativeEvent.contentSize.height,
									});
								}}
								placeholder="Tell us what you think*"
								underlineColorAndroid={'transparent'}
								style={[styles.feedback_text, { height: Math.max(400, this.state.commentsHeight) }]}
								returnKeyType={'done'}
								maxLength={500}
							/>
						</View>

						<View style={styles.text_container}>
							<TextInput
								ref={(ref) => { this._email = ref; }}
								value={this.state.emailText}
								onChangeText={(text) => this.setState({ emailText: text })}
								placeholder="Email"
								underlineColorAndroid={'transparent'}
								style={styles.feedback_text}
								returnKeyType={'done'}
								keyboardType={'email-address'}
								maxLength={100}
							/>
						</View>

						<TouchableOpacity underlayColor={'rgba(200,200,200,.1)'} onPress={() => this._postFeedback()}>
							<View style={styles.submit_container}>
								<Text style={styles.submit_text}>Submit</Text>
							</View>
						</TouchableOpacity>

					</View>
				</View>
			</TouchableWithoutFeedback>
 */<commit_msg>Use ColorConstants for FeedbackView<commit_after>import React, { Component } from 'react';
import {
	Text,
	View,
	InteractionManager,
	ActivityIndicator,
	TextInput,
	StyleSheet,
	Alert,
	TouchableWithoutFeedback,
	TouchableOpacity,
	KeyboardAvoidingView,
} from 'react-native';
import { connect } from 'react-redux';
import Device from 'react-native-device-info';

import Touchable from './common/Touchable';
import { hideKeyboard } from '../util/general';
import logger from '../util/logger';
import css from '../styles/css';
import AppSettings from '../AppSettings';
import {
	COLOR_WHITE,
	COLOR_PRIMARY
} from '../styles/ColorConstants';

class FeedbackView extends Component {

	constructor(props) {
		super(props);

		this.state = {
			commentsText: '',
			nameText: '',
			emailText: '',
			commentsHeight: 0,
			loaded: false,
			submit: false,
			labelText: 'Help us make the ' + AppSettings.APP_NAME +
				' app better. Submit your thoughts and suggestions.'
		};
	}

	componentDidMount() {
		logger.ga('View Loaded: Feedback');

		InteractionManager.runAfterInteractions(() => {
			this.setState({ loaded: true });
		});
	}

	componentWillReceiveProps(nextProps) {
		// Clear search results when navigating away
		if (nextProps.scene.key !== this.props.scene.key) {
			this.setState({
				commentsText: '',
				nameText: '',
				emailText: '',
			});
		}
	}

	/**
	 * Called after state change
	 * @return bool whether the component should re-render.
	**/
	shouldComponentUpdate(nextProps, nextState) {
		return true;
	}

	_postFeedback() {
		if (this.state.commentsText !== '') {
			this.setState({ loaded: false });

			const formData = new FormData();
			formData.append('element_1', this.state.commentsText);
			formData.append('element_2', this.state.nameText);
			formData.append('element_3', this.state.emailText);
			formData.append(
				'element_4',
				'Device Manufacturer: ' + Device.getManufacturer() + '\n' +
				'Device Brand: ' + Device.getBrand() + '\n' +
				'Device Model: ' + Device.getModel() + '\n' +
				'Device ID: ' + Device.getDeviceId() + '\n' +
				'System Name: ' + Device.getSystemName() + '\n' +
				'System Version: ' + Device.getSystemVersion() + '\n' +
				'Bundle ID: ' + Device.getBundleId() + '\n' +
				'App Version: ' + Device.getVersion() + '\n' +
				'Build Number: ' + Device.getBuildNumber() + '\n' +
				'Device Name: ' + Device.getDeviceName() + '\n' +
				'User Agent: ' + Device.getUserAgent() + '\n' +
				'Device Locale: ' + Device.getDeviceLocale() + '\n' +
				'Device Country: ' + Device.getDeviceCountry() + '\n' +
				'Timezone: ' + Device.getTimezone()
			);
			formData.append('form_id','175631');
			formData.append('submit_form','1');
			formData.append('page_number','1');
			formData.append('submit_form','Submit');

			fetch('https://eforms.ucsd.edu/view.php?id=175631', {
				method: 'POST',
				body: formData
			})
			.then((response) => {
				// Clear fields and alert user
				Alert.alert(
					'Thank you!',
					'We will take your feedback into consideration as we continue developing and improving the app.',
				);

				this.setState({
					submit: true,
					commentsText: '',
					nameText: '',
					emailText: '',
					commentsHeight: 0,
					loaded: true
				});
				return response.json();
			})
			.then((responseJson) => {
				// logger.log(responseJson);
			})
			.catch((error) => {
				logger.error('Error submitting Feedback: ' + error);
			});
		}
		else {
			return;
		}
	}

	_renderLoadingView() {
		return (
			<View style={css.main_container}>
				<ActivityIndicator
					animating={true}
					style={styles.loadingIcon}
					size="large"
				/>
			</View>
		);
	}

	_renderFormView() {
		return (
			<KeyboardAvoidingView
				style={css.main_container}
				behavior="padding"
			>
				<TouchableWithoutFeedback
					onPress={() => hideKeyboard()}
				>
					<View
						style={{ flex: 1 }}
					>
						<Text style={styles.feedbackText}>
							{this.state.labelText}
						</Text>
						<TextInput
							ref={(ref) => { this._feedback = ref; }}
							multiline={true}
							blurOnSubmit={true}
							value={this.state.commentsText}
							onFocus={() => this.setState({
								labelText: ''
							})}
							onChange={(event) => {
								this.setState({
									commentsText: event.nativeEvent.text,
								});
							}}
							placeholder="Tell us what you think*"
							underlineColorAndroid={'transparent'}
							style={[styles.feedbackInput]}
							returnKeyType={'done'}
							maxLength={500}
						/>
						<TextInput
							ref={(ref) => { this._email = ref; }}
							value={this.state.emailText}
							onChangeText={(text) => this.setState({ emailText: text })}
							placeholder="Email"
							underlineColorAndroid={'transparent'}
							style={styles.emailInput}
							returnKeyType={'done'}
							keyboardType={'email-address'}
							maxLength={100}
						/>
						<Touchable
							onPress={() => this._postFeedback()}
						>
							<View style={styles.submitContainer}>
								<Text style={styles.submitText}>Submit</Text>
							</View>
						</Touchable>
					</View>
				</TouchableWithoutFeedback>
			</KeyboardAvoidingView>
		);
	}

	render() {
		// return this._renderSubmitView();
		if (!this.state.loaded) {
			return this._renderLoadingView();
		} else {
			return this._renderFormView();
		}
	}
}

const styles = StyleSheet.create({
	loadingIcon: { flex: 1, alignItems: 'center', justifyContent: 'center' },
	feedbackText: { flexWrap: 'wrap', fontSize: 18, margin: 8, lineHeight: 24 },
	feedbackInput: { flex: 1, backgroundColor: COLOR_WHITE, fontSize: 18, alignItems: 'center', padding: 8, margin: 8, minHeight: 50 },
	emailInput: { backgroundColor: COLOR_WHITE, fontSize: 18, alignItems: 'center', padding: 8, margin: 8, minHeight: 50 },
	submitContainer: { justifyContent: 'center', alignItems: 'center', backgroundColor: COLOR_PRIMARY, borderRadius: 3, padding: 10, margin: 8 },
	submitText: { fontSize: 16, color: COLOR_WHITE },
});

const mapStateToProps = (state, props) => (
	{
		scene: state.routes.scene
	}
);

export default connect(mapStateToProps)(FeedbackView);
<|endoftext|>


<commit_before>/**common -- iServer**/
import './common/iServer/AddressMatchServiceSpec.js';
import './common/iServer/AggQueryBuilderParameterSpec.js';
import './common/iServer/AggregationParameterSpec.js';
import './common/iServer/AreaSolarRadiationParametersSpec.js';
import './common/iServer/BufferAnalystServiceSpec.js';
import './common/iServer/BufferDistanceSpec.js';
import './common/iServer/BufferSettingSpec.js';
import './common/iServer/BurstPipelineAnalystServiceSpec.js';
import './common/iServer/ChartQueryFilterParameterSpec.js';
import './common/iServer/ChartQueryParametersSpec.js';
import './common/iServer/ClipParameterSpec.js';
import './common/iServer/ComputeWeightMatrixServiceSpec.js';
import './common/iServer/DensityAnalystServiceSpec.js';
import './common/iServer/EditFeaturesServiceSpec.js';
import './common/iServer/FacilityAnalystStreamParametersSpec.js';
import './common/iServer/FacilityAnalystUpstream3DParametersSpec.js';
import './common/iServer/FieldStatisticServiceSpec.js';
import './common/iServer/FilterAggParameterSpec.js';
import './common/iServer/FindClosestFacilitiesServiceSpec.js';
import './common/iServer/FindLocationServiceSpec.js';
import './common/iServer/FindMTSPPathsServiceSpec.js';
import './common/iServer/FindPathServiceSpec.js';
import './common/iServer/FindServiceAreasServiceSpec.js';
import './common/iServer/FindTSPPathsServiceSpec.js';
import './common/iServer/GenerateSpatialDataServiceSpec.js';
import './common/iServer/GeoBoundingBoxQueryBuilderParameterSpec.js';
import './common/iServer/GeoHashGridAggParameterSpec.js';
import './common/iServer/GeometryBatchAnalystServiceSpec.js';
import './common/iServer/GeoRelationAnalystServiceSpec.js';
import './common/iServer/GetFeaturesByBoundsServiceSpec.js';
import './common/iServer/GetFeaturesByBufferServiceSpec.js';
import './common/iServer/GetFeaturesByGeometryServiceSpec.js';
import './common/iServer/GetFeaturesByIDsServiceSpec.js';
import './common/iServer/GetFeaturesBySQLServiceSpec.js';
import './common/iServer/GetFieldsServiceSpec.js';
import './common/iServer/GetGridCellInfosServiceSpec.js';
import './common/iServer/GetLayersInfoServiceSpec.js';
import './common/iServer/GridSpec.js';
import './common/iServer/ImageSpec.js';
import './common/iServer/InterpolationAnalystServiceSpec.js';
import './common/iServer/LabelImageCellSpec.js';
import './common/iServer/LabelMixedStyleSpec.js';
import './common/iServer/LinkItemSpec.js';
import './common/iServer/MapServiceSpec.js';
import './common/iServer/MathExpressionAnalysisServiceSpec.js';
import './common/iServer/MeasureServiceSpec.js';
import './common/iServer/OverlapDisplayedOptionsSpec.js';
import './common/iServer/OverlayAnalystServiceSpec.js';
import './common/iServer/QueryByBoundsServiceSpec.js';
import './common/iServer/QueryByDistanceServiceSpec.js';
import './common/iServer/QueryByGeometryServiceSpec.js';
import './common/iServer/QueryBySQLServiceSpec.js';
import './common/iServer/QueryServiceSpec.js';
import './common/iServer/RouteCalculateMeasureServiceSpec.js';
import './common/iServer/RouteLocatorServiceSpec.js';
import './common/iServer/RouteSpec.js';
import './common/iServer/ServerGeometrySpec.js';
import './common/iServer/SetLayerInfoServiceSpec.js';
import './common/iServer/SetLayersInfoServiceSpec.js';
import './common/iServer/SetLayerStatusServiceSpec.js';
import './common/iServer/StopQueryServiceSpec.js';
import './common/iServer/SummaryAttributesJobsParameterSpec.js';
import './common/iServer/SurfaceAnalystServiceSpec.js';
import './common/iServer/TerrainCurvatureCalculationServiceSpec.js';
import './common/iServer/ThemeDotDensitySpec.js';
import './common/iServer/ThemeGridRangeSpec.js';
import './common/iServer/ThemeGridUniqueSpec.js';
import './common/iServer/ThemeLabelUniqueItemSpec.js';
import './common/iServer/ThemeRangeSpec.js';
import './common/iServer/ThemeServiceSpec.js';
import './common/iServer/ThiessenAnalystServiceSpec.js';
import './common/iServer/TilesetsServiceSpec.js';
import './common/iServer/TransferLineSpec.js';
import './common/iServer/TransferPathServiceSpec.js';
import './common/iServer/TransferSolutionServiceSpec.js';
import './common/iServer/UpdateEdgeWeightServiceSpec.js';
import './common/iServer/UpdateTurnNodeWeightServiceSpec.js';
// import './common/iServer/AreaSolarRadiationServiceSpec.js';       //iclient8注释掉
// import './common/iServer/ChartFeatureInfoSpecsServiceSpec.js';    //iclient8注释掉,海图测试LayerServices相关的类，等待服务端支持后添加
// import './common/iServer/ChartQueryServiceSpec.js';
// import './common/iServer/FacilityAnalystSinks3DServiceSpec.js';   //三维网络分析Facility系列的测试全部被iClient8注释掉
// import './common/iServer/FacilityAnalystSources3DServiceSpec.js';
// import './common/iServer/FacilityAnalystStreamServiceSpec.js';
// import './common/iServer/FacilityAnalystTracedown3DServiceSpec.js';
// import './common/iServer/FacilityAnalystTraceup3DServiceSpec.js';
// import './common/iServer/FacilityAnalystUpstream3DServiceSpec.js';

/**common -- control**/
import './common/control/TimeControlBaseSpec.js';
import './common/control/TimeFlowControlSpec.js';

/**common -- format**/
import './common/format/GeoJSONSpec.js';
import './common/format/JSONSpec.js';
import './common/format/WKTSpec.js';

/**common -- style**/
import './common/style/CartoCSSSpec.js';

/**common -- security**/
import './common/security/KeyServiceParameterSpec.js';
import './common/security/SecurityManagerSpec.js';

/**common -- commontypes**/
import './common/commontypes/BaseTypesSpec.js';
import './common/commontypes/BoundsSpec.js';
import './common/commontypes/DateSpec.js';
import './common/commontypes/LonLatSpec.js';
import './common/commontypes/PixelSpec.js';
import './common/commontypes/VectorSpec.js';
import './common/commontypes/UtilSpec.js';
import './common/commontypes/geometry/CollectionSpec.js';
import './common/commontypes/geometry/GeoTextSpec.js';
import './common/commontypes/geometry/LineStringSpec.js';
import './common/commontypes/geometry/LinearRingSpec.js';

/**common -- overlay**/
import './common/overlay/feature/ShapeFactorySpec.js';
import './common/overlay/levelRenderer/AreaSpec.js';
import './common/overlay/levelRenderer/ClipSpec.js';
import './common/overlay/levelRenderer/AnimationSpec.js';
import './common/overlay/levelRenderer/ColorSpec.js';
import './common/overlay/levelRenderer/ComputeBoundingBoxSpec';
import './common/overlay/levelRenderer/CurveSpec.js';
import './common/overlay/levelRenderer/EasingSpec.js';
import './common/overlay/levelRenderer/GroupSpec.js';
import './common/overlay/levelRenderer/LevelRendererSpec.js';
import './common/overlay/levelRenderer/MatrixSpec.js';
import './common/overlay/levelRenderer/PainterSpec.js';
import './common/overlay/levelRenderer/RenderSpec.js';
import './common/overlay/levelRenderer/ShapeSepc.js';
import './common/overlay/levelRenderer/SmicBrokenLineSpec.js';
import './common/overlay/levelRenderer/SmicCircleSpec.js';
import './common/overlay/levelRenderer/SmicEllipseSpec';
import './common/overlay/levelRenderer/SmicImageSpec.js';
import './common/overlay/levelRenderer/SmicIsogonSpec.js';
import './common/overlay/levelRenderer/SmicPointSpec.js';
import './common/overlay/levelRenderer/SmicPolygonSpec.js';
import './common/overlay/levelRenderer/SmicRectangleSpec.js';
import './common/overlay/levelRenderer/SmicRingSpec.js';
import './common/overlay/levelRenderer/SmicSectorSpec.js';
import './common/overlay/levelRenderer/SmicStarSpec.js';
import './common/overlay/levelRenderer/SmicTextSpec.js';
import './common/overlay/levelRenderer/StorageSpec.js';
import './common/overlay/levelRenderer/TransformableSpec.js';
import './common/overlay/levelRenderer/UtilSpec.js';
import './common/overlay/levelRenderer/VectorSpec.js';
import './common/overlay/GraphSpec';

/**common -- online**/
import './common/online/OnlineDataSpec.js';
import './common/online/OnlineSpec.js';
import './common/online/OnlineQueryDatasParameterSpec';

/**common -- iManager**/
import './common/iManager/iManagerCreateNodeParamSpec.js';

/**common -- iPortal**/
import './common/iPortal/iPortalQueryParamSpec.js';
import './common/iPortal/iPortalUserSpec.js';
// import './common/iPortal/iPortalShareEntitySpec.js';
// import './common/iPortal/iPortalShareParamSpec.js';
// import './common/iPortal/iPortalResourceSpec.js';
// import './common/iPortal/iPortalQueryResultSpec.js';
import './common/iPortal/iPortalSpec.js';
import './common/iPortal/iPortalAddResourceParamSpec';
// import './common/iPortal/iPortalRegisterServiceParamSpec';
// import './common/iPortal/iPortalAddDataParamSpec.js';
import './common/iPortal/iPortalDataMetaInfoParamSpec.js';
import './common/iPortal/iPortalDataStoreInfoParamSpec.js';
import './common/iPortal/iPortalDataConnectionInfoParamSpec.js';

/**common -- thirdparty**/
import './common/thirdparty/elasticsearch/ElasticSearchSpec.js';

/**common -- component**/
import './common/components/templates/IndexTabsPageContainerSpec.js';
import './common/components/templates/NavTabsPageSpec.js';
// import './common/components/templates/CommonContainerSpec.js';
import './common/components/chart/ChartModelSpec.js';
import './common/components/chart/ChartViewModelSpec';
import './common/components/chart/ChartViewSpec';

import './common/util/FetchRequestSpec';

<commit_msg>Update test-main-common.js<commit_after>/**common -- iServer**/
import './common/iServer/AddressMatchServiceSpec.js';
import './common/iServer/AggQueryBuilderParameterSpec.js';
import './common/iServer/AggregationParameterSpec.js';
import './common/iServer/AreaSolarRadiationParametersSpec.js';
import './common/iServer/BufferAnalystServiceSpec.js';
import './common/iServer/BufferDistanceSpec.js';
import './common/iServer/BufferSettingSpec.js';
import './common/iServer/BurstPipelineAnalystServiceSpec.js';
import './common/iServer/ChartQueryFilterParameterSpec.js';
import './common/iServer/ChartQueryParametersSpec.js';
import './common/iServer/ClipParameterSpec.js';
import './common/iServer/ComputeWeightMatrixServiceSpec.js';
import './common/iServer/DensityAnalystServiceSpec.js';
import './common/iServer/EditFeaturesServiceSpec.js';
import './common/iServer/FacilityAnalystStreamParametersSpec.js';
import './common/iServer/FacilityAnalystUpstream3DParametersSpec.js';
import './common/iServer/FieldStatisticServiceSpec.js';
import './common/iServer/FilterAggParameterSpec.js';
import './common/iServer/FindClosestFacilitiesServiceSpec.js';
import './common/iServer/FindLocationServiceSpec.js';
import './common/iServer/FindMTSPPathsServiceSpec.js';
import './common/iServer/FindPathServiceSpec.js';
import './common/iServer/FindServiceAreasServiceSpec.js';
import './common/iServer/FindTSPPathsServiceSpec.js';
import './common/iServer/GenerateSpatialDataServiceSpec.js';
import './common/iServer/GeoBoundingBoxQueryBuilderParameterSpec.js';
import './common/iServer/GeoHashGridAggParameterSpec.js';
import './common/iServer/GeometryBatchAnalystServiceSpec.js';
import './common/iServer/GeoRelationAnalystServiceSpec.js';
import './common/iServer/GetFeaturesByBoundsServiceSpec.js';
import './common/iServer/GetFeaturesByBufferServiceSpec.js';
import './common/iServer/GetFeaturesByGeometryServiceSpec.js';
import './common/iServer/GetFeaturesByIDsServiceSpec.js';
import './common/iServer/GetFeaturesBySQLServiceSpec.js';
import './common/iServer/GetFieldsServiceSpec.js';
import './common/iServer/GetGridCellInfosServiceSpec.js';
import './common/iServer/GetLayersInfoServiceSpec.js';
import './common/iServer/GridSpec.js';
import './common/iServer/ImageSpec.js';
import './common/iServer/InterpolationAnalystServiceSpec.js';
import './common/iServer/LabelImageCellSpec.js';
import './common/iServer/LabelMixedStyleSpec.js';
import './common/iServer/LinkItemSpec.js';
import './common/iServer/MapServiceSpec.js';
import './common/iServer/MathExpressionAnalysisServiceSpec.js';
import './common/iServer/MeasureServiceSpec.js';
import './common/iServer/OverlapDisplayedOptionsSpec.js';
import './common/iServer/OverlayAnalystServiceSpec.js';
import './common/iServer/QueryByBoundsServiceSpec.js';
import './common/iServer/QueryByDistanceServiceSpec.js';
import './common/iServer/QueryByGeometryServiceSpec.js';
import './common/iServer/QueryBySQLServiceSpec.js';
import './common/iServer/QueryServiceSpec.js';
import './common/iServer/RouteCalculateMeasureServiceSpec.js';
import './common/iServer/RouteLocatorServiceSpec.js';
import './common/iServer/RouteSpec.js';
import './common/iServer/ServerGeometrySpec.js';
import './common/iServer/SetLayerInfoServiceSpec.js';
import './common/iServer/SetLayersInfoServiceSpec.js';
import './common/iServer/SetLayerStatusServiceSpec.js';
import './common/iServer/StopQueryServiceSpec.js';
import './common/iServer/SummaryAttributesJobsParameterSpec.js';
import './common/iServer/SurfaceAnalystServiceSpec.js';
import './common/iServer/TerrainCurvatureCalculationServiceSpec.js';
import './common/iServer/ThemeDotDensitySpec.js';
import './common/iServer/ThemeGridRangeSpec.js';
import './common/iServer/ThemeGridUniqueSpec.js';
import './common/iServer/ThemeLabelUniqueItemSpec.js';
import './common/iServer/ThemeRangeSpec.js';
import './common/iServer/ThemeServiceSpec.js';
import './common/iServer/ThiessenAnalystServiceSpec.js';
import './common/iServer/TilesetsServiceSpec.js';
import './common/iServer/TransferLineSpec.js';
import './common/iServer/TransferPathServiceSpec.js';
import './common/iServer/TransferSolutionServiceSpec.js';
import './common/iServer/UpdateEdgeWeightServiceSpec.js';
import './common/iServer/UpdateTurnNodeWeightServiceSpec.js';
// import './common/iServer/AreaSolarRadiationServiceSpec.js';       //iclient8注释掉
// import './common/iServer/ChartFeatureInfoSpecsServiceSpec.js';    //iclient8注释掉,海图测试LayerServices相关的类，等待服务端支持后添加
// import './common/iServer/ChartQueryServiceSpec.js';
// import './common/iServer/FacilityAnalystSinks3DServiceSpec.js';   //三维网络分析Facility系列的测试全部被iClient8注释掉
// import './common/iServer/FacilityAnalystSources3DServiceSpec.js';
// import './common/iServer/FacilityAnalystStreamServiceSpec.js';
// import './common/iServer/FacilityAnalystTracedown3DServiceSpec.js';
// import './common/iServer/FacilityAnalystTraceup3DServiceSpec.js';
// import './common/iServer/FacilityAnalystUpstream3DServiceSpec.js';

/**common -- control**/
import './common/control/TimeControlBaseSpec.js';
import './common/control/TimeFlowControlSpec.js';

/**common -- format**/
import './common/format/GeoJSONSpec.js';
import './common/format/JSONSpec.js';
import './common/format/WKTSpec.js';

/**common -- style**/
import './common/style/CartoCSSSpec.js';

/**common -- security**/
import './common/security/KeyServiceParameterSpec.js';
import './common/security/SecurityManagerSpec.js';

/**common -- commontypes**/
import './common/commontypes/BaseTypesSpec.js';
import './common/commontypes/BoundsSpec.js';
import './common/commontypes/DateSpec.js';
import './common/commontypes/LonLatSpec.js';
import './common/commontypes/PixelSpec.js';
import './common/commontypes/VectorSpec.js';
import './common/commontypes/UtilSpec.js';
import './common/commontypes/geometry/CollectionSpec.js';
import './common/commontypes/geometry/GeoTextSpec.js';
import './common/commontypes/geometry/LineStringSpec.js';
import './common/commontypes/geometry/LinearRingSpec.js';

/**common -- overlay**/
import './common/overlay/feature/ShapeFactorySpec.js';
import './common/overlay/levelRenderer/AreaSpec.js';
import './common/overlay/levelRenderer/ClipSpec.js';
import './common/overlay/levelRenderer/AnimationSpec.js';
import './common/overlay/levelRenderer/ColorSpec.js';
import './common/overlay/levelRenderer/ComputeBoundingBoxSpec';
import './common/overlay/levelRenderer/CurveSpec.js';
import './common/overlay/levelRenderer/EasingSpec.js';
import './common/overlay/levelRenderer/GroupSpec.js';
import './common/overlay/levelRenderer/LevelRendererSpec.js';
import './common/overlay/levelRenderer/MatrixSpec.js';
import './common/overlay/levelRenderer/PainterSpec.js';
import './common/overlay/levelRenderer/RenderSpec.js';
import './common/overlay/levelRenderer/ShapeSepc.js';
import './common/overlay/levelRenderer/SmicBrokenLineSpec.js';
import './common/overlay/levelRenderer/SmicCircleSpec.js';
import './common/overlay/levelRenderer/SmicEllipseSpec';
import './common/overlay/levelRenderer/SmicImageSpec.js';
import './common/overlay/levelRenderer/SmicIsogonSpec.js';
import './common/overlay/levelRenderer/SmicPointSpec.js';
import './common/overlay/levelRenderer/SmicPolygonSpec.js';
import './common/overlay/levelRenderer/SmicRectangleSpec.js';
import './common/overlay/levelRenderer/SmicRingSpec.js';
import './common/overlay/levelRenderer/SmicSectorSpec.js';
import './common/overlay/levelRenderer/SmicStarSpec.js';
import './common/overlay/levelRenderer/SmicTextSpec.js';
import './common/overlay/levelRenderer/StorageSpec.js';
import './common/overlay/levelRenderer/TransformableSpec.js';
import './common/overlay/levelRenderer/UtilSpec.js';
import './common/overlay/levelRenderer/VectorSpec.js';
import './common/overlay/GraphSpec';

/**common -- online**/
import './common/online/OnlineDataSpec.js';
import './common/online/OnlineSpec.js';
import './common/online/OnlineQueryDatasParameterSpec';

/**common -- iManager**/
import './common/iManager/iManagerCreateNodeParamSpec.js';

/**common -- iPortal**/
import './common/iPortal/iPortalQueryParamSpec.js';
import './common/iPortal/iPortalUserSpec.js';
// import './common/iPortal/iPortalShareEntitySpec.js';
// import './common/iPortal/iPortalShareParamSpec.js';
// import './common/iPortal/iPortalResourceSpec.js';
// import './common/iPortal/iPortalQueryResultSpec.js';
import './common/iPortal/iPortalSpec.js';
import './common/iPortal/iPortalAddResourceParamSpec';
// import './common/iPortal/iPortalRegisterServiceParamSpec';
// import './common/iPortal/iPortalAddDataParamSpec.js';
// import './common/iPortal/iPortalDataMetaInfoParamSpec.js';
import './common/iPortal/iPortalDataStoreInfoParamSpec.js';
import './common/iPortal/iPortalDataConnectionInfoParamSpec.js';

/**common -- thirdparty**/
import './common/thirdparty/elasticsearch/ElasticSearchSpec.js';

/**common -- component**/
import './common/components/templates/IndexTabsPageContainerSpec.js';
import './common/components/templates/NavTabsPageSpec.js';
// import './common/components/templates/CommonContainerSpec.js';
import './common/components/chart/ChartModelSpec.js';
import './common/components/chart/ChartViewModelSpec';
import './common/components/chart/ChartViewSpec';

import './common/util/FetchRequestSpec';

<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var async = require('async');

module.exports = {
  loadPriority:  0,
  initialize: function(api, next){

    if(!api.utils){ api.utils = {}; }

    ////////////////////////////////////////////////////////////////////////////
    // merge two hashes recursively
    api.utils.hashMerge = function(a, b, arg){
      var c = {};
      var i;
      var response;

      for(i in a){
        if(api.utils.isPlainObject(a[i]) && Object.keys(a[i]).length > 0){
          c[i] = api.utils.hashMerge(c[i], a[i], arg);
        }else{
          if(typeof a[i] === 'function'){
            response = a[i](arg);
            if(api.utils.isPlainObject(response)){
              c[i] = api.utils.hashMerge(c[i], response, arg);
            }else{
              c[i] = response;
            }
          }else{
            c[i] = a[i];
          }
        }
      }
      for(i in b){
        if(api.utils.isPlainObject(b[i]) && Object.keys(b[i]).length > 0){
          c[i] = api.utils.hashMerge(c[i], b[i], arg);
        }else{
          if(typeof b[i] === 'function'){
            response = b[i](arg);
            if(api.utils.isPlainObject(response)){
              c[i] = api.utils.hashMerge(c[i], response, arg);
            }else{
              c[i] = response;
            }
          }else{
            c[i] = b[i];
          }
        }
      }
      return c;
    };

    api.utils.isPlainObject = function(o){
      var safeTypes     = [Boolean, Number, String, Function, Array, Date, RegExp, Buffer];
      var safeInstances = ['boolean', 'number', 'string', 'function'];
      var expandPreventMatchKey = '_toExpand'; // set `_toExpand = false` within an object if you don't want to expand it
      var i;

      if(!o){ return false; }
      if((o instanceof Object) === false){ return false; }
      for(i in safeTypes){
        if(o instanceof safeTypes[i]){ return false; }
      }
      for(i in safeInstances){
        if(typeof o === safeInstances[i]){ return false; }
      }
      if(o[expandPreventMatchKey] === false){ return false; }
      return (o.toString() === '[object Object]');
    };

    ////////////////////////////////////////////////////////////////////////////
    // string to hash
    // http://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference
    api.utils.stringToHash = function(path, object){
      if(!object){ object = api; }
      function _index(obj, i){ return obj[i]; }
      return path.split('.').reduce(_index, object);
    };

    ////////////////////////////////////////////////////////////////////////////
    // unique-ify an array
    api.utils.arrayUniqueify = function(arr){
      var a = [];
      for(var i = 0; i < arr.length; i++){
        for(var j = i + 1; j < arr.length; j++){
          if(arr[i] === arr[j]){ j = ++i; }
        }
        a.push(arr[i]);
      }
      return a;
    };

    ////////////////////////////////////////////////////////////////////////////
    // get all .js files in a directory
    api.utils.recursiveDirectoryGlob = function(dir, extension, followLinkFiles){
      var results = [];

      if(!extension){ extension = '.js'; }
      if(!followLinkFiles){ followLinkFiles = true; }

      extension = extension.replace('.', '');

      if(fs.existsSync(dir)){
        fs.readdirSync(dir).forEach(function(file){
          var fullFilePath = path.join(dir, file);
          if(file[0] !== '.'){ // ignore 'system' files
            var stats = fs.statSync(fullFilePath);
            var child;
            if(stats.isDirectory()){
              child = api.utils.recursiveDirectoryGlob(fullFilePath, extension, followLinkFiles);
              child.forEach(function(c){ results.push(c); });
            }else if(stats.isSymbolicLink()){
              var realPath = fs.readlinkSync(fullFilePath);
              child = api.utils.recursiveDirectoryGlob(realPath, extension, followLinkFiles);
              child.forEach(function(c){ results.push(c); });
            }else if(stats.isFile()){
              var fileParts = file.split('.');
              var ext = fileParts[(fileParts.length - 1)];
              // real file match
              if(ext === extension){ results.push(fullFilePath); }
              // linkfile traversal
              if(ext === 'link' && followLinkFiles === true){
                var linkedPath = api.utils.sourceRelativeLinkPath(fullFilePath, api.config.general.paths.plugin);
                if(linkedPath){
                  child = api.utils.recursiveDirectoryGlob(linkedPath, extension, followLinkFiles);
                  child.forEach(function(c){ results.push(c); });
                }else{
                  try{
                    api.log(['cannot find linked refrence to `%s`', file], 'warning');
                  }catch(e){
                    throw('cannot find linked refrence to' + file);
                  }
                }
              }
            }
          }
        });
      }

      return results.sort();
    };

    api.utils.sourceRelativeLinkPath = function(linkfile, pluginPaths){
      var type = fs.readFileSync(linkfile).toString();
      var pathParts = linkfile.split(path.sep);
      var name = pathParts[(pathParts.length - 1)].split('.')[0];
      var pathsToTry = pluginPaths.slice(0);
      var pluginRoot;

      // TODO: always also try the local destination's `node_modules` to allow for nested plugins
      // This might be a security risk without requiring explicit sourcing

      pathsToTry.forEach(function(pluginPath){
        var pluginPathAttempt = path.normalize(pluginPath + path.sep + name);
        try{
          var stats = fs.lstatSync(pluginPathAttempt);
          if(!pluginRoot && (stats.isDirectory() || stats.isSymbolicLink())){ pluginRoot = pluginPathAttempt; }
        }catch(e){ }
      });

      if(!pluginRoot){ return false; }
      var pluginSection = path.normalize(pluginRoot + path.sep + type);
      return pluginSection;
    };

    ////////////////////////////////////////////////////////////////////////////
    // object Clone
    api.utils.objClone = function(obj){
      return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyNames(obj).reduce(function(memo, name){
        return (memo[name] = Object.getOwnPropertyDescriptor(obj, name)) && memo;
      }, {}));
    };

    ////////////////////////////////////////////////////////////////////////////
    // attempt to collapse this object to an array; ie: {"0": "a", "1": "b"}
    api.utils.collapseObjectToArray = function(obj){
      try{
        var keys = Object.keys(obj);
        if(keys.length < 1){ return false; }
        if(keys[0] !== '0'){ return false; }
        if(keys[(keys.length - 1)] !== String(keys.length - 1)){ return false; }

        var arr = [];
        for(var i in keys){
          var key = keys[i];
          if(String(parseInt(key)) !== key){ return false; }
          else{ arr.push(obj[key]); }
        }

        return arr;
      }catch(e){
        return false;
      }
    };

    ////////////////////////////////////////////////////////////////////////////
    // get this servers external interface
    api.utils.getExternalIPAddress = function(){
      var os = require('os');
      var ifaces = os.networkInterfaces();
      var ip = false;
      for(var dev in ifaces){
        ifaces[dev].forEach(function(details){
          if(details.family === 'IPv4' && details.address !== '127.0.0.1'){
            ip = details.address;
          }
        });
      }
      return ip;
    };

    ////////////////////////////////////////////////////////////////////////////
    // cookie parse from headers of http(s) requests
    api.utils.parseCookies = function(req){
      var cookies = {};
      if(req.headers.cookie){
        req.headers.cookie.split(';').forEach(function(cookie){
          var parts = cookie.split('=');
          cookies[parts[0].trim()] = (parts[1] || '').trim();
        });
      }
      return cookies;
    };

    ////////////////////////////////////////////////////////////////////////////
    // parse an IPv6 address
    // https://github.com/evantahler/actionhero/issues/275 && https://github.com/nullivex
    api.utils.parseIPv6URI = function(addr){
      var host = '::1';
      var port = '80';
      var regexp = new RegExp(/\[([0-9a-f:]+)\]:([0-9]{1,5})/);
      //if we have brackets parse them and find a port
      if(addr.indexOf('[') > -1 && addr.indexOf(']') > -1){
        var res = regexp.exec(addr);
        if(res === null){
          throw new Error('failed to parse address');
        }
        host = res[1];
        port = res[2];
      }else{
        host = addr;
      }
      return {host: host, port: parseInt(port, 10)};
    };

    ////////////////////////////////////////////////////////////////////////////
    // Check on how long the event loop is blocked for
    api.utils.eventLoopDelay = function(itterations, callback){
      var intervalJobs = [];
      var intervalTimes = [];

      if(!itterations){ return callback(new Error('itterations is required')); }

      var i = 0;
      while(i < itterations){
        intervalJobs.push(function(intervalDone){
          var start = process.hrtime();
          process.nextTick(function(){
            var delta = process.hrtime(start);
            var ms = (delta[0] * 1000) + (delta[1] / 1000000);
            intervalTimes.push(ms);
            intervalDone();
          });
        });
        i++;
      }

      async.series(intervalJobs, function(){
        var sum = 0;
        intervalTimes.forEach(function(t){ sum += t; });
        var avg = Math.round(sum / intervalTimes.length * 10000) / 1000;
        return callback(null, avg);
      });
    };

    ////////////////////////////////////////////////////////////////////////////
    // Sort Global Middleware
    api.utils.sortGlobalMiddleware = function(globalMiddlewareList, middleware){
      globalMiddlewareList.sort(function(a, b){
        if(middleware[a].priority > middleware[b].priority){
          return 1;
        }else{
          return -1;
        }
      });
    };

    ////////////////////////////////////////////////////////////////////////////
    // File utils
    api.utils.dirExists = function(dir){
      try{
        var stats = fs.lstatSync(dir);
        return (stats.isDirectory() || stats.isSymbolicLink());
      }catch(e){ return false; }
    };

    api.utils.fileExists = function(file){
      try{
        var stats = fs.lstatSync(file);
        return (stats.isFile() || stats.isSymbolicLink());
      }catch(e){ return false; }
    },

    api.utils.createDirSafely = function(dir){
      if(api.utils.dirExists(dir)){
        api.log(' - directory \'' + path.normalize(dir) + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating directory \'' + path.normalize(dir) + '\'');
        fs.mkdirSync(path.normalize(dir), '0766');
      }
    };

    api.utils.createFileSafely = function(file, data, overwrite){
      if(api.utils.fileExists(file) && !overwrite){
        api.log(' - file \'' + path.normalize(file) + '\' already exists, skipping', 'alert');
      }else{
        if(overwrite && api.utils.fileExists(file)){
          api.log(' - overwritten file \'' + path.normalize(file) + '\'');
        }else{
          api.log(' - wrote file \'' + path.normalize(file) + '\'');
        }
        fs.writeFileSync(path.normalize(file), data);
      }
    };

    api.utils.createLinkfileSafely = function(filePath, type, refrence){
      if(api.utils.fileExists(filePath)){
        api.log(' - link file \'' + filePath + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating linkfile \'' + filePath + '\'');
        fs.writeFileSync(filePath, type);
      }
    };

    api.utils.removeLinkfileSafely = function(filePath, type, refrence){
      if(!api.utils.fileExists(filePath)){
        api.log(' - link file \'' + filePath + '\' doesn\'t exist, skipping', 'alert');
      }else{
        api.log(' - removing linkfile \'' + filePath + '\'');
        fs.unlinkSync(filePath);
      }
    };

    api.utils.createSymlinkSafely = function(destination, source){
      if(api.utils.dirExists(destination)){
        api.log(' - symbolic link \'' + destination + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating symbolic link \'' + destination + '\' => \'' + source + '\'');
        fs.symlinkSync(source, destination, 'dir');
      }
    };

    next();
  }
};
<commit_msg>Updates error string formatting - moar whitespace<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var async = require('async');

module.exports = {
  loadPriority:  0,
  initialize: function(api, next){

    if(!api.utils){ api.utils = {}; }

    ////////////////////////////////////////////////////////////////////////////
    // merge two hashes recursively
    api.utils.hashMerge = function(a, b, arg){
      var c = {};
      var i;
      var response;

      for(i in a){
        if(api.utils.isPlainObject(a[i]) && Object.keys(a[i]).length > 0){
          c[i] = api.utils.hashMerge(c[i], a[i], arg);
        }else{
          if(typeof a[i] === 'function'){
            response = a[i](arg);
            if(api.utils.isPlainObject(response)){
              c[i] = api.utils.hashMerge(c[i], response, arg);
            }else{
              c[i] = response;
            }
          }else{
            c[i] = a[i];
          }
        }
      }
      for(i in b){
        if(api.utils.isPlainObject(b[i]) && Object.keys(b[i]).length > 0){
          c[i] = api.utils.hashMerge(c[i], b[i], arg);
        }else{
          if(typeof b[i] === 'function'){
            response = b[i](arg);
            if(api.utils.isPlainObject(response)){
              c[i] = api.utils.hashMerge(c[i], response, arg);
            }else{
              c[i] = response;
            }
          }else{
            c[i] = b[i];
          }
        }
      }
      return c;
    };

    api.utils.isPlainObject = function(o){
      var safeTypes     = [Boolean, Number, String, Function, Array, Date, RegExp, Buffer];
      var safeInstances = ['boolean', 'number', 'string', 'function'];
      var expandPreventMatchKey = '_toExpand'; // set `_toExpand = false` within an object if you don't want to expand it
      var i;

      if(!o){ return false; }
      if((o instanceof Object) === false){ return false; }
      for(i in safeTypes){
        if(o instanceof safeTypes[i]){ return false; }
      }
      for(i in safeInstances){
        if(typeof o === safeInstances[i]){ return false; }
      }
      if(o[expandPreventMatchKey] === false){ return false; }
      return (o.toString() === '[object Object]');
    };

    ////////////////////////////////////////////////////////////////////////////
    // string to hash
    // http://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference
    api.utils.stringToHash = function(path, object){
      if(!object){ object = api; }
      function _index(obj, i){ return obj[i]; }
      return path.split('.').reduce(_index, object);
    };

    ////////////////////////////////////////////////////////////////////////////
    // unique-ify an array
    api.utils.arrayUniqueify = function(arr){
      var a = [];
      for(var i = 0; i < arr.length; i++){
        for(var j = i + 1; j < arr.length; j++){
          if(arr[i] === arr[j]){ j = ++i; }
        }
        a.push(arr[i]);
      }
      return a;
    };

    ////////////////////////////////////////////////////////////////////////////
    // get all .js files in a directory
    api.utils.recursiveDirectoryGlob = function(dir, extension, followLinkFiles){
      var results = [];

      if(!extension){ extension = '.js'; }
      if(!followLinkFiles){ followLinkFiles = true; }

      extension = extension.replace('.', '');

      if(fs.existsSync(dir)){
        fs.readdirSync(dir).forEach(function(file){
          var fullFilePath = path.join(dir, file);
          if(file[0] !== '.'){ // ignore 'system' files
            var stats = fs.statSync(fullFilePath);
            var child;
            if(stats.isDirectory()){
              child = api.utils.recursiveDirectoryGlob(fullFilePath, extension, followLinkFiles);
              child.forEach(function(c){ results.push(c); });
            }else if(stats.isSymbolicLink()){
              var realPath = fs.readlinkSync(fullFilePath);
              child = api.utils.recursiveDirectoryGlob(realPath, extension, followLinkFiles);
              child.forEach(function(c){ results.push(c); });
            }else if(stats.isFile()){
              var fileParts = file.split('.');
              var ext = fileParts[(fileParts.length - 1)];
              // real file match
              if(ext === extension){ results.push(fullFilePath); }
              // linkfile traversal
              if(ext === 'link' && followLinkFiles === true){
                var linkedPath = api.utils.sourceRelativeLinkPath(fullFilePath, api.config.general.paths.plugin);
                if(linkedPath){
                  child = api.utils.recursiveDirectoryGlob(linkedPath, extension, followLinkFiles);
                  child.forEach(function(c){ results.push(c); });
                }else{
                  try{
                    api.log(['cannot find linked refrence to `%s`', file], 'warning');
                  }catch(e){
                    throw('cannot find linked refrence to ' + file);
                  }
                }
              }
            }
          }
        });
      }

      return results.sort();
    };

    api.utils.sourceRelativeLinkPath = function(linkfile, pluginPaths){
      var type = fs.readFileSync(linkfile).toString();
      var pathParts = linkfile.split(path.sep);
      var name = pathParts[(pathParts.length - 1)].split('.')[0];
      var pathsToTry = pluginPaths.slice(0);
      var pluginRoot;

      // TODO: always also try the local destination's `node_modules` to allow for nested plugins
      // This might be a security risk without requiring explicit sourcing

      pathsToTry.forEach(function(pluginPath){
        var pluginPathAttempt = path.normalize(pluginPath + path.sep + name);
        try{
          var stats = fs.lstatSync(pluginPathAttempt);
          if(!pluginRoot && (stats.isDirectory() || stats.isSymbolicLink())){ pluginRoot = pluginPathAttempt; }
        }catch(e){ }
      });

      if(!pluginRoot){ return false; }
      var pluginSection = path.normalize(pluginRoot + path.sep + type);
      return pluginSection;
    };

    ////////////////////////////////////////////////////////////////////////////
    // object Clone
    api.utils.objClone = function(obj){
      return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyNames(obj).reduce(function(memo, name){
        return (memo[name] = Object.getOwnPropertyDescriptor(obj, name)) && memo;
      }, {}));
    };

    ////////////////////////////////////////////////////////////////////////////
    // attempt to collapse this object to an array; ie: {"0": "a", "1": "b"}
    api.utils.collapseObjectToArray = function(obj){
      try{
        var keys = Object.keys(obj);
        if(keys.length < 1){ return false; }
        if(keys[0] !== '0'){ return false; }
        if(keys[(keys.length - 1)] !== String(keys.length - 1)){ return false; }

        var arr = [];
        for(var i in keys){
          var key = keys[i];
          if(String(parseInt(key)) !== key){ return false; }
          else{ arr.push(obj[key]); }
        }

        return arr;
      }catch(e){
        return false;
      }
    };

    ////////////////////////////////////////////////////////////////////////////
    // get this servers external interface
    api.utils.getExternalIPAddress = function(){
      var os = require('os');
      var ifaces = os.networkInterfaces();
      var ip = false;
      for(var dev in ifaces){
        ifaces[dev].forEach(function(details){
          if(details.family === 'IPv4' && details.address !== '127.0.0.1'){
            ip = details.address;
          }
        });
      }
      return ip;
    };

    ////////////////////////////////////////////////////////////////////////////
    // cookie parse from headers of http(s) requests
    api.utils.parseCookies = function(req){
      var cookies = {};
      if(req.headers.cookie){
        req.headers.cookie.split(';').forEach(function(cookie){
          var parts = cookie.split('=');
          cookies[parts[0].trim()] = (parts[1] || '').trim();
        });
      }
      return cookies;
    };

    ////////////////////////////////////////////////////////////////////////////
    // parse an IPv6 address
    // https://github.com/evantahler/actionhero/issues/275 && https://github.com/nullivex
    api.utils.parseIPv6URI = function(addr){
      var host = '::1';
      var port = '80';
      var regexp = new RegExp(/\[([0-9a-f:]+)\]:([0-9]{1,5})/);
      //if we have brackets parse them and find a port
      if(addr.indexOf('[') > -1 && addr.indexOf(']') > -1){
        var res = regexp.exec(addr);
        if(res === null){
          throw new Error('failed to parse address');
        }
        host = res[1];
        port = res[2];
      }else{
        host = addr;
      }
      return {host: host, port: parseInt(port, 10)};
    };

    ////////////////////////////////////////////////////////////////////////////
    // Check on how long the event loop is blocked for
    api.utils.eventLoopDelay = function(itterations, callback){
      var intervalJobs = [];
      var intervalTimes = [];

      if(!itterations){ return callback(new Error('itterations is required')); }

      var i = 0;
      while(i < itterations){
        intervalJobs.push(function(intervalDone){
          var start = process.hrtime();
          process.nextTick(function(){
            var delta = process.hrtime(start);
            var ms = (delta[0] * 1000) + (delta[1] / 1000000);
            intervalTimes.push(ms);
            intervalDone();
          });
        });
        i++;
      }

      async.series(intervalJobs, function(){
        var sum = 0;
        intervalTimes.forEach(function(t){ sum += t; });
        var avg = Math.round(sum / intervalTimes.length * 10000) / 1000;
        return callback(null, avg);
      });
    };

    ////////////////////////////////////////////////////////////////////////////
    // Sort Global Middleware
    api.utils.sortGlobalMiddleware = function(globalMiddlewareList, middleware){
      globalMiddlewareList.sort(function(a, b){
        if(middleware[a].priority > middleware[b].priority){
          return 1;
        }else{
          return -1;
        }
      });
    };

    ////////////////////////////////////////////////////////////////////////////
    // File utils
    api.utils.dirExists = function(dir){
      try{
        var stats = fs.lstatSync(dir);
        return (stats.isDirectory() || stats.isSymbolicLink());
      }catch(e){ return false; }
    };

    api.utils.fileExists = function(file){
      try{
        var stats = fs.lstatSync(file);
        return (stats.isFile() || stats.isSymbolicLink());
      }catch(e){ return false; }
    },

    api.utils.createDirSafely = function(dir){
      if(api.utils.dirExists(dir)){
        api.log(' - directory \'' + path.normalize(dir) + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating directory \'' + path.normalize(dir) + '\'');
        fs.mkdirSync(path.normalize(dir), '0766');
      }
    };

    api.utils.createFileSafely = function(file, data, overwrite){
      if(api.utils.fileExists(file) && !overwrite){
        api.log(' - file \'' + path.normalize(file) + '\' already exists, skipping', 'alert');
      }else{
        if(overwrite && api.utils.fileExists(file)){
          api.log(' - overwritten file \'' + path.normalize(file) + '\'');
        }else{
          api.log(' - wrote file \'' + path.normalize(file) + '\'');
        }
        fs.writeFileSync(path.normalize(file), data);
      }
    };

    api.utils.createLinkfileSafely = function(filePath, type, refrence){
      if(api.utils.fileExists(filePath)){
        api.log(' - link file \'' + filePath + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating linkfile \'' + filePath + '\'');
        fs.writeFileSync(filePath, type);
      }
    };

    api.utils.removeLinkfileSafely = function(filePath, type, refrence){
      if(!api.utils.fileExists(filePath)){
        api.log(' - link file \'' + filePath + '\' doesn\'t exist, skipping', 'alert');
      }else{
        api.log(' - removing linkfile \'' + filePath + '\'');
        fs.unlinkSync(filePath);
      }
    };

    api.utils.createSymlinkSafely = function(destination, source){
      if(api.utils.dirExists(destination)){
        api.log(' - symbolic link \'' + destination + '\' already exists, skipping', 'alert');
      }else{
        api.log(' - creating symbolic link \'' + destination + '\' => \'' + source + '\'');
        fs.symlinkSync(source, destination, 'dir');
      }
    };

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


<commit_before>
// show the installed versions of packages
//
// --parseable creates output like this:
// <fullpath>:<name@ver>:<realpath>:<flags>
// Flags are a :-separated list of zero or more indicators

module.exports = exports = ls

var npm = require("./npm.js")
  , readInstalled = require("./utils/read-installed.js")
  , output = require("./utils/output.js")
  , log = require("./utils/log.js")
  , relativize = require("./utils/relativize.js")
  , path = require("path")

ls.usage = "npm ls"

function ls (args, silent, cb) {
  if (typeof cb !== "function") cb = silent, silent = false

  if (args.length) {
    log.warn("ls doesn't take positional args. Try the 'search' command")
  }

  var dir = path.resolve(npm.dir, "..")

  readInstalled(dir, function (er, data) {
    var lite = getLite(bfsify(data))
    if (er || silent) return cb(er, data, lite)

    var long = npm.config.get("long")
      , json = npm.config.get("json")
      , out
    if (json) {
      var seen = []
      var d = long ? bfsify(data) : lite
      // the raw data can be circular
      out = JSON.stringify(d, function (k, o) {
        if (typeof o === "object") {
          if (-1 !== seen.indexOf(o)) return "[Circular]"
          seen.push(o)
        }
        return o
      }, 2)
    } else {
      out = makePretty(bfsify(data), long, dir).join("\n")
    }
    output.write(out, function (er) { cb(er, data, lite) })
  })
}

function getLite (data, noname) {
  var lite = {}
    , maxDepth = npm.config.get("depth")
    , url = require("url")

  if (!noname && data.name) lite.name = data.name
  if (data.version) lite.version = data.version
  if (data.extraneous) {
    lite.extraneous = true
    lite.problems = lite.problems || []
    lite.problems.push( "extraneous: "
                      + data.name + "@" + data.version
                      + " " + (data.path || "") )
  }

  if (data._from) {
    var u = url.parse(data._from)
    if (u.protocol) lite.from = data._from
  }

  if (data.invalid) {
    lite.invalid = true
    lite.problems = lite.problems || []
    lite.problems.push( "invalid: "
                      + data.name + "@" + data.version
                      + " " + (data.path || "") )
  }

  if (data.dependencies) {
    var deps = Object.keys(data.dependencies)
    if (deps.length) lite.dependencies = deps.map(function (d) {
      var dep = data.dependencies[d]
      if (typeof dep === "string") {
        lite.problems = lite.problems || []
        var p
        if (data.depth >= maxDepth) {
          p = "max depth reached: "
        } else {
          p = "missing: "
        }
        p += d + "@" + dep
          + ", required by "
          + data.name + "@" + data.version
        lite.problems.push(p)
        return [d, { required: dep, missing: true }]
      }
      return [d, getLite(dep, true)]
    }).reduce(function (deps, d) {
      if (d[1].problems) {
        lite.problems = lite.problems || []
        lite.problems.push.apply(lite.problems, d[1].problems)
      }
      deps[d[0]] = d[1]
      return deps
    }, {})
  }
  return lite
}

function bfsify (root, current, queue, seen) {
  // walk over the data, and turn it from this:
  // +-- a
  // |   `-- b
  // |       `-- a (truncated)
  // `--b (truncated)
  // into this:
  // +-- a
  // `-- b
  // which looks nicer
  current = current || root
  queue = queue || []
  seen = seen || [root]
  var deps = current.dependencies = current.dependencies || {}
  Object.keys(deps).forEach(function (d) {
    var dep = deps[d]
    if (typeof dep !== "object") return
    if (seen.indexOf(dep) !== -1) {
      if (npm.config.get("parseable") || !npm.config.get("long")) {
        delete deps[d]
        return
      } else {
        dep = deps[d] = Object.create(dep)
        dep.dependencies = {}
      }
    }
    queue.push(dep)
    seen.push(dep)
  })
  if (!queue.length) return root
  return bfsify(root, queue.shift(), queue, seen)
}

function makePretty (data, long, dir, prefix, list) {
  var top = !list
  list = list || []
  prefix = prefix || ""
  list.push(format(data, long, prefix, dir))
  var deps = data.dependencies || {}
    , childPref = prefix.split("├─").join("│ ")
                        .split("└─").join("  ")
    , depList = Object.keys(deps)
    , depLast = depList.length - 1
    , maxDepth = npm.config.get("depth")
  Object.keys(deps).sort(function (a, b) {
    return a > b ? 1 : -1
  }).forEach(function (d, i) {
    var depData = deps[d]
    if (typeof depData === "string") {
      if (data.depth < maxDepth) {
        var p = data.link || data.path
        log.warn("Unmet dependency in "+p, d+" "+deps[d])
        depData = npm.config.get("parseable")
                ? ( npm.config.get("long")
                    ? path.resolve(data.path, "node_modules", d)
                    + ":"+d+"@"+JSON.stringify(depData)+":INVALID:MISSING"
                    : "" )
                : "─ \033[31;40mUNMET DEPENDENCY\033[0m "+d+" "+depData
      } else {
        if (npm.config.get("parseable")) {
          depData = path.resolve(data.path, "node_modules", d)
                  + (npm.config.get("long")
                    ? ":" + d + "@" + JSON.stringify(depData)
                    + ":" // no realpath resolved
                    + ":MAXDEPTH"
                    : "")
        } else {
          depData = "─ "+d+"@'"+depData +"' (max depth reached)"
        }
      }
    }
    var c = i === depLast ? "└─" : "├─"
    makePretty(depData, long, dir, childPref + c, list)
  })
  if (top && list.length === 1 && !data._id) {
    if (!npm.config.get("parseable")) {
      list.push("(empty)")
    } else if (npm.config.get("long")) list[0] += ":EMPTY"
  }
  return list.filter(function (l) { return l && l.trim() })
}

function ugly (data) {
  if (typeof data === "string") {
    return data
  }
  if (!npm.config.get("long")) return data.path

  return data.path
       + ":" + (data._id || "")
       + ":" + (data.realPath !== data.path ? data.realPath : "")
       + (data.extraneous ? ":EXTRANEOUS" : "")
       + (data.invalid ? ":INVALID" : "")
}

function format (data, long, prefix, dir) {
  if (npm.config.get("parseable")) return ugly(data)
  if (typeof data === "string") {
    return prefix + data
  }
//  console.log([data.path, dir], "relativize")
  var depLen = Object.keys(data.dependencies).length
    , space = prefix.split("├─").join("│ ")
                    .split("└─").join("  ")
            + (depLen ? "" : " ")
    , rel = relativize(data.path || "", dir)
    , l = prefix
        + (rel === "." ? "" : depLen ? "┬ " : "─ ")
        + (data._id ? data._id + " " : "")
        + (data.link ? "-> " + data.link : "") + ""
        + (rel === "." && !(long && data._id) ? dir : "")
  if (data.invalid) {
    if (data.realName !== data.name) l += " ("+data.realName+")"
    l += " \033[31;40minvalid\033[0m"
  }
  if (data.extraneous && rel !== ".") {
    l += " \033[32;40mextraneous\033[0m"
  }
  if (!long || !data._id) return l
  var extras = []
  if (rel !== ".") extras.push(rel)
  else extras.push(dir)
  if (data.description) extras.push(data.description)
  if (data.repository) extras.push(data.repository.url)
  if (data.homepage) extras.push(data.homepage)
  extras = extras.filter(function (e) { return e })
  var lastExtra = !depLen && extras.length - 1
  l += extras.map(function (e, i) {
    var indent = !depLen ? " " : "│ "
    return "\n" + space + indent + e
  }).join("")
  return l
}
<commit_msg>Handle 'name@http://url' style _from fields<commit_after>
// show the installed versions of packages
//
// --parseable creates output like this:
// <fullpath>:<name@ver>:<realpath>:<flags>
// Flags are a :-separated list of zero or more indicators

module.exports = exports = ls

var npm = require("./npm.js")
  , readInstalled = require("./utils/read-installed.js")
  , output = require("./utils/output.js")
  , log = require("./utils/log.js")
  , relativize = require("./utils/relativize.js")
  , path = require("path")

ls.usage = "npm ls"

function ls (args, silent, cb) {
  if (typeof cb !== "function") cb = silent, silent = false

  if (args.length) {
    log.warn("ls doesn't take positional args. Try the 'search' command")
  }

  var dir = path.resolve(npm.dir, "..")

  readInstalled(dir, function (er, data) {
    var lite = getLite(bfsify(data))
    if (er || silent) return cb(er, data, lite)

    var long = npm.config.get("long")
      , json = npm.config.get("json")
      , out
    if (json) {
      var seen = []
      var d = long ? bfsify(data) : lite
      // the raw data can be circular
      out = JSON.stringify(d, function (k, o) {
        if (typeof o === "object") {
          if (-1 !== seen.indexOf(o)) return "[Circular]"
          seen.push(o)
        }
        return o
      }, 2)
    } else {
      out = makePretty(bfsify(data), long, dir).join("\n")
    }
    output.write(out, function (er) { cb(er, data, lite) })
  })
}

function getLite (data, noname) {
  var lite = {}
    , maxDepth = npm.config.get("depth")
    , url = require("url")

  if (!noname && data.name) lite.name = data.name
  if (data.version) lite.version = data.version
  if (data.extraneous) {
    lite.extraneous = true
    lite.problems = lite.problems || []
    lite.problems.push( "extraneous: "
                      + data.name + "@" + data.version
                      + " " + (data.path || "") )
  }

  if (data._from) {
    var from = data._from
    if (from.indexOf(data.name + "@") === 0) {
      from = from.substr(data.name.length + 1)
    }
    var u = url.parse(from)
    if (u.protocol) lite.from = from
  }

  if (data.invalid) {
    lite.invalid = true
    lite.problems = lite.problems || []
    lite.problems.push( "invalid: "
                      + data.name + "@" + data.version
                      + " " + (data.path || "") )
  }

  if (data.dependencies) {
    var deps = Object.keys(data.dependencies)
    if (deps.length) lite.dependencies = deps.map(function (d) {
      var dep = data.dependencies[d]
      if (typeof dep === "string") {
        lite.problems = lite.problems || []
        var p
        if (data.depth >= maxDepth) {
          p = "max depth reached: "
        } else {
          p = "missing: "
        }
        p += d + "@" + dep
          + ", required by "
          + data.name + "@" + data.version
        lite.problems.push(p)
        return [d, { required: dep, missing: true }]
      }
      return [d, getLite(dep, true)]
    }).reduce(function (deps, d) {
      if (d[1].problems) {
        lite.problems = lite.problems || []
        lite.problems.push.apply(lite.problems, d[1].problems)
      }
      deps[d[0]] = d[1]
      return deps
    }, {})
  }
  return lite
}

function bfsify (root, current, queue, seen) {
  // walk over the data, and turn it from this:
  // +-- a
  // |   `-- b
  // |       `-- a (truncated)
  // `--b (truncated)
  // into this:
  // +-- a
  // `-- b
  // which looks nicer
  current = current || root
  queue = queue || []
  seen = seen || [root]
  var deps = current.dependencies = current.dependencies || {}
  Object.keys(deps).forEach(function (d) {
    var dep = deps[d]
    if (typeof dep !== "object") return
    if (seen.indexOf(dep) !== -1) {
      if (npm.config.get("parseable") || !npm.config.get("long")) {
        delete deps[d]
        return
      } else {
        dep = deps[d] = Object.create(dep)
        dep.dependencies = {}
      }
    }
    queue.push(dep)
    seen.push(dep)
  })
  if (!queue.length) return root
  return bfsify(root, queue.shift(), queue, seen)
}

function makePretty (data, long, dir, prefix, list) {
  var top = !list
  list = list || []
  prefix = prefix || ""
  list.push(format(data, long, prefix, dir))
  var deps = data.dependencies || {}
    , childPref = prefix.split("├─").join("│ ")
                        .split("└─").join("  ")
    , depList = Object.keys(deps)
    , depLast = depList.length - 1
    , maxDepth = npm.config.get("depth")
  Object.keys(deps).sort(function (a, b) {
    return a > b ? 1 : -1
  }).forEach(function (d, i) {
    var depData = deps[d]
    if (typeof depData === "string") {
      if (data.depth < maxDepth) {
        var p = data.link || data.path
        log.warn("Unmet dependency in "+p, d+" "+deps[d])
        depData = npm.config.get("parseable")
                ? ( npm.config.get("long")
                    ? path.resolve(data.path, "node_modules", d)
                    + ":"+d+"@"+JSON.stringify(depData)+":INVALID:MISSING"
                    : "" )
                : "─ \033[31;40mUNMET DEPENDENCY\033[0m "+d+" "+depData
      } else {
        if (npm.config.get("parseable")) {
          depData = path.resolve(data.path, "node_modules", d)
                  + (npm.config.get("long")
                    ? ":" + d + "@" + JSON.stringify(depData)
                    + ":" // no realpath resolved
                    + ":MAXDEPTH"
                    : "")
        } else {
          depData = "─ "+d+"@'"+depData +"' (max depth reached)"
        }
      }
    }
    var c = i === depLast ? "└─" : "├─"
    makePretty(depData, long, dir, childPref + c, list)
  })
  if (top && list.length === 1 && !data._id) {
    if (!npm.config.get("parseable")) {
      list.push("(empty)")
    } else if (npm.config.get("long")) list[0] += ":EMPTY"
  }
  return list.filter(function (l) { return l && l.trim() })
}

function ugly (data) {
  if (typeof data === "string") {
    return data
  }
  if (!npm.config.get("long")) return data.path

  return data.path
       + ":" + (data._id || "")
       + ":" + (data.realPath !== data.path ? data.realPath : "")
       + (data.extraneous ? ":EXTRANEOUS" : "")
       + (data.invalid ? ":INVALID" : "")
}

function format (data, long, prefix, dir) {
  if (npm.config.get("parseable")) return ugly(data)
  if (typeof data === "string") {
    return prefix + data
  }
//  console.log([data.path, dir], "relativize")
  var depLen = Object.keys(data.dependencies).length
    , space = prefix.split("├─").join("│ ")
                    .split("└─").join("  ")
            + (depLen ? "" : " ")
    , rel = relativize(data.path || "", dir)
    , l = prefix
        + (rel === "." ? "" : depLen ? "┬ " : "─ ")
        + (data._id ? data._id + " " : "")
        + (data.link ? "-> " + data.link : "") + ""
        + (rel === "." && !(long && data._id) ? dir : "")
  if (data.invalid) {
    if (data.realName !== data.name) l += " ("+data.realName+")"
    l += " \033[31;40minvalid\033[0m"
  }
  if (data.extraneous && rel !== ".") {
    l += " \033[32;40mextraneous\033[0m"
  }
  if (!long || !data._id) return l
  var extras = []
  if (rel !== ".") extras.push(rel)
  else extras.push(dir)
  if (data.description) extras.push(data.description)
  if (data.repository) extras.push(data.repository.url)
  if (data.homepage) extras.push(data.homepage)
  extras = extras.filter(function (e) { return e })
  var lastExtra = !depLen && extras.length - 1
  l += extras.map(function (e, i) {
    var indent = !depLen ? " " : "│ "
    return "\n" + space + indent + e
  }).join("")
  return l
}
<|endoftext|>


<commit_before>const BigNumber = require('bignumber.js')
const cbor = require('../')
const test = require('ava')
const vectors = require('../test-vectors/appendix_a')
const rterror = 'roundtrip:'

vectors.forEach( v => {
  const hex = v.hex;
  if (hex) {

    test(`hex: ${hex}`, t => {
      const buffer = Buffer.from(hex, "hex")

      const decoded = cbor.decodeFirstSync(buffer)
      const encoded = cbor.encode(decoded)
      const redecoded = cbor.decodeFirstSync(encoded)

      if (v.hasOwnProperty('cbor'))
        t.deepEqual( Buffer.from(v.cbor,"base64"), buffer, "base64 and hex encoded bytes mismatched ")

        t.deepEqual(decoded, redecoded, `round trip error: ${hex} -> ${encoded.toString('hex')}`);

        if (v.hasOwnProperty('diagnostic'))
        {
          return cbor.diagnose(buffer)
              .then(d => t.deepEqual( d.trim().replace(/_\d+($|\))/,'$1'), v.diagnostic))
        }

        if (v.hasOwnProperty('decoded')) {

        if (!BigNumber.isBigNumber(decoded))
          t.deepEqual(decoded, v.decoded)
        else
          t.deepEqual(decoded, redecoded, "BigNum error")

        // if (v.roundtrip) {
        //   if (!encoded.equals(buffer)) {
        //     if (decoded)
        //     t.fail(`${rterror} ${hex} -> ${encoded.toString("hex")} [${decoded} -> ${cbor.decodeFirstSync(encoded)}]`)
        //   }
        // }
      } else {
        t.pass('no decoded member');
      }
    })
  }

});

<commit_msg>Produce meaningful message if test-vectors missing<commit_after>const BigNumber = require('bignumber.js')
const cbor = require('../')
const test = require('ava')
var vectors = null;
const rterror = 'roundtrip:'
try {
  vectors = require('../test-vectors/appendix_a')
} catch (ex) { }

test('test-vectors', t => {
  if (vectors) t.pass('test-vectors found')
  else t.fail('use command `git submodule update --init` to load test-vectors')
})

if (vectors) {
  vectors.forEach(v => {
    const hex = v.hex;
    if (hex) {

      test(`hex: ${hex}`, t => {
        const buffer = Buffer.from(hex, "hex")

        const decoded = cbor.decodeFirstSync(buffer)
        const encoded = cbor.encode(decoded)
        const redecoded = cbor.decodeFirstSync(encoded)

        if (v.hasOwnProperty('cbor'))
          t.deepEqual(Buffer.from(v.cbor, "base64"), buffer, "base64 and hex encoded bytes mismatched ")

        t.deepEqual(decoded, redecoded, `round trip error: ${hex} -> ${encoded.toString('hex')}`);

        if (v.hasOwnProperty('diagnostic')) {
          return cbor.diagnose(buffer)
            .then(d => t.deepEqual(d.trim().replace(/_\d+($|\))/, '$1'), v.diagnostic))
        }

        if (v.hasOwnProperty('decoded')) {

          if (!BigNumber.isBigNumber(decoded))
            t.deepEqual(decoded, v.decoded)
          else
            t.deepEqual(decoded, redecoded, "BigNum error")

          // if (v.roundtrip) {
          //   if (!encoded.equals(buffer)) {
          //     if (decoded)
          //     t.fail(`${rterror} ${hex} -> ${encoded.toString("hex")} [${decoded} -> ${cbor.decodeFirstSync(encoded)}]`)
          //   }
          // }
        } else {
          t.pass('no decoded member');
        }
      })
    }
  })
}<|endoftext|>