<commit_before>/**
 * Copyright 2015, Yahoo! Inc.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

import Ember from 'ember';
import Base from 'ember-cp-validations/validators/base';

const {
  isEmpty
} = Ember;

export default Base.extend({
  validate(value, options) {
    if (options.allowBlank && isEmpty(value)) {
      return true;
    }

    let numValue = Number(value);
    let optionKeys = Object.keys(options);

    if (typeof value === 'string' && (isEmpty(value) || !options.allowString)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (!this.isNumber(numValue)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (options.integer && !this.isInteger(numValue)) {
      return this.createErrorMessage('notAnInteger', value, options);
    }

    for (let i = 0; i < optionKeys.length; i++) {
      let type = optionKeys[i];
      let m = this._validateType(type, options, numValue);
      if (typeof m === 'string') {
        return m;
      }
    }

    return true;
  },

  _validateType(type, options, value) {
    let expected = options[type];
    let actual = value;

    if (type === 'is' && actual !== expected) {
      return this.createErrorMessage('equalTo', value, options);
    } else if (type === 'lt' && actual >= expected) {
      return this.createErrorMessage('lessThan', value, options);
    } else if (type === 'lte' && actual > expected) {
      return this.createErrorMessage('lessThanOrEqualTo', value, options);
    } else if (type === 'gt' && actual <= expected) {
      return this.createErrorMessage('greaterThan', value, options);
    } else if (type === 'gte' && actual < expected) {
      return this.createErrorMessage('greaterThanOrEqualTo', value, options);
    } else if (type === 'positive' && actual < 0) {
      return this.createErrorMessage('positive', value, options);
    } else if (type === 'odd' && actual % 2 === 0) {
      return this.createErrorMessage('odd', value, options);
    } else if (type === 'even' && actual % 2 !== 0) {
      return this.createErrorMessage('even', value, options);
    }

    return true;
  },

  /* Use polyfills instead of Number.isNaN or Number.isInteger to support IE & Safari */

  isNumber(value) {
    return typeof value === "number" && !isNaN(value);
  },

  isInteger(value) {
    return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
  }
});
<commit_msg>move number validator allow blank check below the variable declarations<commit_after>/**
 * Copyright 2015, Yahoo! Inc.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

import Ember from 'ember';
import Base from 'ember-cp-validations/validators/base';

const {
  isEmpty
} = Ember;

export default Base.extend({
  validate(value, options) {
    let numValue = Number(value);
    let optionKeys = Object.keys(options);

    if (options.allowBlank && isEmpty(value)) {
      return true;
    }

    if (typeof value === 'string' && (isEmpty(value) || !options.allowString)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (!this.isNumber(numValue)) {
      return this.createErrorMessage('notANumber', value, options);
    }

    if (options.integer && !this.isInteger(numValue)) {
      return this.createErrorMessage('notAnInteger', value, options);
    }

    for (let i = 0; i < optionKeys.length; i++) {
      let type = optionKeys[i];
      let m = this._validateType(type, options, numValue);
      if (typeof m === 'string') {
        return m;
      }
    }

    return true;
  },

  _validateType(type, options, value) {
    let expected = options[type];
    let actual = value;

    if (type === 'is' && actual !== expected) {
      return this.createErrorMessage('equalTo', value, options);
    } else if (type === 'lt' && actual >= expected) {
      return this.createErrorMessage('lessThan', value, options);
    } else if (type === 'lte' && actual > expected) {
      return this.createErrorMessage('lessThanOrEqualTo', value, options);
    } else if (type === 'gt' && actual <= expected) {
      return this.createErrorMessage('greaterThan', value, options);
    } else if (type === 'gte' && actual < expected) {
      return this.createErrorMessage('greaterThanOrEqualTo', value, options);
    } else if (type === 'positive' && actual < 0) {
      return this.createErrorMessage('positive', value, options);
    } else if (type === 'odd' && actual % 2 === 0) {
      return this.createErrorMessage('odd', value, options);
    } else if (type === 'even' && actual % 2 !== 0) {
      return this.createErrorMessage('even', value, options);
    }

    return true;
  },

  /* Use polyfills instead of Number.isNaN or Number.isInteger to support IE & Safari */

  isNumber(value) {
    return typeof value === "number" && !isNaN(value);
  },

  isInteger(value) {
    return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
  }
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import HTML5Backend from 'react-dnd-html5-backend';
import { Autobind } from 'es-decorators';
import { DragDropContext } from 'react-dnd';
import { toastr } from 'react-redux-toastr';

// Redux
import { connect } from 'react-redux';

import { toggleModal, setModalOptions } from 'redactions/modal';
import { setChartType, setAreaIntersection } from 'redactions/widgetEditor';

// Components
import FilterContainer from 'components/widgets/FilterContainer';
import DimensionsContainer from 'components/widgets/DimensionsContainer';
import FieldsContainer from 'components/widgets/FieldsContainer';
import SortContainer from 'components/widgets/SortContainer';
import LimitContainer from 'components/widgets/LimitContainer';
import CustomSelect from 'components/ui/CustomSelect';
import Select from 'components/form/SelectInput';
import SaveWidgetModal from 'components/modal/SaveWidgetModal';
import HowToWidgetEditorModal from 'components/modal/HowToWidgetEditorModal';
import UploadAreaIntersectionModal from 'components/modal/UploadAreaIntersectionModal';
import Spinner from 'components/ui/Spinner';

// Services
import AreasService from 'services/AreasService';
import UserService from 'services/UserService';

const AREAS = [
  {
    label: 'Custom area',
    value: 'custom',
    items: [
      {
        label: 'Upload new area',
        value: 'upload',
        as: 'Custom area'
      }
    ]
  }
];

@DragDropContext(HTML5Backend)
class ChartEditor extends React.Component {
  /**
   * Return the geostore id associated with the country's ISO
   * NOTE: errors are not caught intentionally
   * @param {string} iso Valid 3-letter ISO
   * @returns {Promise<string>}
   */
  static getCountryGeostoreId(iso) {
    return fetch(`${process.env.WRI_API_URL}/geostore/admin/${iso}`)
      .then((response) => {
        if (response.ok) return response.json();
        throw new Error(`Unable to get the geostore id associated with the ISO ${iso}`);
      })
      .then(({ data }) => data.id);
  }

  constructor(props) {
    super(props);

    this.state = {
      areaOptions: [],
      loadingAreaIntersection: false,
      loadingUserAreas: false
    };

    // Services
    this.areasService = new AreasService({ apiURL: process.env.WRI_API_URL });
    this.userService = new UserService({ apiURL: process.env.WRI_API_URL });
  }

  /**
  * COMPONENT LIFECYCLE
  * - componentDidMount
  */
  componentDidMount() {
    if (this.props.hasGeoInfo) {
      this.fetchAreas();
      this.fetchUserAreas();
    }
  }

  /**
   * Event handler executed when the selected area
   * intersection is changed
   * @param {{ label: string, value: string }} item Option of the selector
   */
  @Autobind
  async onChangeAreaIntersection(item) {
    return new Promise((resolve) => {
      // The user unselected the option
      if (!item) {
        this.props.setAreaIntersection(null);
      } else if (item.value === 'upload') {
        this.props.toggleModal(true, {
          children: UploadAreaIntersectionModal,
          childrenProps: {
            onUploadArea: (id) => {
              // We close the modal
              this.props.toggleModal(false, {});

              // We save the ID of the area
              this.props.setAreaIntersection(id);

              resolve(true);
            }
          },
          onCloseModal: () => resolve(false)
        });
      } else if (item.isGeostore) {
        // The user selected a custom area that is not a country
        this.props.setAreaIntersection(item.value);
        resolve(true);
      } else {
        this.setState({ loadingAreaIntersection: true });
        ChartEditor.getCountryGeostoreId(item.value)
          .then((id) => {
            this.props.setAreaIntersection(id);
            resolve(true);
          })
          .catch((err) => {
            // In case of an error, we prevent the selector from setting
            // the area as selected
            resolve(false);

            // TODO: improve this 💩
            toastr.error('Error', `Unable to filter with this country. ${err}`);
          })
          .then(() => this.setState({ loadingAreaIntersection: false }));
      }
    });
  }

  @Autobind
  handleChartTypeChange(val) {
    this.props.setChartType(val);
  }

  @Autobind
  handleSaveWidget() {
    const options = {
      children: SaveWidgetModal,
      childrenProps: {
        dataset: this.props.dataset,
        datasetType: this.props.datasetType,
        datasetProvider: this.props.datasetProvider,
        tableName: this.props.tableName
      }
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  @Autobind
  handleUpdateWidget() {
    this.props.onUpdateWidget();
  }

  @Autobind
  handleNeedHelp() {
    const options = {
      children: HowToWidgetEditorModal,
      childrenProps: {}
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  /**
   * Fetch the list of the areas for the area intersection
   * filter
   */
  fetchAreas() {
    this.setState({ loadingAreaIntersection: true });

    // When this resolves, we'll also be able to display the countries
    this.areasService.fetchCountries()
      .then(({ data }) => {
        this.setState({
          areaOptions: [...this.state.areaOptions, ...AREAS, ...data]
        });
      })
      // We don't really care if the countries don't load, we can still
      // let the user use a custom area
      .catch(err => toastr.error('Error', err))
      .then(() => this.setState({ loadingAreaIntersection: false }));
  }

  /**
   * Fetchs the user areas
   */
  fetchUserAreas() {
    this.setState({ loadingUserAreas: true });
    this.userService.getUserAreas(this.props.user.token)
      .then((response) => {
        const userAreas = response.map(val => ({
          label: val.attributes.name,
          value: val.attributes.geostore ? val.attributes.geostore : val.attributes.iso.country,
          isGeostore: val.attributes.geostore
        }));
        this.setState({
          loadingUserAreas: false,
          areaOptions: [...this.state.areaOptions, ...userAreas]
        });
      })
      .catch((err) => {
        this.setState({ loadingUserAreas: false });
        toastr.error('Error loading user areas', err);
      });
  }

  render() {
    const {
      dataset,
      tableName,
      jiminy,
      widgetEditor,
      tableViewMode,
      user,
      mode,
      showSaveButton,
      hasGeoInfo
    } = this.props;
    const { chartType, fields, category, value } = widgetEditor;
    const { areaOptions, loadingAreaIntersection } = this.state;
    const showSaveButtonFlag =
      chartType && category && value && user && user.token && showSaveButton;
    const showUpdateButton = showSaveButtonFlag;
    const chartOptions = (
      jiminy
      && jiminy.general
      && jiminy.general.map(val => ({ label: val, value: val }))
    ) || [];

    return (

          {!tableViewMode &&

                  Chart style

                <Select
                  id="chart-style-select"
                  properties={{
                    name: 'chart-type',
                    value: chartType,
                    default: chartType
                  }}
                  options={chartOptions}
                  onChange={this.handleChartTypeChange}
                />

          }
          {hasGeoInfo &&

                  Area intersection { loadingAreaIntersection && <Spinner isLoading className="-light -small -inline" /> }

                <CustomSelect
                  id="area-intersection-select"
                  placeholder="Select area"
                  options={areaOptions}
                  onValueChange={this.onChangeAreaIntersection}
                  allowNonLeafSelection={false}
                  waitForChangeConfirmation
                />

          }

Drag and drop elements from the list to the boxes:

          {fields &&
            <FieldsContainer
              dataset={dataset}
              tableName={tableName}
              fields={fields}
            />
          }

            <DimensionsContainer />
            <FilterContainer />
            <SortContainer />
            <LimitContainer />

          <button
            type="button"
            className="c-button -secondary"
            onClick={this.handleNeedHelp}
          >
            Need help?
          </button>
          {showSaveButtonFlag && mode === 'save' &&

            Save widget

          }
          {showUpdateButton && mode === 'update' &&

            Save widget

          }

    );
  }
}

ChartEditor.propTypes = {
  mode: PropTypes.oneOf(['save', 'update']).isRequired,
  tableName: PropTypes.string.isRequired,
  hasGeoInfo: PropTypes.bool.isRequired,
  jiminy: PropTypes.object,
  dataset: PropTypes.string.isRequired, // Dataset ID
  datasetType: PropTypes.string,
  datasetProvider: PropTypes.string,
  tableViewMode: PropTypes.bool.isRequired,
  showSaveButton: PropTypes.bool.isRequired,
  // Store
  widgetEditor: PropTypes.object.isRequired,
  user: PropTypes.object.isRequired,
  setChartType: PropTypes.func.isRequired,
  toggleModal: PropTypes.func.isRequired,
  setModalOptions: PropTypes.func.isRequired,
  setAreaIntersection: PropTypes.func.isRequired,
  // Callback
  onUpdateWidget: PropTypes.func
};

const mapStateToProps = ({ widgetEditor, user }) => ({ widgetEditor, user });
const mapDispatchToProps = dispatch => ({
  setChartType: (type) => {
    dispatch(setChartType(type));
  },
  toggleModal: (open, opts) => { dispatch(toggleModal(open, opts)); },
  setModalOptions: (options) => { dispatch(setModalOptions(options)); },
  setAreaIntersection: id => dispatch(setAreaIntersection(id))
});

export default connect(mapStateToProps, mapDispatchToProps)(ChartEditor);
<commit_msg>fetch user areas only when there is a user logged in<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import HTML5Backend from 'react-dnd-html5-backend';
import { Autobind } from 'es-decorators';
import { DragDropContext } from 'react-dnd';
import { toastr } from 'react-redux-toastr';

// Redux
import { connect } from 'react-redux';

import { toggleModal, setModalOptions } from 'redactions/modal';
import { setChartType, setAreaIntersection } from 'redactions/widgetEditor';

// Components
import FilterContainer from 'components/widgets/FilterContainer';
import DimensionsContainer from 'components/widgets/DimensionsContainer';
import FieldsContainer from 'components/widgets/FieldsContainer';
import SortContainer from 'components/widgets/SortContainer';
import LimitContainer from 'components/widgets/LimitContainer';
import CustomSelect from 'components/ui/CustomSelect';
import Select from 'components/form/SelectInput';
import SaveWidgetModal from 'components/modal/SaveWidgetModal';
import HowToWidgetEditorModal from 'components/modal/HowToWidgetEditorModal';
import UploadAreaIntersectionModal from 'components/modal/UploadAreaIntersectionModal';
import Spinner from 'components/ui/Spinner';

// Services
import AreasService from 'services/AreasService';
import UserService from 'services/UserService';

const AREAS = [
  {
    label: 'Custom area',
    value: 'custom',
    items: [
      {
        label: 'Upload new area',
        value: 'upload',
        as: 'Custom area'
      }
    ]
  }
];

@DragDropContext(HTML5Backend)
class ChartEditor extends React.Component {
  /**
   * Return the geostore id associated with the country's ISO
   * NOTE: errors are not caught intentionally
   * @param {string} iso Valid 3-letter ISO
   * @returns {Promise<string>}
   */
  static getCountryGeostoreId(iso) {
    return fetch(`${process.env.WRI_API_URL}/geostore/admin/${iso}`)
      .then((response) => {
        if (response.ok) return response.json();
        throw new Error(`Unable to get the geostore id associated with the ISO ${iso}`);
      })
      .then(({ data }) => data.id);
  }

  constructor(props) {
    super(props);

    this.state = {
      areaOptions: [],
      loadingAreaIntersection: false,
      loadingUserAreas: false
    };

    // Services
    this.areasService = new AreasService({ apiURL: process.env.WRI_API_URL });
    this.userService = new UserService({ apiURL: process.env.WRI_API_URL });
  }

  /**
  * COMPONENT LIFECYCLE
  * - componentDidMount
  */
  componentDidMount() {
    if (this.props.hasGeoInfo) {
      this.fetchAreas();
      if (this.props.user.id) { // Only try to load the user areas when an user is logged in
        this.fetchUserAreas();
      }
    }
  }

  /**
   * Event handler executed when the selected area
   * intersection is changed
   * @param {{ label: string, value: string }} item Option of the selector
   */
  @Autobind
  async onChangeAreaIntersection(item) {
    return new Promise((resolve) => {
      // The user unselected the option
      if (!item) {
        this.props.setAreaIntersection(null);
      } else if (item.value === 'upload') {
        this.props.toggleModal(true, {
          children: UploadAreaIntersectionModal,
          childrenProps: {
            onUploadArea: (id) => {
              // We close the modal
              this.props.toggleModal(false, {});

              // We save the ID of the area
              this.props.setAreaIntersection(id);

              resolve(true);
            }
          },
          onCloseModal: () => resolve(false)
        });
      } else if (item.isGeostore) {
        // The user selected a custom area that is not a country
        this.props.setAreaIntersection(item.value);
        resolve(true);
      } else {
        this.setState({ loadingAreaIntersection: true });
        ChartEditor.getCountryGeostoreId(item.value)
          .then((id) => {
            this.props.setAreaIntersection(id);
            resolve(true);
          })
          .catch((err) => {
            // In case of an error, we prevent the selector from setting
            // the area as selected
            resolve(false);

            // TODO: improve this 💩
            toastr.error('Error', `Unable to filter with this country. ${err}`);
          })
          .then(() => this.setState({ loadingAreaIntersection: false }));
      }
    });
  }

  @Autobind
  handleChartTypeChange(val) {
    this.props.setChartType(val);
  }

  @Autobind
  handleSaveWidget() {
    const options = {
      children: SaveWidgetModal,
      childrenProps: {
        dataset: this.props.dataset,
        datasetType: this.props.datasetType,
        datasetProvider: this.props.datasetProvider,
        tableName: this.props.tableName
      }
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  @Autobind
  handleUpdateWidget() {
    this.props.onUpdateWidget();
  }

  @Autobind
  handleNeedHelp() {
    const options = {
      children: HowToWidgetEditorModal,
      childrenProps: {}
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  /**
   * Fetch the list of the areas for the area intersection
   * filter
   */
  fetchAreas() {
    this.setState({ loadingAreaIntersection: true });

    // When this resolves, we'll also be able to display the countries
    this.areasService.fetchCountries()
      .then(({ data }) => {
        this.setState({
          areaOptions: [...this.state.areaOptions, ...AREAS, ...data]
        });
      })
      // We don't really care if the countries don't load, we can still
      // let the user use a custom area
      .catch(err => toastr.error('Error', err))
      .then(() => this.setState({ loadingAreaIntersection: false }));
  }

  /**
   * Fetchs the user areas
   */
  fetchUserAreas() {
    this.setState({ loadingUserAreas: true });
    this.userService.getUserAreas(this.props.user.token)
      .then((response) => {
        const userAreas = response.map(val => ({
          label: val.attributes.name,
          value: val.attributes.geostore ? val.attributes.geostore : val.attributes.iso.country,
          isGeostore: val.attributes.geostore
        }));
        this.setState({
          loadingUserAreas: false,
          areaOptions: [...this.state.areaOptions, ...userAreas]
        });
      })
      .catch((err) => {
        this.setState({ loadingUserAreas: false });
        toastr.error('Error loading user areas', err);
      });
  }

  render() {
    const {
      dataset,
      tableName,
      jiminy,
      widgetEditor,
      tableViewMode,
      user,
      mode,
      showSaveButton,
      hasGeoInfo
    } = this.props;
    const { chartType, fields, category, value } = widgetEditor;
    const { areaOptions, loadingAreaIntersection } = this.state;
    const showSaveButtonFlag =
      chartType && category && value && user && user.token && showSaveButton;
    const showUpdateButton = showSaveButtonFlag;
    const chartOptions = (
      jiminy
      && jiminy.general
      && jiminy.general.map(val => ({ label: val, value: val }))
    ) || [];

    return (

          {!tableViewMode &&

                  Chart style

                <Select
                  id="chart-style-select"
                  properties={{
                    name: 'chart-type',
                    value: chartType,
                    default: chartType
                  }}
                  options={chartOptions}
                  onChange={this.handleChartTypeChange}
                />

          }
          {hasGeoInfo &&

                  Area intersection { loadingAreaIntersection && <Spinner isLoading className="-light -small -inline" /> }

                <CustomSelect
                  id="area-intersection-select"
                  placeholder="Select area"
                  options={areaOptions}
                  onValueChange={this.onChangeAreaIntersection}
                  allowNonLeafSelection={false}
                  waitForChangeConfirmation
                />

          }

Drag and drop elements from the list to the boxes:

          {fields &&
            <FieldsContainer
              dataset={dataset}
              tableName={tableName}
              fields={fields}
            />
          }

            <DimensionsContainer />
            <FilterContainer />
            <SortContainer />
            <LimitContainer />

          <button
            type="button"
            className="c-button -secondary"
            onClick={this.handleNeedHelp}
          >
            Need help?
          </button>
          {showSaveButtonFlag && mode === 'save' &&

            Save widget

          }
          {showUpdateButton && mode === 'update' &&

            Save widget

          }

    );
  }
}

ChartEditor.propTypes = {
  mode: PropTypes.oneOf(['save', 'update']).isRequired,
  tableName: PropTypes.string.isRequired,
  hasGeoInfo: PropTypes.bool.isRequired,
  jiminy: PropTypes.object,
  dataset: PropTypes.string.isRequired, // Dataset ID
  datasetType: PropTypes.string,
  datasetProvider: PropTypes.string,
  tableViewMode: PropTypes.bool.isRequired,
  showSaveButton: PropTypes.bool.isRequired,
  // Store
  widgetEditor: PropTypes.object.isRequired,
  user: PropTypes.object.isRequired,
  setChartType: PropTypes.func.isRequired,
  toggleModal: PropTypes.func.isRequired,
  setModalOptions: PropTypes.func.isRequired,
  setAreaIntersection: PropTypes.func.isRequired,
  // Callback
  onUpdateWidget: PropTypes.func
};

const mapStateToProps = ({ widgetEditor, user }) => ({ widgetEditor, user });
const mapDispatchToProps = dispatch => ({
  setChartType: (type) => {
    dispatch(setChartType(type));
  },
  toggleModal: (open, opts) => { dispatch(toggleModal(open, opts)); },
  setModalOptions: (options) => { dispatch(setModalOptions(options)); },
  setAreaIntersection: id => dispatch(setAreaIntersection(id))
});

export default connect(mapStateToProps, mapDispatchToProps)(ChartEditor);
<|endoftext|>


<commit_before>var bot = require('./bot');
const help = require('./help');
const web = require('./web');
//const music = require('./music');
var commands = require('./commands');
var config = require('./config');
var functions = require('./functions');
let messageDB = require('./messagedb.json');
fs = require('fs');
if(!messageDB.data)
{messageDB.data = new Array();}
bot.on('message', message => {
    if (message.author.bot == true) return; // prevent loop
    if (message.content.toLowerCase() === 'hi' || message.content.toLowerCase() === 'hello' || message.content.toLowerCase() === 'hey') {
        message.reply('hello');
        return;
    }
    if (message.channel.id == '271350052188979201') {
        bot.channels.get('271349742099759104').sendMessage("**" + message.author.username + ":** " + message.content)
		.then(msg => messageDB.data.push({oldMessage:message.id,newMessage:msg.id}));
    } else if (message.channel.id == '271349742099759104') {
        bot.channels.get('271350052188979201').sendMessage("**" + message.author.username + ":** " + message.content)
		.then(msg => messageDB.data.push({oldMessage:message,newMessage:msg}));
    }
});
bot.on('messageUpdate', (oldMessage,newMessage)=>{
	if(newMessage.channel == '271350052188979201' ||newMessage.channel == '271349742099759104')
	{
		messageDB.find("oldMessage",oldMessage.id).newMessage.edit(newMessage.content);
	}
})
process.on('uncaughtException', function(err) {
    console.log('Caught exception: ' + err);
	fs.writeFileSync('messagedb.json', JSON.stringify(messageDB));
    bot = require('./bot');
});
process.on('Exit', function(code) {
	fs.writeFileSync('messagedb.json', JSON.stringify(messageDB));
});
bot.on("guildMemberAdd", (member) => {
    var user = member.user;
    user.sendMessage("Welcome to the Revive Network");
    functions.refreshUser(user);
});
bot.on('message', message => {
    if (message.content.toLowerCase() === '~stop') {
        if (message.guild != bot.guilds.find("name", "Revive Network Dev")) {
            return;
        };
        process.exit();
    }
});
<commit_msg>Logging<commit_after>var bot = require('./bot');
const help = require('./help');
const web = require('./web');
//const music = require('./music');
var commands = require('./commands');
var config = require('./config');
var functions = require('./functions');
let messageDB = require('./messagedb.json');
fs = require('fs');
if(!messageDB.data)
{messageDB.data = new Array();}
bot.on('message', message => {
    if (message.author.bot == true) return; // prevent loop
    if (message.content.toLowerCase() === 'hi' || message.content.toLowerCase() === 'hello' || message.content.toLowerCase() === 'hey') {
        message.reply('hello');
        return;
    }
    if (message.channel.id == '271350052188979201') {
        bot.channels.get('271349742099759104').sendMessage("**" + message.author.username + ":** " + message.content)
		.then(msg => messageDB.data.push({oldMessage:message.id,newMessage:msg.id}));
    } else if (message.channel.id == '271349742099759104') {
        bot.channels.get('271350052188979201').sendMessage("**" + message.author.username + ":** " + message.content)
		.then(msg => messageDB.data.push({oldMessage:message,newMessage:msg}));
    }
});
bot.on('messageUpdate', (oldMessage,newMessage)=>{
	console.log("executing");
	if(newMessage.channel == '271350052188979201' ||newMessage.channel == '271349742099759104')
	{
		messageDB.find("oldMessage",oldMessage.id).newMessage.edit(newMessage.content);
	}
});
process.on('uncaughtException', function(err) {
    console.log('Caught exception: ' + err);
	fs.writeFileSync('messagedb.json', JSON.stringify(messageDB));
    bot = require('./bot');
});
process.on('Exit', function(code) {
	fs.writeFileSync('messagedb.json', JSON.stringify(messageDB));
});
bot.on("guildMemberAdd", (member) => {
    var user = member.user;
    user.sendMessage("Welcome to the Revive Network");
    functions.refreshUser(user);
});
bot.on('message', message => {
    if (message.content.toLowerCase() === '~stop') {
        if (message.guild != bot.guilds.find("name", "Revive Network Dev")) {
            return;
        };
        process.exit();
    }
});
<|endoftext|>


<commit_before>Ext.define('doweown.view.WorldCatView', {
    extend: 'Ext.DataView',
    xtype: 'worldcatview',

    config: {
           //title: 'WorldCat Listings',
	   title: 'Sorry, we don\'t own it but...',
           store: 'WorldCatStore',
           /*onItemDisclosure: function( record, btn, index ) {
                                Ext.Msg.alert( record.get('collection.collectionname'), Ext.emptyFn);
            },*/
            //itemTpl: '
 {repository.name} <tpl for="collection">
 {collectionname}<tpl for="items">
 <tpl switch="isavail"><tpl case="N" case="n">Not Available<tpl default>Available</tpl>  :{stat}
 Call#: {call}
 {req.content}
</tpl> <tpl for="holdtag">
 {availkey} {availval.content}
</tpl>  <tpl for="online"> {content}
</tpl> </tpl>

'
	itemTpl: '
<tpl if="thumbnail"></tpl> {title}
 {author}
 {date}
 {publisher}

Libraries:
<tpl for="library">{institutionName}
 map
 catalog link
</tpl>
'
     }

});
<commit_msg>map links<commit_after>Ext.define('doweown.view.WorldCatView', {
    extend: 'Ext.DataView',
    xtype: 'worldcatview',

    config: {
           //title: 'WorldCat Listings',
	   title: 'Sorry, we don\'t own it but...',
           store: 'WorldCatStore',
           /*onItemDisclosure: function( record, btn, index ) {
                                Ext.Msg.alert( record.get('collection.collectionname'), Ext.emptyFn);
            },*/
            //itemTpl: '
 {repository.name} <tpl for="collection">
 {collectionname}<tpl for="items">
 <tpl switch="isavail"><tpl case="N" case="n">Not Available<tpl default>Available</tpl>  :{stat}
 Call#: {call}
 {req.content}
</tpl> <tpl for="holdtag">
 {availkey} {availval.content}
</tpl>  <tpl for="online"> {content}
</tpl> </tpl>

'
	itemTpl: '
<tpl if="thumbnail"></tpl> {title}
 {author}
 {date}
 {publisher}

Libraries:
<tpl for="library">{institutionName}
 map
 catalog link
</tpl>
'
     }

});
<|endoftext|>


<commit_before>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

const ZOTERO_AC_CONTRACTID = '@mozilla.org/autocomplete/search;1?name=zotero';
const ZOTERO_AC_CLASSNAME = 'Zotero AutoComplete';
const ZOTERO_AC_CID = Components.ID('{06a2ed11-d0a4-4ff0-a56f-a44545eee6ea}');

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

/*
 * Implements nsIAutoCompleteSearch
 */
function ZoteroAutoComplete() {
	// Get the Zotero object
	this._zotero = Components.classes["@zotero.org/Zotero;1"]
				.getService(Components.interfaces.nsISupports)
				.wrappedJSObject;
}

ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParams, previousResult, listener) {
	var result = Cc["@mozilla.org/autocomplete/simple-result;1"]
					.createInstance(Ci.nsIAutoCompleteSimpleResult);
	result.setSearchString(searchString);

	this._result = result;
	this._results = [];
	this._listener = listener;
	this._cancelled = false;

	this._zotero.debug("Starting autocomplete search with data '"
		+ searchParams + "'" + " and string '" + searchString + "'");

	searchParams = JSON.parse(searchParams);
	if (!searchParams) {
		throw new Error("Invalid JSON passed to autocomplete");
	}
	var [fieldName, , subField] = searchParams.fieldName.split("-");

	this.stopSearch();

	var self = this;
	var statement;

	switch (fieldName) {
		case '':
			break;

		case 'tag':
			var sql = "SELECT DISTINCT name AS val, NULL AS comment FROM tags WHERE name LIKE ?";
			var sqlParams = [searchString + '%'];
			if (typeof searchParams.libraryID != 'undefined') {
				sql += " AND libraryID=?";
				sqlParams.push(searchParams.libraryID);
			}
			if (searchParams.itemID) {
				sql += " AND name NOT IN (SELECT name FROM tags WHERE tagID IN ("
					+ "SELECT tagID FROM itemTags WHERE itemID = ?))";
				sqlParams.push(searchParams.itemID);
			}
			sql += " ORDER BY val COLLATE locale";
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'creator':
			// Valid fieldMode values:
			// 		0 == search two-field creators
			// 		1 == search single-field creators
			// 		2 == search both
			if (searchParams.fieldMode == 2) {
				var sql = "SELECT DISTINCT CASE fieldMode WHEN 1 THEN lastName "
					+ "WHEN 0 THEN firstName || ' ' || lastName END AS val, NULL AS comment "
					+ "FROM creators NATURAL JOIN creatorData WHERE CASE fieldMode "
					+ "WHEN 1 THEN lastName "
					+ "WHEN 0 THEN firstName || ' ' || lastName END "
					+ "LIKE ? ";
				var sqlParams = [searchString + '%'];
				if (typeof searchParams.libraryID != 'undefined') {
					sql += " AND libraryID=?";
					sqlParams.push(searchParams.libraryID);
				}
				sql += "ORDER BY val";
			}
			else
			{
				var sql = "SELECT DISTINCT ";
				if (searchParams.fieldMode == 1) {
					sql += "lastName AS val, creatorID || '-1' AS comment";
				}
				// Retrieve the matches in the specified field
				// as well as any full names using the name
				//
				// e.g. "Shakespeare" and "Shakespeare, William"
				//
				// creatorID is in the format "12345-1" or "12345-2",
				// 		- 1 means the row uses only the specified field
				// 		- 2 means it uses both
				else {
					sql += "CASE WHEN firstName='' OR firstName IS NULL THEN lastName "
						+ "ELSE lastName || ', ' || firstName END AS val, "
						+ "creatorID || '-' || CASE "
						+ "WHEN (firstName = '' OR firstName IS NULL) THEN 1 "
						+ "ELSE 2 END AS comment";
				}

				var fromSQL = " FROM creators NATURAL JOIN creatorData "
					+ "WHERE " + subField + " LIKE ? " + "AND fieldMode=?";
				var sqlParams = [
					searchString + '%',
					searchParams.fieldMode ? searchParams.fieldMode : 0
				];
				if (searchParams.itemID) {
					fromSQL += " AND creatorID NOT IN (SELECT creatorID FROM "
						+ "itemCreators WHERE itemID=?";
					sqlParams.push(searchParams.itemID);
					if (searchParams.creatorTypeID) {
						fromSQL += " AND creatorTypeID=?";
						sqlParams.push(searchParams.creatorTypeID);
					}
					fromSQL += ")";
				}
				if (typeof searchParams.libraryID != 'undefined') {
					if (searchParams.libraryID) {
						fromSQL += " AND libraryID=?";
						sqlParams.push(searchParams.libraryID);
					}
					else {
						fromSQL += " AND libraryID IS NULL";
					}
				}

				sql += fromSQL;

				// If double-field mode, include matches for just this field
				// as well (i.e. "Shakespeare"), and group to collapse repeats
				if (searchParams.fieldMode != 1) {
					sql = "SELECT * FROM (" + sql + " UNION SELECT DISTINCT "
						+ subField + " AS val, creatorID || '-1' AS comment"
						+ fromSQL + ") GROUP BY val";
					sqlParams = sqlParams.concat(sqlParams);
				}

				sql += " ORDER BY val";
			}

			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'dateModified':
		case 'dateAdded':
			var sql = "SELECT DISTINCT DATE(" + fieldName + ", 'localtime') AS val, NULL AS comment FROM items "
				+ "WHERE " + fieldName + " LIKE ? ORDER BY " + fieldName;
			var sqlParams = [searchString + '%'];
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'accessDate':
			var fieldID = this._zotero.ItemFields.getID('accessDate');

			var sql = "SELECT DISTINCT DATE(value, 'localtime') AS val, NULL AS comment FROM itemData "
				+ "WHERE fieldID=? AND value LIKE ? ORDER BY value";
			var sqlParams = [fieldID, searchString + '%'];
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		default:
			var fieldID = this._zotero.ItemFields.getID(fieldName);
			if (!fieldID) {
				this._zotero.debug("'" + fieldName + "' is not a valid autocomplete scope", 1);
				this.updateResults([], false, Ci.nsIAutoCompleteResult.RESULT_IGNORED);
				return;
			}

			// We don't use date autocomplete anywhere, but if we're not
			// disallowing it altogether, we should at least do it right and
			// use the user part of the multipart field
			var valueField = fieldName == 'date' ? 'SUBSTR(value, 12, 100)' : 'value';

			var sql = "SELECT DISTINCT " + valueField + " AS val, NULL AS comment "
				+ "FROM itemData NATURAL JOIN itemDataValues "
				+ "WHERE fieldID=?1 AND " + valueField
				+ " LIKE ?2 "

			var sqlParams = [fieldID, searchString + '%'];
			if (searchParams.itemID) {
				sql += "AND value NOT IN (SELECT value FROM itemData "
					+ "NATURAL JOIN itemDataValues WHERE fieldID=?1 AND itemID=?3) ";
				sqlParams.push(searchParams.itemID);
			}
			sql += "ORDER BY value";
			statement = this._zotero.DB.getStatement(sql, sqlParams);
	}

	var self = this;

	this.pendingStatement = statement.executeAsync({
		handleResult: function (storageResultSet) {
			self._zotero.debug("Handling autocomplete results");

			var results = [];
			var comments = [];

			for (let row = storageResultSet.getNextRow();
					row;
					row = storageResultSet.getNextRow()) {
				results.push(row.getResultByIndex(0));
				let comment = row.getResultByIndex(1);
				if (comment) {
					comments.push(comment);
				}
			}

			self.updateResults(results, comments, true);
		},

		handleError: function (e) {
			Components.utils.reportError(e.message);
		},

		handleCompletion: function (reason) {
			self.pendingStatement = null;

			if (reason != Ci.mozIStorageStatementCallback.REASON_FINISHED) {
				var resultCode = Ci.nsIAutoCompleteResult.RESULT_FAILURE;
			}
			else {
				var resultCode = null;
			}

			self.updateResults(null, null, false, resultCode);

			if (resultCode) {
				self._zotero.debug("Autocomplete query aborted");
			}
			else {
				self._zotero.debug("Autocomplete query completed");
			}
		}
	});
}

ZoteroAutoComplete.prototype.updateResults = function (results, comments, ongoing, resultCode) {
	if (!results) {
		results = [];
	}
	if (!comments) {
		comments = [];
	}

	for (var i=0; i<results.length; i++) {
		let result = results[i];

		if (this._results.indexOf(result) == -1) {
			comment = comments[i] ? comments[i] : null;
			this._zotero.debug("Appending autocomplete value '" + result + "'" + (comment ? " (" + comment + ")" : ""));
			this._result.appendMatch(result, comment, null, null);
			this._results.push(result);
		}
		else {
			//this._zotero.debug("Skipping existing value '" + result + "'");
		}
	}

	if (!resultCode) {
		resultCode = "RESULT_";
		if (!this._results.length) {
			resultCode += "NOMATCH";
		}
		else {
			resultCode += "SUCCESS";
		}
		if (ongoing) {
			resultCode += "_ONGOING";
		}
		resultCode = Ci.nsIAutoCompleteResult[resultCode];
	}

	this._result.setSearchResult(resultCode);
	this._listener.onSearchResult(this, this._result);
}

ZoteroAutoComplete.prototype.stopSearch = function(){
	if (this.pendingStatement) {
		this._zotero.debug('Stopping autocomplete search');
		this.pendingStatement.cancel();
	}
}

//
// XPCOM goop
//

ZoteroAutoComplete.prototype.classDescription = ZOTERO_AC_CLASSNAME;
ZoteroAutoComplete.prototype.classID = ZOTERO_AC_CID;
ZoteroAutoComplete.prototype.contractID = ZOTERO_AC_CONTRACTID;
ZoteroAutoComplete.prototype.QueryInterface = XPCOMUtils.generateQI([
	Components.interfaces.nsIAutoCompleteSearch,
	Components.interfaces.nsIAutoCompleteObserver,
	Components.interfaces.nsISupports]);

/**
* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
*/
if (XPCOMUtils.generateNSGetFactory) {
	var NSGetFactory = XPCOMUtils.generateNSGetFactory([ZoteroAutoComplete]);
} else {
	var NSGetModule = XPCOMUtils.generateNSGetModule([ZoteroAutoComplete]);
}<commit_msg>Match last name alone for two-field names in search autocomplete<commit_after>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

const ZOTERO_AC_CONTRACTID = '@mozilla.org/autocomplete/search;1?name=zotero';
const ZOTERO_AC_CLASSNAME = 'Zotero AutoComplete';
const ZOTERO_AC_CID = Components.ID('{06a2ed11-d0a4-4ff0-a56f-a44545eee6ea}');

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

/*
 * Implements nsIAutoCompleteSearch
 */
function ZoteroAutoComplete() {
	// Get the Zotero object
	this._zotero = Components.classes["@zotero.org/Zotero;1"]
				.getService(Components.interfaces.nsISupports)
				.wrappedJSObject;
}

ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParams, previousResult, listener) {
	var result = Cc["@mozilla.org/autocomplete/simple-result;1"]
					.createInstance(Ci.nsIAutoCompleteSimpleResult);
	result.setSearchString(searchString);

	this._result = result;
	this._results = [];
	this._listener = listener;
	this._cancelled = false;

	this._zotero.debug("Starting autocomplete search with data '"
		+ searchParams + "'" + " and string '" + searchString + "'");

	searchParams = JSON.parse(searchParams);
	if (!searchParams) {
		throw new Error("Invalid JSON passed to autocomplete");
	}
	var [fieldName, , subField] = searchParams.fieldName.split("-");

	this.stopSearch();

	var self = this;
	var statement;

	switch (fieldName) {
		case '':
			break;

		case 'tag':
			var sql = "SELECT DISTINCT name AS val, NULL AS comment FROM tags WHERE name LIKE ?";
			var sqlParams = [searchString + '%'];
			if (typeof searchParams.libraryID != 'undefined') {
				sql += " AND libraryID=?";
				sqlParams.push(searchParams.libraryID);
			}
			if (searchParams.itemID) {
				sql += " AND name NOT IN (SELECT name FROM tags WHERE tagID IN ("
					+ "SELECT tagID FROM itemTags WHERE itemID = ?))";
				sqlParams.push(searchParams.itemID);
			}
			sql += " ORDER BY val COLLATE locale";
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'creator':
			// Valid fieldMode values:
			// 		0 == search two-field creators
			// 		1 == search single-field creators
			// 		2 == search both
			if (searchParams.fieldMode == 2) {
				var sql = "SELECT DISTINCT CASE fieldMode WHEN 1 THEN lastName "
					+ "WHEN 0 THEN firstName || ' ' || lastName END AS val, NULL AS comment "
					+ "FROM creators NATURAL JOIN creatorData "
					+ "WHERE CASE fieldMode "
					+ "WHEN 1 THEN lastName LIKE ? "
					+ "WHEN 0 THEN (firstName || ' ' || lastName LIKE ?) OR (lastName LIKE ?) END "
				var sqlParams = [searchString + '%', searchString + '%', searchString + '%'];
				if (typeof searchParams.libraryID != 'undefined') {
					sql += " AND libraryID=?";
					sqlParams.push(searchParams.libraryID);
				}
				sql += "ORDER BY val";
			}
			else
			{
				var sql = "SELECT DISTINCT ";
				if (searchParams.fieldMode == 1) {
					sql += "lastName AS val, creatorID || '-1' AS comment";
				}
				// Retrieve the matches in the specified field
				// as well as any full names using the name
				//
				// e.g. "Shakespeare" and "Shakespeare, William"
				//
				// creatorID is in the format "12345-1" or "12345-2",
				// 		- 1 means the row uses only the specified field
				// 		- 2 means it uses both
				else {
					sql += "CASE WHEN firstName='' OR firstName IS NULL THEN lastName "
						+ "ELSE lastName || ', ' || firstName END AS val, "
						+ "creatorID || '-' || CASE "
						+ "WHEN (firstName = '' OR firstName IS NULL) THEN 1 "
						+ "ELSE 2 END AS comment";
				}

				var fromSQL = " FROM creators NATURAL JOIN creatorData "
					+ "WHERE " + subField + " LIKE ? " + "AND fieldMode=?";
				var sqlParams = [
					searchString + '%',
					searchParams.fieldMode ? searchParams.fieldMode : 0
				];
				if (searchParams.itemID) {
					fromSQL += " AND creatorID NOT IN (SELECT creatorID FROM "
						+ "itemCreators WHERE itemID=?";
					sqlParams.push(searchParams.itemID);
					if (searchParams.creatorTypeID) {
						fromSQL += " AND creatorTypeID=?";
						sqlParams.push(searchParams.creatorTypeID);
					}
					fromSQL += ")";
				}
				if (typeof searchParams.libraryID != 'undefined') {
					if (searchParams.libraryID) {
						fromSQL += " AND libraryID=?";
						sqlParams.push(searchParams.libraryID);
					}
					else {
						fromSQL += " AND libraryID IS NULL";
					}
				}

				sql += fromSQL;

				// If double-field mode, include matches for just this field
				// as well (i.e. "Shakespeare"), and group to collapse repeats
				if (searchParams.fieldMode != 1) {
					sql = "SELECT * FROM (" + sql + " UNION SELECT DISTINCT "
						+ subField + " AS val, creatorID || '-1' AS comment"
						+ fromSQL + ") GROUP BY val";
					sqlParams = sqlParams.concat(sqlParams);
				}

				sql += " ORDER BY val";
			}

			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'dateModified':
		case 'dateAdded':
			var sql = "SELECT DISTINCT DATE(" + fieldName + ", 'localtime') AS val, NULL AS comment FROM items "
				+ "WHERE " + fieldName + " LIKE ? ORDER BY " + fieldName;
			var sqlParams = [searchString + '%'];
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		case 'accessDate':
			var fieldID = this._zotero.ItemFields.getID('accessDate');

			var sql = "SELECT DISTINCT DATE(value, 'localtime') AS val, NULL AS comment FROM itemData "
				+ "WHERE fieldID=? AND value LIKE ? ORDER BY value";
			var sqlParams = [fieldID, searchString + '%'];
			statement = this._zotero.DB.getStatement(sql, sqlParams);
			break;

		default:
			var fieldID = this._zotero.ItemFields.getID(fieldName);
			if (!fieldID) {
				this._zotero.debug("'" + fieldName + "' is not a valid autocomplete scope", 1);
				this.updateResults([], false, Ci.nsIAutoCompleteResult.RESULT_IGNORED);
				return;
			}

			// We don't use date autocomplete anywhere, but if we're not
			// disallowing it altogether, we should at least do it right and
			// use the user part of the multipart field
			var valueField = fieldName == 'date' ? 'SUBSTR(value, 12, 100)' : 'value';

			var sql = "SELECT DISTINCT " + valueField + " AS val, NULL AS comment "
				+ "FROM itemData NATURAL JOIN itemDataValues "
				+ "WHERE fieldID=?1 AND " + valueField
				+ " LIKE ?2 "

			var sqlParams = [fieldID, searchString + '%'];
			if (searchParams.itemID) {
				sql += "AND value NOT IN (SELECT value FROM itemData "
					+ "NATURAL JOIN itemDataValues WHERE fieldID=?1 AND itemID=?3) ";
				sqlParams.push(searchParams.itemID);
			}
			sql += "ORDER BY value";
			statement = this._zotero.DB.getStatement(sql, sqlParams);
	}

	var self = this;

	this.pendingStatement = statement.executeAsync({
		handleResult: function (storageResultSet) {
			self._zotero.debug("Handling autocomplete results");

			var results = [];
			var comments = [];

			for (let row = storageResultSet.getNextRow();
					row;
					row = storageResultSet.getNextRow()) {
				results.push(row.getResultByIndex(0));
				let comment = row.getResultByIndex(1);
				if (comment) {
					comments.push(comment);
				}
			}

			self.updateResults(results, comments, true);
		},

		handleError: function (e) {
			Components.utils.reportError(e.message);
		},

		handleCompletion: function (reason) {
			self.pendingStatement = null;

			if (reason != Ci.mozIStorageStatementCallback.REASON_FINISHED) {
				var resultCode = Ci.nsIAutoCompleteResult.RESULT_FAILURE;
			}
			else {
				var resultCode = null;
			}

			self.updateResults(null, null, false, resultCode);

			if (resultCode) {
				self._zotero.debug("Autocomplete query aborted");
			}
			else {
				self._zotero.debug("Autocomplete query completed");
			}
		}
	});
}

ZoteroAutoComplete.prototype.updateResults = function (results, comments, ongoing, resultCode) {
	if (!results) {
		results = [];
	}
	if (!comments) {
		comments = [];
	}

	for (var i=0; i<results.length; i++) {
		let result = results[i];

		if (this._results.indexOf(result) == -1) {
			comment = comments[i] ? comments[i] : null;
			this._zotero.debug("Appending autocomplete value '" + result + "'" + (comment ? " (" + comment + ")" : ""));
			this._result.appendMatch(result, comment, null, null);
			this._results.push(result);
		}
		else {
			//this._zotero.debug("Skipping existing value '" + result + "'");
		}
	}

	if (!resultCode) {
		resultCode = "RESULT_";
		if (!this._results.length) {
			resultCode += "NOMATCH";
		}
		else {
			resultCode += "SUCCESS";
		}
		if (ongoing) {
			resultCode += "_ONGOING";
		}
		resultCode = Ci.nsIAutoCompleteResult[resultCode];
	}

	this._result.setSearchResult(resultCode);
	this._listener.onSearchResult(this, this._result);
}

ZoteroAutoComplete.prototype.stopSearch = function(){
	if (this.pendingStatement) {
		this._zotero.debug('Stopping autocomplete search');
		this.pendingStatement.cancel();
	}
}

//
// XPCOM goop
//

ZoteroAutoComplete.prototype.classDescription = ZOTERO_AC_CLASSNAME;
ZoteroAutoComplete.prototype.classID = ZOTERO_AC_CID;
ZoteroAutoComplete.prototype.contractID = ZOTERO_AC_CONTRACTID;
ZoteroAutoComplete.prototype.QueryInterface = XPCOMUtils.generateQI([
	Components.interfaces.nsIAutoCompleteSearch,
	Components.interfaces.nsIAutoCompleteObserver,
	Components.interfaces.nsISupports]);

/**
* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
*/
if (XPCOMUtils.generateNSGetFactory) {
	var NSGetFactory = XPCOMUtils.generateNSGetFactory([ZoteroAutoComplete]);
} else {
	var NSGetModule = XPCOMUtils.generateNSGetModule([ZoteroAutoComplete]);
}<|endoftext|>


<commit_before>"use strict";

const path = require('path');
const del = require('del');
const runSequence = require('run-sequence');
const streamqueue = require('streamqueue');
const remoteSrc = require('gulp-remote-src');
const concat = require('gulp-concat');
const URL = require('url');
const karmaServer = require('karma').Server;

class Erik {
  /**
   * @param {Object} options
   * @param {Object} options.gulp - The gulp instance with which to register Erik's tasks.
   * @param {Boolean} [options.watch] - When watch is set, Erik will watch for changes to your
   * bundled spec and re-run the test suite when changes occur.
   * @param {String[]} [options.taskDependencies] - Names of tasks to be run before any Erik
   * processing is done. Useful for registering your spec-building/processing tasks as dependencies
   * of Erik's testing task. These tasks will be run in serial as passed.
   * @param {String[]} [options.localDependencies] - Local dependencies to be bundled alongisde your
   * remote dependencies. Glob strings. Useful for including your bower-installed packages, for
   * example.
   * @param {String[]} [options.remoteDependencies] - URLs corresponding to remote dependencies.
   * @param {String} options.bundledSpecPath - Path to your bundled and processed test suite.
   * @param {Object} [options.karmaConfig]
   * @param {Number} [options.karmaConfig.port=9876] - Port on which to run the Karma server.
   * @param {String} [bundlePath] - Base bath to use for Erik's bundled files. A directory named
   * `erik` will be created here.
   */
  constructor(options) {
    this._gulp = options.gulp;
    this._watch = options.watch || false;
    this._taskDependencies = options.taskDependencies || [];
    this._localDependencies = options.localDependencies || [];
    this._remoteDependencies = options.remoteDependencies || [];
    this._bundledSpecPath = options.bundledSpecPath;
    this._port = (options.karmaConfig && options.karmaConfig.port) || 9876;
    this._bundlePath = options.bundlePath || '';

    this._assertValidOptions(options);

    this._erikPath = path.join(options.bundlePath, '.erik');

    this._cleanPath();

    this._registerTasks();
  }

  _assertValidOptions() {
    if (typeof this._gulp !== 'object') {
      throw new Error('`options.gulp` is of an invalid type.');
    }

    if (typeof this._watch !== 'boolean') {
      throw new Error('`options.watch` is of an invalid type.');
    }

    if (!Array.isArray(this._taskDependencies)) {
      throw new Error('`options.taskDependencies` is of an invalid type.');
    }

    if (!Array.isArray(this._localDependencies)) {
      throw new Error('`options.localDependencies` is of an invalid type.');
    }

    if (!Array.isArray(this._remoteDependencies)) {
      throw new Error('`options.remoteDependencies` is of an invalid type.');
    }

    if (typeof this._bundledSpecPath !== 'string') {
      throw new Error('`options.bundledSpecPath` is of an invalid type.');
    }

    if (typeof this._port !== 'number') {
      throw new Error('`options.karmaConfig.port` is of an invalid type.');
    }

    if (typeof this._bundlePath !== 'string') {
      throw new Error('`options.bundlePath` is of an invalid type.');
    }
   }

  _cleanPath() {
    del(this._erikPath);
  }

  _registerTasks() {
    this._registerFetchRemoteDeps();
    this._registerBundleDeps();
    this._registerRunSpec();
    this._registerErik();
  }

  _registerFetchRemoteDeps() {
    this._gulp.task('erik-fetch-remote-deps', () => {
      /**
       * `streamqueue` hangs and `gulp` exits if `_remoteDependencies` is empty and we don't return
       * early here.
       */
      if (this._remoteDependencies.length === 0) return;

      return streamqueue({
        objectMode: true
      }, ...this._remoteDependencies.map((urlStr) => {
        const url = URL.parse(urlStr);
        const base = `${url.protocol}//${url.host}`;
        const path = url.path;

        return remoteSrc([path], {
          base
        });
      }))
        .pipe(concat('remote-deps.js'))
        .pipe(this._gulp.dest(this._erikPath));
    });
  }

  _registerBundleDeps() {
    this._gulp.task('erik-bundle-deps', () => {
      return this._gulp.src([
        `${this._erikPath}/remote-deps.js`,
        ...this._localDependencies
      ])
        .pipe(concat('bundled-deps.js'))
        .pipe(this._gulp.dest(this._erikPath));
    });
  }

  _registerRunSpec() {
    this._gulp.task('erik-run-spec', (done) => {
      new karmaServer.start({
        frameworks: ['jasmine'],
        browsers: ['PhantomJS'],
        reporters: ['mocha'],

        /**
         * Pass an empty object for `preprocessors` in order to disable Karma's default processing
         * of coffescript files.
         */
        preprocessors: {
        },

        files: [
          `${this._erikPath}/bundled-deps.js`,
          this._bundledSpecPath,
        ],

        port: this._port,

        autoWatch: this._watch,
        singleRun: !this._watch
      }, function(error) {
        /**
         * We must create our own Error object because the error Karma returns is not a proper Error
         * object per https://github.com/karma-runner/gulp-karma/issues/18#issuecomment-188413903.
         */
        error = error ? new Error(`Karma returned with the error code: ${error}`) : undefined;

        done(error);
      });
    });
  }

  _registerErik() {
    this._gulp.task('erik', (done) => {
      const tasks = this._taskDependencies.concat([
        'erik-fetch-remote-deps',
        'erik-bundle-deps',
        'erik-run-spec',
        done
      ]);

      // Run everything serially.
      runSequence.use(this._gulp)(...tasks);
    });
  }
}

module.exports = Erik;
<commit_msg>Clean on task run, not on initialization<commit_after>"use strict";

const path = require('path');
const del = require('del');
const runSequence = require('run-sequence');
const streamqueue = require('streamqueue');
const remoteSrc = require('gulp-remote-src');
const concat = require('gulp-concat');
const URL = require('url');
const karmaServer = require('karma').Server;

class Erik {
  /**
   * @param {Object} options
   * @param {Object} options.gulp - The gulp instance with which to register Erik's tasks.
   * @param {Boolean} [options.watch] - When watch is set, Erik will watch for changes to your
   * bundled spec and re-run the test suite when changes occur.
   * @param {String[]} [options.taskDependencies] - Names of tasks to be run before any Erik
   * processing is done. Useful for registering your spec-building/processing tasks as dependencies
   * of Erik's testing task. These tasks will be run in serial as passed.
   * @param {String[]} [options.localDependencies] - Local dependencies to be bundled alongisde your
   * remote dependencies. Glob strings. Useful for including your bower-installed packages, for
   * example.
   * @param {String[]} [options.remoteDependencies] - URLs corresponding to remote dependencies.
   * @param {String} options.bundledSpecPath - Path to your bundled and processed test suite.
   * @param {Object} [options.karmaConfig]
   * @param {Number} [options.karmaConfig.port=9876] - Port on which to run the Karma server.
   * @param {String} [bundlePath] - Base bath to use for Erik's bundled files. A directory named
   * `erik` will be created here.
   */
  constructor(options) {
    this._gulp = options.gulp;
    this._watch = options.watch || false;
    this._taskDependencies = options.taskDependencies || [];
    this._localDependencies = options.localDependencies || [];
    this._remoteDependencies = options.remoteDependencies || [];
    this._bundledSpecPath = options.bundledSpecPath;
    this._port = (options.karmaConfig && options.karmaConfig.port) || 9876;
    this._bundlePath = options.bundlePath || '';

    this._assertValidOptions(options);

    this._erikPath = path.join(options.bundlePath, '.erik');

    this._registerTasks();
  }

  _assertValidOptions() {
    if (typeof this._gulp !== 'object') {
      throw new Error('`options.gulp` is of an invalid type.');
    }

    if (typeof this._watch !== 'boolean') {
      throw new Error('`options.watch` is of an invalid type.');
    }

    if (!Array.isArray(this._taskDependencies)) {
      throw new Error('`options.taskDependencies` is of an invalid type.');
    }

    if (!Array.isArray(this._localDependencies)) {
      throw new Error('`options.localDependencies` is of an invalid type.');
    }

    if (!Array.isArray(this._remoteDependencies)) {
      throw new Error('`options.remoteDependencies` is of an invalid type.');
    }

    if (typeof this._bundledSpecPath !== 'string') {
      throw new Error('`options.bundledSpecPath` is of an invalid type.');
    }

    if (typeof this._port !== 'number') {
      throw new Error('`options.karmaConfig.port` is of an invalid type.');
    }

    if (typeof this._bundlePath !== 'string') {
      throw new Error('`options.bundlePath` is of an invalid type.');
    }
   }

  _registerTasks() {
    this._registerFetchRemoteDeps();
    this._registerBundleDeps();
    this._registerRunSpec();
    this._registerErik();
  }

  _registerFetchRemoteDeps() {
    this._gulp.task('erik-fetch-remote-deps', () => {
      /**
       * `streamqueue` hangs and `gulp` exits if `_remoteDependencies` is empty and we don't return
       * early here.
       */
      if (this._remoteDependencies.length === 0) return;

      return streamqueue({
        objectMode: true
      }, ...this._remoteDependencies.map((urlStr) => {
        const url = URL.parse(urlStr);
        const base = `${url.protocol}//${url.host}`;
        const path = url.path;

        return remoteSrc([path], {
          base
        });
      }))
        .pipe(concat('remote-deps.js'))
        .pipe(this._gulp.dest(this._erikPath));
    });
  }

  _registerBundleDeps() {
    this._gulp.task('erik-bundle-deps', () => {
      return this._gulp.src([
        `${this._erikPath}/remote-deps.js`,
        ...this._localDependencies
      ])
        .pipe(concat('bundled-deps.js'))
        .pipe(this._gulp.dest(this._erikPath));
    });
  }

  _registerRunSpec() {
    this._gulp.task('erik-run-spec', (done) => {
      new karmaServer.start({
        frameworks: ['jasmine'],
        browsers: ['PhantomJS'],
        reporters: ['mocha'],

        /**
         * Pass an empty object for `preprocessors` in order to disable Karma's default processing
         * of coffescript files.
         */
        preprocessors: {
        },

        files: [
          `${this._erikPath}/bundled-deps.js`,
          this._bundledSpecPath,
        ],

        port: this._port,

        autoWatch: this._watch,
        singleRun: !this._watch
      }, function(error) {
        /**
         * We must create our own Error object because the error Karma returns is not a proper Error
         * object per https://github.com/karma-runner/gulp-karma/issues/18#issuecomment-188413903.
         */
        error = error ? new Error(`Karma returned with the error code: ${error}`) : undefined;

        done(error);
      });
    });
  }

  _registerErik() {
    this._gulp.task('erik', (done) => {
      del(this._erikPath);

      const tasks = this._taskDependencies.concat([
        'erik-fetch-remote-deps',
        'erik-bundle-deps',
        'erik-run-spec',
        done
      ]);

      // Run everything serially.
      runSequence.use(this._gulp)(...tasks);
    });
  }
}

module.exports = Erik;
<|endoftext|>


<commit_before>'use strict';

let util = require('util');

/**
 * This Controller is for building the response
 */
let FilePathBuilderService = function() {

    /**
     *
     * @param method
     * @param url
     * @param queryString
     * @returns {Array}
     * @private
     */
    function _generatePaths(method, url, queryString) {
        let urls = [];

        let request = url.split('?');
        let path = request[0];
        // TODO: Gestion des paramètres dans la recherche de fichiers
        let parameters = url[1].split('&');
        let allParts = path.split('/');

        // method.json
        {
            let url1 = allParts.join('/') + '/' + method + '\\.*';
            urls.push(url1);
        }

        // ../method_lastElement.json
        // ../../method_beforeLastElement_lastElement.json
        // etc.
        let partsCount = allParts.length;
        for(let p=1; p <= (partsCount-1); ++p) {
            let pathParts = [];
            let fileBodyName = [method];
            let fileExtensionName = '\\.*';
            for(let i=0; i<allParts.length; ++i) {
                if(i < allParts.length - (p)) {
                    pathParts.push(allParts[i]);
                } else {
                    fileBodyName.push(allParts[i]);
                }
            }
            let url = pathParts.join('/') + '/' + fileBodyName.join('_') + fileExtensionName;
            urls.push(url);
        }

        // ../@default/method.json
        // ../../@default/method_lastElement.json
        // ../../../@default/method_beforeLastElement_lastElement.json
        // etc.
        for(let p=1; p <= (partsCount-1); ++p) {
            let pathParts = [];
            let fileBodyName = [method];
            let fileExtensionName = '\\.*';
            for(let i=0; i<allParts.length; ++i) {
                if(i < allParts.length - (p)) {
                    pathParts.push(allParts[i]);
                }
                else if(i == allParts.length - (p)) {
                    pathParts.push('@default');
                }
                else {
                    fileBodyName.push(allParts[i]);
                }
            }
            let url = pathParts.join('/') + '/' + fileBodyName.join('_') + fileExtensionName;
            urls.push(url);
        }

        return urls;
    }

    return {
        generatePaths: _generatePaths
    }

}

module.exports = FilePathBuilderService;
<commit_msg>Ajout de commentaire sur pathbuilder<commit_after>'use strict';

let util = require('util');

/**
 * This Controller is for building the response
 */
let FilePathBuilderService = function() {

    /**
     *
     * @param method
     * @param url
     * @param queryString
     * @returns {Array}
     * @private
     */
    function _generatePaths(method, url, queryString) {

        let urls = [];

        // Remove the parameters for building paths (at the moment)
        let request = url.split('?');
        let path = request[0];

        // @TODO Use parameters to build more paths
        let parameters = request[1].split('&');

        // Let's split the path to work with it
        let allParts = path.split('/');

        // method.json
        {
            let url1 = allParts.join('/') + '/' + method + '\\.*';
            urls.push(url1);
        }

        // ../method_lastElement.json
        // ../../method_beforeLastElement_lastElement.json
        // etc.
        let partsCount = allParts.length;
        for(let p=1; p <= (partsCount-1); ++p) {
            let pathParts = [];
            let fileBodyName = [method];
            let fileExtensionName = '\\.*';
            for(let i=0; i<allParts.length; ++i) {
                if(i < allParts.length - (p)) {
                    pathParts.push(allParts[i]);
                } else {
                    fileBodyName.push(allParts[i]);
                }
            }
            let url = pathParts.join('/') + '/' + fileBodyName.join('_') + fileExtensionName;
            urls.push(url);
        }

        // ../@default/method.json
        // ../../@default/method_lastElement.json
        // ../../../@default/method_beforeLastElement_lastElement.json
        // etc.
        for(let p=1; p <= (partsCount-1); ++p) {
            let pathParts = [];
            let fileBodyName = [method];
            let fileExtensionName = '\\.*';
            for(let i=0; i<allParts.length; ++i) {
                if(i < allParts.length - (p)) {
                    pathParts.push(allParts[i]);
                }
                else if(i == allParts.length - (p)) {
                    pathParts.push('@default');
                }
                else {
                    fileBodyName.push(allParts[i]);
                }
            }
            let url = pathParts.join('/') + '/' + fileBodyName.join('_') + fileExtensionName;
            urls.push(url);
        }

        return urls;
    }

    return {
        generatePaths: _generatePaths
    }

}

module.exports = FilePathBuilderService;
<|endoftext|>


<commit_before>var fs = require('fs');
var betfair = require('./ca-betfair.js');
var utils = require('./ca-utils.js');
var csv = require('fast-csv')
var yaml_config = require('node-yaml-config');
var config = yaml_config.load(__dirname + '/config/betfair_config.yml');
var moment = require('moment');

var marketTimers = new Map();
var marketStartTimes = new Map();
var marketData = new Map();

var stream = fs.createReadStream(config.betfair.data_dir + '/data/' + generateDirectoryName() + '/markets.csv');
//var stream = fs.createReadStream(config.betfair.data_dir + '/data/' + '2016-8-7' + '/markets.csv');

function runApplication() {
  console.log('Running ' + new Date());
  betfair.login(setUpTimeouts);
}
// handle CTRL-C if want to quit application
// This will force a logoff
process.on('SIGINT', function() {
  //console.log('Got SIGINT');
  logout();

});
// logoff from betfair
function logout() {
    betfair.logout(quit);
}
function quit() {
  console.log('Finished ' + new Date());
  process.exit(0);
}

function setUpTimeouts() {
utils.writeToFileAddDay('matched.csv','course,marketName,distance,marketId,startTime,totalMatched');
var csvStream = csv
    .parse({headers : true})
    .on("data", function(data) {
        marketStartTimes.set(data.marketId,moment(data.marketStartTime));
        var marketInfo = data.course  + ',' + data.marketName + ',' + data.distance;
        marketData.set(data.marketId,marketInfo);
        setMarketTimeout(data.marketStartTime, data.marketId);
    })
    .on("end", function(){
         console.log("Timeouts setup");
    });
stream.pipe(csvStream);
}

function processMarket(market) {
  betfair.getMarketBook(market, handleData);
}

function handleData(data)   {
//console.log(data);
  var marketId = data[0].result[0].marketId;
  //utils.writeToFileJson('book-' + marketId + '.txt',data);
  var status = data[0].result[0].status;
  if(moment().isAfter(marketStartTimes.get(marketId))) {
    var message = marketData.get(marketId) + ',' + marketId + ',' + moment(marketStartTimes.get(marketId)).format() + ',' + data[0].result[0].totalMatched;
    utils.writeToFileAddDay('matched.csv',message)
    console.log('Closed ' + marketId)
    clearTimeout(marketTimers.get(marketId));
    marketStartTimes.delete(marketId);
    if(marketStartTimes.size == 0) {
        console.log('No markets left - Logging off');
        logout();
    }
  }
}

function generateDirectoryName() {
  var date = new Date();
  return date.getFullYear() + '-' + (date.getMonth() + 1)  + '-' + date.getDate();
}

function setMarketTimeout(marketStartTime,market) {
  console.log('Register ' +  market);
  var now = moment();
  var startTime = moment(marketStartTime).subtract(6,'minutes');
  var length = startTime.diff(moment());
  setTimeout(function(){ setMarketInterval(market) },length);
}

function setMarketInterval(market) {
  console.log('Active ' + market + " - " + marketStartTimes.get(market).format());
  var timer = setInterval( function(){ processMarket(market) },1000);
  marketTimers.set(market,timer);
}

runApplication()
<commit_msg>Update Report<commit_after>var fs = require('fs');
var betfair = require('./ca-betfair.js');
var utils = require('./ca-utils.js');
var csv = require('fast-csv')
var yaml_config = require('node-yaml-config');
var config = yaml_config.load(__dirname + '/config/betfair_config.yml');
var moment = require('moment');

var marketTimers = new Map();
var marketStartTimes = new Map();
var marketData = new Map();

var stream = fs.createReadStream(config.betfair.data_dir + '/data/' + generateDirectoryName() + '/markets.csv');
//var stream = fs.createReadStream(config.betfair.data_dir + '/data/' + '2016-8-7' + '/markets.csv');

function runApplication() {
  console.log('Running ' + new Date());
  betfair.login(setUpTimeouts);
}
// handle CTRL-C if want to quit application
// This will force a logoff
process.on('SIGINT', function() {
  //console.log('Got SIGINT');
  logout();

});
// logoff from betfair
function logout() {
    betfair.logout(quit);
}
function quit() {
  console.log('Finished ' + new Date());
  process.exit(0);
}

function setUpTimeouts() {
utils.writeToFileAddDay('matched.csv','course,marketName,distance,runners,marketId,startTime,totalMatched');
var csvStream = csv
    .parse({headers : true})
    .on("data", function(data) {
        marketStartTimes.set(data.marketId,moment(data.marketStartTime));
        var marketInfo = data.course  + ',' + data.marketName + ',' + data.distance + ',' + data.runners;
        marketData.set(data.marketId,marketInfo);
        setMarketTimeout(data.marketStartTime, data.marketId);
    })
    .on("end", function(){
         console.log("Timeouts setup");
    });
stream.pipe(csvStream);
}

function processMarket(market) {
  betfair.getMarketBook(market, handleData);
}

function handleData(data)   {
//console.log(data);
  var marketId = data[0].result[0].marketId;
  //utils.writeToFileJson('book-' + marketId + '.txt',data);
  var status = data[0].result[0].status;
  if(moment().isAfter(marketStartTimes.get(marketId))) {
    var message = marketData.get(marketId) + ',' + marketId + ',' + moment(marketStartTimes.get(marketId)).format() + ',' + data[0].result[0].totalMatched;
    utils.writeToFileAddDay('matched.csv',message)
    console.log('Closed ' + marketId)
    clearTimeout(marketTimers.get(marketId));
    marketStartTimes.delete(marketId);
    if(marketStartTimes.size == 0) {
        console.log('No markets left - Logging off');
        logout();
    }
  }
}

function generateDirectoryName() {
  var date = new Date();
  return date.getFullYear() + '-' + (date.getMonth() + 1)  + '-' + date.getDate();
}

function setMarketTimeout(marketStartTime,market) {
  console.log('Register ' +  market);
  var now = moment();
  var startTime = moment(marketStartTime).subtract(6,'minutes');
  var length = startTime.diff(moment());
  setTimeout(function(){ setMarketInterval(market) },length);
}

function setMarketInterval(market) {
  console.log('Active ' + market + " - " + marketStartTimes.get(market).format());
  var timer = setInterval( function(){ processMarket(market) },1000);
  marketTimers.set(market,timer);
}

runApplication()
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var fs          = require('fs');
var merge       = require('merge');
var mergeTrees  = require('broccoli-merge-trees');
var flatiron    = require('broccoli-flatiron');
var Funnel      = require('broccoli-funnel');
var SVGOptmizer = require('./svg-optimizer');

module.exports = {
  name: 'ember-inline-svg',

  included: function(app) {
    if (app.app) {
      app = app.app;
    }
    this.app = app;
  },

  options: function() {
    return merge(true, {}, {
      paths:   ['public'],
      optimize: { /* svgo defaults */ }
    }, this.app.options.svg || {});
  },

  svgPaths: function() {
    if (this.isDevelopingAddon()) {
      return ['tests/dummy/public'];
    }
    return this.options().paths;
  },

  optimizeSVGs: function(tree) {
    var config = this.options().optimize;
    if (!config) {
      return tree;
    }

    return new SVGOptmizer(tree, {svgoConfig: config});
  },

  treeForApp: function(tree) {
    var svgs = mergeTrees(this.svgPaths().filter(function(path) {
      return fs.existsSync(path);
    }));

    svgs = new Funnel(svgs, {
      include: [new RegExp(/\.svg$/)]
    });

    svgs = this.optimizeSVGs(svgs);

    svgs = flatiron(svgs, {
      outputFile: 'svgs.js',
      trimExtensions: true
    });

    return mergeTrees([tree, svgs]);
  }
};
<commit_msg>Dont need to call included first to be able to introspect options<commit_after>/* jshint node: true */
'use strict';

var fs          = require('fs');
var merge       = require('merge');
var mergeTrees  = require('broccoli-merge-trees');
var flatiron    = require('broccoli-flatiron');
var Funnel      = require('broccoli-funnel');
var SVGOptmizer = require('./svg-optimizer');

module.exports = {
  name: 'ember-inline-svg',

  included: function(app) {
    if (app.app) {
      app = app.app;
    }
    this.app = app;
  },

  options: function() {
    return merge(true, {}, {
      paths:   ['public'],
      optimize: { /* svgo defaults */ }
    }, (this.app && this.app.options && this.app.options.svg) || {});
  },

  svgPaths: function() {
    if (this.isDevelopingAddon()) {
      return ['tests/dummy/public'];
    }
    return this.options().paths;
  },

  optimizeSVGs: function(tree) {
    var config = this.options().optimize;
    if (!config) {
      return tree;
    }

    return new SVGOptmizer(tree, {svgoConfig: config});
  },

  treeForApp: function(tree) {
    var svgs = mergeTrees(this.svgPaths().filter(function(path) {
      return fs.existsSync(path);
    }));

    svgs = new Funnel(svgs, {
      include: [new RegExp(/\.svg$/)]
    });

    svgs = this.optimizeSVGs(svgs);

    svgs = flatiron(svgs, {
      outputFile: 'svgs.js',
      trimExtensions: true
    });

    return mergeTrees([tree, svgs]);
  }
};
<|endoftext|>


<commit_before>'use strict';

angular.module('classBrowserUHApp.class', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/class', {
        templateUrl: 'views/class/class.html',
        controller: 'ClassCtrl'
    });
}]).
controller('ClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    $scope.rowCollection = [];

    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("class");

    $scope.populateClasses = function(){
        $scope.isDataLoading = true;
        $scope.isError = false;
        $scope.hasNoResults = false;
        $scope.rowCollection = [];
        $scope.numberOfRows = 0;

        var apiURLs = buildApiUrlsFromModel($scope.subjectModel, $scope.creditHourModel, $scope.coreModel);

        console.log(apiURLs);

        _.each(apiURLs, function(apiURL) {
            $rootScope.httpService.getData(apiURL)
                .then(appendResults)
                .then(populateFields)
                .catch(onError)
                .then(finallyDo)
            }
        );
    };

    var buildApiUrlsFromModel = function(subject, creditHour, core) {
        var baseUrl = $scope.apiUrl + '/information?';
        var allParametersFromScope = [
            {
                model: subject,
                parameterToPluck: 'subject',
                apiParameter: 'department'
            },
            {
                model: creditHour,
                parameterToPluck: 'credit-hours',
                apiParameter: 'credit-hours'
            },
            {
                model: core,
                parameterToPluck: 'categoryNumber',
                apiParameter: 'core'
            }
        ];

        return generateApiURLsFromModel(allParametersFromScope, baseUrl);
    };

    var generateApiURLsFromModel = function(allParametersFromScope, baseUrl) {
        allParametersFromScope.forEach(function(part, index, arr) {
            var apiParameter = part.apiParameter;
            arr[index] = _.pluck(part.model, part.parameterToPluck);
            checkArrayAndExpandInPlace(arr[index], apiParameter);
        });

        var allAPIUrls = allParametersFromScope
            .filter($rootScope.cartesianProductService.nonEmpty)
            .reduce($rootScope.cartesianProductService.productAdd, [""]);

        return $rootScope.apiURLService.appendParametersAndReturnAPIUrls(allAPIUrls, baseUrl);
    };

    var checkArrayAndExpandInPlace = function(arrayValue, apiParameter) {
        if(!$rootScope.arrayService.isArrayUndefinedOrNull(arrayValue)) {
            $rootScope.apiURLService.appendParameterEqualsValueInPlace(arrayValue, apiParameter);
        }
    };

    var appendResults = function(result) {
        $scope.numberOfRows += result.numberOfRows;
        $scope.rowCollection = $scope.rowCollection.concat(result.result);
    };

    var generateMessage = function(model, type, objToPluck) {
        if(model == undefined || model.length == 0) {
            return "";
        }
        else {
            return " " + type + ": " + _.pluck(model, objToPluck).join(', ') + "
";
        }
    };

    var populateFields = function(){
        if($scope.rowCollection.length > 0) {
            $scope.showResults = true;
            $scope.hasNoResults = false;

            $scope.numberOfRowsMessage = "Retrieved " + $scope.numberOfRows + " class";
            $scope.numberOfRowsMessage += $scope.numberOfRows == 1 ? "." : "es.";

            if ([$scope.departmentModel, $scope.creditHourModel, $scope.coreModel].allParametersUndefinedOrNull()) {
                $scope.parametersMessage = "No parameters were chosen, so all classes have been retrieved.";
            }
            else {
                $scope.subjectMessage = generateMessage($scope.subjectModel, 'Subjects', 'subjectFullName');
                $scope.creditHoursMessage = generateMessage($scope.creditHourModel, 'Credit Hours', 'credit-hours');
                $scope.coreMessage = generateMessage($scope.coreModel, 'Core Categories', 'categoryName');
                $scope.parametersMessage = $scope.subjectMessage +
                    $scope.creditHoursMessage +
                    $scope.coreMessage;
            }
        }
    };

    var onError = function(err) {
        $scope.isError = true;
        $scope.errorMessage = "Unable to populate classes for the class directory. Please try again later.";
    };

    var finallyDo = function() {
        $scope.isDataLoading = false;
        if($scope.rowCollection.length == 0 && !$scope.isError) {
            $scope.hasNoResults = true;
            $scope.warningMessage = "There are no classes found with the categories you have specified. Please try again.";
        }
    };

    var deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.goBack = function() {
        console.log('Going back to class search page.');
        deleteModel('hasNoResults', 'isError', 'isDataLoading', 'showResults',
            'subjectMessage', 'creditHoursMessage', 'coreMessage', 'parametersMessage',
            'rowCollection');
    };

    $scope.clearForms = function() {
        deleteModel('subjectModel', 'creditHourModel', 'coreModel',
            'parametersMessage', 'rowCollection', 'hasNoResults', 'isError',
            'isDataLoading');
    };

}]);<commit_msg>Removed console.log statements.<commit_after>'use strict';

angular.module('classBrowserUHApp.class', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/class', {
        templateUrl: 'views/class/class.html',
        controller: 'ClassCtrl'
    });
}]).
controller('ClassCtrl', ['$scope', '$http', '$q', '$rootScope', '$parse', '$window', function ($scope, $http, $q, $rootScope, $parse, $window) {
    $scope.rowCollection = [];

    var setScopeVariableFromJSON = function(filePath, scopeVariable) {
        $rootScope.httpService.getData(filePath).then(function(result) {
            $parse(scopeVariable).assign($scope, result);
        });
    };

    var initializeAllJSONAndScopeNames = function(name) {
        $rootScope.httpService.getData('resources/allScopeVariables.json').then(function(result) {
            $scope.allJSONAndScopeNames = result[name];
            $scope.allJSONAndScopeNames.forEach(function(e) {
                setScopeVariableFromJSON(e.path, e.scopeName);
            });
        });
    };

    initializeAllJSONAndScopeNames("class");

    $scope.populateClasses = function(){
        $scope.isDataLoading = true;
        $scope.isError = false;
        $scope.hasNoResults = false;
        $scope.rowCollection = [];
        $scope.numberOfRows = 0;

        var apiURLs = buildApiUrlsFromModel($scope.subjectModel, $scope.creditHourModel, $scope.coreModel);

        _.each(apiURLs, function(apiURL) {
            $rootScope.httpService.getData(apiURL)
                .then(appendResults)
                .then(populateFields)
                .catch(onError)
                .then(finallyDo)
            }
        );
    };

    var buildApiUrlsFromModel = function(subject, creditHour, core) {
        var baseUrl = $scope.apiUrl + '/information?';
        var allParametersFromScope = [
            {
                model: subject,
                parameterToPluck: 'subject',
                apiParameter: 'department'
            },
            {
                model: creditHour,
                parameterToPluck: 'credit-hours',
                apiParameter: 'credit-hours'
            },
            {
                model: core,
                parameterToPluck: 'categoryNumber',
                apiParameter: 'core'
            }
        ];

        return generateApiURLsFromModel(allParametersFromScope, baseUrl);
    };

    var generateApiURLsFromModel = function(allParametersFromScope, baseUrl) {
        allParametersFromScope.forEach(function(part, index, arr) {
            var apiParameter = part.apiParameter;
            arr[index] = _.pluck(part.model, part.parameterToPluck);
            checkArrayAndExpandInPlace(arr[index], apiParameter);
        });

        var allAPIUrls = allParametersFromScope
            .filter($rootScope.cartesianProductService.nonEmpty)
            .reduce($rootScope.cartesianProductService.productAdd, [""]);

        return $rootScope.apiURLService.appendParametersAndReturnAPIUrls(allAPIUrls, baseUrl);
    };

    var checkArrayAndExpandInPlace = function(arrayValue, apiParameter) {
        if(!$rootScope.arrayService.isArrayUndefinedOrNull(arrayValue)) {
            $rootScope.apiURLService.appendParameterEqualsValueInPlace(arrayValue, apiParameter);
        }
    };

    var appendResults = function(result) {
        $scope.numberOfRows += result.numberOfRows;
        $scope.rowCollection = $scope.rowCollection.concat(result.result);
    };

    var generateMessage = function(model, type, objToPluck) {
        if(model == undefined || model.length == 0) {
            return "";
        }
        else {
            return " " + type + ": " + _.pluck(model, objToPluck).join(', ') + "
";
        }
    };

    var populateFields = function(){
        if($scope.rowCollection.length > 0) {
            $scope.showResults = true;
            $scope.hasNoResults = false;

            $scope.numberOfRowsMessage = "Retrieved " + $scope.numberOfRows + " class";
            $scope.numberOfRowsMessage += $scope.numberOfRows == 1 ? "." : "es.";

            if ([$scope.departmentModel, $scope.creditHourModel, $scope.coreModel].allParametersUndefinedOrNull()) {
                $scope.parametersMessage = "No parameters were chosen, so all classes have been retrieved.";
            }
            else {
                $scope.subjectMessage = generateMessage($scope.subjectModel, 'Subjects', 'subjectFullName');
                $scope.creditHoursMessage = generateMessage($scope.creditHourModel, 'Credit Hours', 'credit-hours');
                $scope.coreMessage = generateMessage($scope.coreModel, 'Core Categories', 'categoryName');
                $scope.parametersMessage = $scope.subjectMessage +
                    $scope.creditHoursMessage +
                    $scope.coreMessage;
            }
        }
    };

    var onError = function(err) {
        $scope.isError = true;
        $scope.errorMessage = "Unable to populate classes for the class directory. Please try again later.";
    };

    var finallyDo = function() {
        $scope.isDataLoading = false;
        if($scope.rowCollection.length == 0 && !$scope.isError) {
            $scope.hasNoResults = true;
            $scope.warningMessage = "There are no classes found with the categories you have specified. Please try again.";
        }
    };

    var deleteModel = function() {
        [].slice.call(arguments).forEach(function(arg) {
            delete $scope[arg];
        });
    };

    $scope.goBack = function() {
        deleteModel('hasNoResults', 'isError', 'isDataLoading', 'showResults',
            'subjectMessage', 'creditHoursMessage', 'coreMessage', 'parametersMessage',
            'rowCollection');
    };

    $scope.clearForms = function() {
        deleteModel('subjectModel', 'creditHourModel', 'coreModel',
            'parametersMessage', 'rowCollection', 'hasNoResults', 'isError',
            'isDataLoading');
    };

}]);<|endoftext|>