<commit_before>/**
 * WebSocket Server Settings
 * (sails.config.sockets)
 *
 * These settings provide transparent access to the options for Sails'
 * encapsulated WebSocket server, as well as some additional Sails-specific
 * configuration layered on top.
 *
 * For more information on sockets configuration, including advanced config options, see:
 * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.sockets.html
 */

module.exports.sockets = {

  /***************************************************************************
  *                                                                          *
  * This custom onDisconnect function will be run each time a socket         *
  * disconnects                                                              *
  *                                                                          *
  ***************************************************************************/
  afterDisconnect: function(session, socket) {
    Player.destroy({socket: socket.id}, function(err, deletedPlayers) {
      if (err) console.log(err);
    });
  },

  /***************************************************************************
  *                                                                          *
  * `transports`                                                             *
  *                                                                          *
  * A array of allowed transport methods which the clients will try to use.  *
  * The flashsocket transport is disabled by default You can enable          *
  * flashsockets by adding 'flashsocket' to this list:                       *
  *                                                                          *
  ***************************************************************************/
  // transports: [
  //   'websocket',
  //   'htmlfile',
  //   'xhr-polling',
  //   'jsonp-polling'
  // ],

  /***************************************************************************
  *                                                                          *
  * Use this option to set the datastore socket.io will use to manage        *
  * rooms/sockets/subscriptions: default: memory                             *
  *                                                                          *
  ***************************************************************************/

  // adapter: 'memory',

  /***************************************************************************
  *                                                                          *
  * Node.js (and consequently Sails.js) apps scale horizontally. It's a      *
  * powerful, efficient approach, but it involves a tiny bit of planning. At *
  * scale, you'll want to be able to copy your app onto multiple Sails.js    *
  * servers and throw them behind a load balancer.                           *
  *                                                                          *
  * One of the big challenges of scaling an application is that these sorts  *
  * of clustered deployments cannot share memory, since they are on          *
  * physically different machines. On top of that, there is no guarantee     *
  * that a user will "stick" with the same server between requests (whether  *
  * HTTP or sockets), since the load balancer will route each request to the *
  * Sails server with the most available resources. However that means that  *
  * all room/pubsub/socket processing and shared memory has to be offloaded  *
  * to a shared, remote messaging queue (usually Redis)                      *
  *                                                                          *
  * Luckily, Socket.io (and consequently Sails.js) apps support Redis for    *
  * sockets by default. To enable a remote redis pubsub server, uncomment    *
  * the config below.                                                        *
  *                                                                          *
  * Worth mentioning is that, if `adapter` config is `redis`, but host/port  *
  * is left unset, Sails will try to connect to redis running on localhost   *
  * via port 6379                                                            *
  *                                                                          *
  ***************************************************************************/

  // adapter: 'redis',
  // host: '127.0.0.1',
  // port: 6379,
  // db: 'sails',
  // pass: '<redis auth password>'

  /***************************************************************************
  *                                                                          *
  * `authorization`                                                          *
  *                                                                          *
  * Global authorization for Socket.IO access, this is called when the       *
  * initial handshake is performed with the server.                          *
  *                                                                          *
  * By default (`authorization: false`), when a socket tries to connect,     *
  * Sails allows it, every time. If no valid cookie was sent, a temporary    *
  * session will be created for the connecting socket.                       *
  *                                                                          *
  * If `authorization: true`, before allowing a connection, Sails verifies   *
  * that a valid cookie was sent with the upgrade request. If the cookie     *
  * doesn't match any known user session, a new user session is created for  *
  * it. (In most cases, the user would already have a cookie since they      *
  * loaded the socket.io client and the initial HTML page.)                  *
  *                                                                          *
  * However, in the case of cross-domain requests, it is possible to receive *
  * a connection upgrade request WITHOUT A COOKIE (for certain transports)   *
  * In this case, there is no way to keep track of the requesting user       *
  * between requests, since there is no identifying information to link      *
  * him/her with a session. The sails.io.js client solves this by connecting *
  * to a CORS endpoint first to get a 3rd party cookie (fortunately this     *
  * works, even in Safari), then opening the connection.                     *
  *                                                                          *
  * You can also pass along a ?cookie query parameter to the upgrade url,    *
  * which Sails will use in the absense of a proper cookie e.g. (when        *
  * connection from the client):                                             *
  * io.connect('http://localhost:1337?cookie=smokeybear')                    *
  *                                                                          *
  * (Un)fortunately, the user's cookie is (should!) not accessible in        *
  * client-side js. Using HTTP-only cookies is crucial for your app's        *
  * security. Primarily because of this situation, as well as a handful of   *
  * other advanced use cases, Sails allows you to override the authorization *
  * behavior with your own custom logic by specifying a function, e.g:       *
  *                                                                          *
  *    authorization: function authSocketConnectionAttempt(reqObj, cb) {     *
  *                                                                          *
  *        // Any data saved in `handshake` is available in subsequent       *
  *        requests from this as `req.socket.handshake.*`                    *
  *                                                                          *
  *        // to allow the connection, call `cb(null, true)`                 *
  *        // to prevent the connection, call `cb(null, false)`              *
  *        // to report an error, call `cb(err)`                             *
  *     }                                                                    *
  *                                                                          *
  ***************************************************************************/

  // authorization: false,

  /***************************************************************************
  *                                                                          *
  * Whether to run code which supports legacy usage for connected sockets    *
  * running the v0.9 version of the socket client SDK (i.e. sails.io.js).    *
  * Disabled in newly generated projects, but enabled as an implicit default *
  * (i.e. legacy usage/v0.9 clients be supported if this property is set to  *
  * true, but also if it is removed from this configuration file or set to   *
  * `undefined`)                                                             *
  *                                                                          *
  ***************************************************************************/

  // 'backwardsCompatibilityFor0.9SocketClients': false,

  /***************************************************************************
  *                                                                          *
  * Whether to expose a 'get /__getcookie' route with CORS support that sets *
  * a cookie (this is used by the sails.io.js socket client to get access to *
  * a 3rd party cookie and to enable sessions).                              *
  *                                                                          *
  * Warning: Currently in this scenario, CORS settings apply to interpreted  *
  * requests sent via a socket.io connection that used this cookie to        *
  * connect, even for non-browser clients! (e.g. iOS apps, toasters, node.js *
  * unit tests)                                                              *
  *                                                                          *
  ***************************************************************************/

  // grant3rdPartyCookie: true,

  /***************************************************************************
  *                                                                          *
  * Match string representing the origins that are allowed to connect to the *
  * Socket.IO server                                                         *
  *                                                                          *
  ***************************************************************************/

  // origins: '*:*',

};
<commit_msg>Updated sockets.js to new config for v0.11.0.<commit_after>/**
 * WebSocket Server Settings
 * (sails.config.sockets)
 *
 * These settings provide transparent access to the options for Sails'
 * encapsulated WebSocket server, as well as some additional Sails-specific
 * configuration layered on top.
 *
 * For more information on sockets configuration, including advanced config options, see:
 * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.sockets.html
 */

module.exports.sockets = {

  /***************************************************************************
  *                                                                          *
  * Node.js (and consequently Sails.js) apps scale horizontally. It's a      *
  * powerful, efficient approach, but it involves a tiny bit of planning. At *
  * scale, you'll want to be able to copy your app onto multiple Sails.js    *
  * servers and throw them behind a load balancer.                           *
  *                                                                          *
  * One of the big challenges of scaling an application is that these sorts  *
  * of clustered deployments cannot share memory, since they are on          *
  * physically different machines. On top of that, there is no guarantee     *
  * that a user will "stick" with the same server between requests (whether  *
  * HTTP or sockets), since the load balancer will route each request to the *
  * Sails server with the most available resources. However that means that  *
  * all room/pubsub/socket processing and shared memory has to be offloaded  *
  * to a shared, remote messaging queue (usually Redis)                      *
  *                                                                          *
  * Luckily, Socket.io (and consequently Sails.js) apps support Redis for    *
  * sockets by default. To enable a remote redis pubsub server, uncomment    *
  * the config below.                                                        *
  *                                                                          *
  * Worth mentioning is that, if `adapter` config is `redis`, but host/port  *
  * is left unset, Sails will try to connect to redis running on localhost   *
  * via port 6379                                                            *
  *                                                                          *
  ***************************************************************************/
  // adapter: 'memory',

  //
  // -OR-
  //

  // adapter: 'redis',
  // host: '127.0.0.1',
  // port: 6379,
  // db: 'sails',
  // pass: '<redis auth password>'

 /***************************************************************************
  *                                                                          *
  * Whether to expose a 'get /__getcookie' route with CORS support that sets *
  * a cookie (this is used by the sails.io.js socket client to get access to *
  * a 3rd party cookie and to enable sessions).                              *
  *                                                                          *
  * Warning: Currently in this scenario, CORS settings apply to interpreted  *
  * requests sent via a socket.io connection that used this cookie to        *
  * connect, even for non-browser clients! (e.g. iOS apps, toasters, node.js *
  * unit tests)                                                              *
  *                                                                          *
  ***************************************************************************/

  // grant3rdPartyCookie: true,

  /***************************************************************************
  *                                                                          *
  * `beforeConnect`                                                          *
  *                                                                          *
  * This custom beforeConnect function will be run each time BEFORE a new    *
  * socket is allowed to connect, when the initial socket.io handshake is    *
  * performed with the server.                                               *
  *                                                                          *
  * By default, when a socket tries to connect, Sails allows it, every time. *
  * (much in the same way any HTTP request is allowed to reach your routes.  *
  * If no valid cookie was sent, a temporary session will be created for the *
  * connecting socket.                                                       *
  *                                                                          *
  * If the cookie sent as part of the connetion request doesn't match any    *
  * known user session, a new user session is created for it.                *
  *                                                                          *
  * In most cases, the user would already have a cookie since they loaded    *
  * the socket.io client and the initial HTML pageyou're building.           *
  *                                                                          *
  * However, in the case of cross-domain requests, it is possible to receive *
  * a connection upgrade request WITHOUT A COOKIE (for certain transports)   *
  * In this case, there is no way to keep track of the requesting user       *
  * between requests, since there is no identifying information to link      *
  * him/her with a session. The sails.io.js client solves this by connecting *
  * to a CORS/jsonp endpoint first to get a 3rd party cookie(fortunately this*
  * works, even in Safari), then opening the connection.                     *
  *                                                                          *
  * You can also pass along a ?cookie query parameter to the upgrade url,    *
  * which Sails will use in the absense of a proper cookie e.g. (when        *
  * connecting from the client):                                             *
  * io.sails.connect('http://localhost:1337?cookie=smokeybear')              *
  *                                                                          *
  * Finally note that the user's cookie is NOT (and will never be) accessible*
  * from client-side javascript. Using HTTP-only cookies is crucial for your *
  * app's security.                                                          *
  *                                                                          *
  ***************************************************************************/
  // beforeConnect: function(handshake, cb) {
  //   // `true` allows the connection
  //   return cb(null, true);
  //
  //   // (`false` would reject the connection)
  // },

  /***************************************************************************
  *                                                                          *
  * This custom afterDisconnect function will be run each time a socket      *
  * disconnects                                                              *
  *                                                                          *
  ***************************************************************************/
  afterDisconnect: function(session, socket) {
    Player.destroy({socket: socket.id}, function(err, deletedPlayers) {
      if (err) console.log(err);
    });
  },

  // More configuration options for Sails+Socket.io:
  // http://sailsjs.org/#/documentation/reference/sails.config/sails.config.sockets.html

};
<|endoftext|>


<commit_before>import {
  REPLACE_STREET_DATA,
  ADD_SEGMENT,
  REMOVE_SEGMENT,
  MOVE_SEGMENT,
  UPDATE_SEGMENTS,
  CHANGE_SEGMENT_WIDTH,
  CHANGE_SEGMENT_VARIANT,
  CHANGE_SEGMENT_PROPERTIES,
  ADD_LOCATION,
  CLEAR_LOCATION,
  SAVE_STREET_NAME,
  SAVE_CREATOR_ID,
  SAVE_STREET_ID,
  SET_UPDATE_TIME,
  SAVE_ORIGINAL_STREET_ID,
  UPDATE_EDIT_COUNT,
  SET_UNITS,
  UPDATE_STREET_WIDTH,
  UPDATE_SCHEMA_VERSION,
  // BUILDINGS
  ADD_BUILDING_FLOOR,
  REMOVE_BUILDING_FLOOR,
  SET_BUILDING_FLOOR_VALUE,
  SET_BUILDING_VARIANT,
  SET_ENVIRONMENT
} from './'

import {
  RESIZE_TYPE_INCREMENT,
  RESIZE_TYPE_PRECISE_DRAGGING,
  resolutionForResizeType,
  normalizeSegmentWidth,
  cancelSegmentResizeTransitions
} from '../../segments/resizing'
import { recalculateWidth } from '../../streets/width'
import { saveStreetToServerIfNecessary } from '../../streets/data_model'

export function updateStreetData (street) {
  return {
    type: REPLACE_STREET_DATA,
    street
  }
}

export function addSegment (index, segment) {
  return {
    type: ADD_SEGMENT,
    index,
    segment
  }
}

export function removeSegment (index, immediate = true) {
  return {
    type: REMOVE_SEGMENT,
    index,
    immediate
  }
}

export function moveSegment (index, newIndex) {
  return {
    type: MOVE_SEGMENT,
    index,
    newIndex
  }
}

export function updateSegments (segments, occupiedWidth, remainingWidth) {
  return {
    type: UPDATE_SEGMENTS,
    segments,
    occupiedWidth,
    remainingWidth
  }
}

export function clearSegments () {
  return {
    type: UPDATE_SEGMENTS,
    segments: [],
    immediate: true
  }
}

export function changeSegmentWidth (index, width) {
  return {
    type: CHANGE_SEGMENT_WIDTH,
    index,
    width
  }
}

export function changeSegmentVariant (index, set, selection) {
  return {
    type: CHANGE_SEGMENT_VARIANT,
    index,
    set,
    selection
  }
}

export function changeSegmentProperties (index, properties) {
  return {
    type: CHANGE_SEGMENT_PROPERTIES,
    index,
    properties
  }
}

export function saveStreetName (streetName, userUpdated, system = false) {
  return {
    type: SAVE_STREET_NAME,
    streetName,
    userUpdated,
    system
  }
}

export function saveCreatorId (creatorId) {
  return {
    type: SAVE_CREATOR_ID,
    creatorId
  }
}

export function saveStreetId (id, namespacedId) {
  return {
    type: SAVE_STREET_ID,
    id,
    namespacedId
  }
}

// TODO: validate time is a string matching ISO string format
export function setUpdateTime (time) {
  return {
    type: SET_UPDATE_TIME,
    time
  }
}

export function saveOriginalStreetId (id) {
  return {
    type: SAVE_ORIGINAL_STREET_ID,
    id
  }
}

export function updateEditCount (count) {
  return {
    type: UPDATE_EDIT_COUNT,
    count
  }
}

export function setUnits (units) {
  return {
    type: SET_UNITS,
    units
  }
}

export function updateStreetWidth (width) {
  return {
    type: UPDATE_STREET_WIDTH,
    width
  }
}

/**
 * updateStreetWidth as a thunk action that automatically
 * dispatches segmentChanged
 *
 * @param {Number} width
 */
export function updateStreetWidthAction (width) {
  return async (dispatch, getState) => {
    await dispatch(updateStreetWidth(width))
    await dispatch(segmentsChanged())
  }
}

export function updateSchemaVersion (version) {
  return {
    type: UPDATE_SCHEMA_VERSION,
    version
  }
}

export function addLocation (location) {
  return {
    type: ADD_LOCATION,
    location
  }
}

export function clearLocation () {
  return {
    type: CLEAR_LOCATION,
    defaultName: null
  }
}

// Buildings

/**
 * Adds one more building floor
 *
 * @param {string} position - must be 'left' or 'right
 */
export function addBuildingFloor (position) {
  return {
    type: ADD_BUILDING_FLOOR,
    position
  }
}

/**
 * Removes one building floor
 *
 * @param {string} position - must be 'left' or 'right
 */
export function removeBuildingFloor (position) {
  return {
    type: REMOVE_BUILDING_FLOOR,
    position
  }
}

/**
 * Sets building floor to specific value
 *
 * @param {string} position - must be 'left' or 'right
 * @param {Number} value - the value to set it to
 */
export function setBuildingFloorValue (position, value) {
  return {
    type: SET_BUILDING_FLOOR_VALUE,
    position,
    value
  }
}

/**
 * Sets building to a selected variant
 *
 * @param {string} position - must be 'left' or 'right
 * @param {string} variant - the variant to set it to
 */
export function setBuildingVariant (position, variant) {
  return {
    type: SET_BUILDING_VARIANT,
    position,
    variant
  }
}

// Environment

/**
 * Sets environment
 *
 * @param {string} env - name of the environment
 */

export function setEnvironment (env) {
  return {
    type: SET_ENVIRONMENT,
    env
  }
}

export const segmentsChanged = () => {
  return async (dispatch, getState) => {
    const street = getState().street
    const updatedStreet = recalculateWidth(street)
    await dispatch(updateSegments(updatedStreet.segments, updatedStreet.occupiedWidth, updatedStreet.remainingWidth))
    // ToDo: Refactor this out to be dispatched as well
    saveStreetToServerIfNecessary()
  }
}

export const removeSegmentAction = (dataNo) => {
  return async (dispatch, getState) => {
    await dispatch(removeSegment(dataNo, false))
    await dispatch(segmentsChanged())
  }
}

export const incrementSegmentWidth = (dataNo, add, precise, origWidth, resizeType = RESIZE_TYPE_INCREMENT) => {
  return async (dispatch, getState) => {
    const units = getState().street.units
    let resolution

    if (precise) {
      resolution = resolutionForResizeType(RESIZE_TYPE_PRECISE_DRAGGING, units)
    } else {
      resolution = resolutionForResizeType(resizeType, units)
    }

    let increment = resolution

    if (!add) {
      increment = -increment
    }

    cancelSegmentResizeTransitions()
    const width = normalizeSegmentWidth(origWidth + increment, resolution)
    await dispatch(changeSegmentWidth(dataNo, width))
    await dispatch(segmentsChanged())
  }
}
<commit_msg>clearSegmentsAction as thunk action that dispatches segmentsChanged automatically after clearing segments<commit_after>import {
  REPLACE_STREET_DATA,
  ADD_SEGMENT,
  REMOVE_SEGMENT,
  MOVE_SEGMENT,
  UPDATE_SEGMENTS,
  CHANGE_SEGMENT_WIDTH,
  CHANGE_SEGMENT_VARIANT,
  CHANGE_SEGMENT_PROPERTIES,
  ADD_LOCATION,
  CLEAR_LOCATION,
  SAVE_STREET_NAME,
  SAVE_CREATOR_ID,
  SAVE_STREET_ID,
  SET_UPDATE_TIME,
  SAVE_ORIGINAL_STREET_ID,
  UPDATE_EDIT_COUNT,
  SET_UNITS,
  UPDATE_STREET_WIDTH,
  UPDATE_SCHEMA_VERSION,
  // BUILDINGS
  ADD_BUILDING_FLOOR,
  REMOVE_BUILDING_FLOOR,
  SET_BUILDING_FLOOR_VALUE,
  SET_BUILDING_VARIANT,
  SET_ENVIRONMENT
} from './'

import {
  RESIZE_TYPE_INCREMENT,
  RESIZE_TYPE_PRECISE_DRAGGING,
  resolutionForResizeType,
  normalizeSegmentWidth,
  cancelSegmentResizeTransitions
} from '../../segments/resizing'
import { recalculateWidth } from '../../streets/width'
import { saveStreetToServerIfNecessary } from '../../streets/data_model'

export function updateStreetData (street) {
  return {
    type: REPLACE_STREET_DATA,
    street
  }
}

export function addSegment (index, segment) {
  return {
    type: ADD_SEGMENT,
    index,
    segment
  }
}

export function removeSegment (index, immediate = true) {
  return {
    type: REMOVE_SEGMENT,
    index,
    immediate
  }
}

export function moveSegment (index, newIndex) {
  return {
    type: MOVE_SEGMENT,
    index,
    newIndex
  }
}

export function updateSegments (segments, occupiedWidth, remainingWidth) {
  return {
    type: UPDATE_SEGMENTS,
    segments,
    occupiedWidth,
    remainingWidth
  }
}

export function clearSegments () {
  return {
    type: UPDATE_SEGMENTS,
    segments: [],
    immediate: true
  }
}

export function changeSegmentWidth (index, width) {
  return {
    type: CHANGE_SEGMENT_WIDTH,
    index,
    width
  }
}

export function changeSegmentVariant (index, set, selection) {
  return {
    type: CHANGE_SEGMENT_VARIANT,
    index,
    set,
    selection
  }
}

export function changeSegmentProperties (index, properties) {
  return {
    type: CHANGE_SEGMENT_PROPERTIES,
    index,
    properties
  }
}

export function saveStreetName (streetName, userUpdated, system = false) {
  return {
    type: SAVE_STREET_NAME,
    streetName,
    userUpdated,
    system
  }
}

export function saveCreatorId (creatorId) {
  return {
    type: SAVE_CREATOR_ID,
    creatorId
  }
}

export function saveStreetId (id, namespacedId) {
  return {
    type: SAVE_STREET_ID,
    id,
    namespacedId
  }
}

// TODO: validate time is a string matching ISO string format
export function setUpdateTime (time) {
  return {
    type: SET_UPDATE_TIME,
    time
  }
}

export function saveOriginalStreetId (id) {
  return {
    type: SAVE_ORIGINAL_STREET_ID,
    id
  }
}

export function updateEditCount (count) {
  return {
    type: UPDATE_EDIT_COUNT,
    count
  }
}

export function setUnits (units) {
  return {
    type: SET_UNITS,
    units
  }
}

export function updateStreetWidth (width) {
  return {
    type: UPDATE_STREET_WIDTH,
    width
  }
}

/**
 * updateStreetWidth as a thunk action that automatically
 * dispatches segmentChanged
 *
 * @param {Number} width
 */
export function updateStreetWidthAction (width) {
  return async (dispatch, getState) => {
    await dispatch(updateStreetWidth(width))
    await dispatch(segmentsChanged())
  }
}

export function updateSchemaVersion (version) {
  return {
    type: UPDATE_SCHEMA_VERSION,
    version
  }
}

export function addLocation (location) {
  return {
    type: ADD_LOCATION,
    location
  }
}

export function clearLocation () {
  return {
    type: CLEAR_LOCATION,
    defaultName: null
  }
}

// Buildings

/**
 * Adds one more building floor
 *
 * @param {string} position - must be 'left' or 'right
 */
export function addBuildingFloor (position) {
  return {
    type: ADD_BUILDING_FLOOR,
    position
  }
}

/**
 * Removes one building floor
 *
 * @param {string} position - must be 'left' or 'right
 */
export function removeBuildingFloor (position) {
  return {
    type: REMOVE_BUILDING_FLOOR,
    position
  }
}

/**
 * Sets building floor to specific value
 *
 * @param {string} position - must be 'left' or 'right
 * @param {Number} value - the value to set it to
 */
export function setBuildingFloorValue (position, value) {
  return {
    type: SET_BUILDING_FLOOR_VALUE,
    position,
    value
  }
}

/**
 * Sets building to a selected variant
 *
 * @param {string} position - must be 'left' or 'right
 * @param {string} variant - the variant to set it to
 */
export function setBuildingVariant (position, variant) {
  return {
    type: SET_BUILDING_VARIANT,
    position,
    variant
  }
}

// Environment

/**
 * Sets environment
 *
 * @param {string} env - name of the environment
 */

export function setEnvironment (env) {
  return {
    type: SET_ENVIRONMENT,
    env
  }
}

export const segmentsChanged = () => {
  return async (dispatch, getState) => {
    const street = getState().street
    const updatedStreet = recalculateWidth(street)
    await dispatch(updateSegments(updatedStreet.segments, updatedStreet.occupiedWidth, updatedStreet.remainingWidth))
    // ToDo: Refactor this out to be dispatched as well
    saveStreetToServerIfNecessary()
  }
}

export const removeSegmentAction = (dataNo) => {
  return async (dispatch, getState) => {
    await dispatch(removeSegment(dataNo, false))
    await dispatch(segmentsChanged())
  }
}

export const clearSegmentsAction = () => {
  return async (dispatch, getState) => {
    await dispatch(clearSegments())
    await dispatch(segmentsChanged())
  }
}

export const incrementSegmentWidth = (dataNo, add, precise, origWidth, resizeType = RESIZE_TYPE_INCREMENT) => {
  return async (dispatch, getState) => {
    const units = getState().street.units
    let resolution

    if (precise) {
      resolution = resolutionForResizeType(RESIZE_TYPE_PRECISE_DRAGGING, units)
    } else {
      resolution = resolutionForResizeType(resizeType, units)
    }

    let increment = resolution

    if (!add) {
      increment = -increment
    }

    cancelSegmentResizeTransitions()
    const width = normalizeSegmentWidth(origWidth + increment, resolution)
    await dispatch(changeSegmentWidth(dataNo, width))
    await dispatch(segmentsChanged())
  }
}
<|endoftext|>


<commit_before>/**
 * Library Name: opacityChangeOnScroll
 * Library URL: https://github.com/sukritchhabra/opacityChangeOnScroll
 * Description: The library allows you to, by just assigning classes to your HTML elements to change the opacities of these elements on scroll.
 * Author: Sukrit Chhabra
 * Author URI: http://sukritchhabra.com
 * License: MIT
 */

/*jslint browser: true*/
/*jslint node: true*/
/*global $, jQuery, alert*/

$(document).ready(function(){
    $(document).on("scroll", function(event) {
        $(".increase-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();

            var newOpacity;

            var startPercentage = $(this).attr('data-start');   // Percentage offset from BOTTOM to start "animation"
            var endPercentage = $(this).attr('data-end');       // Percentage offset from TOP to start "animation"

            if(startPercentage == undefined) {
                startPercentage = 0;
            } else {
                startPercentage = parseInt(startPercentage);
            }

            if(endPercentage == undefined) {
                endPercentage = 0;
            } else {
                endPercentage = parseInt(endPercentage);
            }

            if (endPercentage > startPercentage) {
                throwError_startGreaterThanEnd();
            }

            var endValue = heightOfWindow*endPercentage/100;

            if(distanceOfElementFromTop < heightOfWindow) {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll)/distanceOfElementFromTop);
            } else {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll - endValue)/((heightOfWindow*(100 - startPercentage-endPercentage)/100)));
            }

            /**
             * To decrease on scroll down remove the "1 -".
             * Also change the .css("opacity", "1") to .css("opacity", "0") on line 42
             */

            /**
             * LOGIC
             *
             * If you're at the position where if you scroll the exact height of the window the top of your element will be the top of the page(not document, page),
             * that means (distanceOfElementFromTop(top of the document)-currentScroll) = heightOfWindow;
             * This yeilds an opacity 0. Basically when the element is just below the current window, i.e.,
             * one more pixel of a scroll down will reveal one pixel of the elementon the page, we want the opacity to be zero.
             *
             * eg: lets say windowHeight=1000; distanceOfElementFromTop(top of the document)=4000; currntScroll(the amount you've scrolled right now)=3000;
             * This means that on scrolling 1px currentScroll=3001; You are now 999px away from reaching 4000px but our element also exists at 4000px.
             * So when you reach a currentScroll=4000, the top of our element will align with the top of the page.
             */

            if(currentScroll <= distanceOfElementFromTop) {
                $(this).css("opacity", newOpacity);
            } else {
                $(this).css("opacity", "1");
            }
        });

        $(".decrease-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();

            var newOpacity;

            var startPercentage = $(this).attr('data-start');       // Percentage offset from BOTTOM to start "animation"
            var endPercentage = $(this).attr('data-end');           // Percentage offset from TOP to start "animation"

            if(startPercentage == undefined) {
                startPercentage = 0;
            } else {
                startPercentage = parseInt(startPercentage);
            }

            if(endPercentage == undefined) {
                endPercentage = 0;
            } else {
                endPercentage = parseInt(endPercentage);
            }

            if (endPercentage > startPercentage) {
                throwError_startGreaterThanEnd();
            }

            var endValue = heightOfWindow*endPercentage/100;

            if(distanceOfElementFromTop < heightOfWindow) {
                newOpacity = ((distanceOfElementFromTop - currentScroll)/distanceOfElementFromTop);
            } else {
                newOpacity = ((distanceOfElementFromTop - currentScroll - endValue)/((heightOfWindow*(100 - startPercentage-endPercentage)/100)));

               /**
                * LOGIC
                *
                * The calculation above was different before the addition of different attributes.
                * newOpacity = ((distanceOfElementFromTop - currentScroll )/heightOfWindow);
                *
                * For all purposes ahead lets assume distanceOfElementFromTop = 4000; currentScroll = 3000; heightOfWindow = 1000;
                *     In the earlier calculation difference(Step) between Opacity1(currentScroll = 3000) and Opacity2(currentScroll = 3001)
                *     was 1/1000 i.e. 0.001. That means, after a scroll of 1px, OPacity would decrease by 0.001;
                *     [for increase-on-scroll-down, it wouuld increase instead of decreasing]
                *
                *     Therefore, after a scroll of heightOfWindow, i.e., 1000px, the opacity would have decrease a complete 1 (from 1 -> 0)
                *     With the data-attributes, We want the step to be biggere because we are defining a region of the window
                *     where we want this change to take place.
                *     So if a user says, data-start = 20 and data-end = 40, i.e., start change when element is at a distance 80% away
                *     from the top and end it when it is at a distance 40% away from the top, In our example we want the change to take
                *     place between 800px and 400px. Therefore the step needs to be 1/(800-400) => 1/(heightOfWindow*((100 - startPercentage)-endPercentage)/100)
                *
                *     But we also want it to start from 1/0 => (distanceOfElementFromTop - currentScroll - (heightOfWindow*endPercentage/100) )
                */

                console.log(newOpacity);
            }

            if(currentScroll <= distanceOfElementFromTop) {
                $(this).css("opacity", newOpacity);
            } else {
                $(this).css("opacity", "0");
            }
        });

        $(".increase-decrease-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();
            var newOpacity;

            if (currentScroll <= distanceOfElementFromTop) {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll)/(heightOfWindow));
                if (newOpacity < 0) {
                    newOpacity = 0;
                }
                $(this).css("opacity", newOpacity);
            } else if (currentScroll > distanceOfElementFromTop) {
                newOpacity = 1 - ((currentScroll - distanceOfElementFromTop)/heightOfElement);
                if (newOpacity < 0) {
                    newOpacity = 0;
                }
                $(this).css("opacity", newOpacity);
            }
        });

        function throwError_startGreaterThanEnd() {
            alert('ERROR!\n\'data-end\' attribute has a greater value than \'data-start\' attribute');
        }
    });
});
<commit_msg>fixed incorrect condition, Fixes #1<commit_after>/**
 * Library Name: opacityChangeOnScroll
 * Library URL: https://github.com/sukritchhabra/opacityChangeOnScroll
 * Description: The library allows you to, by just assigning classes to your HTML elements to change the opacities of these elements on scroll.
 * Author: Sukrit Chhabra
 * Author URI: http://sukritchhabra.com
 * License: MIT
 */

/*jslint browser: true*/
/*jslint node: true*/
/*global $, jQuery, alert*/

$(document).ready(function(){
    $(document).on("scroll", function(event) {
        $(".increase-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();

            var newOpacity;

            var startPercentage = $(this).attr('data-start');   // Percentage offset from BOTTOM to start "animation"
            var endPercentage = $(this).attr('data-end');       // Percentage offset from TOP to start "animation"

            if(startPercentage == undefined) {
                startPercentage = 0;
            } else {
                startPercentage = parseInt(startPercentage);
            }

            if(endPercentage == undefined) {
                endPercentage = 0;
            } else {
                endPercentage = parseInt(endPercentage);
            }

            if ((endPercentage + startPercentage) > 100) {
                throwError_startGreaterThanEnd();
            }

            var endValue = heightOfWindow*endPercentage/100;

            if(distanceOfElementFromTop < heightOfWindow) {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll)/distanceOfElementFromTop);
            } else {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll - endValue)/((heightOfWindow*(100 - startPercentage-endPercentage)/100)));
            }

            /**
             * To decrease on scroll down remove the "1 -".
             * Also change the .css("opacity", "1") to .css("opacity", "0") on line 42
             */

            /**
             * LOGIC
             *
             * If you're at the position where if you scroll the exact height of the window the top of your element will be the top of the page(not document, page),
             * that means (distanceOfElementFromTop(top of the document)-currentScroll) = heightOfWindow;
             * This yeilds an opacity 0. Basically when the element is just below the current window, i.e.,
             * one more pixel of a scroll down will reveal one pixel of the elementon the page, we want the opacity to be zero.
             *
             * eg: lets say windowHeight=1000; distanceOfElementFromTop(top of the document)=4000; currntScroll(the amount you've scrolled right now)=3000;
             * This means that on scrolling 1px currentScroll=3001; You are now 999px away from reaching 4000px but our element also exists at 4000px.
             * So when you reach a currentScroll=4000, the top of our element will align with the top of the page.
             */

            if(currentScroll <= distanceOfElementFromTop) {
                $(this).css("opacity", newOpacity);
            } else {
                $(this).css("opacity", "1");
            }
        });

        $(".decrease-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();

            var newOpacity;

            var startPercentage = $(this).attr('data-start');       // Percentage offset from BOTTOM to start "animation"
            var endPercentage = $(this).attr('data-end');           // Percentage offset from TOP to start "animation"

            if(startPercentage == undefined) {
                startPercentage = 0;
            } else {
                startPercentage = parseInt(startPercentage);
            }

            if(endPercentage == undefined) {
                endPercentage = 0;
            } else {
                endPercentage = parseInt(endPercentage);
            }

            if ((endPercentage + startPercentage) > 100) {
                throwError_startGreaterThanEnd();
            }

            var endValue = heightOfWindow*endPercentage/100;

            if(distanceOfElementFromTop < heightOfWindow) {
                newOpacity = ((distanceOfElementFromTop - currentScroll)/distanceOfElementFromTop);
            } else {
                newOpacity = ((distanceOfElementFromTop - currentScroll - endValue)/((heightOfWindow*(100 - startPercentage-endPercentage)/100)));

               /**
                * LOGIC
                *
                * The calculation above was different before the addition of different attributes.
                * newOpacity = ((distanceOfElementFromTop - currentScroll )/heightOfWindow);
                *
                * For all purposes ahead lets assume distanceOfElementFromTop = 4000; currentScroll = 3000; heightOfWindow = 1000;
                *     In the earlier calculation difference(Step) between Opacity1(currentScroll = 3000) and Opacity2(currentScroll = 3001)
                *     was 1/1000 i.e. 0.001. That means, after a scroll of 1px, OPacity would decrease by 0.001;
                *     [for increase-on-scroll-down, it wouuld increase instead of decreasing]
                *
                *     Therefore, after a scroll of heightOfWindow, i.e., 1000px, the opacity would have decrease a complete 1 (from 1 -> 0)
                *     With the data-attributes, We want the step to be biggere because we are defining a region of the window
                *     where we want this change to take place.
                *     So if a user says, data-start = 20 and data-end = 40, i.e., start change when element is at a distance 80% away
                *     from the top and end it when it is at a distance 40% away from the top, In our example we want the change to take
                *     place between 800px and 400px. Therefore the step needs to be 1/(800-400) => 1/(heightOfWindow*((100 - startPercentage)-endPercentage)/100)
                *
                *     But we also want it to start from 1/0 => (distanceOfElementFromTop - currentScroll - (heightOfWindow*endPercentage/100) )
                */

                console.log(newOpacity);
            }

            if(currentScroll <= distanceOfElementFromTop) {
                $(this).css("opacity", newOpacity);
            } else {
                $(this).css("opacity", "0");
            }
        });

        $(".increase-decrease-on-scroll-down").each(function(index, el) {
            var distanceOfElementFromTop = $(this).offset().top;
            var currentScroll = $(window).scrollTop();
            var heightOfWindow = $(window).height();
            var heightOfElement = $(this).height();
            var newOpacity;

            if (currentScroll <= distanceOfElementFromTop) {
                newOpacity = 1 - ((distanceOfElementFromTop - currentScroll)/(heightOfWindow));
                if (newOpacity < 0) {
                    newOpacity = 0;
                }
                $(this).css("opacity", newOpacity);
            } else if (currentScroll > distanceOfElementFromTop) {
                newOpacity = 1 - ((currentScroll - distanceOfElementFromTop)/heightOfElement);
                if (newOpacity < 0) {
                    newOpacity = 0;
                }
                $(this).css("opacity", newOpacity);
            }
        });

        function throwError_startGreaterThanEnd() {
            alert('ERROR!\n\'data-end\' attribute has a greater value than \'data-start\' attribute');
        }
    });
});
<|endoftext|>


<commit_before>const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const webpackConfigCommon = require('@insum/config/webpack/webpack.config.common.js');

const isDevMode = process.env.NODE_ENV === 'development';

module.exports = function (helper) {

  let commonCFG = webpackConfigCommon(helper);

  commonCFG.plugins = [
    // Copy directory contents to {output}/path/to/dist/directory/
    new CopyWebpackPlugin([
      {
        from: helper.PATHS.root + '/CNAME',
        to: path.join(helper.PATHS.build)
      },
      {
        from: helper.PATHS.src + '/public',
        to: path.join(helper.PATHS.build, helper.PATHS.outputPath),
        toType: 'dir'
      },
      {
        from: helper.PATHS.src + '/data',
        to: path.join(helper.PATHS.build, helper.PATHS.outputPath, '/data'),
        toType: 'dir'
      },
    ]),
    new HtmlWebpackPlugin({
      template: path.resolve(helper.PATHS.src, 'index.html'),
      chunks: ['app', 'polyfills', 'vendors'],
      hash: false,
      inject: true,
      favicon: false,
      minify: false,
      cache: true,
    }),
    new HtmlWebpackPlugin({
      filename: '404.html',
      template: path.resolve(helper.PATHS.src, '404.html'),
      hash: false,
      inject: true,
      favicon: false,
      minify: false,
      cache: true,
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
  ]

  commonCFG.entry = {
    'app': path.resolve(helper.PATHS.src, 'main.ts'),
    'vendor': path.resolve(helper.PATHS.src, 'vendor.ts'),
    'note': path.resolve(helper.PATHS.src, 'note/index.ts'),
  };

  commonCFG.output = {
    path: helper.PATHS.build,
    publicPath: '/',
    filename: 'js/[name].js',
    chunkFilename: 'js/[name].bundle.js',
  }

  commonCFG.resolve = {
    modules: [helper.PATHS.src, helper.PATHS.node_modules],
    extensions: ['.ts', '.js', '.json', '.svg']
  };

  commonCFG.module.rules[2] = {
    test: /\.(png|jpg|jpeg|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
    loader: 'file-loader',
    options: {
      name: '[folder]/[name].[ext]?[hash]'
    },
    exclude: [helper.PATHS.node_modules]
  };

  commonCFG.module.rules[6] = {
    test: /\.(svg)$/,
    loader: 'html-loader',
    exclude: [path.join(helper.PATHS.src, 'components'), path.join(helper.PATHS.src, 'data')]
  };

  commonCFG.module.rules.unshift(
    {
      test: /\.scss$/,
      use: [
        {loader:  MiniCssExtractPlugin.loader,},
        'css-loader',
        'postcss-loader',
        'sass-loader',
      ],
      include: [path.join(helper.PATHS.src, 'note')]
    }
  );

  commonCFG.module.rules[5] = {
    ...commonCFG.module.rules[5],
    exclude: [path.join(helper.PATHS.src, 'note')]
  };

  commonCFG.module.rules.unshift(
    {
      test: /\.less$/,
      use: [
        'raw-loader',
        'postcss-loader',
        'less-loader',
      ],
      include: [path.join(helper.PATHS.src, 'components')]
    }
  );

  commonCFG.optimization = {
    minimize: !isDevMode,
    minimizer: [new TerserPlugin()],
    sideEffects: false,
    splitChunks: {
      cacheGroups: {
        vendors: {
          enforce: true
        }
      }
    }
  };

  return commonCFG;
};<commit_msg>change webpack config<commit_after>const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const webpackConfigCommon = require('@insum/config/webpack/webpack.config.common.js');

const isDevMode = process.env.NODE_ENV === 'development';

module.exports = function (helper) {

  let commonCFG = webpackConfigCommon(helper);

  commonCFG.plugins = [
    // Copy directory contents to {output}/path/to/dist/directory/
    new CopyWebpackPlugin([
      {
        from: helper.PATHS.root + '/CNAME',
        to: path.join(helper.PATHS.build)
      },
      {
        from: helper.PATHS.src + '/public',
        to: path.join(helper.PATHS.build, helper.PATHS.outputPath),
        toType: 'dir'
      },
      {
        from: helper.PATHS.src + '/data',
        to: path.join(helper.PATHS.build, helper.PATHS.outputPath, '/data'),
        toType: 'dir'
      },
    ]),
    new HtmlWebpackPlugin({
      template: path.resolve(helper.PATHS.src, 'index.html'),
      chunks: ['app', 'polyfills', 'vendors'],
      hash: false,
      inject: true,
      favicon: false,
      minify: false,
      cache: true,
    }),
    new HtmlWebpackPlugin({
      filename: '404.html',
      template: path.resolve(helper.PATHS.src, '404.html'),
      hash: false,
      inject: true,
      favicon: false,
      minify: false,
      cache: true,
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
  ]

  commonCFG.entry = {
    'app': path.resolve(helper.PATHS.src, 'main.ts'),
    'vendor': path.resolve(helper.PATHS.src, 'vendor.ts'),
    'note': path.resolve(helper.PATHS.src, 'modules/note/index.ts'),
  };

  commonCFG.output = {
    path: helper.PATHS.build,
    publicPath: '/',
    filename: 'js/[name].js',
    chunkFilename: 'js/[name].bundle.js',
  }

  commonCFG.resolve = {
    modules: [helper.PATHS.src, helper.PATHS.node_modules],
    extensions: ['.ts', '.js', '.json', '.svg']
  };

  commonCFG.module.rules[2] = {
    test: /\.(png|jpg|jpeg|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
    loader: 'file-loader',
    options: {
      name: '[folder]/[name].[ext]?[hash]'
    },
    exclude: [helper.PATHS.node_modules]
  };

  commonCFG.module.rules[6] = {
    test: /\.(svg)$/,
    loader: 'html-loader',
    exclude: [path.join(helper.PATHS.src, 'components'), path.join(helper.PATHS.src, 'data')]
  };

  commonCFG.module.rules.unshift(
    {
      test: /\.scss$/,
      use: [
        {loader:  MiniCssExtractPlugin.loader,},
        'css-loader',
        'postcss-loader',
        'sass-loader',
      ],
      include: [path.join(helper.PATHS.src, 'modules/note')]
    }
  );

  commonCFG.module.rules[5] = {
    ...commonCFG.module.rules[5],
    exclude: [path.join(helper.PATHS.src, 'modules/note')]
  };

  commonCFG.module.rules.unshift(
    {
      test: /\.less$/,
      use: [
        'raw-loader',
        'postcss-loader',
        'less-loader',
      ],
      // include: [path.join(helper.PATHS.src, 'components')]
    }
  );

  commonCFG.optimization = {
    minimize: !isDevMode,
    minimizer: [new TerserPlugin()],
    sideEffects: false,
    splitChunks: {
      cacheGroups: {
        vendors: {
          enforce: true
        }
      }
    }
  };

  return commonCFG;
};<|endoftext|>


<commit_before><commit_msg>Removed console.debug.<commit_after><|endoftext|>


<commit_before>// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')<commit_msg>Delete npm.js<commit_after><|endoftext|>


<commit_before>/**
 * @module  calendar
 * @author  Flavio De Stefano <flavio.destefano@caffeina.com>
 */

/**
 * @property config
 */
exports.config = _.extend({
}, Alloy.CFG.T ? Alloy.CFG.T.calendar : {});

var Util = require('T/util');
var Moment = require('alloy/moment');
var Permissions = require('T/permissions');

var RRule = require('T/ext/rrule');

if (OS_ANDROID) {
	var LDACalendar = require('lucadamico.android.calendar');
}

var RRT = {
	IOS_DATE_FORMAT: 'YYYY-MM-DDTHH:mm:ss.SSS+0000',
	map: {
		IOS_to_RR: {
			frequency: {},
			weekday: {},
		},
		RR_to_IOS: {
			freq: {},
			weekday: {},
		},
	},
	props: {
		RR_to_IOS: {
			interval : 'interval',
			count: 'end.occurrenceCount',
			until: function(ios, value) { ios.end = { endDate: Moment(value).format(RRT.IOS_DATE_FORMAT) }; },
			freq : 'frequency',
			bymonth: 'monthsOfTheYear',
			bymonthday: 'daysOfTheMonth',
			byyearday: 'daysOfTheYear',
			byweekday: function(ios, value) {
				ios.daysOfTheWeek = value.map(function(day) {
					return { dayOfWeek: RRT.map.RR_to_IOS.weekday[ JSON.stringify(day) ] };
				});
			}
		},
		IOS_to_RR: {
			interval : 'interval',
			'end.occurrenceCount': 'count',
			'end.endDate': function(rruleOpt, value) { rruleOpt.until = Moment(value).toDate(); },
			frequency: 'freq',
			monthsOfTheYear: 'bymonth',
			daysOfTheMonth: 'bymonthday',
			daysOfTheYear: 'byyearday',
			daysOfTheWeek: function(rruleOpt, value) {
				rruleOpt.byweekday = value.map(function(o) {
					return RRT.map.IOS_to_RR.weekday[ JSON.stringify(o.dayOfWeek) ];
				});
			}
		}
	}
};

_.each(['SU','MO','TU','WE','TH','FR','SA'], function(day, index) {
	RRT.map.RR_to_IOS.weekday[ JSON.stringify(RRule[day]) ] = (index+1);
	RRT.map.IOS_to_RR.weekday[ (index+1) ] = RRule[day];
});

_.each(['YEARLY','MONTHLY','WEEKLY','DAILY'], function(rec) {
	RRT.map.RR_to_IOS.freq[ JSON.stringify(RRule[rec]) ] = Ti.Calendar['RECURRENCEFREQUENCY_' + rec];
	RRT.map.IOS_to_RR.frequency[ JSON.stringify(Ti.Calendar['RECURRENCEFREQUENCY_' + rec]) ] = RRule[rec];
});

RRT.transformer = function(input) {
	var verse = this;
	var out = {};

	_.each(RRT.props[verse], function(out_prop_key, input_prop_key) {

		// retrieve the input value
		var input_prop_val = input;
		var input_prop_key_split = input_prop_key.split('.');

		for (var i = 0; i < input_prop_key_split.length; i++) {
			input_prop_val = input_prop_val[ input_prop_key_split[i] ];
			if (input_prop_val == null) return;
			if (_.isArray(input_prop_val) && input_prop_val.length === 0) return;
		}

		// check if exists a transform map of this attribute in this verse
		if (RRT.map[verse][input_prop_key]) {
			input_prop_val = RRT.map[verse][input_prop_key][ JSON.stringify(input_prop_val) ];
		}

		// define the output
		if (_.isString(out_prop_key)) {
			var mid_out = out;
			var out_prop_key_split = out_prop_key.split('.');
			for (var j = 0; j < out_prop_key_split.length; j++) {
				if (j+1 == out_prop_key_split.length) {
					mid_out[ out_prop_key_split[j] ] = input_prop_val;
				} else {
					mid_out[ out_prop_key_split[j] ] = mid_out[ out_prop_key_split[j] ] || {};
					mid_out = mid_out[ out_prop_key_split[j] ];
				}
			}
		} else if (_.isFunction(out_prop_key)) {
			// immediate callback alteration
			out_prop_key(out, input_prop_val);
		}
	});

	return out;
};

RRT.RR_to_IOS = RRT.transformer.bind('RR_to_IOS');
RRT.IOS_to_RR = RRT.transformer.bind('IOS_to_RR');

/**
 * Create an event in calendar
 * @param {Ti.Calendar.Calendar} calendar The calendar object
 * @param {Object} opt  Event properties. All properties are inherithed by Titanium.Calendar.Event
 * @param {Object} [opt.recurrenceRule] An optional recurrence rule.
 * @param {Object} [opt.alerts] An array of alerts.
 * @return {String} Event ID
 */
exports.createEvent = function(calendar, opt) {
	if (calendar == null) throw new Error("Calendar: passed calendar is null");
	if (calendar.id == null) throw new Error("Calendar: passed calendar doesn't have an ID");

	if (opt.title == null) throw new Error("Calendar: Set a title");
	if (opt.begin == null) throw new Error("Calendar: Set a begin date");
	if (opt.end == null && opt.allDay != true) throw new Error("Calendar: Set an end date or an allDay event");

	if (_.isString(opt.begin)) opt.begin = Moment(opt.begin).toDate();
	if (_.isString(opt.end)) opt.end = Moment(opt.end).toDate();

	if (opt.end != null && opt.end < opt.begin) throw new Error("Calendar: The end date is lesser than begin date");

	var event = calendar.createEvent( _.omit(opt, 'recurrenceRule', 'alerts') );

	if (opt.recurrenceRule != null) {
		exports.setRecurrenceRule(event, opt.recurrenceRule);
	}

	if (opt.alerts != null) {
		exports.setAlerts(event, opt.alerts);
	}

	if (OS_IOS) {
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );
	}

	return event.id;
};

/**
 * Retrieve an event by its ID
 * @param  {Ti.Calendar.Calendar} calendar The calendar object
 * @param  {String} id	The ID
 * @return {Ti.Calendar.Event}
 */
exports.getEventById = function(calendar, id) {
	return calendar.getEventById(id);
};

/**
 * Set a recurrence rule for the event.
 * Multiple recurrences are not supported for platform parity.
 * @param {Ti.Calendar.Event} event  The event.
 * @param {Object} rule  An object with recurrence rule.
 */
exports.setRecurrenceRule = function(event, rruleOpt) {
	rruleOpt.interval = rruleOpt.interval || 1;
	rruleOpt.dtstart = Moment(event.begin).toDate();
	var rrule = new RRule(rruleOpt);

 	if (OS_IOS) {

 		event.recurrenceRules = [ event.createRecurrenceRuleFromString(rrule.toString()) ];
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );

	} else if (OS_ANDROID) {

		var rows = LDACalendar.updateEventRecurrenceRule(event.id, rrule.toString());
		if (rows != 1) {
			throw new Error("Error while saving recurrence rules");
		}

	}

	return event;
};

/**
 * Get a recurrence rule instance for an event
 * @param  {Ti.Calendar.Event}
 * @return {calendar.RRule}
 */
exports.getRecurrenceRule = function(event) {
	var rrule = null;

	if (OS_IOS) {
		if (!_.isEmpty(event.recurrenceRules)) {
			rrule = new RRule(_.extend(RRT.IOS_to_RR(event.recurrenceRules[0]), {
				dtstart: Moment(event.begin).toDate()
			}));
		}
	} else if (OS_ANDROID) {
		if (!_.isEmpty(event.rrule)) {
			rrule = RRule.fromString(event.rrule);
		}
	}

	return rrule;
};

/**
 * Set the alerts for the event.
 * Each alert specifies how many minutes in advance the user will receive the notification (must be positive)
 * @param  {Ti.Calendar.Event} event
 * @param  {Array} alerts
 * @return {Ti.Calendar.Event}
 */
exports.setAlerts = function(event, alerts) {
	if (OS_IOS) {
		event.alerts = _.map(alerts, function(minutes) {
			return event.createAlert({
				relativeOffset: -1 * (minutes * 60 * 1000)
			});
		});
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );
	} else if (OS_ANDROID) {
		LDACalendar.deleteAllEventReminders(event.id);
		_.each(alerts, function(minutes) {
			var status = (1 == LDACalendar.addReminderToEvent(event.id, minutes));
			if (!status) throw new Error("Calendar: error in update event recurrence rule");
		});
	}

	return event;
};

/**
 * Get the alerts for the event.
 * @param  {Ti.Calendar.Event} event
 * @return {Array} alerts
 */
exports.getAlerts = function(event) {
	var alerts = [];

	if (OS_IOS) {
		alerts = event.getAlerts().map(function(a) {
			return -1 * (a.relativeOffset / (60 * 1000));
		});
	} else if (OS_ANDROID) {
		alerts = event.getAlerts().map(function(a) {
			return a.minutes;
		});
	}

	return alerts;
};

/**
 * Delete an event by its ID.
 * @param  {Ti.Calendar.Event} event The event.
 * @return {Boolean}
 */
exports.deleteEvent = function(event) {
	if (OS_IOS) {
		try {
			event.remove( Ti.Calendar.SPAN_FUTUREEVENTS );
			return true;
		} catch (ex) {
			Ti.API.error("Calendar: failed deleting event", ex.message);
			return false;
		}
	} else if (OS_ANDROID) {
		try {
			var rows = LDACalendar.deleteEvent(event.id);
			return (rows == 1);
		} catch (ex) {
			return false;
		}
	}
};

/**
 * Create a calendar.
 * @param  {Object} opt
 * @return {String} The calendar ID.
 */
exports.createCalendar = function(opt) {
	return Ti.Calendar.createCalendar(opt);
};

/**
 * Get a calendar by its ID.
 * @param  {String} id
 * @return {Ti.Calendar.Calendar}
 */
exports.getCalendarById = function(id) {
	return Ti.Calendar.getCalendarById(id);
};

/**
 * Get the default calendar for adding new events.
 * @return {Ti.Calendar.Calendar}
 */
exports.getDefaultCalendar = function() {
	// TODO: Create if zero calendar founds
	return Ti.Calendar.defaultCalendar || Ti.Calendar.allCalendars[0];
};

/**
 * Retrieve all calendars.
 * @return {Ti.Calendar.Calendar[]}
 */
exports.getAllCalendars = function() {
	return Ti.Calendar.allCalendars;
};

/**
 * Get the events of a calendar between two dates.
 * @param  {Ti.Calendar.Calendar}  cal
 * @param  {Object} d1  The date from
 * @param  {Object} d2  The date to
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsBetweenDates = function(cal, d1, d2) {
	d1 = Moment(d1).format(RRT.IOS_DATE_FORMAT);
	d2 = Moment(d2).format(RRT.IOS_DATE_FORMAT);
	return cal.getEventsBetweenDates(d1, d2);
};

/**
 * Get the events of a calendar in a specified date.
 * @param  {Ti.Calendar.Calendar} cal
 * @param  {Number} year
 * @param  {Number} month
 * @param  {Number} day
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInDate = function(cal, year, month, day) {
	return cal.getEventsInDate(year, month, day);
};

/**
 * Get the events of a calendar in a month.
 * @param  {Number} cal
 * @param  {Number} year
 * @param  {Number} month
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInMonth = function(cal, year, month) {
	return cal.getEventsInMonth(year, month);
};

/**
 * Get the events of a calendar in a year.
 * @param  {Number} cal
 * @param  {Number} year
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInYear = function(cal, year) {
	return cal.getEventsInYear(year);
};

/**
 * Get or create a Calendar that can be used by the application without dirtying other calendars.
 * The calendar ID object is saved in a persistent storage that will be deleted when the app
 * will be uninstalled, so take care of your ID.
 * The calendar name is automatically set by application name.
 * @return {Ti.Calendar.Calendar}
 */
exports.getOrCreateAppCalendar = function() {
	var id = Ti.App.Properties.getString('calendar_id', null);
	var cal = id != null ? exports.getCalendarById(id) : null;

	if (cal != null) return cal;

	id = exports.createCalendar({ name: Ti.App.name });
	if (id != null) {
		cal = exports.getCalendarById(id);
		Ti.App.Properties.setString('calendar_id', id);
	}

	if (cal != null) return cal;

	var defaultCalendar = exports.getDefaultCalendar();
	Ti.App.Properties.setString('calendar_id', defaultCalendar.id);
	return defaultCalendar;
};

/**
 * Delete a calendar by its ID
 * @param  {String} id The ID
 * @return {Boolean}
 */
exports.deleteCalendarById = function(id) {
	return Ti.Calendar.deleteCalendarById(id);
};

/**
 * Delete a calendar
 * @param  {Ti.Calendar} Calendar object
 * @return {Boolean}
 */
exports.deleteCalendar = function(c) {
	return exports.deleteCalendarById(c.id);
};

/**
 * Request the permissions to use calendars functions.
 * @param  {Function} success
 * @param  {Function} error
 */
exports.requestPermissions = function(success, error) {
	return Permissions.requestCalendarPermissions(success, error);
};

/**
 * RRule instance
 * @type {RRule}
 */
exports.RRule = RRule;

<commit_msg>New behav for getOrCreate<commit_after>/**
 * @module  calendar
 * @author  Flavio De Stefano <flavio.destefano@caffeina.com>
 */

/**
 * @property config
 */
exports.config = _.extend({
}, Alloy.CFG.T ? Alloy.CFG.T.calendar : {});

var Util = require('T/util');
var Moment = require('alloy/moment');
var Permissions = require('T/permissions');
var Dialog = require('T/dialog');

var RRule = require('T/ext/rrule');

if (OS_ANDROID) {
	var LDACalendar = require('lucadamico.android.calendar');
}

var RRT = {
	IOS_DATE_FORMAT: 'YYYY-MM-DDTHH:mm:ss.SSS+0000',
	map: {
		IOS_to_RR: {
			frequency: {},
			weekday: {},
		},
		RR_to_IOS: {
			freq: {},
			weekday: {},
		},
	},
	props: {
		RR_to_IOS: {
			interval : 'interval',
			count: 'end.occurrenceCount',
			until: function(ios, value) { ios.end = { endDate: Moment(value).format(RRT.IOS_DATE_FORMAT) }; },
			freq : 'frequency',
			bymonth: 'monthsOfTheYear',
			bymonthday: 'daysOfTheMonth',
			byyearday: 'daysOfTheYear',
			byweekday: function(ios, value) {
				ios.daysOfTheWeek = value.map(function(day) {
					return { dayOfWeek: RRT.map.RR_to_IOS.weekday[ JSON.stringify(day) ] };
				});
			}
		},
		IOS_to_RR: {
			interval : 'interval',
			'end.occurrenceCount': 'count',
			'end.endDate': function(rruleOpt, value) { rruleOpt.until = Moment(value).toDate(); },
			frequency: 'freq',
			monthsOfTheYear: 'bymonth',
			daysOfTheMonth: 'bymonthday',
			daysOfTheYear: 'byyearday',
			daysOfTheWeek: function(rruleOpt, value) {
				rruleOpt.byweekday = value.map(function(o) {
					return RRT.map.IOS_to_RR.weekday[ JSON.stringify(o.dayOfWeek) ];
				});
			}
		}
	}
};

_.each(['SU','MO','TU','WE','TH','FR','SA'], function(day, index) {
	RRT.map.RR_to_IOS.weekday[ JSON.stringify(RRule[day]) ] = (index+1);
	RRT.map.IOS_to_RR.weekday[ (index+1) ] = RRule[day];
});

_.each(['YEARLY','MONTHLY','WEEKLY','DAILY'], function(rec) {
	RRT.map.RR_to_IOS.freq[ JSON.stringify(RRule[rec]) ] = Ti.Calendar['RECURRENCEFREQUENCY_' + rec];
	RRT.map.IOS_to_RR.frequency[ JSON.stringify(Ti.Calendar['RECURRENCEFREQUENCY_' + rec]) ] = RRule[rec];
});

RRT.transformer = function(input) {
	var verse = this;
	var out = {};

	_.each(RRT.props[verse], function(out_prop_key, input_prop_key) {

		// retrieve the input value
		var input_prop_val = input;
		var input_prop_key_split = input_prop_key.split('.');

		for (var i = 0; i < input_prop_key_split.length; i++) {
			input_prop_val = input_prop_val[ input_prop_key_split[i] ];
			if (input_prop_val == null) return;
			if (_.isArray(input_prop_val) && input_prop_val.length === 0) return;
		}

		// check if exists a transform map of this attribute in this verse
		if (RRT.map[verse][input_prop_key]) {
			input_prop_val = RRT.map[verse][input_prop_key][ JSON.stringify(input_prop_val) ];
		}

		// define the output
		if (_.isString(out_prop_key)) {
			var mid_out = out;
			var out_prop_key_split = out_prop_key.split('.');
			for (var j = 0; j < out_prop_key_split.length; j++) {
				if (j+1 == out_prop_key_split.length) {
					mid_out[ out_prop_key_split[j] ] = input_prop_val;
				} else {
					mid_out[ out_prop_key_split[j] ] = mid_out[ out_prop_key_split[j] ] || {};
					mid_out = mid_out[ out_prop_key_split[j] ];
				}
			}
		} else if (_.isFunction(out_prop_key)) {
			// immediate callback alteration
			out_prop_key(out, input_prop_val);
		}
	});

	return out;
};

RRT.RR_to_IOS = RRT.transformer.bind('RR_to_IOS');
RRT.IOS_to_RR = RRT.transformer.bind('IOS_to_RR');

/**
 * Create an event in calendar
 * @param {Ti.Calendar.Calendar} calendar The calendar object
 * @param {Object} opt  Event properties. All properties are inherithed by Titanium.Calendar.Event
 * @param {Object} [opt.recurrenceRule] An optional recurrence rule.
 * @param {Object} [opt.alerts] An array of alerts.
 * @return {String} Event ID
 */
exports.createEvent = function(calendar, opt) {
	if (calendar == null) throw new Error("Calendar: passed calendar is null");
	if (calendar.id == null) throw new Error("Calendar: passed calendar doesn't have an ID");

	if (opt.title == null) throw new Error("Calendar: Set a title");
	if (opt.begin == null) throw new Error("Calendar: Set a begin date");
	if (opt.end == null && opt.allDay != true) throw new Error("Calendar: Set an end date or an allDay event");

	if (_.isString(opt.begin)) opt.begin = Moment(opt.begin).toDate();
	if (_.isString(opt.end)) opt.end = Moment(opt.end).toDate();

	if (opt.end != null && opt.end < opt.begin) throw new Error("Calendar: The end date is lesser than begin date");

	var event = calendar.createEvent( _.omit(opt, 'recurrenceRule', 'alerts') );

	if (opt.recurrenceRule != null) {
		exports.setRecurrenceRule(event, opt.recurrenceRule);
	}

	if (opt.alerts != null) {
		exports.setAlerts(event, opt.alerts);
	}

	if (OS_IOS) {
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );
	}

	return event.id;
};

/**
 * Retrieve an event by its ID
 * @param  {Ti.Calendar.Calendar} calendar The calendar object
 * @param  {String} id	The ID
 * @return {Ti.Calendar.Event}
 */
exports.getEventById = function(calendar, id) {
	return calendar.getEventById(id);
};

/**
 * Set a recurrence rule for the event.
 * Multiple recurrences are not supported for platform parity.
 * @param {Ti.Calendar.Event} event  The event.
 * @param {Object} rule  An object with recurrence rule.
 */
exports.setRecurrenceRule = function(event, rruleOpt) {
	rruleOpt.interval = rruleOpt.interval || 1;
	rruleOpt.dtstart = Moment(event.begin).toDate();
	var rrule = new RRule(rruleOpt);

 	if (OS_IOS) {

 		event.recurrenceRules = [ event.createRecurrenceRuleFromString(rrule.toString()) ];
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );

	} else if (OS_ANDROID) {

		var rows = LDACalendar.updateEventRecurrenceRule(event.id, rrule.toString());
		if (rows != 1) {
			throw new Error("Error while saving recurrence rules");
		}

	}

	return event;
};

/**
 * Get a recurrence rule instance for an event
 * @param  {Ti.Calendar.Event}
 * @return {calendar.RRule}
 */
exports.getRecurrenceRule = function(event) {
	var rrule = null;

	if (OS_IOS) {
		if (!_.isEmpty(event.recurrenceRules)) {
			rrule = new RRule(_.extend(RRT.IOS_to_RR(event.recurrenceRules[0]), {
				dtstart: Moment(event.begin).toDate()
			}));
		}
	} else if (OS_ANDROID) {
		if (!_.isEmpty(event.rrule)) {
			rrule = RRule.fromString(event.rrule);
		}
	}

	return rrule;
};

/**
 * Set the alerts for the event.
 * Each alert specifies how many minutes in advance the user will receive the notification (must be positive)
 * @param  {Ti.Calendar.Event} event
 * @param  {Array} alerts
 * @return {Ti.Calendar.Event}
 */
exports.setAlerts = function(event, alerts) {
	if (OS_IOS) {
		event.alerts = _.map(alerts, function(minutes) {
			return event.createAlert({
				relativeOffset: -1 * (minutes * 60 * 1000)
			});
		});
		event.save( Ti.Calendar.SPAN_FUTUREEVENTS );
	} else if (OS_ANDROID) {
		LDACalendar.deleteAllEventReminders(event.id);
		_.each(alerts, function(minutes) {
			var status = (1 == LDACalendar.addReminderToEvent(event.id, minutes));
			if (!status) throw new Error("Calendar: error in update event recurrence rule");
		});
	}

	return event;
};

/**
 * Get the alerts for the event.
 * @param  {Ti.Calendar.Event} event
 * @return {Array} alerts
 */
exports.getAlerts = function(event) {
	var alerts = [];

	if (OS_IOS) {
		alerts = event.getAlerts().map(function(a) {
			return -1 * (a.relativeOffset / (60 * 1000));
		});
	} else if (OS_ANDROID) {
		alerts = event.getAlerts().map(function(a) {
			return a.minutes;
		});
	}

	return alerts;
};

/**
 * Delete an event by its ID.
 * @param  {Ti.Calendar.Event} event The event.
 * @return {Boolean}
 */
exports.deleteEvent = function(event) {
	if (OS_IOS) {
		try {
			event.remove( Ti.Calendar.SPAN_FUTUREEVENTS );
			return true;
		} catch (ex) {
			Ti.API.error("Calendar: failed deleting event", ex.message);
			return false;
		}
	} else if (OS_ANDROID) {
		try {
			var rows = LDACalendar.deleteEvent(event.id);
			return (rows == 1);
		} catch (ex) {
			return false;
		}
	}
};

/**
 * Create a calendar.
 * @param  {Object} opt
 * @return {String} The calendar ID.
 */
exports.createCalendar = function(opt) {
	return Ti.Calendar.createCalendar(opt);
};

/**
 * Get a calendar by its ID.
 * @param  {String} id
 * @return {Ti.Calendar.Calendar}
 */
exports.getCalendarById = function(id) {
	return Ti.Calendar.getCalendarById(id);
};

/**
 * Get the default calendar for adding new events.
 * @return {Ti.Calendar.Calendar}
 */
exports.getDefaultCalendar = function() {
	// TODO: Create if zero calendar founds
	return Ti.Calendar.defaultCalendar || Ti.Calendar.allCalendars[0];
};

/**
 * Retrieve all calendars.
 * @return {Ti.Calendar.Calendar[]}
 */
exports.getAllCalendars = function() {
	return Ti.Calendar.allCalendars;
};

/**
 * Get the events of a calendar between two dates.
 * @param  {Ti.Calendar.Calendar}  cal
 * @param  {Object} d1  The date from
 * @param  {Object} d2  The date to
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsBetweenDates = function(cal, d1, d2) {
	d1 = Moment(d1).format(RRT.IOS_DATE_FORMAT);
	d2 = Moment(d2).format(RRT.IOS_DATE_FORMAT);
	return cal.getEventsBetweenDates(d1, d2);
};

/**
 * Get the events of a calendar in a specified date.
 * @param  {Ti.Calendar.Calendar} cal
 * @param  {Number} year
 * @param  {Number} month
 * @param  {Number} day
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInDate = function(cal, year, month, day) {
	return cal.getEventsInDate(year, month, day);
};

/**
 * Get the events of a calendar in a month.
 * @param  {Number} cal
 * @param  {Number} year
 * @param  {Number} month
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInMonth = function(cal, year, month) {
	return cal.getEventsInMonth(year, month);
};

/**
 * Get the events of a calendar in a year.
 * @param  {Number} cal
 * @param  {Number} year
 * @return {Ti.Calendar.Event[]}
 */
exports.getEventsInYear = function(cal, year) {
	return cal.getEventsInYear(year);
};

/**
 * Get or create a Calendar that can be used by the application without dirtying other calendars.
 * The calendar ID object is saved in a persistent storage that will be deleted when the app
 * will be uninstalled, so take care of your ID.
 * The calendar name is automatically set by application name.
 * @return {Ti.Calendar.Calendar}
 */
exports.getOrCreateAppCalendar = function() {
	var cal = null;
	var name = Ti.App.name;

	var id = Ti.App.Properties.getString('calendar_id', null);
	if (id != null) {
		cal = exports.getCalendarById(id);
	}

	if (cal == null) {
		cal = _.find(exports.getAllCalendars(), function(c) { return (c.name === name); });
		if (cal != null) {
			Ti.App.Properties.setString('calendar_id', cal.id);
		}
	}

	if (cal == null) {
		var idCr = exports.createCalendar({ name: name });
		if (idCr != null) {
			cal = exports.getCalendarById(idCr);
			if (cal != null) {
				Ti.App.Properties.setString('calendar_id', cal.id);
			}
		}
	}

	if (cal == null) {
		cal = exports.getDefaultCalendar();
		Ti.App.Properties.setString('calendar_id', cal.id);
	}

	return cal;
};

/**
 * Delete a calendar by its ID
 * @param  {String} id The ID
 * @return {Boolean}
 */
exports.deleteCalendarById = function(id) {
	return Ti.Calendar.deleteCalendarById(id);
};

/**
 * Delete a calendar
 * @param  {Ti.Calendar} Calendar object
 * @return {Boolean}
 */
exports.deleteCalendar = function(c) {
	return exports.deleteCalendarById(c.id);
};

/**
 * Request the permissions to use calendars functions.
 * @param  {Function} success
 * @param  {Function} error
 */
exports.requestPermissions = function(success, error) {
	return Permissions.requestCalendarPermissions(success, error);
};

/**
 * RRule instance
 * @type {RRule}
 */
exports.RRule = RRule;

<|endoftext|>


<commit_before>$(function() {
    $('#report-user-modal').modal('#report-user-abuse', {delegate: '#page'});

    if($('#user_edit').exists()) {
        $('.more-all, .more-none').click(_pd(function() {
            var $this = $(this);
            $this.closest('li').find('input:not([disabled]').attr('checked', $this.hasClass('more-all'));
        }));
    }

    // Hide change password box
    $('#acct-password').hide();
    $('#change-acct-password').click(_pd(function() {
          $('#acct-password').show();
          $('#id_oldpassword').focus();
          $(this).closest('li').hide();
    }));

    // Display image inline
    var $avatar = $('.profile-photo .avatar'),
        $a = $('<a>', {'text': gettext('use original'), 'class': 'use-original delete', 'href': '#'}).hide();

    $avatar.attr('data-original', $avatar.attr('src'));
    function use_original() {
        $('.use-original').hide();
        $('#id_photo').val("");
        $avatar.attr('src', $avatar.attr('data-original'));
    }
    $a.click(_pd(use_original));

    $avatar.after($a);
    $('#id_photo').change(function() {
        var $li = $(this).closest('li'),
            file = $(this)[0].files[0],
            file_name = file.name || file.fileName;
        $li.find('.errorlist').remove();
        if(!file_name.match(/\.(jpg|png|jpeg)$/)) {
            $ul = $('<ul>', {'class': 'errorlist'});
            $ul.append($('<li>', {'text': gettext('Images must be either PNG or JPG.')}));
            $li.append($ul);
            use_original();
            return;
        }
        var img = $(this).objectUrl();
        if(img) {
            $a.css('display', 'inline');
            $avatar.attr('src', img);
        }
    });
});

$('#admin-login').click(function() {
  window.location = $(this).attr('data-url');
});

<commit_msg>Make it more obvious the password field is being shown<commit_after>$(function() {
    $('#report-user-modal').modal('#report-user-abuse', {delegate: '#page'});

    if($('#user_edit').exists()) {
        $('.more-all, .more-none').click(_pd(function() {
            var $this = $(this);
            $this.closest('li').find('input:not([disabled]').attr('checked', $this.hasClass('more-all'));
        }));
    }

    // Hide change password box
    $('#acct-password').hide();
    $('#change-acct-password').click(_pd(function() {
          $('#acct-password').fadeIn();
          $('#id_oldpassword').focus();
          $(this).closest('li').hide();
    }));

    // Display image inline
    var $avatar = $('.profile-photo .avatar'),
        $a = $('<a>', {'text': gettext('use original'), 'class': 'use-original delete', 'href': '#'}).hide();

    $avatar.attr('data-original', $avatar.attr('src'));
    function use_original() {
        $('.use-original').hide();
        $('#id_photo').val("");
        $avatar.attr('src', $avatar.attr('data-original'));
    }
    $a.click(_pd(use_original));

    $avatar.after($a);
    $('#id_photo').change(function() {
        var $li = $(this).closest('li'),
            file = $(this)[0].files[0],
            file_name = file.name || file.fileName;
        $li.find('.errorlist').remove();
        if(!file_name.match(/\.(jpg|png|jpeg)$/)) {
            $ul = $('<ul>', {'class': 'errorlist'});
            $ul.append($('<li>', {'text': gettext('Images must be either PNG or JPG.')}));
            $li.append($ul);
            use_original();
            return;
        }
        var img = $(this).objectUrl();
        if(img) {
            $a.css('display', 'inline');
            $avatar.attr('src', img);
        }
    });
});

$('#admin-login').click(function() {
  window.location = $(this).attr('data-url');
});

<|endoftext|>


<commit_before>const { ServiceBroker } = require("../");

// Create broker Client
const brokerClient = new ServiceBroker({
	nodeID: "client",
	transporter: "NATS",
	logger: console,
	logLevel: "info"
});

// Create broker #1
const broker1 = new ServiceBroker({
	nodeID: "demo1",
	transporter: "NATS",
	logger: console,
	logLevel: "info"
});

// Create broker #2
const broker2 = new ServiceBroker({
	nodeID: "demo2",
	transporter: "NATS",
	logger: console,
	logLevel: "info"
});

// Create broker #3
const broker3 = new ServiceBroker({
	nodeID: "demo3",
	transporter: "NATS",
	logger: console,
	logLevel: "info"
});

// Create brokerListen
const brokerListen = new ServiceBroker({
	nodeID: "listen",
	transporter: "NATS",
	logger: console,
	logLevel: "info"
});

broker1.createService({
	name: "demo1",
	actions: {
		hello1(ctx) {
			console.log("call demo1.hello1 at: ", Date.now());
			return ctx.call("demo2.hello2");
		},
		hello1WithEvent(ctx) {
			broker1.emit("t1", { a: "abc", b: 123, c: true });
			console.log("call demo1.hello1WithEvent at: ", Date.now());
			return ctx.call("demo2.hello2WithEvent");
		}
	}
});

broker2.createService({
	name: "demo2",
	actions: {
		hello2(ctx) {
			console.log("call demo2.hello2 at: ", Date.now());
			return ctx.call("demo3.hello3");
		},
		hello2WithEvent(ctx) {
			broker2.emit("t2", { a: "abc", b: 123, c: true });
			console.log("call demo2.hello2WithEvent at: ", Date.now());
			return ctx.call("demo3.hello3WithEvent");
		}
	}
});

broker3.createService({
	name: "demo3",
	actions: {
		hello3(ctx) {
			console.log("call demo3.hello3 at: ", Date.now());
			return "hello from demo3";
		},
		hello3WithEvent(ctx) {
			broker3.emit("t3", { a: "abc", b: 123, c: true });
			console.log("call demo3.hello3WithEvent at: ", Date.now());
			return "hello from hello3WithEvent";
		}
	}
});

brokerListen.createService({
	name: "listen",
	events: {
		t1: (ctx) => {
			console.log("listen t1 at: ", Date.now());
		},
		t2: (ctx) => {
			console.log("listen t2 at: ", Date.now());
		},
		t3: (ctx) => {
			console.log("listen t3 at: ", Date.now());
		},
	}
});

brokerClient.Promise.all([brokerClient.start(), broker1.start(), broker2.start(), broker3.start(), brokerListen.start()])
	.delay(2000)
	.then(async () => {

		let startTime = Date.now();
		await brokerClient.call("demo1.hello1");
		let endTime = Date.now();
		console.log("call demo1.hello1 use time = ", endTime - startTime);

		startTime = Date.now();
		await brokerClient.call("demo1.hello1WithEvent");
		endTime = Date.now();
		console.log("call demo1.hello1WithEvent use time = ", endTime - startTime);

		// startTime = Date.now()
		// await brokerClient.call('demo1.hello1WithEvent')
		// endTime = Date.now()
		// console.log("call demo1.hello1WithEvent again use time = ", endTime - startTime)

	});
<commit_msg>add perf meter to emit latency test<commit_after>const { ServiceBroker } = require("../");

const transporter = "TCP";

// Create broker Client
const brokerClient = new ServiceBroker({
	nodeID: "client",
	transporter,
	logger: console,
	logLevel: "info"
});

// Create broker #1
const broker1 = new ServiceBroker({
	nodeID: "demo1",
	transporter,
	logger: console,
	logLevel: "info"
});

// Create broker #2
const broker2 = new ServiceBroker({
	nodeID: "demo2",
	transporter,
	logger: console,
	logLevel: "info"
});

// Create broker #3
const broker3 = new ServiceBroker({
	nodeID: "demo3",
	transporter,
	logger: console,
	logLevel: "info"
});

// Create brokerListen
const brokerListen = new ServiceBroker({
	nodeID: "listen",
	transporter,
	logger: console,
	logLevel: "info"
});

broker1.createService({
	name: "demo1",
	actions: {
		hello1(ctx) {
			// console.log("call demo1.hello1 at: ", Date.now());
			return ctx.call("demo2.hello2");
		},
		hello1WithEvent(ctx) {
			broker1.emit("t1", { a: "abc", b: 123, c: true });
			// console.log("call demo1.hello1WithEvent at: ", Date.now());
			return ctx.call("demo2.hello2WithEvent");
		}
	}
});

broker2.createService({
	name: "demo2",
	actions: {
		hello2(ctx) {
			// console.log("call demo2.hello2 at: ", Date.now());
			return ctx.call("demo3.hello3");
		},
		hello2WithEvent(ctx) {
			broker2.emit("t2", { a: "abc", b: 123, c: true });
			// console.log("call demo2.hello2WithEvent at: ", Date.now());
			return ctx.call("demo3.hello3WithEvent");
		}
	}
});

broker3.createService({
	name: "demo3",
	actions: {
		hello3(ctx) {
			// console.log("call demo3.hello3 at: ", Date.now());
			return "hello from demo3";
		},
		hello3WithEvent(ctx) {
			broker3.emit("t3", { a: "abc", b: 123, c: true });
			//console.log("call demo3.hello3WithEvent at: ", Date.now());
			return "hello from hello3WithEvent";
		}
	}
});

brokerListen.createService({
	name: "listen",
	events: {
		t1: (ctx) => {
			//console.log("listen t1 at: ", Date.now());
		},
		t2: (ctx) => {
			//console.log("listen t2 at: ", Date.now());
		},
		t3: (ctx) => {
			//console.log("listen t3 at: ", Date.now());
		},
	}
});

brokerClient.Promise.all([brokerClient.start(), broker1.start(), broker2.start(), broker3.start(), brokerListen.start()])
	.delay(10000)
	/*.then(async () => {

		let startTime = Date.now();
		await brokerClient.call("demo1.hello1");
		let endTime = Date.now();
		console.log("call demo1.hello1 use time = ", endTime - startTime);

		startTime = Date.now();
		await brokerClient.call("demo1.hello1WithEvent");
		endTime = Date.now();
		console.log("call demo1.hello1WithEvent use time = ", endTime - startTime);

		// startTime = Date.now()
		// await brokerClient.call('demo1.hello1WithEvent')
		// endTime = Date.now()
		// console.log("call demo1.hello1WithEvent again use time = ", endTime - startTime)

	});*/

	.then(() => {

		let count = 0;
		function doRequest() {
			count++;
			//return brokerClient.call("demo1.hello1")
			return brokerClient.call("demo1.hello1WithEvent")
				.then(() => {
					if (count % 10000) {
						// Fast cycle
						doRequest();
					} else {
						// Slow cycle
						setImmediate(() => doRequest());
					}
				});
		}

		let startTime = Date.now();

		setInterval(() => {
			let rps = count / ((Date.now() - startTime) / 1000);
			console.log("RPS:", rps.toLocaleString("hu-HU", {maximumFractionDigits: 0}), "req/s");
			count = 0;
			startTime = Date.now();
		}, 1000);

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


<commit_before>const shell = require('shelljs')
const path = require('path')

const phenylModules = shell.ls('./modules')

const linkPhenylModules = (moduleNames) => {
  moduleNames.forEach(module => {
    shell.cd('node_modules')
    shell.echo(`link ${module}`)
    shell.ln('-s', `../../${module}`, module)
    shell.cd('../')
  })
}

shell.exec('npm i')

phenylModules.forEach(module => {
  shell.cd(`modules/${module}`)

  const packageJson = require(path.join(__dirname, `../modules/${module}/package.json`))
  let modulesInPhenyl = []

  if (packageJson.dependencies != null) {
    const dependencies = Object.keys(packageJson.dependencies)
    modulesInPhenyl = modulesInPhenyl.concat(dependencies.filter(dependency => (phenylModules.includes(dependency))))
  }

  if (packageJson.devDependencies != null) {
    const devDependencies = Object.keys(packageJson.devDependencies)
    modulesInPhenyl = modulesInPhenyl.concat(devDependencies.filter(devDependency => (phenylModules.includes(devDependency))))
  }

  shell.mkdir('-p', 'node_modules')
  linkPhenylModules(modulesInPhenyl)
  shell.exec('npm i')

  shell.cd('../../')
})
<commit_msg>phenyl: ignore files in modules on loading<commit_after>const shell = require('shelljs')
const path = require('path')

const phenylModules = shell.exec(
  'ls -F ./modules | grep / | tr -d "/"',
  { silent: true }
).trim().split('\n')

const linkPhenylModules = (moduleNames) => {
  moduleNames.forEach(module => {
    shell.cd('node_modules')
    shell.echo(`link ${module}`)
    shell.ln('-s', `../../${module}`, module)
    shell.cd('../')
  })
}

shell.exec('npm i')

phenylModules.forEach(module => {
  shell.cd(`modules/${module}`)

  const packageJson = require(path.join(__dirname, `../modules/${module}/package.json`))
  let modulesInPhenyl = []

  if (packageJson.dependencies != null) {
    const dependencies = Object.keys(packageJson.dependencies)
    modulesInPhenyl = modulesInPhenyl.concat(dependencies.filter(dependency => (phenylModules.includes(dependency))))
  }

  if (packageJson.devDependencies != null) {
    const devDependencies = Object.keys(packageJson.devDependencies)
    modulesInPhenyl = modulesInPhenyl.concat(devDependencies.filter(devDependency => (phenylModules.includes(devDependency))))
  }

  shell.mkdir('-p', 'node_modules')
  linkPhenylModules(modulesInPhenyl)
  shell.exec('npm i')

  shell.cd('../../')
})
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const CONST = require('../common/constants');
const Agent = require('../data-access-layer/service-agent');
const errors = require('../common/errors');
const NotImplemented = errors.NotImplemented;

class BaseService {
  constructor(plan) {
    this.plan = plan;
    this.agent = new Agent(this.settings.agent);
  }

  get settings() {
    return this.plan.manager.settings;
  }

  getTenantGuid(context) {
    if (context.platform === CONST.PLATFORM.CF) {
      return context.space_guid;
    } else if (context.platform === CONST.PLATFORM.K8S) {
      return context.namespace;
    }
  }

  get service() {
    return this.plan.service;
  }

  verifyFeatureSupport(feature) {
    if (!_.includes(this.agent.features, feature)) {
      throw new NotImplemented(`Feature '${feature}' not supported`);
    }
  }
}

module.exports = BaseService;<commit_msg>Added subnet() to fetch subnet from plan setting in BaseService<commit_after>'use strict';

const _ = require('lodash');
const CONST = require('../common/constants');
const Agent = require('../data-access-layer/service-agent');
const errors = require('../common/errors');
const NotImplemented = errors.NotImplemented;

class BaseService {
  constructor(plan) {
    this.plan = plan;
    this.agent = new Agent(this.settings.agent);
  }

  get settings() {
    return this.plan.manager.settings;
  }

  get subnet() {
    return this.settings.subnet || this.service.subnet;
  }

  getTenantGuid(context) {
    if (context.platform === CONST.PLATFORM.CF) {
      return context.space_guid;
    } else if (context.platform === CONST.PLATFORM.K8S) {
      return context.namespace;
    }
  }

  get service() {
    return this.plan.service;
  }

  verifyFeatureSupport(feature) {
    if (!_.includes(this.agent.features, feature)) {
      throw new NotImplemented(`Feature '${feature}' not supported`);
    }
  }
}

module.exports = BaseService;<|endoftext|>