<commit_before>var inputController = namespace('systemPlugin.inputController');
inputController.Gamepad = function(cockpit) {
  var self = this;
  self.gp = new inputController.GamepadAbstraction(cockpit);

  self.register = function(control) {
    if (control.bindings.gamepad !== undefined) {
      var gpKey = control.bindings.gamepad;
      if (gpKey !== undefined) {
        self.gp.assignment[gpKey] = { };
        if (control.down !== undefined) self.gp.assignment[gpKey].BUTTON_DOWN = control.down;
        if (control.up !== undefined) self.gp.assignment[gpKey].BUTTON_UP = control.up;
        if (control.axis !== undefined) self.gp.assignment[gpKey].AXIS_CHANGED = control.axis;

        if (control.secondary !== undefined) {
          control.secondary.forEach(function (secondary) {
            if (secondary.bindings.gamepad !== undefined) {
              var subKey = gpKey + '+' + secondary.bindings.gamepad;
              self.gp.assignment[subKey] = { };
              if (secondary.down !== undefined) self.gp.assignment[subKey].BUTTON_DOWN = secondary.down;
              if (secondary.up !== undefined) self.gp.assignment[subKey].BUTTON_UP = secondary.up;
              if (secondary.axis !== undefined) self.gp.assignment[subKey].AXIS_CHANGED = secondary.axis;
            }
          });
        }
      }
    }
  };

  self.unregister = function(control) {
    var gpKey = control.bindings.gamepad;
    if (gpKey !== undefiend) {
      self.gp.assignment[gpKey] = undefined;

      if (control.secondary !== undefined) {
        control.secondary.forEach(function (secondary) {
          if (secondary.bindings.gamepad !== undefined) {
            var subKey = gpKey + '+' + secondary.bindings.gamepad;
            self.gp.assignment[subKey] = undefined;
          }
        });
      }
    }
  };

  self.reset = function () {
    for (var control in self.gp.assignment) {
      self.gp.assignment[control] = undefined;
    }
  };

  return self;
};<commit_msg>Fixed typo<commit_after>var inputController = namespace('systemPlugin.inputController');
inputController.Gamepad = function(cockpit) {
  var self = this;
  self.gp = new inputController.GamepadAbstraction(cockpit);

  self.register = function(control) {
    if (control.bindings.gamepad !== undefined) {
      var gpKey = control.bindings.gamepad;
      if (gpKey !== undefined) {
        self.gp.assignment[gpKey] = { };
        if (control.down !== undefined) self.gp.assignment[gpKey].BUTTON_DOWN = control.down;
        if (control.up !== undefined) self.gp.assignment[gpKey].BUTTON_UP = control.up;
        if (control.axis !== undefined) self.gp.assignment[gpKey].AXIS_CHANGED = control.axis;

        if (control.secondary !== undefined) {
          control.secondary.forEach(function (secondary) {
            if (secondary.bindings.gamepad !== undefined) {
              var subKey = gpKey + '+' + secondary.bindings.gamepad;
              self.gp.assignment[subKey] = { };
              if (secondary.down !== undefined) self.gp.assignment[subKey].BUTTON_DOWN = secondary.down;
              if (secondary.up !== undefined) self.gp.assignment[subKey].BUTTON_UP = secondary.up;
              if (secondary.axis !== undefined) self.gp.assignment[subKey].AXIS_CHANGED = secondary.axis;
            }
          });
        }
      }
    }
  };

  self.unregister = function(control) {
    var gpKey = control.bindings.gamepad;
    if (gpKey !== undefined) {
      self.gp.assignment[gpKey] = undefined;

      if (control.secondary !== undefined) {
        control.secondary.forEach(function (secondary) {
          if (secondary.bindings.gamepad !== undefined) {
            var subKey = gpKey + '+' + secondary.bindings.gamepad;
            self.gp.assignment[subKey] = undefined;
          }
        });
      }
    }
  };

  self.reset = function () {
    for (var control in self.gp.assignment) {
      self.gp.assignment[control] = undefined;
    }
  };

  return self;
};
<|endoftext|>


<commit_before>import axios from 'axios'

/* -------------------------------ACTIONS------------------------------------ */
const SET_CART = 'SET_CART'
const GET_CART = 'GET_CART'
const ADD_ITEM = 'ADD_ITEM'
const REMOVE_ITEM = 'REMOVE_ITEM'
const UPDATE_ITEM_QUANTITY = 'UPDATE_ITEM_QUANTITY'
const LOGIN_ACTION = 'LOGIN_ACTION'

/* ---------------------------ACTION CREATORS-------------------------------- */
const setCart = (user) => ({type: SET_CART, cartId: user.id})

const getCart = currentCart => ({type: GET_CART, currentCart})

const addItem = item => ({type: ADD_ITEM, item})

const removeItem = item => ({type: REMOVE_ITEM, item})

const updateItem = item => ({type: UPDATE_ITEM_QUANTITY, item})

/* -------------------STATE-------------------------------------------------- */
const initialState = {
  currentCart: {},
  cartItems: [],
}

/* -------------------------------REDUCER------------------------------------ */
const reducer = (state = initialState, action) => {
  const newState = Object.assign({}, state)
  switch (action.type) {

  case SET_CART:
    newState.id = action.id
    return newState

  case GET_CART:
    newState.currentCart = action.currentCart
    return newState

  case ADD_ITEM:
    newState.cartItems = [...newState.cartItems, action.item]
    return newState

  case REMOVE_ITEM:
    newState.currentCart.products = state.currentCart.products.filter(prod => prod !== action.item)
    return newState
  }

  return state
}

// Thunk action creator
export const setCartId = (cartId) => (dispatch) => {
  axios.get(`/api/cart/${cartId}`)
  .then(res => res.data)
  .then(cart => dispatch(setCart(cart.id)))
  .catch(console.error.bind(console))
}
export const retrieveItems = () => (dispatch) => {
  axios.get(`/api/cart/products`)
  .then(res => res.data)
  .then(cart => dispatch(getCart(cart)))
  .catch(console.error.bind(console))
}

export const addToCart = (item) => (dispatch) => {
  axios.put(`/api/cart/products/add`, item)
  .then(res => {
    // does this check need to happen if errors are thrown farther down the promise chain?
    if (res.data === 'OK') dispatch(addItem(item))
  })
  .catch(console.error.bind(console))
}

export const removeFromCart = (item) => (dispatch) => {
  axios.put(`/api/cart/products/sub`, item)
  .then( res => {
    if (res.data === 'OK') dispatch(removeItem(item))
  })
  .catch(console.error.bind(console))
}

export const mergeSessionCartToUser = () =>
  dispatch =>
    axios.get('/api/auth/whoami')
    .then( user => {
      const userId = user.data.id
      return axios.put(`/api/cart/mergeCart/${userId}`)
      .then( () => dispatch(setCart(userId)))
    })
    .catch(console.error.bind(console))

export default reducer
<commit_msg>Feat(Manage Cart): refresh page to render updated cart upon deleting item, deletion reflected in db<commit_after>import axios from 'axios'

/* -------------------------------ACTIONS------------------------------------ */
const SET_CART = 'SET_CART'
const GET_CART = 'GET_CART'
const ADD_ITEM = 'ADD_ITEM'
const REMOVE_ITEM = 'REMOVE_ITEM'
const UPDATE_ITEM_QUANTITY = 'UPDATE_ITEM_QUANTITY'
const LOGIN_ACTION = 'LOGIN_ACTION'

/* ---------------------------ACTION CREATORS-------------------------------- */
const setCart = (user) => ({type: SET_CART, cartId: user.id})

const getCart = currentCart => ({type: GET_CART, currentCart})

const addItem = item => ({type: ADD_ITEM, item})

const removeItem = item => ({type: REMOVE_ITEM, item})

const updateItem = item => ({type: UPDATE_ITEM_QUANTITY, item})

/* -------------------STATE-------------------------------------------------- */
const initialState = {
  currentCart: {},
  cartItems: [],
}

/* -------------------------------REDUCER------------------------------------ */
const reducer = (state = initialState, action) => {
  const newState = Object.assign({}, state)
  switch (action.type) {

  case SET_CART:
    newState.id = action.id
    return newState

  case GET_CART:
    newState.currentCart = action.currentCart
    return newState

  case ADD_ITEM:
    newState.cartItems = [...newState.cartItems, action.item]
    return newState

  case REMOVE_ITEM:
    newState.currentCart.products = state.currentCart.products.filter(prod => prod !== action.item)
    return newState
  }

  return state
}

// Thunk action creator
export const setCartId = (cartId) => (dispatch) => {
  axios.get(`/api/cart/${cartId}`)
  .then(res => res.data)
  .then(cart => dispatch(setCart(cart.id)))
  .catch(console.error.bind(console))
}
export const retrieveItems = () => (dispatch) => {
  axios.get(`/api/cart/products`)
  .then(res => res.data)
  .then(cart => dispatch(getCart(cart)))
  .catch(console.error.bind(console))
}

export const addToCart = (item) => (dispatch) => {
  axios.put(`/api/cart/products/add`, item)
  .then(res => {
    // does this check need to happen if errors are thrown farther down the promise chain?
    if (res.data === 'OK') dispatch(addItem(item))
  })
  .catch(console.error.bind(console))
}

export const removeFromCart = (item) => (dispatch) => {
  axios.put(`/api/cart/products/sub`, item)
  .then( res => {
    if (res.data === 'OK') dispatch(retrieveItems())
  })
  .catch(console.error.bind(console))
}

export const mergeSessionCartToUser = () =>
  dispatch =>
    axios.get('/api/auth/whoami')
    .then( user => {
      const userId = user.data.id
      return axios.put(`/api/cart/mergeCart/${userId}`)
      .then( () => dispatch(setCart(userId)))
    })
    .catch(console.error.bind(console))

export default reducer
<|endoftext|>


<commit_before>document.addEventListener('DOMContentLoaded', function() {
  // Inititate Select2 on any select element with the class .select2
  $('select.select2').select2({
    // change that
    allowClear: false,
    placeholder: {
      id: '-1', // the value of the option
      text: 'Select an option'
    }
  })
})

$.fn.addSelect2Options = function (data) {
  var select = this

  function appendOption(select, data) {
    var option = new Option(data.name, data.id, true, true)
    select.append(option).trigger('change')
  }

  if (Array.isArray(data)) {
    data.map(function(row) {
      appendOption(select, row)
    })
  } else {
    appendOption(select, data)
  }
  select.trigger({
    type: 'select2:select',
    params: {
      data: data
    }
  })
}

$.fn.select2.defaults.set("width", "style")
$.fn.select2.defaults.set("dropdownAutoWidth", false)
$.fn.select2.defaults.set('theme', 'bootstrap4')
<commit_msg>Use single quotes.<commit_after>document.addEventListener('DOMContentLoaded', function() {
  // Inititate Select2 on any select element with the class .select2
  $('select.select2').select2({
    // change that
    allowClear: false,
    placeholder: {
      id: '-1', // the value of the option
      text: 'Select an option'
    }
  })
})

$.fn.addSelect2Options = function (data) {
  var select = this

  function appendOption(select, data) {
    var option = new Option(data.name, data.id, true, true)
    select.append(option).trigger('change')
  }

  if (Array.isArray(data)) {
    data.map(function(row) {
      appendOption(select, row)
    })
  } else {
    appendOption(select, data)
  }
  select.trigger({
    type: 'select2:select',
    params: {
      data: data
    }
  })
}

$.fn.select2.defaults.set('width', 'style')
$.fn.select2.defaults.set('dropdownAutoWidth', false)
$.fn.select2.defaults.set('theme', 'bootstrap4')
<|endoftext|>


<commit_before>import Theme from 'config/theme';
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
  container: {
    borderRadius: 32,
    backgroundColor: Theme.background.secondary,
    overflow: 'hidden'
  },
  iconContainer: {
    width: Theme.icon.width
  },
  light: {
    backgroundColor: Theme.background.white
  },
  disabled: {
    backgroundColor: Theme.colors.color6
  },
  error: {
    backgroundColor: Theme.colors.color7
  },
  button: {
    height: 64,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    paddingLeft: 16
  },
  buttonLight: {
    justifyContent: 'flex-start'
  },
  buttonText: {
    flex: 1,
    textAlign: 'center',
    color: Theme.fontColors.white,
    fontFamily: Theme.font,
    fontSize: 15,
    fontWeight: '500'
  },
  buttonTextLeft: {
    marginLeft: 8,
    textAlign: 'left'
  },
  buttonTextMain: {
    textAlign: 'center',
    fontStyle: 'normal',
    fontSize: 16
  },
  buttonTextMonochrome: {
    fontStyle: 'normal',
    fontSize: 16,
    color: Theme.fontColors.main
  },
  buttonTextLight: {
    color: Theme.fontColors.secondary,
    fontSize: 17,
    fontWeight: '400'
  },
  buttonTextDisabled: {
    color: Theme.fontColors.light,
    fontWeight: '400',
    marginLeft: 0,
    fontStyle: 'italic'
  },
  buttonTextError: {
    color: Theme.fontColors.white,
    fontWeight: '400',
    marginLeft: 0,
    fontStyle: 'normal',
    fontSize: 16
  }
});
<commit_msg>fix center text on buttons<commit_after>import Theme from 'config/theme';
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
  container: {
    borderRadius: 32,
    backgroundColor: Theme.background.secondary,
    overflow: 'hidden'
  },
  iconContainer: {
    width: Theme.icon.width
  },
  light: {
    backgroundColor: Theme.background.white
  },
  disabled: {
    backgroundColor: Theme.colors.color6
  },
  error: {
    backgroundColor: Theme.colors.color7
  },
  button: {
    height: 64,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    paddingLeft: 0
  },
  buttonLight: {
    justifyContent: 'flex-start'
  },
  buttonText: {
    flex: 1,
    textAlign: 'center',
    color: Theme.fontColors.white,
    fontFamily: Theme.font,
    fontSize: 15,
    fontWeight: '500'
  },
  buttonTextLeft: {
    marginLeft: 8,
    textAlign: 'left'
  },
  buttonTextMain: {
    textAlign: 'center',
    fontStyle: 'normal',
    fontSize: 16
  },
  buttonTextMonochrome: {
    fontStyle: 'normal',
    fontSize: 16,
    color: Theme.fontColors.main
  },
  buttonTextLight: {
    color: Theme.fontColors.secondary,
    fontSize: 17,
    fontWeight: '400'
  },
  buttonTextDisabled: {
    color: Theme.fontColors.light,
    fontWeight: '400',
    marginLeft: 0,
    fontStyle: 'italic'
  },
  buttonTextError: {
    color: Theme.fontColors.white,
    fontWeight: '400',
    marginLeft: 0,
    fontStyle: 'normal',
    fontSize: 16
  }
});
<|endoftext|>


<commit_before>({
    // Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
    events: {
        //On click of our "button" element
        'click [data-action=open_phone]': 'togglePopup',
    },

    // tagName attribute is inherited from Backbone.js.
    // We set it to "span" instead of default "div" so that our "button" element is displayed inline.
    tagName: "span",
    // Used to keep track of Popup since it is not attached to this View's DOM
    $popup: undefined,
    /**
     * Toggle the display of the popup.  Called when the phone icon is pressed in the footer of the page.
     */
    togglePopup: function () {
        //Toggle active status on button in footer
        var $button = this.$('[data-action="open_phone"]');
        $button.toggleClass('active');
        //Create popup if necessary, otherwise just toggle the hidden class to hide/show.
        if (!this.$popup) {
            this._createPopup();
        } else {
            this.$popup.toggleClass('hidden');
        }
    },
    /**
     * Used to create Popup as needed. Avoid calling this directly, should only need to be called once.
     * @private
     */
    _createPopup: function () {
        var popupCss = app.template.get("click-to-call.popup-css");
        // We need to load some custom CSS, this is an easy way to do it without having to edit custom.less
        $('head').append(popupCss());
        var popup = app.template.get("click-to-call.popup")(this);
        // Add to main content pane of screen
        $('#content').append(popup);
        this.$popup = $('#sidecar').find('div.cti-popup');
        // Hide pop up on click of X (close button)
        this.$popup.find('[data-action=close]').click(_.bind(this._closePopup, this));
        // Make pop up draggable using existing jQuery UI plug-in
        this.$popup.draggable();
    },
    /**
     * Called when close button is pressed on CTI popup.
     * @private
     */
    _closePopup: function () {
        this.$popup.addClass('hidden');
        var $button = this.$('[data-action="open_phone"]');
        $button.removeClass('active');
    },
    /**
     * Dispose of unattached popup when footer destroyed
     * @private
     */
    _dispose: function(){
        this._super('_dispose');
        this.$popup.remove();
        this.$popup = null;
    }

})

<commit_msg>Add popup frame to correct DIV element<commit_after>({
    // Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
    events: {
        //On click of our "button" element
        'click [data-action=open_phone]': 'togglePopup',
    },

    // tagName attribute is inherited from Backbone.js.
    // We set it to "span" instead of default "div" so that our "button" element is displayed inline.
    tagName: "span",
    // Used to keep track of Popup since it is not attached to this View's DOM
    $popup: undefined,
    /**
     * Toggle the display of the popup.  Called when the phone icon is pressed in the footer of the page.
     */
    togglePopup: function () {
        //Toggle active status on button in footer
        var $button = this.$('[data-action="open_phone"]');
        $button.toggleClass('active');
        //Create popup if necessary, otherwise just toggle the hidden class to hide/show.
        if (!this.$popup) {
            this._createPopup();
        } else {
            this.$popup.toggleClass('hidden');
        }
    },
    /**
     * Used to create Popup as needed. Avoid calling this directly, should only need to be called once.
     * @private
     */
    _createPopup: function () {
        var popupCss = app.template.get("click-to-call.popup-css");
        // We need to load some custom CSS, this is an easy way to do it without having to edit custom.less
        $('head').append(popupCss());
        var popup = app.template.get("click-to-call.popup")(this);
        // Add to main content pane of screen
        $('#sidecar').append(popup);
        this.$popup = $('#sidecar').find('div.cti-popup');
        // Hide pop up on click of X (close button)
        this.$popup.find('[data-action=close]').click(_.bind(this._closePopup, this));
        // Make pop up draggable using existing jQuery UI plug-in
        this.$popup.draggable();
    },
    /**
     * Called when close button is pressed on CTI popup.
     * @private
     */
    _closePopup: function () {
        this.$popup.addClass('hidden');
        var $button = this.$('[data-action="open_phone"]');
        $button.removeClass('active');
    },
    /**
     * Dispose of unattached popup when footer destroyed
     * @private
     */
    _dispose: function(){
        this._super('_dispose');
        this.$popup.remove();
        this.$popup = null;
    }

})

<|endoftext|>


<commit_before>import React from 'react';
import Relay from 'react-relay';
import moment from 'moment';
import classNames from 'classnames';

import Bar from './bar';
import BuildTooltip from './build-tooltip';

const PASSED_COLOR = "#B0DF21";
const PASSED_COLOR_HOVER = "#669611";
const RUNNING_COLOR = "#FFBA03";
const RUNNING_COLOR_HOVER = "#DE8F0C";
const FAILED_COLOR = "#F83F23";
const FAILED_COLOR_HOVER = "#AA0A12";
const PENDING_COLOR = "#DDDDDD";
const PENDING_COLOR_HOVER = "#DDDDDD";

const MAXIMUM_NUMBER_OF_BUILDS = 30;

const BAR_HEIGHT_MINIMUM = 3;
const BAR_WIDTH = 7;
const BAR_SEPERATOR_WIDTH = 1;
const BAR_WIDTH_WITH_SEPERATOR = BAR_WIDTH + BAR_SEPERATOR_WIDTH;

const GRAPH_HEIGHT = 35;
const GRAPH_WIDTH = (BAR_WIDTH * MAXIMUM_NUMBER_OF_BUILDS) + ((MAXIMUM_NUMBER_OF_BUILDS * BAR_SEPERATOR_WIDTH) - 1);

class Graph extends React.Component {
  static propTypes = {
    pipeline: React.PropTypes.shape({
      id: React.PropTypes.string.isRequired,
      builds: React.PropTypes.shape({
        edges: React.PropTypes.arrayOf(
          React.PropTypes.shape({
            node: React.PropTypes.shape({
              state: React.PropTypes.string.isRequired,
              url: React.PropTypes.string.isRequired,
              startedAt: React.PropTypes.string,
              finishedAt: React.PropTypes.string
            }).isRequired
          }).isRequired
        )
      }).isRequired
    }).isRequired
  };

  state = {
    height: 0
  }

  componentDidMount() {
    this.toggleRenderInterval(this.props.pipeline.builds.edges);

    // As soon as the graph has mounted, set the height back to 100% to animate
    // the bars growing into view.
    setTimeout(() => {
      this.setState({ height: "100%" });
    }, 0);
  }

  componentWillReceiveProps(nextProps) {
    const thisLatestBuild = this.props.pipeline.builds.edges[0];
    const nextLatestBuild = nextProps.pipeline.builds.edges[0];

    // Set `shifting` if all the builds are being moved due to a new one coming in.
    if ((thisLatestBuild && nextLatestBuild) && thisLatestBuild.node.id !== nextLatestBuild.node.id) {
      this._shifting = true;
    }
  }

  componentDidUpdate() {
    this.toggleRenderInterval(this.props.pipeline.builds.edges);

    delete this._shifting;
  }

  render() {
    const classes = classNames("animation-height align-bottom relative absolute", {
      "animation-disable": this._shifting
    });

    return (

          {this.renderBars()}

    );
  }

  renderBars() {
    const bars = [];
    let maximumDuration = 1; // 1 to avoid a `0/0` when we calculate percentages

    for (let buildIndex = 0; buildIndex < MAXIMUM_NUMBER_OF_BUILDS; buildIndex++) {
      const buildEdge = this.props.pipeline.builds.edges[buildIndex];

      if (buildEdge) {
        const duration = this.durationForBuild(buildEdge.node);
        if (duration > maximumDuration) {maximumDuration = duration;}

        bars[MAXIMUM_NUMBER_OF_BUILDS - buildIndex - 1] = { color: this.colorForBuild(buildEdge.node), hoverColor: this.hoverColorForBuild(buildEdge.node), duration: duration, href: buildEdge.node.url, build: buildEdge.node };
      } else {
        bars[MAXIMUM_NUMBER_OF_BUILDS - buildIndex - 1] = { color: PENDING_COLOR, hoverColor: PENDING_COLOR_HOVER, duration: 0 };
      }
    }

    return bars.map((bar, index) => {
      const left = index * BAR_WIDTH_WITH_SEPERATOR;

      // Calcualte what percentage this bar is in relation to the longest
      // running build
      let height = (bar.duration / maximumDuration);

      // See if the height is less than our minimum. If it is, set a hard pixel
      // height, otherwise make the height a percentage. We use percentages so
      // we can animate the height of the graph as it loads in.
      let heightInPixels = (height * GRAPH_HEIGHT);
      if (heightInPixels < BAR_HEIGHT_MINIMUM) {
        height = BAR_HEIGHT_MINIMUM;
      } else {
        height = (height * 100) + "%";
      }

      return <Bar key={index} left={left} color={bar.color} hoverColor={bar.hoverColor} width={BAR_WIDTH_WITH_SEPERATOR} height={height} href={bar.href} build={bar.build || null} />;
    });
  }

  durationForBuild(build) {
    if (build.startedAt) {
      // Passing `null` to moment will result in a blank moment instance, so if
      // there isn't a finishedAt, just switch to undefined.
      return moment(build.finishedAt || undefined).diff(moment(build.startedAt));
    } else {
      return 0;
    }
  }

  colorForBuild(build) {
    if (build.state === "running") {
      return RUNNING_COLOR;
    } else if (build.state === "passed" || build.state == "blocked") {
      return PASSED_COLOR;
    } else {
      return FAILED_COLOR;
    }
  }

  hoverColorForBuild(build) {
    if (build.state === "running") {
      return RUNNING_COLOR_HOVER;
    } else if (build.state === "passed" || build.state == "blocked") {
      return PASSED_COLOR_HOVER;
    } else {
      return FAILED_COLOR_HOVER;
    }
  }

  toggleRenderInterval(buildEdges) {
    // See if there is a build running
    let running = false;
    for (const edge of buildEdges) {
      if (edge.node.state === "running") {
        running = true;
        break;
      }
    }

    // If a build is running, ensure we have an interval setup that re-renders
    // the graph every second.
    if (running) {
      if (this._interval) {
        // no-op, interval already running
      } else {
        this._interval = setInterval(() => {
          this.forceUpdate();
        }, 1000);
      }
    } else {
      // Clear the interval now that nothing is running
      if (this._interval) {
        clearTimeout(this._interval);
        delete this._interval;
      }
    }
  }
}

export default Relay.createContainer(Graph, {
  fragments: {
    pipeline: () => Relay.QL`
      fragment on Pipeline {
        id
        builds(first: 30, branch: "%default", state: [ BUILD_STATE_RUNNING, BUILD_STATE_PASSED, BUILD_STATE_FAILED, BUILD_STATE_CANCELED, BUILD_STATE_CANCELING, BUILD_STATE_BLOCKED ]) {
          edges {
            node {
              id
              state
              url
              startedAt
              finishedAt
              ${BuildTooltip.getFragment('build')}
            }
          }
        }
      }
    `
  }
});
<commit_msg>Show scheduled builds in graph<commit_after>import React from 'react';
import Relay from 'react-relay';
import moment from 'moment';
import classNames from 'classnames';

import Bar from './bar';
import BuildTooltip from './build-tooltip';

const PASSED_COLOR = "#B0DF21";
const PASSED_COLOR_HOVER = "#669611";
const RUNNING_COLOR = "#FFBA03";
const RUNNING_COLOR_HOVER = "#DE8F0C";
const FAILED_COLOR = "#F83F23";
const FAILED_COLOR_HOVER = "#AA0A12";
const SCHEDULED_COLOR = "#aeaeae";
const SCHEDULED_COLOR_HOVER = "#6e6e6e";
const PENDING_COLOR = "#DDDDDD";
const PENDING_COLOR_HOVER = "#DDDDDD";

const MAXIMUM_NUMBER_OF_BUILDS = 30;

const BAR_HEIGHT_MINIMUM = 3;
const BAR_WIDTH = 7;
const BAR_SEPERATOR_WIDTH = 1;
const BAR_WIDTH_WITH_SEPERATOR = BAR_WIDTH + BAR_SEPERATOR_WIDTH;

const GRAPH_HEIGHT = 35;
const GRAPH_WIDTH = (BAR_WIDTH * MAXIMUM_NUMBER_OF_BUILDS) + ((MAXIMUM_NUMBER_OF_BUILDS * BAR_SEPERATOR_WIDTH) - 1);

class Graph extends React.Component {
  static propTypes = {
    pipeline: React.PropTypes.shape({
      id: React.PropTypes.string.isRequired,
      builds: React.PropTypes.shape({
        edges: React.PropTypes.arrayOf(
          React.PropTypes.shape({
            node: React.PropTypes.shape({
              state: React.PropTypes.string.isRequired,
              url: React.PropTypes.string.isRequired,
              startedAt: React.PropTypes.string,
              finishedAt: React.PropTypes.string
            }).isRequired
          }).isRequired
        )
      }).isRequired
    }).isRequired
  };

  state = {
    height: 0
  }

  componentDidMount() {
    this.toggleRenderInterval(this.props.pipeline.builds.edges);

    // As soon as the graph has mounted, set the height back to 100% to animate
    // the bars growing into view.
    setTimeout(() => {
      this.setState({ height: "100%" });
    }, 0);
  }

  componentWillReceiveProps(nextProps) {
    const thisLatestBuild = this.props.pipeline.builds.edges[0];
    const nextLatestBuild = nextProps.pipeline.builds.edges[0];

    // Set `shifting` if all the builds are being moved due to a new one coming in.
    if ((thisLatestBuild && nextLatestBuild) && thisLatestBuild.node.id !== nextLatestBuild.node.id) {
      this._shifting = true;
    }
  }

  componentDidUpdate() {
    this.toggleRenderInterval(this.props.pipeline.builds.edges);

    delete this._shifting;
  }

  render() {
    const classes = classNames("animation-height align-bottom relative absolute", {
      "animation-disable": this._shifting
    });

    return (

          {this.renderBars()}

    );
  }

  renderBars() {
    const bars = [];
    let maximumDuration = 1; // 1 to avoid a `0/0` when we calculate percentages

    for (let buildIndex = 0; buildIndex < MAXIMUM_NUMBER_OF_BUILDS; buildIndex++) {
      const buildEdge = this.props.pipeline.builds.edges[buildIndex];

      if (buildEdge) {
        const duration = this.durationForBuild(buildEdge.node);
        if (duration > maximumDuration) {maximumDuration = duration;}

        bars[MAXIMUM_NUMBER_OF_BUILDS - buildIndex - 1] = { color: this.colorForBuild(buildEdge.node), hoverColor: this.hoverColorForBuild(buildEdge.node), duration: duration, href: buildEdge.node.url, build: buildEdge.node };
      } else {
        bars[MAXIMUM_NUMBER_OF_BUILDS - buildIndex - 1] = { color: PENDING_COLOR, hoverColor: PENDING_COLOR_HOVER, duration: 0 };
      }
    }

    return bars.map((bar, index) => {
      const left = index * BAR_WIDTH_WITH_SEPERATOR;

      // Calcualte what percentage this bar is in relation to the longest
      // running build
      let height = (bar.duration / maximumDuration);

      // See if the height is less than our minimum. If it is, set a hard pixel
      // height, otherwise make the height a percentage. We use percentages so
      // we can animate the height of the graph as it loads in.
      let heightInPixels = (height * GRAPH_HEIGHT);
      if (heightInPixels < BAR_HEIGHT_MINIMUM) {
        height = BAR_HEIGHT_MINIMUM;
      } else {
        height = (height * 100) + "%";
      }

      return <Bar key={index} left={left} color={bar.color} hoverColor={bar.hoverColor} width={BAR_WIDTH_WITH_SEPERATOR} height={height} href={bar.href} build={bar.build || null} />;
    });
  }

  durationForBuild(build) {
    if (build.startedAt) {
      // Passing `null` to moment will result in a blank moment instance, so if
      // there isn't a finishedAt, just switch to undefined.
      return moment(build.finishedAt || undefined).diff(moment(build.startedAt));
    } else {
      return 0;
    }
  }

  colorForBuild(build) {
    if (build.state === "scheduled") {
      return SCHEDULED_COLOR;
    } else if (build.state === "running") {
      return RUNNING_COLOR;
    } else if (build.state === "passed" || build.state == "blocked") {
      return PASSED_COLOR;
    } else {
      return FAILED_COLOR;
    }
  }

  hoverColorForBuild(build) {
    if (build.state === "scheduled") {
      return SCHEDULED_COLOR_HOVER;
    } else if (build.state === "running") {
      return RUNNING_COLOR_HOVER;
    } else if (build.state === "passed" || build.state == "blocked") {
      return PASSED_COLOR_HOVER;
    } else {
      return FAILED_COLOR_HOVER;
    }
  }

  toggleRenderInterval(buildEdges) {
    // See if there is a build running
    let running = false;
    for (const edge of buildEdges) {
      if (edge.node.state === "running") {
        running = true;
        break;
      }
    }

    // If a build is running, ensure we have an interval setup that re-renders
    // the graph every second.
    if (running) {
      if (this._interval) {
        // no-op, interval already running
      } else {
        this._interval = setInterval(() => {
          this.forceUpdate();
        }, 1000);
      }
    } else {
      // Clear the interval now that nothing is running
      if (this._interval) {
        clearTimeout(this._interval);
        delete this._interval;
      }
    }
  }
}

export default Relay.createContainer(Graph, {
  fragments: {
    pipeline: () => Relay.QL`
      fragment on Pipeline {
        id
        builds(first: 30, branch: "%default", state: [ BUILD_STATE_SCHEDULED, BUILD_STATE_RUNNING, BUILD_STATE_PASSED, BUILD_STATE_FAILED, BUILD_STATE_CANCELED, BUILD_STATE_CANCELING, BUILD_STATE_BLOCKED ]) {
          edges {
            node {
              id
              state
              url
              startedAt
              finishedAt
              ${BuildTooltip.getFragment('build')}
            }
          }
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>import React from 'react'
import { Card, Flexbox2 as Flexbox, Table } from 'bonde-styleguide'
import { Gadget } from 'components'
import ListEmpty from './ListEmpty'

const TableCardGadget = ({
  title,
  loading,
  data,
  columns,
  border,
  emptyIcon,
  emptyText,
  renderFilter,
  renderPagination,
  HeaderComponent,
  page,
  pageTotal
}) => {
  const showPagination = (
    page && pageTotal && pageTotal > 1 && renderPagination
  )

  return (
    <Gadget
      title={title}
      renderFilter={renderFilter}
      WrapperComponent={({ children }) => (
        <Card height='275px'>
          {children}
        </Card>
      )}
    >
      <Flexbox vertical>
        {loading ?
Loading...
 : (

 (
              <ListEmpty
                iconColorfulName={emptyIcon}
                text={emptyText}
              />
            )}
          />
        )}
        {showPagination && (

            {renderPagination()}

        )}
      </Flexbox>
    </Gadget>
  )
}

export default TableCardGadget
<commit_msg>chore(admin-canary): remove load unpattern on home gadgets<commit_after>import React from 'react'
import { Card, Flexbox2 as Flexbox, Table } from 'bonde-styleguide'
import { Gadget } from 'components'
import ListEmpty from './ListEmpty'

const TableCardGadget = ({
  title,
  loading,
  data,
  columns,
  border,
  emptyIcon,
  emptyText,
  renderFilter,
  renderPagination,
  HeaderComponent,
  page,
  pageTotal
}) => {
  const showPagination = (
    page && pageTotal && pageTotal > 1 && renderPagination
  )

  return (
    <Gadget
      title={title}
      renderFilter={renderFilter}
      WrapperComponent={({ children }) => (
        <Card height='275px'>
          {children}
        </Card>
      )}
    >
      <Flexbox vertical>

 (
            <ListEmpty
              iconColorfulName={emptyIcon}
              text={emptyText}
            />
          )}
        />
        {showPagination && (

            {renderPagination()}

        )}
      </Flexbox>
    </Gadget>
  )
}

TableCardGadget.defaultProps = {
  data: []
}

export default TableCardGadget
<|endoftext|>


<commit_before>import { useHistory } from 'react-router-dom'
import { saveAuthorisation, isAuthorised } from '../../utils/auth'
import { useIntl } from 'react-intl'
import Page from 'material-ui-shell/lib/containers/Page/Page'
import React, { useState } from 'react'
import TextField from '@material-ui/core/TextField'
import Typography from '@material-ui/core/Typography'
import { makeStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import Home from '@material-ui/icons/Home'
import Paper from '@material-ui/core/Paper'

const useStyles = makeStyles((theme) => ({
  paper: {
    margin: 0,
    height: `calc(100vh - 64px)`,
  },
  avatar: {
    margin: theme.spacing(1),
    width: 192,
    height: 192,
    color: theme.palette.secondary.main,
  },
  form: {
    marginTop: theme.spacing(1),
  },
  submit: {
    margin: theme.spacing(3, 0, 2),
  },
  container: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    height: `100%`,
  },
}))

const SignIn = () => {
  const classes = useStyles()
  const intl = useIntl()
  const history = useHistory()
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')

  function handleSubmit(event) {
    event.preventDefault()
    authenticate({
      displayName: 'User',
      email: username,
    })
  }

  const authenticate = (user) => {
    saveAuthorisation(user)
    let _location = history.location
    let isAuth = isAuthorised()
    if (isAuth) {
      let _route = '/home'
      if (_location.state && _location.state.from) {
        _route = _location.state.from.pathname
        history.push(_route)
      } else {
        history.push(_route)
      }
    }
  }

  return (
    <Page pageTitle={intl.formatMessage({ id: 'sign_in' })}>
      <Paper className={classes.paper} elevation={6}>

          <Typography component="h1" variant="h5">
            {intl.formatMessage({ id: 'sign_in' })}
          </Typography>
          <form className={classes.form} onSubmit={handleSubmit} noValidate>
            <TextField
              value={username}
              onInput={(e) => setUsername(e.target.value)}
              variant="outlined"
              margin="normal"
              required
              fullWidth
              id="username"
              label={intl.formatMessage({ id: 'username' })}
              name="username"
              autoComplete="username"
              autoFocus
            />
            <TextField
              value={password}
              onInput={(e) => setPassword(e.target.value)}
              variant="outlined"
              margin="normal"
              required
              fullWidth
              name="password"
              label={intl.formatMessage({ id: 'password' })}
              type="password"
              id="password"
              autoComplete="current-password"
            />
            <Button
              type="submit"
              fullWidth
              variant="contained"
              color="primary"
              className={classes.submit}
            >
              {intl.formatMessage({ id: 'sign_in' })}
            </Button>
          </form>

      </Paper>
    </Page>
  )
}

export default SignIn
<commit_msg>Fixed open auth menu after sign in #133<commit_after>import { useHistory } from 'react-router-dom'
import { saveAuthorisation, isAuthorised } from '../../utils/auth'
import { useIntl } from 'react-intl'
import Page from 'material-ui-shell/lib/containers/Page/Page'
import React, { useState, useContext } from 'react'
import TextField from '@material-ui/core/TextField'
import Typography from '@material-ui/core/Typography'
import { makeStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import Home from '@material-ui/icons/Home'
import Paper from '@material-ui/core/Paper'
import MenuContext from 'material-ui-shell/lib/providers/Menu/Context'

const useStyles = makeStyles((theme) => ({
  paper: {
    margin: 0,
    height: `calc(100vh - 64px)`,
  },
  avatar: {
    margin: theme.spacing(1),
    width: 192,
    height: 192,
    color: theme.palette.secondary.main,
  },
  form: {
    marginTop: theme.spacing(1),
  },
  submit: {
    margin: theme.spacing(3, 0, 2),
  },
  container: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    height: `100%`,
  },
}))

const SignIn = () => {
  const classes = useStyles()
  const intl = useIntl()
  const history = useHistory()
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const { setAuthMenuOpen } = useContext(MenuContext)

  function handleSubmit(event) {
    event.preventDefault()
    authenticate({
      displayName: 'User',
      email: username,
    })
  }

  const authenticate = (user) => {
    saveAuthorisation(user)
    let _location = history.location
    let isAuth = isAuthorised()
    setAuthMenuOpen(false)
    if (isAuth) {
      let _route = '/home'
      if (_location.state && _location.state.from) {
        _route = _location.state.from.pathname
        history.push(_route)
      } else {
        history.push(_route)
      }
    }
  }

  return (
    <Page pageTitle={intl.formatMessage({ id: 'sign_in' })}>
      <Paper className={classes.paper} elevation={6}>

          <Typography component="h1" variant="h5">
            {intl.formatMessage({ id: 'sign_in' })}
          </Typography>
          <form className={classes.form} onSubmit={handleSubmit} noValidate>
            <TextField
              value={username}
              onInput={(e) => setUsername(e.target.value)}
              variant="outlined"
              margin="normal"
              required
              fullWidth
              id="username"
              label={intl.formatMessage({ id: 'username' })}
              name="username"
              autoComplete="username"
              autoFocus
            />
            <TextField
              value={password}
              onInput={(e) => setPassword(e.target.value)}
              variant="outlined"
              margin="normal"
              required
              fullWidth
              name="password"
              label={intl.formatMessage({ id: 'password' })}
              type="password"
              id="password"
              autoComplete="current-password"
            />
            <Button
              type="submit"
              fullWidth
              variant="contained"
              color="primary"
              className={classes.submit}
            >
              {intl.formatMessage({ id: 'sign_in' })}
            </Button>
          </form>

      </Paper>
    </Page>
  )
}

export default SignIn
<|endoftext|>


<commit_before>var db = require('../../persistence/db_access_v4');
var posHelper = require('./positionsHelper');
var queries = require('./dbQueries');
var parallel = require('async/parallel');

const RAILWAY = {
    id: 1,
    name: 'railway',
    description: 'Includes OpenStreetMap-Key:railway, Values: rail, light_rail, narrow_gauge, tram and subway.'
};

const STREET = {
    id: 2,
    name: 'street',
    description: 'Includes OpenStreetMap-Key:highway, Values: motorway, motorway_link, trunk, trunk_link, primary, ' +
    'primary_link, secondary, secondary_link, tertiary, tertiary_link, residential, road, unclassified, service, ' +
    'living_street and track.'
};

const BUILDING = {
    id: 3,
    name: 'building',
    description: 'Includes positions in or on top of a building.'
};

const UNKNOWN = {
    id: -1,
    name: 'unknown',
    description: 'No tagging possible.'
};

function getTag(typeOfMotion, positions, callback) {

    var tags = {
        railway: {
            probability: 0.0,
            location: RAILWAY
        },
        street: {
            probability: 0.0,
            location: STREET
        },
        building: {
            probability: 0.0,
            location: BUILDING
        }
    };

    switch(typeOfMotion.id) {

        //STATIONARY
        case 1:
        //PEDESTRIAN
        case 2:
            calculate_RAILWAY_STREET_BUILDING(tags, positions, callback);
            break;

        //VEHICULAR
        case 3:
            calculate_RAILWAY_STREET(tags, positions, callback);
            break;

        //HIGH_SPEED_VEHICULAR
        case 4:
            checkIf_RAILWAY(tags, positions, callback);
            break;

        default:
            callback({ tag: UNKNOWN, probability: null });
    }
}

function calculate_RAILWAY_STREET_BUILDING(tags, positions, callback) {

    var switzerlandDB = db.getDatabase(db.SWITZERLAND_DB);
    var streetDB = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    parallel([
            //Get the nearest building within 15 meters of each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(switzerlandDB, queries.SWITZERLAND_NEAREST_BUILDING, queryPositions, function (result) {
                        callback(null, result);
                });
            },
            //Get all railways or streets within 10 meters for each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(streetDB, queries.OSM_NEAREST_WAYS, queryPositions, function (result) {
                        callback(null, result);
                });
            }
        ],
        function(err, results) {

            //TODO: Check if this 3 buildings are the same
            var nearestBuildings = results[0];
            var nearestWays = results[1];

            tags = getBuildingProbability(tags, positions, nearestBuildings);
            tags = getStreetAndRailwayProbability(tags, positions, nearestWays);

            returnTag(tags, callback);
        });
}

function calculate_RAILWAY_STREET(tags, positions, callback) {

    var database = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    parallel([
            //Get all railways or streets within 10 meters for each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(database, queries.OSM_NEAREST_WAYS, queryPositions, function (result) {
                        callback(null, result);
                });
            }
        ],
        function(err, results) {

            var nearestWays = results[0];
            tags = getStreetAndRailwayProbability(tags, positions, nearestWays);
            returnTag(tags, callback);
        });
}

function checkIf_RAILWAY(tags, positions, callback) {

    var database = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    parallel([
            //Get all railways or streets within 10 meters for each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(database, queries.OSM_NEAREST_RAILWAYS, queryPositions, function (result) {
                        callback(null, result);
                });
            }
        ],
        function(err, results) {

            var nearestRailways = results[0];
            tags = getRailwayProbability(tags, positions, nearestRailways);
            returnTag(tags, callback);
        });
}

function getBuildingProbability(tags, positions, nearestBuildings) {

    const NUMBER_OF_POINTS = 3;
    var closeBuildingCount = 0;
    var totalAccuracy = 0;

    positions.forEach(function (pos) {
        totalAccuracy += pos.horizontal_accuracy;
    });

    for(var i = 0; i < NUMBER_OF_POINTS; i++) {

        //Check if building was found nearby
        if(nearestBuildings[i].length) {

            //The bigger the horizontal_accuracy (not accurate values), the smaller the pointProbability
            var pointProbability = 1 - (positions[i].horizontal_accuracy / totalAccuracy);
            closeBuildingCount += pointProbability;
        }
    }

    //NUMBER_OF_POINTS - 1: For 3 Input-Points, the maximum totalAccuracy is 2
    tags.building.probability += closeBuildingCount / (NUMBER_OF_POINTS - 1);

    return tags;
}

function getStreetAndRailwayProbability(tags, positions, nearestWays) {

    //each of the 3 points can have at most 3 nearest ways (street or railway)
    const NUMBER_OF_POINTS = 3;
    var totalAmountOfStreets = 0;
    var totalAmountOfRailways = 0;
    var totalAccuracy = 0;

    positions.forEach(function (pos) {
        totalAccuracy += pos.horizontal_accuracy;
    });

    //check each point, if a street or a railway is nearby
    for (var i = 0; i < nearestWays.length; i++){

        var amountOfStreets = 0;
        var amountOfRailways = 0;

        //The bigger the horizontal_accuracy (not accurate values), the smaller the pointProbability
        var pointProbability = 1 - (positions[i].horizontal_accuracy / totalAccuracy);

        //iterate through the nearest ways of 1 point
        for (var j = 0; j < nearestWays[i].length; j++){

            var wayType = clazzToWayType([nearestWays[i][j].clazz]);

            if(wayType === STREET && amountOfStreets === 0) {
                amountOfStreets += pointProbability;
            }
            else if (wayType === RAILWAY && amountOfRailways === 0) {
                amountOfRailways += pointProbability;
            }
        }

        totalAmountOfStreets += amountOfStreets;
        totalAmountOfRailways += amountOfRailways;
    }

    //NUMBER_OF_POINTS - 1: For 3 Input-Points, the maximum totalAccuracy is 2
    tags.street.probability += totalAmountOfStreets / (NUMBER_OF_POINTS - 1);
    tags.railway.probability += totalAmountOfRailways / (NUMBER_OF_POINTS - 1);

    return tags;
}

function getRailwayProbability(tags, positions, nearestWays) {

    const NUMBER_OF_POINTS = 3;
    var totalAmountOfRailways = 0;
    var totalAccuracy = 0;

    positions.forEach(function (pos) {
        totalAccuracy += pos.horizontal_accuracy;
    });

    for(var i = 0; i < NUMBER_OF_POINTS; i++) {

        //Check if railway was found nearby
        if(nearestWays[i].length) {

            //The bigger the horizontal_accuracy (not accurate values), the smaller the pointProbability
            var pointProbability = 1 - (positions[i].horizontal_accuracy / totalAccuracy);
            totalAmountOfRailways += pointProbability;
        }
    }

    //NUMBER_OF_POINTS - 1: For 3 Input-Points, the maximum totalAccuracy is 2
    tags.railway.probability += totalAmountOfRailways / (NUMBER_OF_POINTS - 1);

    return tags;
}

function clazzToWayType(clazz) {

    return (clazz > 0 && clazz < 17) ?  STREET : RAILWAY;
}

function returnTag(tags, callback) {

    var maxLocation = UNKNOWN;
    var maxProbability = 0.0;

    for(var key in tags) {

        if (!tags.hasOwnProperty(key)) continue;

        var tag = tags[key];
        if(tag.probability > maxProbability) {
            maxLocation = tag.location;
            maxProbability = tag.probability;
        }

        delete tag.location;
    }

    callback({ tag: maxLocation, probability: maxProbability, allProbabilities: tags });
}

module.exports = {
    "getTag": getTag
};<commit_msg>Überarbeitung tagging.js<commit_after>var db = require('../../persistence/db_access_v4');
var posHelper = require('./positionsHelper');
var queries = require('./dbQueries');
var parallel = require('async/parallel');

const RAILWAY = {
    id: 1,
    name: 'railway',
    description: 'Includes OpenStreetMap-Key:railway, Values: rail, light_rail, narrow_gauge, tram and subway.'
};

const STREET = {
    id: 2,
    name: 'street',
    description: 'Includes OpenStreetMap-Key:highway, Values: motorway, motorway_link, trunk, trunk_link, primary, ' +
    'primary_link, secondary, secondary_link, tertiary, tertiary_link, residential, road, unclassified, service, ' +
    'living_street and track.'
};

const BUILDING = {
    id: 3,
    name: 'building',
    description: 'Includes positions in or on top of a building.'
};

const UNKNOWN = {
    id: -1,
    name: 'unknown',
    description: 'No tagging possible.'
};

function getTag(typeOfMotion, positions, callback) {

    var tags = {
        railway: {
            probability: 0,
            location: RAILWAY
        },
        street: {
            probability: 0,
            location: STREET
        },
        building: {
            probability: 0,
            location: BUILDING
        }
    };

    switch(typeOfMotion.id) {

        //STATIONARY
        case 1:
        //PEDESTRIAN
        case 2:
            check_RAILWAY_STREET_BUILDING(tags, positions, callback);
            break;

        //VEHICULAR
        case 3:
            check_RAILWAY_STREET(tags, positions, callback);
            break;

        //HIGH_SPEED_VEHICULAR
        case 4:
            checkIf_RAILWAY(tags, positions, callback);
            break;

        default:
            callback({ tag: UNKNOWN, probability: null });
    }
}

function check_RAILWAY_STREET_BUILDING(tags, positions, callback) {

    var switzerlandDB = db.getDatabase(db.SWITZERLAND_DB);
    var streetDB = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    parallel([
            //Get the nearest building within X meters of each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(switzerlandDB, queries.SWITZERLAND_NEAREST_BUILDING, queryPositions, function (result) {
                        callback(null, result);
                });
            },
            //Get all railways or streets within X meters for each of the 3 positions
            function(callback) {
                db.queryMultipleParameterized(streetDB, queries.OSM_NEAREST_WAYS, queryPositions, function (result) {
                        callback(null, result);
                });
            }
        ],
        function(err, results) {

            var nearestBuildings = results[0];
            var nearestWays = results[1];

            tags = getBuildingProbability(tags, positions, nearestBuildings);
            tags = getStreetAndRailwayProbability(tags, positions, nearestWays);

            returnTag(tags, callback);
        });
}

function check_RAILWAY_STREET(tags, positions, callback) {

    var database = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    //Get all railways or streets within X meters for each of the 3 positions
    db.queryMultipleParameterized(database, queries.OSM_NEAREST_WAYS, queryPositions, function (result) {

        var nearestWays = result;
        tags = getStreetAndRailwayProbability(tags, positions, nearestWays);
        returnTag(tags, callback);
    });
}

function checkIf_RAILWAY(tags, positions, callback) {

    var database = db.getDatabase(db.STREETS_DB);
    var queryPositions = posHelper.makePoints(positions);

    //Get all railways or streets within X meters for each of the 3 positions
    db.queryMultipleParameterized(database, queries.OSM_NEAREST_RAILWAYS, queryPositions, function (result) {
        var nearestRailways = result;
        tags = getRailwayProbability(tags, positions, nearestRailways);
        returnTag(tags, callback);
    });
}

function getBuildingProbability(tags, positions, nearestBuildings) {

    //The bigger the horizontal_accuracy (not accurate values), the smaller the positionsWeight
    var positionsWeight = getPositionWeight(positions);

    for(var i = 0; i < positions.length; i++) {

        //Check if building was found nearby
        if(nearestBuildings[i].length) {
            tags.building.probability += positionsWeight[i];
        }
    }

    return tags;
}

function getStreetAndRailwayProbability(tags, positions, nearestWays) {

    //The bigger the horizontal_accuracy (not accurate values), the smaller the positionsWeight
    var positionsWeight = getPositionWeight(positions);

    //check for each point, if a street or a railway is nearby
    for(var i = 0; i < positions.length; i++) {

        var streetWeight = 0;
        var railwayWeight = 0;

        //each of the 3 points can have at most 3 nearest ways (street or railway)
        //a single point can only indicate 1 street and/or 1 railway (prevent double-count)
        nearestWays[i].forEach(function (way) {

            var wayType = clazzToWayType(way.clazz);

            if(wayType === STREET && streetWeight === 0) {
                streetWeight += positionsWeight[i];
            }
            else if (wayType === RAILWAY && railwayWeight === 0) {
                railwayWeight += positionsWeight[i];
            }
        });

        tags.street.probability += streetWeight;
        tags.railway.probability += railwayWeight;
    }

    return tags;
}

function getRailwayProbability(tags, positions, nearestWays) {

    //The bigger the horizontal_accuracy (not accurate values), the smaller the positionsWeight
    var positionsWeight = getPositionWeight(positions);

    for(var i = 0; i < positions.length; i++) {

        //Check if railway was found nearby
        if(nearestWays[i].length) {
            tags.railway.probability += positionsWeight[i];
        }
    }

    return tags;
}

function getPositionWeight(positions) {

    var totalHorizontalAccuracy = 0;
    var denominator = 0;
    var weights = [];

    positions.forEach(function (pos) {
        totalHorizontalAccuracy += pos.horizontal_accuracy;
    });

    positions.forEach(function (pos) {
        denominator += totalHorizontalAccuracy / pos.horizontal_accuracy;
    });

    for(var i = 0; i < positions.length; i++) {
        weights[i] = totalHorizontalAccuracy / denominator / positions[i].horizontal_accuracy;
    }

    return weights;
}

function clazzToWayType(clazz) {

    return (clazz > 0 && clazz < 17) ?  STREET : RAILWAY;
}

function returnTag(tags, callback) {

    var maxLocation = UNKNOWN;
    var maxProbability = 0;

    for(var key in tags) {

        if (!tags.hasOwnProperty(key)) continue;

        var tag = tags[key];
        if(tag.probability > maxProbability) {
            maxLocation = tag.location;
            maxProbability = tag.probability;
        }

        delete tag.location;
    }

    callback({ tag: maxLocation, probability: maxProbability, allProbabilities: tags });
}

module.exports = {
    "getTag": getTag
};<|endoftext|>


<commit_before>'use strict';

var angular = require('camunda-commons-ui/vendor/angular');
var each = angular.forEach;

var fs = require('fs');

var template = fs.readFileSync(__dirname + '/processes.html', 'utf8');

module.exports = [
  'ViewsProvider',
function (
  ViewsProvider
) {
  ViewsProvider.registerDefaultView('cockpit.dashboard.section', {
    id: 'processes',
    label: 'Processes',
    template: template,
    pagePath: '#/processes',
    checkActive: function (path) {
      // matches "#/process/", "#/processes" or "#/migration"
      return path.indexOf('#/process') > -1 || path.indexOf('#/migration') > -1;
    },
    controller: [
      '$scope',
      'Data',
      'dataDepend',
      'camAPI',
    function(
      $scope,
      Data,
      dataDepend,
      camAPI
    ) {
      var processData = $scope.processData = dataDepend.create($scope);

      Data.instantiateProviders('cockpit.dashboard.data', {
        $scope: $scope,
        processData: processData
      });

      var procStats = $scope.procDefStats = {
        definitions: {
          label: [
            'process definition',
            'process definitions'
          ]
        },
        instances: {
          label: [
            'running instance',
            'running instances'
          ]
        },
        incidents: {
          label: [
            'incident',
            'incidents'
          ]
        },
        failedJobs: {
          label: [
            'failed job',
            'failed jobs'
          ]
        }
      };

      $scope.gimmeDaLabel = function (prop) {
        return prop.label[(prop.value === 1) ? 0 : 1];
      };
      $scope.gimmeDaValue = function (count) {
        return count === 0 ? 'No' : count;
      };
      $scope.loadingState = 'LOADING';
      // should I mention how much I love AngularJS?
      $scope.procDefStatsKeys = Object.keys($scope.procDefStats);

      var processDefinitionService = camAPI.resource('process-definition');
      processDefinitionService.list({
        latest: true
      }, function(err, data) {
        $scope.processDefinitionData = data.items;

        procStats.definitions.value = data.items.length;
      });

      processData.observe('processDefinitionStatistics', function (defStats) {
        $scope.loadingState = 'LOADED';

        procStats.incidents.value = 0;
        procStats.instances.value = 0;
        procStats.failedJobs.value = 0;

        each(defStats, function (stats) {
          procStats.instances.value += stats.instances || 0;
          procStats.failedJobs.value += stats.failedJobs || 0;
          procStats.incidents.value += stats.incidents.length;
        });
      });
    }],

    priority: 0
  });
}];
<commit_msg>fix(cockpit): require angular directly in plugins<commit_after>'use strict';

var angular = require('angular');
var each = angular.forEach;

var fs = require('fs');

var template = fs.readFileSync(__dirname + '/processes.html', 'utf8');

module.exports = [
  'ViewsProvider',
function (
  ViewsProvider
) {
  ViewsProvider.registerDefaultView('cockpit.dashboard.section', {
    id: 'processes',
    label: 'Processes',
    template: template,
    pagePath: '#/processes',
    checkActive: function (path) {
      // matches "#/process/", "#/processes" or "#/migration"
      return path.indexOf('#/process') > -1 || path.indexOf('#/migration') > -1;
    },
    controller: [
      '$scope',
      'Data',
      'dataDepend',
      'camAPI',
    function(
      $scope,
      Data,
      dataDepend,
      camAPI
    ) {
      var processData = $scope.processData = dataDepend.create($scope);

      Data.instantiateProviders('cockpit.dashboard.data', {
        $scope: $scope,
        processData: processData
      });

      var procStats = $scope.procDefStats = {
        definitions: {
          label: [
            'process definition',
            'process definitions'
          ]
        },
        instances: {
          label: [
            'running instance',
            'running instances'
          ]
        },
        incidents: {
          label: [
            'incident',
            'incidents'
          ]
        },
        failedJobs: {
          label: [
            'failed job',
            'failed jobs'
          ]
        }
      };

      $scope.gimmeDaLabel = function (prop) {
        return prop.label[(prop.value === 1) ? 0 : 1];
      };
      $scope.gimmeDaValue = function (count) {
        return count === 0 ? 'No' : count;
      };
      $scope.loadingState = 'LOADING';
      // should I mention how much I love AngularJS?
      $scope.procDefStatsKeys = Object.keys($scope.procDefStats);

      var processDefinitionService = camAPI.resource('process-definition');
      processDefinitionService.list({
        latest: true
      }, function(err, data) {
        $scope.processDefinitionData = data.items;

        procStats.definitions.value = data.items.length;
      });

      processData.observe('processDefinitionStatistics', function (defStats) {
        $scope.loadingState = 'LOADED';

        procStats.incidents.value = 0;
        procStats.instances.value = 0;
        procStats.failedJobs.value = 0;

        each(defStats, function (stats) {
          procStats.instances.value += stats.instances || 0;
          procStats.failedJobs.value += stats.failedJobs || 0;
          procStats.incidents.value += stats.incidents.length;
        });
      });
    }],

    priority: 0
  });
}];
<|endoftext|>


<commit_before>/*jslint browser: true*/

if (navigator.serviceWorker && location.host !== 'localhost:8000') {
    navigator.serviceWorker.register('/serviceworker.js', {
        scope: '/'
    });
    window.addEventListener('load', function () {
        if (navigator.serviceWorker.controller) {
            navigator.serviceWorker.controller.postMessage({'command': 'trimCaches'});
        }
    });
}

(function () {
    var cookieMessage = document.getElementById('cookie-message');
    if (cookieMessage && document.cookie.indexOf('seen_cookie_message=yes') === -1) {
        cookieMessage.style.display = 'block';
        document.cookie = 'seen_cookie_message=yes; max-age=31536000; path=/';
    }
})();
<commit_msg>Catch some service worker errors? Does this work with Promises?<commit_after>/*jslint browser: true*/

if (navigator.serviceWorker && location.host !== 'localhost:8000') {
    try {
        navigator.serviceWorker.register('/serviceworker.js', {
            scope: '/'
        });
    } catch (ignore) {
    }
    window.addEventListener('load', function () {
        if (navigator.serviceWorker.controller) {
            navigator.serviceWorker.controller.postMessage({'command': 'trimCaches'});
        }
    });
}

(function () {
    var cookieMessage = document.getElementById('cookie-message');
    if (cookieMessage && document.cookie.indexOf('seen_cookie_message=yes') === -1) {
        cookieMessage.style.display = 'block';
        document.cookie = 'seen_cookie_message=yes; max-age=31536000; path=/';
    }
})();
<|endoftext|>


<commit_before>/**
 *  Router Map
 */

App.Router.map(function(){
    // FIXME: Temporary for testing purposes
    this.resource('order', {path: '/orders/:order_id/:status'});
    // this.resource('order', {path: '/orders/:order_id'});
});

/**
 * Project Routes
 */
App.OrderRoute = Em.Route.extend({
    model: function(params) {
        // FIXME: Temporary for testing purposes
        this.set('status', params.status);

        return App.MyOrder.find(params.order_id);
    },

    redirect: function(model) {
        var _this = this,
            status = _this.get('status');

        App.MyDonation.find({order: model.get('id')}).then(
            function(donations){
                // Take the first donation form the order and redirect to that project.
                var donation = donations.objectAt(0);

                // FIXME: For testing purposes we need to reload the project here.
                donation.get('project').reload().then( function () {
                    _this.transitionTo('project', donation.get('project.id')).promise.then(function () {
                        // FIXME: Temporary for testing purposes
                        switch (status) {
                            case 'success':
                                _this.send('openInDynamic', 'paymentSuccess', donation, 'modalFront');
                                break;
                            case 'pending':
                                _this.send('openInDynamic', 'paymentPending', donation, 'modalFront');
                                break;
                            case 'cancelled':
                                // Create a new payment for this order
                                var payment = App.MyPayment.createRecord({order: model});

                                _this.send('openInDynamic', 'payment', payment, 'modalFront');
                                break;
                        }
                    });
                });
            },
            function(){
                throw new Em.error('Donation not found!');
            }
        );
    }
});
<commit_msg>added check for order status pending with toast BOOK-680<commit_after>/**
 *  Router Map
 */

App.Router.map(function(){
    // FIXME: Temporary for testing purposes
    this.resource('order', {path: '/orders/:order_id/:status'});
    // this.resource('order', {path: '/orders/:order_id'});
});

/**
 * Project Routes
 */
App.OrderRoute = Em.Route.extend({
    model: function(params) {
        // FIXME: Temporary for testing purposes
        this.set('status', params.status);

        return App.MyOrder.find(params.order_id);
    },

    redirect: function(model) {
        var _this = this,
            status = _this.get('status');

        App.MyDonation.find({order: model.get('id')}).then(
            function(donations){
                // Take the first donation form the order and redirect to that project.
                var donation = donations.objectAt(0);

                // FIXME: For testing purposes we need to reload the project here.
                donation.get('project').reload().then( function () {
                    _this.transitionTo('project', donation.get('project.id')).promise.then(function () {
                        // FIXME: Temporary for testing purposes
                        switch (status) {
                            case 'success':
                                _this.send('openInDynamic', 'paymentSuccess', donation, 'modalFront');
                                break;
                            case 'pending':
                                // Display flash message until payment no longer
                                // pending
                                _this.send('setFlash', gettext('Processing payment'), 'welcome', false);

                                // Check the status of the order and then clear
                                // the flash message when the check resolves

                                // FIXME: Temporary for testing purposes we add
                                //        a timeout before checking order as the
                                //        mock api will return a 'success' immediately
                                //        causing the toast to only show briefly.
                                setTimeout(function () {
                                    _this._checkOrderStatus(model).then(function () {
                                        _this.send('clearFlash');
                                    });
                                }, 2000);

                                break;
                            case 'cancelled':
                                // Create a new payment for this order
                                var payment = App.MyPayment.createRecord({order: model});

                                _this.send('openInDynamic', 'payment', payment, 'modalFront');
                                break;
                        }
                    });
                });
            },
            function(){
                throw new Em.error('Donation not found!');
            }
        );
    },

    _checkOrderStatus: function (order) {
        return Ember.RSVP.Promise(function (resolve, reject) {
            // Check the status every 2.5 secs. This check is indefinite unless
            // the reloaded order changes status from pending.
            var checkInterval = setInterval(function () {
                checkStatus();
            }, 2500);

            var checkStatus = function () {
                // reload the order to fetch the latest status. If the order
                // is no longer pending then resolve the promise. If the
                // reload fails then we also resolve the promise.
                order.reload().then(function(reloadedOrder) {
                    if (reloadedOrder.get('status') != 'pending') {
                        // Stop the status check and resolve promise
                        stopCheckStatus();
                        Ember.run(null, resolve, reloadedOrder);
                    }
                }, function (reloadedOrder) {
                    // Stop the status check and resolve promise
                    stopCheckStatus();
                    Ember.run(null, resolve, reloadedOrder);
                });
            };

            var stopCheckStatus = function () {
                clearInterval(checkInterval);
            };
        });
    }
});
<|endoftext|>


<commit_before>function syncDefault() {
  chrome.storage.sync.set({
    lowLimit: 13,
    upLimit: 255,
    autoLoad: false,
    autoPlay: false,
  });
}
function checkOptsUse(cb) {
  chrome.storage.sync.getBytesInUse(null, (bytes) => { if (bytes === 0) cb(); });
}

function onInstalled() {
  chrome.runtime.onInstalled.addListener(() => {
    checkOptsUse(syncDefault);
    chrome.contextMenus.create({ id: 'bracketless', title: 'Bracketless: next action' });
  });
}

const tabState = {
  get(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.get(tabId.toString(), (state) => {
        resolve(state[tabId]);
      });
    });
  },
  set(tabId, value) {
    return new Promise((resolve) => {
      chrome.storage.local.set({ [tabId]: value }, () => resolve());
    });
  },
  remove(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.remove(tabId.toString(), () => resolve());
    });
  },
  clearAll() {
    chrome.storage.local.clear();
  },
};

function load(tabId) {
  return new Promise((resolve) => {
    chrome.tabs.executeScript(tabId, { file: 'src/bracketless.js' }, () => {
      chrome.browserAction.setIcon({ tabId, path: { 16: 'icons/play16.png', 32: 'icons/play32.png' } });
      chrome.browserAction.setTitle({ tabId, title: 'Collapse brackets' });
      chrome.tabs.insertCSS(tabId, { file: 'css/action.css' });
      chrome.tabs.executeScript(tabId, { file: 'src/action.js' }, () => {
        tabState.set(tabId, false)
          .then(() => resolve('load'));
      });
    });
  });
}

function activate(tabId, active) {
  return new Promise((resolve) => {
    const action = active === true ?
      { message: 'Pause collapsing', reverseIcon: 'pause' } :
      { message: 'Collapse brackets', reverseIcon: 'play' };
    chrome.browserAction.setIcon({ tabId, path: { 16: `icons/${action.reverseIcon}16.png`, 32: `icons/${action.reverseIcon}32.png` } });
    chrome.browserAction.setTitle({ tabId, title: action.message });
    chrome.tabs.sendMessage(tabId, active, () => {
      tabState.set(tabId, active)
        .then(() => resolve('action'));
    });
  });
}

function listenerAction(tabId) {
  tabState.get(tabId)
    .then((state) => {
      if (state === undefined) {
        return load(tabId);
      } else if (state === false) {
        return activate(tabId, true);
      } else if (state === true) {
        return activate(tabId, false);
      }
      return Promise.reject(new Error('Bracketless. listenerAction. if else'));
    })
    .catch((reason) => { throw reason; });
}

function autoAction(tabId) {
  // Call directly to bypass listenerAction conditional check.
  chrome.storage.sync.get(null, (options) => {
    if (options.autoPlay) {
      load(tabId).then(() => activate(tabId, true));
    } else if (options.autoLoad) {
      load(tabId);
    }
  });
}

// Filter out chrome util pages. Examples: https://git.io/vFZhQ
const webNavFilter = { url: [{ hostContains: '.' }] };

function webNavCommitted() {
  chrome.webNavigation.onCommitted.addListener((details) => {
    // autoAction reload clean up. tabs & webNav permissions obtained
    if (details.transitionType === 'reload') tabState.remove(details.tabId);
  }, webNavFilter);
}

function webNavLoaded() {
  chrome.webNavigation.onDOMContentLoaded.addListener((details) => {
    if (details.frameId === 0) autoAction(details.tabId);
  }, webNavFilter);
}

function tabsUpdated() {
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    // browserAction reload clean up. No .url access == no permission for this tab
    if (changeInfo.status === 'complete' && !Object.prototype.hasOwnProperty.call(tab, 'url')) {
      tabState.remove(tabId);
    }
  });
}

function tabsRemoved() {
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
    if (removeInfo.isWindowClosing) tabState.clearAll();
    else tabState.remove(tabId);
  });
}

function checkTabsWebNavPerm() {
  return new Promise((resolve, reject) => {
    chrome.permissions.contains({
      permissions: ['tabs', 'webNavigation'],
      origins: ['*://*/'],
    }, (result) => {
      if (result) resolve(result);
      else reject(result);
    });
  });
}

function onEventPage() {
  chrome.browserAction.onClicked.addListener(tab => listenerAction(tab.id));
  chrome.contextMenus.onClicked.addListener((_, tab) => listenerAction(tab.id));

  checkTabsWebNavPerm()
    .then(() => {
      webNavCommitted();
      webNavLoaded();
    }, () => {
      tabsUpdated();
    });
  tabsRemoved();
}

function eventPageReload() {
  chrome.runtime.onMessage.addListener(() => { onEventPage(); });
}

onInstalled();
onEventPage();
eventPageReload();
<commit_msg>Reorganize and add more comments<commit_after>function syncDefault() {
  chrome.storage.sync.set({
    lowLimit: 13,
    upLimit: 255,
    autoLoad: false,
    autoPlay: false,
  });
}
function checkOptsUse(cb) {
  chrome.storage.sync.getBytesInUse(null, (bytes) => { if (bytes === 0) cb(); });
}

function onInstalled() {
  chrome.runtime.onInstalled.addListener(() => {
    checkOptsUse(syncDefault); // for easy retrieval in bracketless.js
    chrome.contextMenus.create({ id: 'bracketless', title: 'Bracketless: next action' });
  });
}

const tabState = {
  get(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.get(tabId.toString(), (state) => {
        resolve(state[tabId]);
      });
    });
  },
  set(tabId, value) {
    return new Promise((resolve) => {
      chrome.storage.local.set({ [tabId]: value }, () => resolve());
    });
  },
  remove(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.remove(tabId.toString(), () => resolve());
    });
  },
  clearAll() {
    chrome.storage.local.clear();
  },
};

function load(tabId) {
  return new Promise((resolve) => {
    chrome.tabs.executeScript(tabId, { file: 'src/bracketless.js' }, () => {
      chrome.browserAction.setIcon({ tabId, path: { 16: 'icons/play16.png', 32: 'icons/play32.png' } });
      chrome.browserAction.setTitle({ tabId, title: 'Collapse brackets' });
      chrome.tabs.insertCSS(tabId, { file: 'css/action.css' });
      chrome.tabs.executeScript(tabId, { file: 'src/action.js' }, () => {
        tabState.set(tabId, false)
          .then(() => resolve('load'));
      });
    });
  });
}

function activate(tabId, active) {
  return new Promise((resolve) => {
    const action = active === true ?
      { message: 'Pause collapsing', reverseIcon: 'pause' } :
      { message: 'Collapse brackets', reverseIcon: 'play' };
    chrome.browserAction.setIcon({ tabId, path: { 16: `icons/${action.reverseIcon}16.png`, 32: `icons/${action.reverseIcon}32.png` } });
    chrome.browserAction.setTitle({ tabId, title: action.message });
    chrome.tabs.sendMessage(tabId, active, () => {
      tabState.set(tabId, active)
        .then(() => resolve('action'));
    });
  });
}

function listenerAction(tabId) {
  tabState.get(tabId)
    .then((state) => {
      if (state === undefined) {
        return load(tabId);
      } else if (state === false) {
        return activate(tabId, true);
      } else if (state === true) {
        return activate(tabId, false);
      }
      return Promise.reject(new Error('Bracketless. listenerAction. if else'));
    })
    .catch((reason) => { throw reason; });
}

// Clean up with any permission(s)
function tabsRemoved() {
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
    if (removeInfo.isWindowClosing) tabState.clearAll();
    else tabState.remove(tabId);
  });
}

// Only 'activeTab' permission
function tabsUpdated() {
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    // tab reload clean up. No .url access == no permission for this tab
    if (changeInfo.status === 'complete' && !Object.prototype.hasOwnProperty.call(tab, 'url')) {
      tabState.remove(tabId);
    }
  });
}

// Automation. 'tabs' and 'webNavigation' required
function checkTabsWebNavPerm() {
  return new Promise((resolve, reject) => {
    chrome.permissions.contains({
      permissions: ['tabs', 'webNavigation'],
      origins: ['*://*/'],
    }, (result) => {
      if (result) resolve(result);
      else reject(result);
    });
  });
}

function autoAction(tabId) {
  chrome.storage.sync.get(null, (options) => {
    if (options.autoPlay) {
      // Call directly to bypass listenerAction conditional check.
      load(tabId).then(() => activate(tabId, true));
    } else if (options.autoLoad) {
      load(tabId);
    }
  });
}

// Filter out chrome util pages. Examples: https://git.io/vFZhQ
const webNavFilter = { url: [{ hostContains: '.' }] };

function webNavCommitted() {
  chrome.webNavigation.onCommitted.addListener((details) => {
    // autoAction reload clean up. tabs & webNav permissions obtained
    if (details.transitionType === 'reload') tabState.remove(details.tabId);
  }, webNavFilter);
}

function webNavLoaded() {
  chrome.webNavigation.onDOMContentLoaded.addListener((details) => {
    if (details.frameId === 0) autoAction(details.tabId); // run only for main frame
  }, webNavFilter);
}

function onEventPage() {
  chrome.browserAction.onClicked.addListener(tab => listenerAction(tab.id));
  chrome.contextMenus.onClicked.addListener((_, tab) => listenerAction(tab.id));
  tabsRemoved();

  // determine which API use to listen for events
  checkTabsWebNavPerm()
    .then(() => {
      webNavCommitted();
      webNavLoaded();
    }, () => {
      tabsUpdated();
    });
}

function eventPageReload() {
  chrome.runtime.onMessage.addListener(() => { onEventPage(); });
}

onInstalled();
onEventPage();
eventPageReload();
<|endoftext|>


<commit_before>function syncDefault() {
  chrome.storage.sync.set({
    lowLimit: 13,
    upLimit: 255,
    autoLoad: false,
    autoPlay: false,
  });
}
function checkOptsUse(cb) {
  chrome.storage.sync.getBytesInUse(null, (bytes) => { if (bytes === 0) cb(); });
}

function onInstalled() {
  chrome.runtime.onInstalled.addListener(() => {
    checkOptsUse(syncDefault);
    chrome.contextMenus.create({ id: 'bracketless', title: 'Bracketless: next action' });
  });
}

const tabState = {
  get(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.get(tabId.toString(), (state) => {
        resolve(state[tabId]);
      });
    });
  },
  set(tabId, value) {
    return new Promise((resolve) => {
      chrome.storage.local.set({ [tabId]: value }, () => resolve());
    });
  },
  remove(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.remove(tabId.toString(), () => resolve());
    });
  },
  clearAll() {
    chrome.storage.local.clear();
  },
  getAll() {
    return new Promise((resolve) => {
      chrome.storage.local.get(null, (all) => {
        const activeIdArr = Object.keys(all).map(key => Number(key));
        resolve(activeIdArr);
      });
    });
  },
};

function load(tabId) {
  return new Promise((resolve) => {
    chrome.tabs.executeScript(tabId, { file: 'src/bracketless.js' }, () => {
      chrome.browserAction.setIcon({ tabId, path: { 16: 'icons/play16.png', 32: 'icons/play32.png' } });
      chrome.browserAction.setTitle({ tabId, title: 'Collapse brackets' });
      chrome.tabs.insertCSS(tabId, { file: 'css/action.css' });
      chrome.tabs.executeScript(tabId, { file: 'src/action.js' }, () => {
        tabState.set(tabId, false)
          .then(() => resolve('load resolved'));
      });
    });
  });
}

function activate(tabId, active) {
  return new Promise((resolve) => {
    const action = active === true ?
      { message: 'Pause collapsing', reverseIcon: 'pause' } :
      { message: 'Collapse brackets', reverseIcon: 'play' };
    chrome.browserAction.setIcon({ tabId, path: { 16: `icons/${action.reverseIcon}16.png`, 32: `icons/${action.reverseIcon}32.png` } });
    chrome.browserAction.setTitle({ tabId, title: action.message });
    chrome.tabs.sendMessage(tabId, active, () => {
      tabState.set(tabId, active)
        .then(() => { resolve(`action resolved. enabled: ${active}`); });
    });
  });
}

function listenerAction(tabId) {
  tabState.get(tabId)
    .then((state) => {
      if (state === undefined) {
        return load(tabId);
      } else if (state === false) {
        return activate(tabId, true);
      } else if (state === true) {
        return activate(tabId, false);
      }
      return Promise.reject(new Error('listenerAction if else'));
    })
    .catch((reason) => {
      throw Error(`Bracketless. listenerAction. Reason: ${reason}`);
    });
}

function checkTabsWebNavPerm() {
  return new Promise((resolve, reject) => {
    chrome.permissions.contains({
      permissions: ['tabs', 'webNavigation'],
      origins: ['http://*/', 'https://*/'],
    }, (result) => {
      if (result) resolve(result);
      else reject(result);
    });
  });
}

function autoAction(tabId) {
  // call fns directly to bypass listenerAction condition checks
  chrome.storage.sync.get(null, (options) => {
    if (options.autoPlay) {
      load(tabId).then(() => activate(tabId, true));
    } else if (options.autoLoad) {
      load(tabId);
    }
  });
}

// filter out chrome util pages. url examples: https://git.io/vFZhQ
const webNavFilter = { url: [{ hostContains: '.' }] };

function onWebNavCommitted() {
  chrome.webNavigation.onCommitted.addListener((details) => {
    if (details.transitionType === 'reload') tabState.remove(details.tabId); // autoAction clean up
  }, webNavFilter);
}

function onWebNavLoaded() {
  chrome.webNavigation.onDOMContentLoaded.addListener((details) => {
    if (details.frameId === 0) autoAction(details.tabId);
  }, webNavFilter);
}

function addOnUpdated() {
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    // as there is no reliable way to detect page reload via onUpdated, do it the weird way
    if (changeInfo.status === 'complete' && !Object.prototype.hasOwnProperty.call(tab, 'url')) {
      tabState.remove(tabId); // activeTab page reload clean up
    }
  });
}

function getOpenTabIdList() {
  return new Promise((resolve) => {
    chrome.tabs.query({ currentWindow: true }, (tabList) => {
      resolve(tabList.map(tab => tab.id));
    });
  });
}
function garbageCollector() {
  return Promise.all([tabState.getAll(), getOpenTabIdList()])
    .then((tabIdArr) => {
      const activeList = tabIdArr[0];
      const openList = tabIdArr[1];

      if (activeList.length > 4) {
        activeList.forEach((id) => {
          if (openList.includes(id) === false) {
            tabState.remove(id);
          }
        });
      }
    });
}
function addOnRemoved() {
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
    // tab is focused (matters only for activeTab) and browser window gets closed
    if (removeInfo.isWindowClosing) {
      tabState.clearAll();
      return;
    }

    checkTabsWebNavPerm()
      .then(() => { // autoOptions enabled, tabs permission obtained
        tabState.remove(tabId);
      }, () => { // autoOptions disabled, clean up via activeTab
        garbageCollector(removeInfo);
      })
      .catch((reason) => {
        throw Error(`Bracketless. addOnRemoved. Reason: ${reason}`);
      });
  });
}

function eventPageListeners() {
  chrome.browserAction.onClicked.addListener(tab => listenerAction(tab.id));
  chrome.contextMenus.onClicked.addListener((_, tab) => listenerAction(tab.id));

  // TODO: FIX
  // checks once for event page invocation
  // meaning that user will not see the changes before event page reboots
  checkTabsWebNavPerm()
    .then(() => {
      console.log('permissions!');
      onWebNavCommitted();
      onWebNavLoaded();
    }, () => {
      console.log('NO permissions.');
    });
  addOnUpdated();
  addOnRemoved();
}

onInstalled();
eventPageListeners();
<commit_msg>Move activeTab listener fns<commit_after>function syncDefault() {
  chrome.storage.sync.set({
    lowLimit: 13,
    upLimit: 255,
    autoLoad: false,
    autoPlay: false,
  });
}
function checkOptsUse(cb) {
  chrome.storage.sync.getBytesInUse(null, (bytes) => { if (bytes === 0) cb(); });
}

function onInstalled() {
  chrome.runtime.onInstalled.addListener(() => {
    checkOptsUse(syncDefault);
    chrome.contextMenus.create({ id: 'bracketless', title: 'Bracketless: next action' });
  });
}

const tabState = {
  get(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.get(tabId.toString(), (state) => {
        resolve(state[tabId]);
      });
    });
  },
  set(tabId, value) {
    return new Promise((resolve) => {
      chrome.storage.local.set({ [tabId]: value }, () => resolve());
    });
  },
  remove(tabId) {
    return new Promise((resolve) => {
      chrome.storage.local.remove(tabId.toString(), () => resolve());
    });
  },
  clearAll() {
    chrome.storage.local.clear();
  },
  getAll() {
    return new Promise((resolve) => {
      chrome.storage.local.get(null, (all) => {
        const activeIdArr = Object.keys(all).map(key => Number(key));
        resolve(activeIdArr);
      });
    });
  },
};

function load(tabId) {
  return new Promise((resolve) => {
    chrome.tabs.executeScript(tabId, { file: 'src/bracketless.js' }, () => {
      chrome.browserAction.setIcon({ tabId, path: { 16: 'icons/play16.png', 32: 'icons/play32.png' } });
      chrome.browserAction.setTitle({ tabId, title: 'Collapse brackets' });
      chrome.tabs.insertCSS(tabId, { file: 'css/action.css' });
      chrome.tabs.executeScript(tabId, { file: 'src/action.js' }, () => {
        tabState.set(tabId, false)
          .then(() => resolve('load resolved'));
      });
    });
  });
}

function activate(tabId, active) {
  return new Promise((resolve) => {
    const action = active === true ?
      { message: 'Pause collapsing', reverseIcon: 'pause' } :
      { message: 'Collapse brackets', reverseIcon: 'play' };
    chrome.browserAction.setIcon({ tabId, path: { 16: `icons/${action.reverseIcon}16.png`, 32: `icons/${action.reverseIcon}32.png` } });
    chrome.browserAction.setTitle({ tabId, title: action.message });
    chrome.tabs.sendMessage(tabId, active, () => {
      tabState.set(tabId, active)
        .then(() => { resolve(`action resolved. enabled: ${active}`); });
    });
  });
}

function listenerAction(tabId) {
  tabState.get(tabId)
    .then((state) => {
      if (state === undefined) {
        return load(tabId);
      } else if (state === false) {
        return activate(tabId, true);
      } else if (state === true) {
        return activate(tabId, false);
      }
      return Promise.reject(new Error('listenerAction if else'));
    })
    .catch((reason) => {
      throw Error(`Bracketless. listenerAction. Reason: ${reason}`);
    });
}

function checkTabsWebNavPerm() {
  return new Promise((resolve, reject) => {
    chrome.permissions.contains({
      permissions: ['tabs', 'webNavigation'],
      origins: ['http://*/', 'https://*/'],
    }, (result) => {
      if (result) resolve(result);
      else reject(result);
    });
  });
}

function autoAction(tabId) {
  // call fns directly to bypass listenerAction condition checks
  chrome.storage.sync.get(null, (options) => {
    if (options.autoPlay) {
      load(tabId).then(() => activate(tabId, true));
    } else if (options.autoLoad) {
      load(tabId);
    }
  });
}

// filter out chrome util pages. url examples: https://git.io/vFZhQ
const webNavFilter = { url: [{ hostContains: '.' }] };

function onWebNavCommitted() {
  chrome.webNavigation.onCommitted.addListener((details) => {
    if (details.transitionType === 'reload') tabState.remove(details.tabId); // autoAction clean up
  }, webNavFilter);
}

function onWebNavLoaded() {
  chrome.webNavigation.onDOMContentLoaded.addListener((details) => {
    if (details.frameId === 0) autoAction(details.tabId);
  }, webNavFilter);
}

function addOnUpdated() {
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    // as there is no reliable way to detect page reload via onUpdated, do it the weird way
    if (changeInfo.status === 'complete' && !Object.prototype.hasOwnProperty.call(tab, 'url')) {
      tabState.remove(tabId); // activeTab page reload clean up
    }
  });
}

function getOpenTabIdList() {
  return new Promise((resolve) => {
    chrome.tabs.query({ currentWindow: true }, (tabList) => {
      resolve(tabList.map(tab => tab.id));
    });
  });
}
function garbageCollector() {
  return Promise.all([tabState.getAll(), getOpenTabIdList()])
    .then((tabIdArr) => {
      const activeList = tabIdArr[0];
      const openList = tabIdArr[1];

      if (activeList.length > 4) {
        activeList.forEach((id) => {
          if (openList.includes(id) === false) {
            tabState.remove(id);
          }
        });
      }
    });
}
function addOnRemoved() {
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
    // tab is focused (matters only for activeTab) and browser window gets closed
    if (removeInfo.isWindowClosing) {
      tabState.clearAll();
      return;
    }

    checkTabsWebNavPerm()
      .then(() => { // autoOptions enabled, tabs permission obtained
        tabState.remove(tabId);
      }, () => { // autoOptions disabled, clean up via activeTab
        garbageCollector(removeInfo);
      })
      .catch((reason) => {
        throw Error(`Bracketless. addOnRemoved. Reason: ${reason}`);
      });
  });
}

function eventPageListeners() {
  chrome.browserAction.onClicked.addListener(tab => listenerAction(tab.id));
  chrome.contextMenus.onClicked.addListener((_, tab) => listenerAction(tab.id));

  // TODO: FIX
  // checks once for event page invocation
  // meaning that user will not see the changes before event page reboots
  checkTabsWebNavPerm()
    .then(() => {
      console.log('permissions!');
      onWebNavCommitted();
      onWebNavLoaded();
    }, () => {
      console.log('NO permissions.');
      addOnUpdated();
      addOnRemoved();
    });
}

onInstalled();
eventPageListeners();
<|endoftext|>