<commit_before>import React, {Component} from 'react';
import config from '../config';
import L from 'mapbox.js';

var Map = React.createClass({
    componentDidMount: function() {
        var token = config.MAPBOX_ACCESS_TOKEN;
        console.log('map component did mount');
        console.log('L', L);
        var map = L.map(this.refs.map)
            .setView([40, -74.50], 9);
        var tileLayer = L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
            attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
            maxZoom: 18,
            id: 'mapbox.streets',
            accessToken: token
        }).addTo(map);

    },

    render: function() {
        return (

        );
    }
});

export default Map;<commit_msg>init Mapbox map correctly, related to #2<commit_after>import React, {Component} from 'react';
import config from '../config';
import L from 'mapbox.js';

var Map = React.createClass({
    componentDidMount: function() {
        var token = config.MAPBOX_ACCESS_TOKEN;
        L.mapbox.accessToken = token;
        L.mapbox.map(this.refs.map, 'mapbox.streets');
    },

    render: function() {
        return (

        );
    }
});

export default Map;<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var Sparkline = require( './../lib' );
var toString = require( './../lib/tostring.js' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof toString, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function serializes a sparkline as a string by rendering a chart', function test( t ) {
	var context;
	var str;

	context = new Sparkline();
	context.render = render;

	str = toString.call( context );

	t.equal( str, '▁█▅▃▆▆▅', 'returns a rendered chart' );

	t.end();

	function render() {
		return '▁█▅▃▆▆▅';
	}
});
<commit_msg>Update `toString` tests<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var ctor = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof ctor, 'function', 'main export is a function' );
	t.end();
});

tape( 'the `toString` method serializes a sparkline as a string by rendering a sparkline', function test( t ) {
	var sparkline;
	var str;

	sparkline = ctor();
	sparkline._render = render; // eslint-disable-line no-underscore-dangle

	str = sparkline.toString();
	t.strictEqual( str, '▁█▅▃▆▆▅', 'returns expected value' );

	t.end();

	function render() {
		return '▁█▅▃▆▆▅';
	}
});
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014-2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program 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 License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { remote } from 'electron';
import * as metrics from '../constants/metrics';
import { Route, Switch } from 'react-router-dom';

const { Menu } = remote;

import bows from 'bows';

import config from '../../lib/config.js';

import carelink from '../../lib/core/carelink.js';
import device from '../../lib/core/device.js';
import localStore from '../../lib/core/localStore.js';

import actions from '../actions/';
const asyncActions = actions.async;
const syncActions = actions.sync;

import * as actionSources from '../constants/actionSources';
import { pages, urls, pagesMap } from '../constants/otherConstants';
import { checkVersion } from '../utils/drivers';
import debugMode from '../utils/debugMode';
import uploadDataPeriod from '../utils/uploadDataPeriod';

import MainPage from './MainPage';
import Login from '../components/Login';
import Loading from '../components/Loading';
import SettingsPage from './SettingsPage';
import ClinicUserSelectPage from './ClinicUserSelectPage';
import ClinicUserEditPage from './ClinicUserEditPage';
import NoUploadTargetsPage from './NoUploadTargetsPage';
import UpdatePlease from '../components/UpdatePlease';
import VersionCheckError from '../components/VersionCheckError';
import Footer from '../components/Footer';
import Header from '../components/Header';
import UpdateModal from '../components/UpdateModal';
import UpdateDriverModal from '../components/UpdateDriverModal';
import DeviceTimeModal from '../components/DeviceTimeModal';
import AdHocModal from '../components/AdHocModal';

import styles from '../../styles/components/App.module.less';

const serverdata = {
  Local: {
    API_URL: 'http://localhost:8009',
    UPLOAD_URL: 'http://localhost:9122',
    DATA_URL: 'http://localhost:9220',
    BLIP_URL: 'http://localhost:3000'
  },
  Development: {
    API_URL: 'https://dev-api.tidepool.org',
    UPLOAD_URL: 'https://dev-uploads.tidepool.org',
    DATA_URL: 'https://dev-api.tidepool.org/dataservices',
    BLIP_URL: 'https://dev-app.tidepool.org'
  },
  Staging: {
    API_URL: 'https://stg-api.tidepool.org',
    UPLOAD_URL: 'https://stg-uploads.tidepool.org',
    DATA_URL: 'https://stg-api.tidepool.org/dataservices',
    BLIP_URL: 'https://stg-app.tidepool.org'
  },
  Integration: {
    API_URL: 'https://int-api.tidepool.org',
    UPLOAD_URL: 'https://int-uploads.tidepool.org',
    DATA_URL: 'https://int-api.tidepool.org/dataservices',
    BLIP_URL: 'https://int-app.tidepool.org'
  },
  Production: {
    API_URL: 'https://api.tidepool.org',
    UPLOAD_URL: 'https://uploads.tidepool.org',
    DATA_URL: 'https://api.tidepool.org/dataservices',
    BLIP_URL: 'https://app.tidepool.org'
  }
};

export class App extends Component {
  static propTypes = {
    route: PropTypes.shape({
      api: PropTypes.func.isRequired
    }).isRequired
  };

  constructor(props) {
    super(props);
    this.log = bows('App');
    const initial_server = _.findKey(serverdata, (key) => key.API_URL === config.API_URL);
    this.state = {
      server: initial_server
    };
  }

  componentWillMount(){
    checkVersion(this.props.dispatch);
    let api = this.props.api;
    this.props.async.doAppInit(
      _.assign({ environment: this.state.server }, config), {
      api: api,
      carelink,
      device,
      localStore,
      log: this.log
    });

    window.addEventListener('contextmenu', this.handleContextMenu, false);
  }

  setServer = info => {
    console.log('will use', info.label, 'server');
    var serverinfo = serverdata[info.label];
    serverinfo.environment = info.label;
    this.props.api.setHosts(serverinfo);
    this.setState({server: info.label});
  };

  setDataPeriod = info => {
    console.log('fetch device data for', info.label);
    uploadDataPeriod.setPeriod(info.id);
  };

  render() {
    return (

        <Switch>
          <Route exact strict path="/" component={Loading} />
          <Route path="/login" component={Login}/>
          <Route path="/main" component={MainPage}/>
          <Route path="/settings" component={SettingsPage}/>
          <Route path="/clinic_user_select" component={ClinicUserSelectPage}/>
          <Route path="/clinic_user_edit" component={ClinicUserEditPage}/>
          <Route path="/no_upload_targets" component={NoUploadTargetsPage}/>
        </Switch>

        {/* VersionCheck as overlay */}
        {this.renderVersionCheck()}
        <UpdateModal />
        <UpdateDriverModal />
        <DeviceTimeModal />
        <AdHocModal />

    );
  }

  handleContextMenu = e => {
    e.preventDefault();
    const { clientX, clientY } = e;
    let template = [];
    if (process.env.NODE_ENV === 'development') {
      template.push({
        label: 'Inspect element',
        click() {
          remote.getCurrentWindow().inspectElement(clientX, clientY);
        }
      });
      template.push({
        type: 'separator'
      });
    }
    if (this.props.location.pathname === pagesMap.LOGIN) {
      template.push({
        label: 'Change server',
        submenu: [
          {
            label: 'Local',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Local'
          },
          {
            label: 'Development',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Development'
          },
          {
            label: 'Staging',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Staging'
          },
          {
            label: 'Integration',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Integration'
          },
          {
            label: 'Production',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Production'
          }
        ]
      });
      template.push({
        label: 'Upload Data',
        submenu: [
          {
            label: 'Everything',
            id: uploadDataPeriod.PERIODS.ALL,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period === uploadDataPeriod.PERIODS.ALL
          },
          {
            label: 'New since last upload',
            id: uploadDataPeriod.PERIODS.DELTA,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period === uploadDataPeriod.PERIODS.DELTA
          },
          {
            label: 'Last 4 weeks',
            id: uploadDataPeriod.PERIODS.FOUR_WEEKS,
            visible: debugMode.isDebug,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period ===
              uploadDataPeriod.PERIODS.FOUR_WEEKS
          }
        ]
      });
      template.push({
        label: 'Toggle Debug Mode',
        type: 'checkbox',
        checked: debugMode.isDebug,
        click() {
          debugMode.setDebug(!debugMode.isDebug);
        }
      });
    }
    const menu = Menu.buildFromTemplate(template);
    menu.popup(remote.getCurrentWindow());
  };

  handleDismissDropdown = () => {
    const { dropdown } = this.props;
    // only toggle the dropdown by clicking elsewhere if it's open
    if (dropdown === true) {
      this.props.sync.toggleDropdown(dropdown);
    }
  };

  renderVersionCheck() {
    const { readyToRenderVersionCheckOverlay, unsupported } = this.props;
    if (readyToRenderVersionCheckOverlay === false || unsupported === false) {
      return null;
    }
    if (unsupported instanceof Error) {
      return (
        <VersionCheckError errorMessage={unsupported.message || 'Unknown error'}/>
      );
    }
    if (unsupported === true) {
      return (
        <UpdatePlease knowledgeBaseLink={urls.HOW_TO_UPDATE_KB_ARTICLE} />
      );
    }
  }
}

App.propTypes = {};

export default connect(
  (state, ownProps) => {
    return {
      // plain state
      dropdown: state.dropdown,
      unsupported: state.unsupported,
      // derived state
      readyToRenderVersionCheckOverlay: (
        !state.working.initializingApp && !state.working.checkingVersion
      )
    };
  },
  (dispatch) => {
    return {
      async: bindActionCreators(asyncActions, dispatch),
      sync: bindActionCreators(syncActions, dispatch),
      dispatch: dispatch
    };
  }
)(App);
<commit_msg>Add `QA1` to list of environments<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014-2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program 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 License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { remote } from 'electron';
import * as metrics from '../constants/metrics';
import { Route, Switch } from 'react-router-dom';

const { Menu } = remote;

import bows from 'bows';

import config from '../../lib/config.js';

import carelink from '../../lib/core/carelink.js';
import device from '../../lib/core/device.js';
import localStore from '../../lib/core/localStore.js';

import actions from '../actions/';
const asyncActions = actions.async;
const syncActions = actions.sync;

import * as actionSources from '../constants/actionSources';
import { pages, urls, pagesMap } from '../constants/otherConstants';
import { checkVersion } from '../utils/drivers';
import debugMode from '../utils/debugMode';
import uploadDataPeriod from '../utils/uploadDataPeriod';

import MainPage from './MainPage';
import Login from '../components/Login';
import Loading from '../components/Loading';
import SettingsPage from './SettingsPage';
import ClinicUserSelectPage from './ClinicUserSelectPage';
import ClinicUserEditPage from './ClinicUserEditPage';
import NoUploadTargetsPage from './NoUploadTargetsPage';
import UpdatePlease from '../components/UpdatePlease';
import VersionCheckError from '../components/VersionCheckError';
import Footer from '../components/Footer';
import Header from '../components/Header';
import UpdateModal from '../components/UpdateModal';
import UpdateDriverModal from '../components/UpdateDriverModal';
import DeviceTimeModal from '../components/DeviceTimeModal';
import AdHocModal from '../components/AdHocModal';

import styles from '../../styles/components/App.module.less';

const serverdata = {
  Local: {
    API_URL: 'http://localhost:8009',
    UPLOAD_URL: 'http://localhost:9122',
    DATA_URL: 'http://localhost:9220',
    BLIP_URL: 'http://localhost:3000'
  },
  Development: {
    API_URL: 'https://dev-api.tidepool.org',
    UPLOAD_URL: 'https://dev-uploads.tidepool.org',
    DATA_URL: 'https://dev-api.tidepool.org/dataservices',
    BLIP_URL: 'https://dev-app.tidepool.org'
  },
  Staging: {
    API_URL: 'https://stg-api.tidepool.org',
    UPLOAD_URL: 'https://stg-uploads.tidepool.org',
    DATA_URL: 'https://stg-api.tidepool.org/dataservices',
    BLIP_URL: 'https://stg-app.tidepool.org'
  },
  QA1: {
    API_URL: 'https://qa1-api.tidepool.org',
    UPLOAD_URL: 'https://qa1-uploads.tidepool.org',
    DATA_URL: 'https://qa1-api.tidepool.org/dataservices',
    BLIP_URL: 'https://qa1-app.tidepool.org'
  },
  Integration: {
    API_URL: 'https://int-api.tidepool.org',
    UPLOAD_URL: 'https://int-uploads.tidepool.org',
    DATA_URL: 'https://int-api.tidepool.org/dataservices',
    BLIP_URL: 'https://int-app.tidepool.org'
  },
  Production: {
    API_URL: 'https://api.tidepool.org',
    UPLOAD_URL: 'https://uploads.tidepool.org',
    DATA_URL: 'https://api.tidepool.org/dataservices',
    BLIP_URL: 'https://app.tidepool.org'
  }
};

export class App extends Component {
  static propTypes = {
    route: PropTypes.shape({
      api: PropTypes.func.isRequired
    }).isRequired
  };

  constructor(props) {
    super(props);
    this.log = bows('App');
    const initial_server = _.findKey(serverdata, (key) => key.API_URL === config.API_URL);
    this.state = {
      server: initial_server
    };
  }

  componentWillMount(){
    checkVersion(this.props.dispatch);
    let api = this.props.api;
    this.props.async.doAppInit(
      _.assign({ environment: this.state.server }, config), {
      api: api,
      carelink,
      device,
      localStore,
      log: this.log
    });

    window.addEventListener('contextmenu', this.handleContextMenu, false);
  }

  setServer = info => {
    console.log('will use', info.label, 'server');
    var serverinfo = serverdata[info.label];
    serverinfo.environment = info.label;
    this.props.api.setHosts(serverinfo);
    this.setState({server: info.label});
  };

  setDataPeriod = info => {
    console.log('fetch device data for', info.label);
    uploadDataPeriod.setPeriod(info.id);
  };

  render() {
    return (

        <Switch>
          <Route exact strict path="/" component={Loading} />
          <Route path="/login" component={Login}/>
          <Route path="/main" component={MainPage}/>
          <Route path="/settings" component={SettingsPage}/>
          <Route path="/clinic_user_select" component={ClinicUserSelectPage}/>
          <Route path="/clinic_user_edit" component={ClinicUserEditPage}/>
          <Route path="/no_upload_targets" component={NoUploadTargetsPage}/>
        </Switch>

        {/* VersionCheck as overlay */}
        {this.renderVersionCheck()}
        <UpdateModal />
        <UpdateDriverModal />
        <DeviceTimeModal />
        <AdHocModal />

    );
  }

  handleContextMenu = e => {
    e.preventDefault();
    const { clientX, clientY } = e;
    let template = [];
    if (process.env.NODE_ENV === 'development') {
      template.push({
        label: 'Inspect element',
        click() {
          remote.getCurrentWindow().inspectElement(clientX, clientY);
        }
      });
      template.push({
        type: 'separator'
      });
    }
    if (this.props.location.pathname === pagesMap.LOGIN) {
      template.push({
        label: 'Change server',
        submenu: [
          {
            label: 'Local',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Local'
          },
          {
            label: 'Development',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Development'
          },
          {
            label: 'Staging',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Staging'
          },
          {
            label: 'QA1',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'QA1'
          },
          {
            label: 'Integration',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Integration'
          },
          {
            label: 'Production',
            click: this.setServer,
            type: 'radio',
            checked: this.state.server === 'Production'
          }
        ]
      });
      template.push({
        label: 'Upload Data',
        submenu: [
          {
            label: 'Everything',
            id: uploadDataPeriod.PERIODS.ALL,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period === uploadDataPeriod.PERIODS.ALL
          },
          {
            label: 'New since last upload',
            id: uploadDataPeriod.PERIODS.DELTA,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period === uploadDataPeriod.PERIODS.DELTA
          },
          {
            label: 'Last 4 weeks',
            id: uploadDataPeriod.PERIODS.FOUR_WEEKS,
            visible: debugMode.isDebug,
            click: this.setDataPeriod,
            type: 'radio',
            checked: uploadDataPeriod.period ===
              uploadDataPeriod.PERIODS.FOUR_WEEKS
          }
        ]
      });
      template.push({
        label: 'Toggle Debug Mode',
        type: 'checkbox',
        checked: debugMode.isDebug,
        click() {
          debugMode.setDebug(!debugMode.isDebug);
        }
      });
    }
    const menu = Menu.buildFromTemplate(template);
    menu.popup(remote.getCurrentWindow());
  };

  handleDismissDropdown = () => {
    const { dropdown } = this.props;
    // only toggle the dropdown by clicking elsewhere if it's open
    if (dropdown === true) {
      this.props.sync.toggleDropdown(dropdown);
    }
  };

  renderVersionCheck() {
    const { readyToRenderVersionCheckOverlay, unsupported } = this.props;
    if (readyToRenderVersionCheckOverlay === false || unsupported === false) {
      return null;
    }
    if (unsupported instanceof Error) {
      return (
        <VersionCheckError errorMessage={unsupported.message || 'Unknown error'}/>
      );
    }
    if (unsupported === true) {
      return (
        <UpdatePlease knowledgeBaseLink={urls.HOW_TO_UPDATE_KB_ARTICLE} />
      );
    }
  }
}

App.propTypes = {};

export default connect(
  (state, ownProps) => {
    return {
      // plain state
      dropdown: state.dropdown,
      unsupported: state.unsupported,
      // derived state
      readyToRenderVersionCheckOverlay: (
        !state.working.initializingApp && !state.working.checkingVersion
      )
    };
  },
  (dispatch) => {
    return {
      async: bindActionCreators(asyncActions, dispatch),
      sync: bindActionCreators(syncActions, dispatch),
      dispatch: dispatch
    };
  }
)(App);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { Strings } from '../constants';

class App extends Component {

  static propTypes = {
    children: PropTypes.any.isRequired,
  }

  render () {
    return (

        {this.props.children}

    );
  }
}

function mapStateToProps (/* state */) {
  return {};
}

export default connect(mapStateToProps)(App);
<commit_msg>Remove unused import<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';

class App extends Component {

  static propTypes = {
    children: PropTypes.any.isRequired,
  }

  render () {
    return (

        {this.props.children}

    );
  }
}

function mapStateToProps (/* state */) {
  return {};
}

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


<commit_before>require('babel-polyfill');

jest.unmock('./../products.controller.js');

const ProductsController = require('./../products.controller.js');
const ProductModelWrapper = require('./../product.model.wrapper');
const _ = require('lodash');

let instance;

describe('ProductsController', () => {
    beforeEach(() => {
        instance = new ProductsController();
        instance._sendRes = jest.fn();
    });

    it('should initialize with null res', () => {
        expect(instance.res).toBe(null);
    });

    pit('should resolve get flow', async () => {
        let expectData = [{a: 1}, {a: 2}];

        ProductModelWrapper.query = jest.fn(() => {
            return Promise.resolve(expectData);
        });

        await instance.get();

        expect(ProductModelWrapper.query).toBeCalledWith('find');
        expect(instance._sendRes).toBeCalledWith(expectData);
    });

    pit('should throw exception', async () => {
        let expectData = {};

        ProductModelWrapper.query = jest.fn(() => {
            return Promise.reject(expectData);
        });

        await instance.get();

        expect(ProductModelWrapper.query).toBeCalled();
        expect(instance._sendRes.mock.calls.length).toBe(0);
    });

    it('should convert data object of arrays to object with 0 indexed props', () => {
        let data = {
            ignoredProp: [],
            title: ['title'],
            prop: [1, 2, 3],
            prop2: [1, 2, 3]
        };

        expect(instance._prepareData(data)).toEqual({
            title: 'title',
            link: `/admin/start/products/title`,
            prop: 1,
            prop2: 1
        });
    });

    pit('should resolve post flow', async () => {
        instance._parseForm = jest.fn(() => {
            return Promise.resolve();
        });

        instance._uploadStatic = jest.fn(() => {
            return Promise.resolve();
        });

        instance._saveProduct = jest.fn(() => {
            return Promise.resolve();
        });

        await instance.post();

        await expect(instance._parseForm).toBeCalled();
        await expect(instance._uploadStatic).toBeCalled();
        await expect(instance._saveProduct).toBeCalled();

        expect(instance._sendRes.mock.calls.length).toBe(0);
    });

    pit('should resolve put flow', async () => {
        instance._parseForm = jest.fn(() => {
            return Promise.resolve();
        });

        instance._uploadStatic = jest.fn(() => {
            return Promise.resolve();
        });

        instance._updateProduct = jest.fn(() => {
            return Promise.resolve();
        });

        await instance.put();

        await expect(instance._parseForm).toBeCalled();
        await expect(instance._uploadStatic).toBeCalled();
        await expect(instance._updateProduct).toBeCalled();

        expect(instance._sendRes.mock.calls.length).toBe(0);
    });
});<commit_msg>Added few tests<commit_after>require('babel-polyfill');

jest.unmock('./../products.controller.js');

const ProductsController = require('./../products.controller.js');
const ProductModelWrapper = require('./../product.model.wrapper');
const cloudinary = require('./../../../helpers/cloudinary/cloudinary');
const _ = require('lodash');

let instance;

describe('ProductsController', () => {
    beforeEach(() => {
        instance = new ProductsController();
        instance._sendRes = jest.fn();
    });

    it('should initialize with null res', () => {
        expect(instance.res).toBe(null);
    });

    pit('should resolve get flow', async () => {
        let expectData = [{a: 1}, {a: 2}];

        ProductModelWrapper.query = jest.fn(() => {
            return Promise.resolve(expectData);
        });

        await instance.get();

        expect(ProductModelWrapper.query).toBeCalledWith('find');
        expect(instance._sendRes).toBeCalledWith(expectData);
    });

    pit('should throw exception', async () => {
        let expectData = {};

        ProductModelWrapper.query = jest.fn(() => {
            return Promise.reject(expectData);
        });

        await instance.get();

        expect(ProductModelWrapper.query).toBeCalled();
        expect(instance._sendRes.mock.calls.length).toBe(0);
    });

    it('should convert data object of arrays to object with 0 indexed props', () => {
        let mockData = {
            ignoredProp: [],
            title: ['title'],
            prop: [1, 2, 3],
            prop2: [1, 2, 3]
        };

        expect(instance._prepareData(mockData)).toEqual({
            title: 'title',
            link: `/admin/start/products/title`,
            prop: 1,
            prop2: 1
        });
    });

    pit('should resolve post flow', async () => {
        instance._parseForm = jest.fn(() => {
            return Promise.resolve();
        });

        instance._uploadStatic = jest.fn(() => {
            return Promise.resolve();
        });

        instance._saveProduct = jest.fn(() => {
            return Promise.resolve();
        });

        await instance.post();

        await expect(instance._parseForm).toBeCalled();
        await expect(instance._uploadStatic).toBeCalled();
        await expect(instance._saveProduct).toBeCalled();

        expect(instance._sendRes.mock.calls.length).toBe(0);
    });

    pit('should resolve put flow', async () => {
        instance._parseForm = jest.fn(() => {
            return Promise.resolve();
        });

        instance._uploadStatic = jest.fn(() => {
            return Promise.resolve();
        });

        instance._updateProduct = jest.fn(() => {
            return Promise.resolve();
        });

        await instance.put();

        await expect(instance._parseForm).toBeCalled();
        await expect(instance._uploadStatic).toBeCalled();
        await expect(instance._updateProduct).toBeCalled();

        expect(instance._sendRes.mock.calls.length).toBe(0);
    });

    pit('should upload file to cloudinary', async () => {
        let mockName = 'name';
        let mockFormData = {};
        let mockFile = {size: 1, path: 'some/path'};

        mockFormData[mockName] = [];

        cloudinary.upload = jest.fn(() => {
            return Promise.resolve();
        });

        await instance._uploadSingleFile(mockFormData, mockName, mockFile);

        expect(cloudinary.upload).toBeCalledWith('some/path');
    });

    pit('should destroy file from cloudinary', async () => {
        let mockProduct = {
            image: {
                public_id: 'id'
            }
        };

        cloudinary.delete = jest.fn(() => {
            return Promise.resolve();
        });

        await instance._destroyFile(mockProduct);

        expect(cloudinary.delete).toBeCalledWith('id');
    });

    it('should upload 3 files', () => {
        let mockName = 'name';
        let mockData = {
            files: {}
        };
        let mockFormData = {};

        mockData.files[mockName] = [1, 2, 3];

        instance._uploadSingleFile = jest.fn(() => {
            return Promise.resolve();
        });

        instance._uploadFiles(mockData, mockName, mockFormData);

        expect(instance._uploadSingleFile.mock.calls.length).toBe(3);
    });
});<|endoftext|>


<commit_before>/**
 * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend
 * events, displaying the in-progress composition to the UI and forwarding the final composition
 * to the handler.
 * @param {HTMLTextAreaElement} textarea The textarea that xterm uses for input.
 * @param {HTMLElement} compositionView The element to display the in-progress composition in.
 * @param {Terminal} terminal The Terminal to forward the finished composition to.
 */
function CompositionHelper(textarea, compositionView, terminal) {
  this.textarea = textarea;
  this.compositionView = compositionView;
  this.terminal = terminal;

  // Whether input composition is currently happening, eg. via a mobile keyboard, speech input
  // or IME. This variable determines whether the compositionText should be displayed on the UI.
  this.isComposing = false;

  // The input currently being composed, eg. via a mobile keyboard, speech input or IME.
  this.compositionText = null;

  // The position within the input textarea's value of the current composition.
  this.compositionPosition = { start: null, end: null };

  // Whether a composition is in the process of being sent, setting this to false will cancel
  // any in-progress composition.
  this.isSendingComposition = false;
}

/**
 * Handles the compositionstart event, activating the composition view.
 */
CompositionHelper.prototype.compositionstart = function() {
  this.isComposing = true;
  this.compositionPosition.start = this.textarea.value.length;
  this.compositionView.textContent = '';
  this.compositionView.classList.add('active');
};

/**
 * Handles the compositionupdate event, updating the composition view.
 * @param {CompositionEvent} ev The event.
 */
CompositionHelper.prototype.compositionupdate = function(ev) {
  this.compositionView.textContent = ev.data;
  this.updateCompositionElements();
  var self = this;
  setTimeout(function() {
    self.compositionPosition.end = self.textarea.value.length;
  }, 0);
};

/**
 * Handles the compositionend event, hiding the composition view and sending the composition to
 * the handler.
 */
CompositionHelper.prototype.compositionend = function() {
  this.finalizeComposition(true);
};

/**
 * Handles the keydown event, routing any necessary events to the CompositionHelper functions.
 * @return Whether the Terminal should continue processing the keydown event.
 */
CompositionHelper.prototype.keydown = function(ev) {
  if (this.isComposing || this.isSendingComposition) {
    if (ev.keyCode === 229) {
      // Continue composing if the keyCode is the "composition character"
      return false;
    } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {
      // Continue composing if the keyCode is a modifier key
      return false;
    } else {
      // Finish composition immediately. This is mainly here for the case where enter is
      // pressed and the handler needs to be triggered before the command is executed.
      this.finalizeComposition(false);
    }
  }

  if (ev.keyCode === 229) {
    // If the "composition character" is used but gets to this point it means a non-composition
    // character (eg. numbers and punctuation) was pressed when the IME was active.
    this.handleAnyTextareaChanges();
    return false;
  }

  return true;
};

/**
 * Finalizes the composition, resuming regular input actions. This is called when a composition
 * is ending.
 * @param {boolean} waitForPropogation Whether to wait for events to propogate before sending
 *   the input. This should be false if a non-composition keystroke is entered before the
 *   compositionend event is triggered, such as enter, so that the composition is send before
 *   the command is executed.
 */
CompositionHelper.prototype.finalizeComposition = function(waitForPropogation) {
  this.compositionView.classList.remove('active');
  this.isComposing = false;
  this.clearTextareaPosition();

  if (!waitForPropogation) {
    // Cancel any delayed composition send requests and send the input immediately.
    this.isSendingComposition = false;
    var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);
    this.terminal.handler(input);
  } else {
    // Make a deep copy of the composition position here as a new compositionstart event may
    // fire before the setTimeout executes.
    var currentCompositionPosition = {
      start: this.compositionPosition.start,
      end: this.compositionPosition.end,
    }

    // Since composition* events happen before the changes take place in the textarea on most
    // browsers, use a setTimeout with 0ms time to allow the native compositionend event to
    // complete. This ensures the correct character is retrieved, this solution was used
    // because:
    // - The compositionend event's data property is unreliable, at least on Chromium
    // - The last compositionupdate event's data property does not always accurately describe
    //   the character, a counter example being Korean where an ending consonsant can move to
    //   the following character if the following input is a vowel.
    var self = this;
    this.isSendingComposition = true;
    setTimeout(function () {
      // Ensure that the input has not already been sent
      if (self.isSendingComposition) {
        self.isSendingComposition = false;
        var input;
        if (self.isComposing) {
          // Use the end position to get the string if a new composition has started.
          input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);
        } else {
          // Don't use the end position here in order to pick up any characters after the
          // composition has finished, for example when typing a non-composition character
          // (eg. 2) after a composition character.
          input = self.textarea.value.substring(currentCompositionPosition.start);
        }
        self.terminal.handler(input);
      }
    }, 0);
  }
};

/**
 * Apply any changes made to the textarea after the current event chain is allowed to complete.
 * This should be called when not currently composing but a keydown event with the "composition
 * character" (229) is triggered, in order to allow non-composition text to be entered when an
 * IME is active.
 */
CompositionHelper.prototype.handleAnyTextareaChanges = function() {
  var oldValue = this.textarea.value;
  var self = this;
  setTimeout(function() {
    // Ignore if a composition has started since the timeout
    if (!self.isComposing) {
      var newValue = self.textarea.value;
      var diff = newValue.replace(oldValue, '');
      if (diff.length > 0) {
        self.terminal.handler(diff);
      }
    }
  }, 0);
};

/**
 * Positions the composition view on top of the cursor and the textarea just below it (so the
 * IME helper dialog is positioned correctly).
 */
CompositionHelper.prototype.updateCompositionElements = function(dontRecurse) {
  if (!this.isComposing) {
    return;
  }
  var cursor = this.terminal.element.querySelector('.terminal-cursor');
  if (cursor) {
    this.compositionView.style.left = cursor.offsetLeft + 'px';
    this.compositionView.style.top = cursor.offsetTop + 'px';
    var compositionViewBounds = this.compositionView.getBoundingClientRect();
    this.textarea.style.left = cursor.offsetLeft + compositionViewBounds.width + 'px';
    this.textarea.style.top = (cursor.offsetTop + cursor.offsetHeight) + 'px';
  }
  if (!dontRecurse) {
    setTimeout(this.updateCompositionElements.bind(this, true), 0);
  }
};

/**
 * Clears the textarea's position so that the cursor does not blink on IE.
 * @private
 */
CompositionHelper.prototype.clearTextareaPosition = function() {
  this.textarea.style.left = '';
  this.textarea.style.top = '';
};

export { CompositionHelper };
<commit_msg>Add copyright line<commit_after>/**
 * xterm.js: xterm, in the browser
 * Copyright (c) 2016, SourceLair Limited <www.sourcelair.com> (MIT License)
 */

/**
 * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend
 * events, displaying the in-progress composition to the UI and forwarding the final composition
 * to the handler.
 * @param {HTMLTextAreaElement} textarea The textarea that xterm uses for input.
 * @param {HTMLElement} compositionView The element to display the in-progress composition in.
 * @param {Terminal} terminal The Terminal to forward the finished composition to.
 */
function CompositionHelper(textarea, compositionView, terminal) {
  this.textarea = textarea;
  this.compositionView = compositionView;
  this.terminal = terminal;

  // Whether input composition is currently happening, eg. via a mobile keyboard, speech input
  // or IME. This variable determines whether the compositionText should be displayed on the UI.
  this.isComposing = false;

  // The input currently being composed, eg. via a mobile keyboard, speech input or IME.
  this.compositionText = null;

  // The position within the input textarea's value of the current composition.
  this.compositionPosition = { start: null, end: null };

  // Whether a composition is in the process of being sent, setting this to false will cancel
  // any in-progress composition.
  this.isSendingComposition = false;
}

/**
 * Handles the compositionstart event, activating the composition view.
 */
CompositionHelper.prototype.compositionstart = function() {
  this.isComposing = true;
  this.compositionPosition.start = this.textarea.value.length;
  this.compositionView.textContent = '';
  this.compositionView.classList.add('active');
};

/**
 * Handles the compositionupdate event, updating the composition view.
 * @param {CompositionEvent} ev The event.
 */
CompositionHelper.prototype.compositionupdate = function(ev) {
  this.compositionView.textContent = ev.data;
  this.updateCompositionElements();
  var self = this;
  setTimeout(function() {
    self.compositionPosition.end = self.textarea.value.length;
  }, 0);
};

/**
 * Handles the compositionend event, hiding the composition view and sending the composition to
 * the handler.
 */
CompositionHelper.prototype.compositionend = function() {
  this.finalizeComposition(true);
};

/**
 * Handles the keydown event, routing any necessary events to the CompositionHelper functions.
 * @return Whether the Terminal should continue processing the keydown event.
 */
CompositionHelper.prototype.keydown = function(ev) {
  if (this.isComposing || this.isSendingComposition) {
    if (ev.keyCode === 229) {
      // Continue composing if the keyCode is the "composition character"
      return false;
    } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {
      // Continue composing if the keyCode is a modifier key
      return false;
    } else {
      // Finish composition immediately. This is mainly here for the case where enter is
      // pressed and the handler needs to be triggered before the command is executed.
      this.finalizeComposition(false);
    }
  }

  if (ev.keyCode === 229) {
    // If the "composition character" is used but gets to this point it means a non-composition
    // character (eg. numbers and punctuation) was pressed when the IME was active.
    this.handleAnyTextareaChanges();
    return false;
  }

  return true;
};

/**
 * Finalizes the composition, resuming regular input actions. This is called when a composition
 * is ending.
 * @param {boolean} waitForPropogation Whether to wait for events to propogate before sending
 *   the input. This should be false if a non-composition keystroke is entered before the
 *   compositionend event is triggered, such as enter, so that the composition is send before
 *   the command is executed.
 */
CompositionHelper.prototype.finalizeComposition = function(waitForPropogation) {
  this.compositionView.classList.remove('active');
  this.isComposing = false;
  this.clearTextareaPosition();

  if (!waitForPropogation) {
    // Cancel any delayed composition send requests and send the input immediately.
    this.isSendingComposition = false;
    var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);
    this.terminal.handler(input);
  } else {
    // Make a deep copy of the composition position here as a new compositionstart event may
    // fire before the setTimeout executes.
    var currentCompositionPosition = {
      start: this.compositionPosition.start,
      end: this.compositionPosition.end,
    }

    // Since composition* events happen before the changes take place in the textarea on most
    // browsers, use a setTimeout with 0ms time to allow the native compositionend event to
    // complete. This ensures the correct character is retrieved, this solution was used
    // because:
    // - The compositionend event's data property is unreliable, at least on Chromium
    // - The last compositionupdate event's data property does not always accurately describe
    //   the character, a counter example being Korean where an ending consonsant can move to
    //   the following character if the following input is a vowel.
    var self = this;
    this.isSendingComposition = true;
    setTimeout(function () {
      // Ensure that the input has not already been sent
      if (self.isSendingComposition) {
        self.isSendingComposition = false;
        var input;
        if (self.isComposing) {
          // Use the end position to get the string if a new composition has started.
          input = self.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);
        } else {
          // Don't use the end position here in order to pick up any characters after the
          // composition has finished, for example when typing a non-composition character
          // (eg. 2) after a composition character.
          input = self.textarea.value.substring(currentCompositionPosition.start);
        }
        self.terminal.handler(input);
      }
    }, 0);
  }
};

/**
 * Apply any changes made to the textarea after the current event chain is allowed to complete.
 * This should be called when not currently composing but a keydown event with the "composition
 * character" (229) is triggered, in order to allow non-composition text to be entered when an
 * IME is active.
 */
CompositionHelper.prototype.handleAnyTextareaChanges = function() {
  var oldValue = this.textarea.value;
  var self = this;
  setTimeout(function() {
    // Ignore if a composition has started since the timeout
    if (!self.isComposing) {
      var newValue = self.textarea.value;
      var diff = newValue.replace(oldValue, '');
      if (diff.length > 0) {
        self.terminal.handler(diff);
      }
    }
  }, 0);
};

/**
 * Positions the composition view on top of the cursor and the textarea just below it (so the
 * IME helper dialog is positioned correctly).
 */
CompositionHelper.prototype.updateCompositionElements = function(dontRecurse) {
  if (!this.isComposing) {
    return;
  }
  var cursor = this.terminal.element.querySelector('.terminal-cursor');
  if (cursor) {
    this.compositionView.style.left = cursor.offsetLeft + 'px';
    this.compositionView.style.top = cursor.offsetTop + 'px';
    var compositionViewBounds = this.compositionView.getBoundingClientRect();
    this.textarea.style.left = cursor.offsetLeft + compositionViewBounds.width + 'px';
    this.textarea.style.top = (cursor.offsetTop + cursor.offsetHeight) + 'px';
  }
  if (!dontRecurse) {
    setTimeout(this.updateCompositionElements.bind(this, true), 0);
  }
};

/**
 * Clears the textarea's position so that the cursor does not blink on IE.
 * @private
 */
CompositionHelper.prototype.clearTextareaPosition = function() {
  this.textarea.style.left = '';
  this.textarea.style.top = '';
};

export { CompositionHelper };
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

var alertaControllers = angular.module('alertaControllers', []);

alertaControllers.controller('MenuController', ['$scope', '$location', '$auth', 'config',
  function($scope, $location, $auth, config) {

    if ($auth.isAuthenticated()) {
      $scope.name = $auth.getPayload().name;
    };

    $scope.isActive = function (viewLocation) {
        return viewLocation === $location.path();
    };

    $scope.isAuthenticated = function() {
      return $auth.isAuthenticated();
    };

    $scope.authenticate = function() {
      $auth.authenticate(config.provider)
        .then(function() {
          $scope.name = $auth.getPayload().name;
        })
        .catch(function(e) {
          alert(e);
        });
    };

  }]);

alertaControllers.controller('AlertListController', ['$scope', '$location', '$timeout', 'Count', 'Environment', 'Service', 'Alert',
  function($scope, $location, $timeout, Count, Environment, Service, Alert){

    $scope.autoRefresh = true;
    $scope.refreshText = 'Auto Update';

    var search = $location.search();
    if (search.environment) {
      $scope.environment = search.environment;
    }
    if (search.service) {
      $scope.service = search.service;
    }
    if (search.status) {
      $scope.status = search.status;
    } else {
      $scope.status = 'open';
    }

    $scope.show = [
      {name: 'Open', status: 'open'},
      {name: 'Active', status: ['open', 'ack', 'assign']},
      {name: 'Closed', status: 'closed'}
    ]

    $scope.alerts = [];
    $scope.alertLimit = 20;
    $scope.reverse = true;
    $scope.query = {};

    $scope.setService = function(service) {
      $scope.service = service;
      updateQuery();
      refresh();
    };

    $scope.setEnv = function(environment) {
      $scope.environment = environment;
      updateQuery();
      refresh();
    };

    $scope.setStatus = function(status) {
      $scope.status = status;
      updateQuery();
      refresh();
    };

    $scope.refresh = function() {
      refresh();
    };

    Service.all(function(response) {
      $scope.services = response.services;
    });

    var updateQuery = function() {
      if ($scope.service) {
        $scope.query['service'] = $scope.service
      } else {
        delete $scope.query['service'];
      }
      if ($scope.environment) {
        $scope.query['environment'] = $scope.environment
      } else {
        delete $scope.query['environment'];
      }
      if ($scope.status) {
        $scope.query['status'] = $scope.status;
      } else {
        delete $scope.query['status'];
      }
      $location.search($scope.query);
    };

    var refresh = function() {
      $scope.refreshText = 'Refreshing...';
      Count.query({}, function(response) {
        $scope.statusCounts = response.statusCounts;
      });
      Environment.all(function(response) {
        $scope.environments = response.environments;
      });
      updateQuery();
      Alert.query($scope.query, function(response) {
        if (response.status == 'ok') {
          $scope.alerts = response.alerts;
        }
        $scope.message = response.status + ' - ' + response.message;
        $scope.autoRefresh = response.autoRefresh;
        if ($scope.autoRefresh) {
          $scope.refreshText = 'Auto Update';
        } else {
          $scope.refreshText = 'Refresh';
        }
      });
    };
    var refreshWithTimeout = function() {
      if ($scope.autoRefresh) {
        refresh();
      }
      timer = $timeout(refreshWithTimeout, 5000);
    };
    var timer = $timeout(refreshWithTimeout, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

    var SEVERITY_MAP = {
        'critical': 1,
        'major': 2,
        'minor': 3,
        'warning': 4,
        'indeterminate': 5,
        'cleared': 5,
        'normal': 5,
        'informational': 6,
        'debug': 7,
        'auth': 8,
        'unknown': 9
    };

    $scope.reverseSeverityCode = function(alert) {
      return -SEVERITY_MAP[alert.severity];
    };

    $scope.severityCode = function(alert) {
      return SEVERITY_MAP[alert.severity];
    };

  }]);

alertaControllers.controller('AlertDetailController', ['$scope', '$route', '$routeParams', '$location', '$auth', 'Alert',
  function($scope, $route, $routeParams, $location, $auth, Alert){

    $scope.user = $auth.getPayload().name;

    $scope.isAuthenticated = function() {
      return $auth.isAuthenticated();
    };

    Alert.get({id: $routeParams.id}, function(response) {
      $scope.alert = response.alert;
    });

    $scope.openAlert = function(id) {
      Alert.status({id: id}, {status: 'open', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.tagAlert = function(id, tags) {
      Alert.tag({id: id}, {tags: tags}, function(data) {
        $route.reload();
      });
    };

    $scope.watchAlert = function(id, user) {
      Alert.tag({id: id}, {tags: ['watch:' + user]}, function(data) {
        $route.reload();
      });
    };

    $scope.unwatchAlert = function(id, user) {
      Alert.untag({id: id}, {tags: ['watch:' + user]}, function(data) {
        $route.reload();
      });
    };

    $scope.ackAlert = function(id) {
      Alert.status({id: id}, {status: 'ack', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.closeAlert = function(id) {
      Alert.status({id: id}, {status: 'closed', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteAlert = function(id) {
      Alert.delete({id: id}, {}, function(data) {
        window.history.back();
      });
    };

    $scope.tagged = function(tags, tagged) {
      angular.forEach(tags, function(tag) {
        if (tag == tagged) {
          return true;
        };
        return false;
      });
    };

    $scope.back = function() {
      window.history.back();
    };

  }]);

alertaControllers.controller('AlertTop10Controller', ['$scope', '$location', '$timeout', 'Count', 'Environment', 'Service', 'Alert',
  function($scope, $location, $timeout, Count, Environment, Service, Alert){

    var search = $location.search();
    if (search.environment) {
      $scope.environment = search.environment;
    }
    if (search.service) {
      $scope.service = search.service;
    }
    if (search.status) {
      $scope.status = search.status;
    } else {
      $scope.status = 'open';
    }

    $scope.show = [
      {name: 'Open', status: 'open'},
      {name: 'Active', status: ['open', 'ack', 'assign']},
      {name: 'Closed', status: 'closed'}
    ]

    $scope.top10 = [];
    $scope.query = {};

    $scope.setService = function(service) {
      $scope.service = service;
      updateQuery();
      refresh();
    };

    $scope.setEnv = function(environment) {
      $scope.environment = environment;
      updateQuery();
      refresh();
    };

    $scope.setStatus = function(status) {
      $scope.status = status;
      updateQuery();
      refresh();
    };

    $scope.refresh = function() {
      refresh();
    };

    Service.all(function(response) {
      $scope.services = response.services;
    });

    var updateQuery = function() {
      if ($scope.service) {
        $scope.query['service'] = $scope.service
      } else {
        delete $scope.query['service'];
      }
      if ($scope.environment) {
        $scope.query['environment'] = $scope.environment
      } else {
        delete $scope.query['environment'];
      }
      if ($scope.status) {
        $scope.query['status'] = $scope.status;
      } else {
        delete $scope.query['status'];
      }
      $location.search($scope.query);
    };

    var refresh = function() {
      Count.query({}, function(response) {
        $scope.statusCounts = response.statusCounts;
      });
      Environment.all(function(response) {
        $scope.environments = response.environments;
      });
      updateQuery();
      Alert.top10($scope.query, function(response) {
        if (response.status == 'ok') {
          $scope.top10 = response.top10;
        }
        $scope.message = response.status + ' - ' + response.message;
      });
      timer = $timeout(refresh, 5000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('AlertWatchController', ['$scope', '$timeout', '$auth', 'Alert',
  function($scope, $timeout, $auth, Alert){

    $scope.watches = [];

    var refresh = function() {
      Alert.query({'tags': 'watch:' + $auth.getPayload().name}, function(response) {
        if (response.status == 'ok') {
          $scope.watches = response.alerts;
        }
        $scope.message = response.status + ' - ' + response.message;
      });
      timer = $timeout(refresh, 5000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('AlertLinkController', ['$scope', '$location',
  function($scope, $location) {

    $scope.getDetails = function(alert) {
      $location.url('/alert/' + alert.id);
    };
  }]);

alertaControllers.controller('UserController', ['$scope', '$route', '$timeout', '$auth', 'Users',
  function($scope, $route, $timeout, $auth, Users) {

    $scope.domains = [];
    $scope.users = [];
    $scope.email = '';

    $scope.createUser = function(name, email) {
      Users.save({}, {name: name, email: email, provider: $auth.getPayload().name}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteUser = function(user) {
      Users.delete({user: user}, {}, function(data) {
        $route.reload();
      });
    };

    Users.query(function(response) {
      $scope.domains = response.domains;
      $scope.users = response.users;
    });

  }]);

alertaControllers.controller('ApiKeyController', ['$scope', '$route', '$timeout', '$auth', 'Keys',
  function($scope, $route, $timeout, $auth, Keys) {

    $scope.keys = [];
    $scope.text = '';

    $scope.createKey = function(text) {
      Keys.save({}, {user: $auth.getPayload().name, text: text}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteKey = function(key) {
      Keys.delete({key: key}, {}, function(data) {
        $route.reload();
      });
    };

    Keys.query({user: $auth.getPayload().name}, function(response) {
      $scope.keys = response.keys;
    });

  }]);

alertaControllers.controller('ProfileController', ['$scope', '$auth',
  function($scope, $auth) {

    $scope.user_id = $auth.getPayload().sub;
    $scope.name = $auth.getPayload().name;
    $scope.email = $auth.getPayload().email;
    $scope.provider = $auth.getPayload().provider;

    $scope.token = $auth.getToken();
    $scope.payload = $auth.getPayload();
  }]);

alertaControllers.controller('AboutController', ['$scope', '$timeout', 'Management', 'Heartbeat',
  function($scope, $timeout, Management, Heartbeat) {

    Management.manifest(function(response) {
      $scope.manifest = response;
    });

    $scope.metrics = [];
    $scope.heartbeats = [];

    var refresh = function() {
      Management.status(function(response) {
        $scope.metrics = response.metrics;
        $scope.lastTime = response.time;
        $scope.uptime = response.uptime;
      });
      Heartbeat.query(function(response) {
        $scope.heartbeats = response.heartbeats;
      });
      timer = $timeout(refresh, 10000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('LoginController', ['$scope', '$auth',
 function($scope, $auth) {
    $scope.authenticate = function(provider) {
      $auth.authenticate(provider)
        .then(function() {
          console.log('You have successfully logged in');
        })
        .catch(function(e) {
          console.log(e);
        });
    };
  }]);

  alertaControllers.controller('LogoutController', ['$auth',
    function($auth) {
    if (!$auth.isAuthenticated()) {
        return;
    }
    $auth.logout()
      .then(function() {
        console.log('You have been logged out');
      });
  }]);
<commit_msg>jsonify the error response<commit_after>'use strict';

/* Controllers */

var alertaControllers = angular.module('alertaControllers', []);

alertaControllers.controller('MenuController', ['$scope', '$location', '$auth', 'config',
  function($scope, $location, $auth, config) {

    if ($auth.isAuthenticated()) {
      $scope.name = $auth.getPayload().name;
    };

    $scope.isActive = function (viewLocation) {
        return viewLocation === $location.path();
    };

    $scope.isAuthenticated = function() {
      return $auth.isAuthenticated();
    };

    $scope.authenticate = function() {
      $auth.authenticate(config.provider)
        .then(function() {
          $scope.name = $auth.getPayload().name;
        })
        .catch(function(e) {
          alert(JSON.stringify(e));
        });
    };

  }]);

alertaControllers.controller('AlertListController', ['$scope', '$location', '$timeout', 'Count', 'Environment', 'Service', 'Alert',
  function($scope, $location, $timeout, Count, Environment, Service, Alert){

    $scope.autoRefresh = true;
    $scope.refreshText = 'Auto Update';

    var search = $location.search();
    if (search.environment) {
      $scope.environment = search.environment;
    }
    if (search.service) {
      $scope.service = search.service;
    }
    if (search.status) {
      $scope.status = search.status;
    } else {
      $scope.status = 'open';
    }

    $scope.show = [
      {name: 'Open', status: 'open'},
      {name: 'Active', status: ['open', 'ack', 'assign']},
      {name: 'Closed', status: 'closed'}
    ]

    $scope.alerts = [];
    $scope.alertLimit = 20;
    $scope.reverse = true;
    $scope.query = {};

    $scope.setService = function(service) {
      $scope.service = service;
      updateQuery();
      refresh();
    };

    $scope.setEnv = function(environment) {
      $scope.environment = environment;
      updateQuery();
      refresh();
    };

    $scope.setStatus = function(status) {
      $scope.status = status;
      updateQuery();
      refresh();
    };

    $scope.refresh = function() {
      refresh();
    };

    Service.all(function(response) {
      $scope.services = response.services;
    });

    var updateQuery = function() {
      if ($scope.service) {
        $scope.query['service'] = $scope.service
      } else {
        delete $scope.query['service'];
      }
      if ($scope.environment) {
        $scope.query['environment'] = $scope.environment
      } else {
        delete $scope.query['environment'];
      }
      if ($scope.status) {
        $scope.query['status'] = $scope.status;
      } else {
        delete $scope.query['status'];
      }
      $location.search($scope.query);
    };

    var refresh = function() {
      $scope.refreshText = 'Refreshing...';
      Count.query({}, function(response) {
        $scope.statusCounts = response.statusCounts;
      });
      Environment.all(function(response) {
        $scope.environments = response.environments;
      });
      updateQuery();
      Alert.query($scope.query, function(response) {
        if (response.status == 'ok') {
          $scope.alerts = response.alerts;
        }
        $scope.message = response.status + ' - ' + response.message;
        $scope.autoRefresh = response.autoRefresh;
        if ($scope.autoRefresh) {
          $scope.refreshText = 'Auto Update';
        } else {
          $scope.refreshText = 'Refresh';
        }
      });
    };
    var refreshWithTimeout = function() {
      if ($scope.autoRefresh) {
        refresh();
      }
      timer = $timeout(refreshWithTimeout, 5000);
    };
    var timer = $timeout(refreshWithTimeout, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

    var SEVERITY_MAP = {
        'critical': 1,
        'major': 2,
        'minor': 3,
        'warning': 4,
        'indeterminate': 5,
        'cleared': 5,
        'normal': 5,
        'informational': 6,
        'debug': 7,
        'auth': 8,
        'unknown': 9
    };

    $scope.reverseSeverityCode = function(alert) {
      return -SEVERITY_MAP[alert.severity];
    };

    $scope.severityCode = function(alert) {
      return SEVERITY_MAP[alert.severity];
    };

  }]);

alertaControllers.controller('AlertDetailController', ['$scope', '$route', '$routeParams', '$location', '$auth', 'Alert',
  function($scope, $route, $routeParams, $location, $auth, Alert){

    $scope.user = $auth.getPayload().name;

    $scope.isAuthenticated = function() {
      return $auth.isAuthenticated();
    };

    Alert.get({id: $routeParams.id}, function(response) {
      $scope.alert = response.alert;
    });

    $scope.openAlert = function(id) {
      Alert.status({id: id}, {status: 'open', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.tagAlert = function(id, tags) {
      Alert.tag({id: id}, {tags: tags}, function(data) {
        $route.reload();
      });
    };

    $scope.watchAlert = function(id, user) {
      Alert.tag({id: id}, {tags: ['watch:' + user]}, function(data) {
        $route.reload();
      });
    };

    $scope.unwatchAlert = function(id, user) {
      Alert.untag({id: id}, {tags: ['watch:' + user]}, function(data) {
        $route.reload();
      });
    };

    $scope.ackAlert = function(id) {
      Alert.status({id: id}, {status: 'ack', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.closeAlert = function(id) {
      Alert.status({id: id}, {status: 'closed', text: 'status change via console'}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteAlert = function(id) {
      Alert.delete({id: id}, {}, function(data) {
        window.history.back();
      });
    };

    $scope.tagged = function(tags, tagged) {
      angular.forEach(tags, function(tag) {
        if (tag == tagged) {
          return true;
        };
        return false;
      });
    };

    $scope.back = function() {
      window.history.back();
    };

  }]);

alertaControllers.controller('AlertTop10Controller', ['$scope', '$location', '$timeout', 'Count', 'Environment', 'Service', 'Alert',
  function($scope, $location, $timeout, Count, Environment, Service, Alert){

    var search = $location.search();
    if (search.environment) {
      $scope.environment = search.environment;
    }
    if (search.service) {
      $scope.service = search.service;
    }
    if (search.status) {
      $scope.status = search.status;
    } else {
      $scope.status = 'open';
    }

    $scope.show = [
      {name: 'Open', status: 'open'},
      {name: 'Active', status: ['open', 'ack', 'assign']},
      {name: 'Closed', status: 'closed'}
    ]

    $scope.top10 = [];
    $scope.query = {};

    $scope.setService = function(service) {
      $scope.service = service;
      updateQuery();
      refresh();
    };

    $scope.setEnv = function(environment) {
      $scope.environment = environment;
      updateQuery();
      refresh();
    };

    $scope.setStatus = function(status) {
      $scope.status = status;
      updateQuery();
      refresh();
    };

    $scope.refresh = function() {
      refresh();
    };

    Service.all(function(response) {
      $scope.services = response.services;
    });

    var updateQuery = function() {
      if ($scope.service) {
        $scope.query['service'] = $scope.service
      } else {
        delete $scope.query['service'];
      }
      if ($scope.environment) {
        $scope.query['environment'] = $scope.environment
      } else {
        delete $scope.query['environment'];
      }
      if ($scope.status) {
        $scope.query['status'] = $scope.status;
      } else {
        delete $scope.query['status'];
      }
      $location.search($scope.query);
    };

    var refresh = function() {
      Count.query({}, function(response) {
        $scope.statusCounts = response.statusCounts;
      });
      Environment.all(function(response) {
        $scope.environments = response.environments;
      });
      updateQuery();
      Alert.top10($scope.query, function(response) {
        if (response.status == 'ok') {
          $scope.top10 = response.top10;
        }
        $scope.message = response.status + ' - ' + response.message;
      });
      timer = $timeout(refresh, 5000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('AlertWatchController', ['$scope', '$timeout', '$auth', 'Alert',
  function($scope, $timeout, $auth, Alert){

    $scope.watches = [];

    var refresh = function() {
      Alert.query({'tags': 'watch:' + $auth.getPayload().name}, function(response) {
        if (response.status == 'ok') {
          $scope.watches = response.alerts;
        }
        $scope.message = response.status + ' - ' + response.message;
      });
      timer = $timeout(refresh, 5000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('AlertLinkController', ['$scope', '$location',
  function($scope, $location) {

    $scope.getDetails = function(alert) {
      $location.url('/alert/' + alert.id);
    };
  }]);

alertaControllers.controller('UserController', ['$scope', '$route', '$timeout', '$auth', 'Users',
  function($scope, $route, $timeout, $auth, Users) {

    $scope.domains = [];
    $scope.users = [];
    $scope.email = '';

    $scope.createUser = function(name, email) {
      Users.save({}, {name: name, email: email, provider: $auth.getPayload().name}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteUser = function(user) {
      Users.delete({user: user}, {}, function(data) {
        $route.reload();
      });
    };

    Users.query(function(response) {
      $scope.domains = response.domains;
      $scope.users = response.users;
    });

  }]);

alertaControllers.controller('ApiKeyController', ['$scope', '$route', '$timeout', '$auth', 'Keys',
  function($scope, $route, $timeout, $auth, Keys) {

    $scope.keys = [];
    $scope.text = '';

    $scope.createKey = function(text) {
      Keys.save({}, {user: $auth.getPayload().name, text: text}, function(data) {
        $route.reload();
      });
    };

    $scope.deleteKey = function(key) {
      Keys.delete({key: key}, {}, function(data) {
        $route.reload();
      });
    };

    Keys.query({user: $auth.getPayload().name}, function(response) {
      $scope.keys = response.keys;
    });

  }]);

alertaControllers.controller('ProfileController', ['$scope', '$auth',
  function($scope, $auth) {

    $scope.user_id = $auth.getPayload().sub;
    $scope.name = $auth.getPayload().name;
    $scope.email = $auth.getPayload().email;
    $scope.provider = $auth.getPayload().provider;

    $scope.token = $auth.getToken();
    $scope.payload = $auth.getPayload();
  }]);

alertaControllers.controller('AboutController', ['$scope', '$timeout', 'Management', 'Heartbeat',
  function($scope, $timeout, Management, Heartbeat) {

    Management.manifest(function(response) {
      $scope.manifest = response;
    });

    $scope.metrics = [];
    $scope.heartbeats = [];

    var refresh = function() {
      Management.status(function(response) {
        $scope.metrics = response.metrics;
        $scope.lastTime = response.time;
        $scope.uptime = response.uptime;
      });
      Heartbeat.query(function(response) {
        $scope.heartbeats = response.heartbeats;
      });
      timer = $timeout(refresh, 10000);
    };
    var timer = $timeout(refresh, 200);

    $scope.$on('$destroy', function() {
      if (timer) {
        $timeout.cancel(timer);
      }
    });

  }]);

alertaControllers.controller('LoginController', ['$scope', '$auth',
 function($scope, $auth) {
    $scope.authenticate = function(provider) {
      $auth.authenticate(provider)
        .then(function() {
          console.log('You have successfully logged in');
        })
        .catch(function(e) {
          console.log(e);
        });
    };
  }]);

  alertaControllers.controller('LogoutController', ['$auth',
    function($auth) {
    if (!$auth.isAuthenticated()) {
        return;
    }
    $auth.logout()
      .then(function() {
        console.log('You have been logged out');
      });
  }]);
<|endoftext|>


<commit_before>app.controller('PhoneController', function($scope) {
  $scope.greeting = "Hello World!";
  $scope.shakeCount;

  window.addEventListener('devicemotion', handleDeviceAccelChange, true);

  function handleDeviceAccelChange(event) {
    $scope.accelEventData = event;

    // we use to determine accel: event.acceleration;
    var xAccel = event.acceleration.x;
    var yAccel = event.acceleration.y;
    var zAccel = event.acceleration.z;

    // Accels are all in is in m/s^2
    $scope.xAcceleration = xAccel;
    $scope.yAcceleration = yAccel;
    $scope.zAcceleration = zAccel;
  }
});
<commit_msg>Checking for events<commit_after>app.controller('PhoneController', function($scope) {
  $scope.greeting = "Hello World!";
  $scope.shakeCount;

  if (window.DeviceMotionEvent) {
    console.log("DeviceMotionEvent supported");
  }
  window.addEventListener('devicemotion', handleDeviceAccelChange, true);

  function handleDeviceAccelChange(event) {
    $scope.accelEventData = event;

    // we use to determine accel: event.acceleration;
    var xAccel = event.acceleration.x;
    var yAccel = event.acceleration.y;
    var zAccel = event.acceleration.z;

    // Accels are all in is in m/s^2
    $scope.xAcceleration = xAccel;
    $scope.yAcceleration = yAccel;
    $scope.zAcceleration = zAccel;
  }
});
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('myApp.controllers', [])
  .controller('LandingPageController', [function() {

  }])
  .controller('WaitlistController', ['$scope', '$firebase', function($scope, $firebase) {
  	// Connect $scope.parties to live Firebase data.
    var partiesRef = new Firebase('https://waitandeat-jonos.firebaseio.com/parties')

    $scope.parties = $firebase(partiesRef);

    // Object to store data from the waitlist form.
    $scope.newParty = {name: '', phone: '', size: '', done: false, notified: 'No'};

    // Function to save a new party to the waitlist.
    $scope.saveParty = function() {
    	$scope.parties.$add($scope.newParty);
      $scope.newParty = {name: '', phone: '', size: '', done: false, notified: 'No'};
    };

    // Function to send text message to a party
    $scope.sendTextMessage = function(party) {
      var textMessageRef = new Firebase('http://waitandeat-jonos.firebaseio.com/textMessages');
      var textMessages = $firebase(textMessageRef);
      var newTextMessage = {
        phoneNumber: party.phone,
        size: party.size,
        name: party.name
      };
      textMessages.$add(newTextMessage);
      party.notified = "Yes";
      $scope.parties.$save(party.$id);
    };
  }])
  .controller('AuthController', ['$scope', '$firebaseSimpleLogin', '$location', function($scope, $firebaseSimpleLogin, $location) {
    var authRef = new Firebase('https://waitandeat-jonos.firebaseio.com/');
    var auth = $firebaseSimpleLogin(authRef);

    $scope.user = {email: '', password: ''};

    $scope.register = function() {
      auth.$createUser($scope.user.email, $scope.user.password).then(function(data) {
      	console.log(data);
      	auth.$login('password', $scope.user)
      });
    };

    $scope.login = function() {
      auth.$login('password', $scope.user).then(function(data) {
        console.log(data);
        // Redirect users to /waitlist.
        $location.path('/waitlist');
      });
    };

    $scope.logout = function() {
      auth.$logout();
      // Redirect users to /.
    };
  }]);<commit_msg>redirect to root after logging out<commit_after>'use strict';

/* Controllers */

angular.module('myApp.controllers', [])
  .controller('LandingPageController', [function() {

  }])
  .controller('WaitlistController', ['$scope', '$firebase', function($scope, $firebase) {
  	// Connect $scope.parties to live Firebase data.
    var partiesRef = new Firebase('https://waitandeat-jonos.firebaseio.com/parties')

    $scope.parties = $firebase(partiesRef);

    // Object to store data from the waitlist form.
    $scope.newParty = {name: '', phone: '', size: '', done: false, notified: 'No'};

    // Function to save a new party to the waitlist.
    $scope.saveParty = function() {
    	$scope.parties.$add($scope.newParty);
      $scope.newParty = {name: '', phone: '', size: '', done: false, notified: 'No'};
    };

    // Function to send text message to a party
    $scope.sendTextMessage = function(party) {
      var textMessageRef = new Firebase('http://waitandeat-jonos.firebaseio.com/textMessages');
      var textMessages = $firebase(textMessageRef);
      var newTextMessage = {
        phoneNumber: party.phone,
        size: party.size,
        name: party.name
      };
      textMessages.$add(newTextMessage);
      party.notified = "Yes";
      $scope.parties.$save(party.$id);
    };
  }])
  .controller('AuthController', ['$scope', '$firebaseSimpleLogin', '$location', function($scope, $firebaseSimpleLogin, $location) {
    var authRef = new Firebase('https://waitandeat-jonos.firebaseio.com/');
    var auth = $firebaseSimpleLogin(authRef);

    $scope.user = {email: '', password: ''};

    $scope.register = function() {
      auth.$createUser($scope.user.email, $scope.user.password).then(function(data) {
      	console.log(data);
      	auth.$login('password', $scope.user)
      });
    };

    $scope.login = function() {
      auth.$login('password', $scope.user).then(function(data) {
        console.log(data);
        // Redirect users to /waitlist.
        $location.path('/waitlist');
      });
    };

    $scope.logout = function() {
      auth.$logout();
      // Redirect users to /.
      $location.path('/');
    };
  }]);<|endoftext|>