<commit_before>var wax = wax || {};
wax.p = wax.p || {};
wax.p.Controls = wax.p.Controls || {};

var p = {};

// Controls constructor.
wax.p.Controls = function(map) {
    this.map = map;
    this.container = this.map.container();
};

wax.p.Controls.prototype.calculateGrid = function(p) {
    var transform = $('g.layer', this.container).attr('transform');
    var tileSize = p.tileSize();
    var offset = transform.animVal.getItem(0).matrix;
    var ratio = (transform.animVal.numberOfItems == 2) ? transform.animVal.getItem(1).matrix.a : 1;
    var interactive_tiles = $('image', this.container);
    var tiles = $(interactive_tiles).map(function(t) {
        var $interactive_tile = $(interactive_tiles[t]);
        var e_offset = $interactive_tile.offset();
        return {
            xy: {
                left: e_offset.left,
                top: e_offset.top
            },
            size: {
                width: tileSize.x * ratio,
                height: tileSize.y * ratio
            },
            tile: interactive_tiles[t]
        };
    });
    return tiles;
};

wax.p.Controls.prototype.inTile = function(sevt, tile) {
    // TODO: pageX correct?
    if  ((tile.xy.top < sevt.pageY) &&
        ((tile.xy.top + tile.size.height) > sevt.pageY) &&
         (tile.xy.left < sevt.pageX) &&
        ((tile.xy.left + tile.size.width) > sevt.pageX)) {
        return true;
    }
};

wax.p.Controls.prototype.Interaction = function() {
  var that = this;
  var gm = new wax.GridManager();
  var f = null;
  var find = function(map, evt) {
    var found = false;
    var interaction_grid = that.calculateGrid(that.map);
    for (var i = 0; i < interaction_grid.length && !found; i++) {
      if (that.inTile(evt, interaction_grid[i])) {
          var found = interaction_grid[i];
      }
    }
    return found;
  };
  $(this.container).mousemove(_.throttle(function(evt) {
    var options = { format: 'teaser' };
    var found = find(this.map, evt);
    if (!found) return;
    gm.getGrid($(found.tile).attr('href'), function(g) {
        if (!g) return;
        g.tileRes = (256 / found.size.height) * 4;
        var feature = g.getFeature(
          evt.pageX,
          evt.pageY,
          found.xy,
          options
        );
        if (feature !== f) {
          wax.tooltip.unselect(feature, $(that.container).parent(), 0);
          wax.tooltip.select(feature, $(that.container).parent(), 0);
          f = feature;
        }
    });
  }, 50));
  // google.maps.event.addListener(this.map, 'click', function(evt) {
  //   var options = { format: 'full' };
  //   var found = find(this.map, evt);
  //   if (!found) return;
  //   gm.getGrid($(found.tile).attr('src'), function(g) {
  //       if (!g) return;
  //       var feature = g.getFeature(
  //         evt.pixel.x + $(that.map.d).offset().left,
  //         evt.pixel.y + $(that.map.d).offset().top,
  //         found.tile,
  //         options
  //       );
  //       feature && wax.tooltip.click(feature, $(that.map.d), 0);
  //   });
  // });
  return this;
};

$(function() {
    var map = { 'wax':
        ['@group',
            ['@call org.polymaps.map'],
            ['@chain container',
                ['@group',
                    ['@call document.getElementById', 'polymaps-canvas'],
                    ['@chain appendChild',
                        ['@call org.polymaps.svg', 'svg']
                    ]
                ]
            ],
            ['@chain add',
                ['@call org.polymaps.interact']
            ],
            ['@chain add',
                ['@group',
                    ['@call org.polymaps.image'],
                    ['@chain url',
                        ['@call mbUrl', 'http://localhost:9000/1.0.0/batch/{Z}/{X}/{Y}.png']
                    ]
                ]
            ],
            ['@chain zoom', 2]
        ]
    };
    p = wax.Record(map);
    var c = new wax.p.Controls(p.wax);
    c.Interaction();
});
<commit_msg>Rethink necessary.<commit_after>var wax = wax || {};
wax.p = wax.p || {};
wax.p.Controls = wax.p.Controls || {};

var p = {};

// Controls constructor.
wax.p.Controls = function(map) {
    this.map = map;
    this.container = this.map.container();
};

wax.p.Controls.prototype.calculateGrid = function(p) {
    var transform = $('g.layer', this.container).attr('transform');
    var tileSize = p.tileSize();
    var container_left = $(this.container).offset().left;
    var container_top = $(this.container).offset().top;
    var centerpoint = transform.animVal.getItem(0).matrix;
    var centerpoint_left = centerpoint.e + container_left;
    var centerpoint_top  = centerpoint.f + container_top;
    var ratio = (transform.animVal.numberOfItems == 2) ? transform.animVal.getItem(1).matrix.a : 1;
    var interactive_tiles = $('image', this.container);
    var tiles = $(interactive_tiles).map(function(t) {
        var $interactive_tile = $(interactive_tiles[t]);
        var e_offset = $interactive_tile.offset();
        return {
            xy: {
                left: ((e_offset.left * (ratio)) + (centerpoint_left * (1 - ratio) *
                    (e_offset.left > centerpoint_left) ? 1 : -1)),
                top:  ((e_offset.top * (ratio))  + (centerpoint_top * (1 - ratio) *
                    (e_offset.top > centerpoint_top) ? 1 : -1)),
            },
            size: {
                width: tileSize.x * ratio,
                height: tileSize.y * ratio
            },
            tile: interactive_tiles[t]
        };
    });
    return tiles;
};

wax.p.Controls.prototype.inTile = function(sevt, tile) {
    // TODO: pageX correct?
    if  ((tile.xy.top < sevt.pageY) &&
        ((tile.xy.top + tile.size.height) > sevt.pageY) &&
         (tile.xy.left < sevt.pageX) &&
        ((tile.xy.left + tile.size.width) > sevt.pageX)) {
        return true;
    }
};

wax.p.Controls.prototype.Interaction = function() {
  var that = this;
  var gm = new wax.GridManager();
  var f = null;
  var find = function(map, evt) {
    var found = false;
    var interaction_grid = that.calculateGrid(that.map);
    for (var i = 0; i < interaction_grid.length && !found; i++) {
      if (that.inTile(evt, interaction_grid[i])) {
          var found = interaction_grid[i];
      }
    }
    return found;
  };
  $(this.container).mousemove(_.throttle(function(evt) {
    var options = { format: 'teaser' };
    var found = find(this.map, evt);
    if (!found) return;
    gm.getGrid($(found.tile).attr('href'), function(g) {
        if (!g) return;
        g.tileRes = (256 / found.size.height) * 4;
        var feature = g.getFeature(
          evt.pageX,
          evt.pageY,
          found.xy,
          options
        );
        if (feature !== f) {
          wax.tooltip.unselect(feature, $(that.container).parent(), 0);
          wax.tooltip.select(feature, $(that.container).parent(), 0);
          f = feature;
        }
    });
  }, 50));
  // google.maps.event.addListener(this.map, 'click', function(evt) {
  //   var options = { format: 'full' };
  //   var found = find(this.map, evt);
  //   if (!found) return;
  //   gm.getGrid($(found.tile).attr('src'), function(g) {
  //       if (!g) return;
  //       var feature = g.getFeature(
  //         evt.pixel.x + $(that.map.d).offset().left,
  //         evt.pixel.y + $(that.map.d).offset().top,
  //         found.tile,
  //         options
  //       );
  //       feature && wax.tooltip.click(feature, $(that.map.d), 0);
  //   });
  // });
  return this;
};

$(function() {
    var map = { 'wax':
        ['@group',
            ['@call org.polymaps.map'],
            ['@chain container',
                ['@group',
                    ['@call document.getElementById', 'polymaps-canvas'],
                    ['@chain appendChild',
                        ['@call org.polymaps.svg', 'svg']
                    ]
                ]
            ],
            ['@chain add',
                ['@call org.polymaps.interact']
            ],
            ['@chain add',
                ['@group',
                    ['@call org.polymaps.image'],
                    ['@chain url',
                        ['@call mbUrl', 'http://localhost:9000/1.0.0/batch/{Z}/{X}/{Y}.png']
                    ]
                ]
            ],
            ['@chain zoom', 2]
        ]
    };
    p = wax.Record(map);
    var c = new wax.p.Controls(p.wax);
    c.Interaction();
});
<|endoftext|>


<commit_before>'use strict';

const main = require('../app/controllers/main');
const api = require('../app/controllers/api');

/**
 * Expose routes
 */

module.exports = function(app) {
  app.get('/', main.index);
  app.post('/:type(orders)', api);
}
<commit_msg>Add order list/item endpoint<commit_after>'use strict';

const main = require('../app/controllers/main');
const api = require('../app/controllers/api');

/**
 * Expose routes
 */

module.exports = function(app) {
  app.get('/', main.index);
  app.get('/:type(orders)', api);
  app.get('/:type(orders)/:id', api);
  app.post('/:type(orders)', api);
}
<|endoftext|>


<commit_before>'use strict';

var cfApp = require('cfenv').getAppEnv();
var postgresqlProductionConfig = cfApp.getServices('postgresql');
console.log(JSON.stringify(postgresqlProductionConfig));
var productionDbUri;

if(postgresqlProductionConfig['ElephantSQL-nx']
  && postgresqlProductionConfig['ElephantSQL-nx'].credentials) {
  console.log(JSON.stringify(postgresqlProductionConfig['ElephantSQL-nx']));
  productionDbUri = postgresqlProductionConfig['ElephantSQL-nx'].credentials;
}
console.log(JSON.stringify(postgresqlProductionConfig['ElephantSQL-nx']));

// Database connection object
module.exports = {

  development: {
    client: 'pg',
    connection: {
      database: 'pwadb',
      host: 'localhost'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      tableName: 'knex_migrations'
    },
    seeds: {
      directory: './seeds'
    },
    debug: true
  },

  production: {
    client: 'pg',
    connection: productionDbUri,
    debug: true
  }
};
<commit_msg>pointing at elephant db uri<commit_after>'use strict';

var cfApp = require('cfenv').getAppEnv();
var postgresqlProductionConfig = cfApp.getServices('postgresql');
console.log(JSON.stringify(postgresqlProductionConfig));
var productionDbUri;

if(postgresqlProductionConfig['ElephantSQL-nx']
  && postgresqlProductionConfig['ElephantSQL-nx'].credentials) {
  console.log(JSON.stringify(postgresqlProductionConfig['ElephantSQL-nx']));
  productionDbUri = postgresqlProductionConfig['ElephantSQL-nx'].credentials.uri;
}
console.log(JSON.stringify(postgresqlProductionConfig['ElephantSQL-nx']));

// Database connection object
module.exports = {

  development: {
    client: 'pg',
    connection: {
      database: 'pwadb',
      host: 'localhost'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      tableName: 'knex_migrations'
    },
    seeds: {
      directory: './seeds'
    },
    debug: true
  },

  production: {
    client: 'pg',
    connection: productionDbUri,
    debug: true
  }
};
<|endoftext|>


<commit_before>"use strict";

// src/components/comment-box.js

import React from "react";
import jQuery from "jquery";
import { CommentForm } from "./comment-form";
import { CommentAvatarList } from "./comment-avatar-list";
import { Comment } from "./comment";

class CommentBox extends React.Component {

  constructor() {
    super();

    this.state = {
      showComments: false,
      comments: []
    };

    this._deleteComment = this._deleteComment.bind(this);
    this._addComment = this._addComment.bind(this);
  }

  componentWillMount() {
    this._fetchComments();
  }

  render() {
    const comments = this._getComments();
    return(

Join The Discussion

            <CommentForm addComment={this._addComment} />
            <CommentAvatarList avatars={this._getAvatars()} />

            {this._getPopularMessage(comments.length)}

{this._getCommentsTitle(comments.length)}

              {comments}

    );
  }

  _getAvatars() {
    return this.state.comments.map(comment => comment.avatarUrl);
  }

  _getPopularMessage(commentCount) {
    const POPULAR_COUNT = 10;
    if (commentCount > POPULAR_COUNT) {
       return (

This post is getting really popular, dont miss out!

       );
    }
  }

  _getComments() {
    return this.state.comments.map((comment) => {
      return <Comment
               { ...comment }
               onDelete={this._deleteComment}
               key={comment.id} />
    });
  }

  _getCommentsTitle(commentCount) {
    if (commentCount === 0) {
      return 'No comments yet';
    } else if (commentCount === 1) {
      return '1 comment';
    } else {
      return `${commentCount} comments`;
    }
  }

  _addComment(commentAuthor, commentBody) {

    const comment = {
      id: this.state.comments.length + 1,
      author: commentAuthor,
      body: commentBody,
      avatarUrl: 'assets/images/avatars/avatar-default.png'
    };

    this.setState({
      comments: this.state.comments.concat([comment])
    });

  }

  _fetchComments() {
    jQuery.ajax({
      method: 'GET',
      url: 'comments.json',
      success: (comments) => {
        this.setState({ comments })
      }
    });
  }

  _deleteComment(commentID) {
    const comments = this.state.comments.filter(
      comment => comment.id !== commentID
    );

    this.setState({ comments });
  }
}

export { CommentBox };
<commit_msg>Edit _fetchComments. Add CommentBox.propType for apiUrl<commit_after>"use strict";

// src/components/comment-box.js

import React from "react";
import jQuery from "jquery";
import { CommentForm } from "./comment-form";
import { CommentAvatarList } from "./comment-avatar-list";
import { Comment } from "./comment";

class CommentBox extends React.Component {

  constructor() {
    super();

    this.state = {
      showComments: false,
      comments: []
    };

    this._deleteComment = this._deleteComment.bind(this);
    this._addComment = this._addComment.bind(this);
  }

  componentWillMount() {
    this._fetchComments();
  }

  render() {
    const comments = this._getComments();
    return(

Join The Discussion

            <CommentForm addComment={this._addComment} />
            <CommentAvatarList avatars={this._getAvatars()} />

            {this._getPopularMessage(comments.length)}

{this._getCommentsTitle(comments.length)}

              {comments}

    );
  }

  _getAvatars() {
    return this.state.comments.map(comment => comment.avatarUrl);
  }

  _getPopularMessage(commentCount) {
    const POPULAR_COUNT = 10;
    if (commentCount > POPULAR_COUNT) {
       return (

This post is getting really popular, dont miss out!

       );
    }
  }

  _getComments() {
    return this.state.comments.map((comment) => {
      return <Comment
               { ...comment }
               onDelete={this._deleteComment}
               key={comment.id} />
    });
  }

  _getCommentsTitle(commentCount) {
    if (commentCount === 0) {
      return 'No comments yet';
    } else if (commentCount === 1) {
      return '1 comment';
    } else {
      return `${commentCount} comments`;
    }
  }

  _addComment(commentAuthor, commentBody) {

    const comment = {
      id: this.state.comments.length + 1,
      author: commentAuthor,
      body: commentBody,
      avatarUrl: 'assets/images/avatars/avatar-default.png'
    };

    this.setState({
      comments: this.state.comments.concat([comment])
    });

  }

  _fetchComments() {
    jQuery.ajax({
      method: 'GET',
      url: this.props.apiUrl,
      success: (comments) => {
        this.setState({ comments })
      }
    });
  }

  _deleteComment(commentID) {
    const comments = this.state.comments.filter(
      comment => comment.id !== commentID
    );

    this.setState({ comments });
  }
}

CommentBox.propType = {
  apiUrl: React.PropTypes.string.isRequired
};

export { CommentBox };
<|endoftext|>


<commit_before>// @flow

import {
    createStartAudioOnlyEvent,
    createStartMutedConfigurationEvent,
    createSyncTrackStateEvent,
    createTrackMutedEvent,
    sendAnalytics
} from '../../analytics';
import { APP_STATE_CHANGED } from '../../mobile/background';
import {
    NOTIFICATION_TIMEOUT_TYPE,
    showWarningNotification
} from '../../notifications';
import { isForceMuted } from '../../participants-pane/functions';
import { SET_AUDIO_ONLY, setAudioOnly } from '../audio-only';
import { isRoomValid, SET_ROOM } from '../conference';
import { getLocalParticipant } from '../participants';
import { MiddlewareRegistry } from '../redux';
import { getPropertyValue } from '../settings';
import {
    destroyLocalTracks,
    isLocalTrackMuted,
    isLocalVideoTrackDesktop,
    setTrackMuted,
    TRACK_ADDED
} from '../tracks';

import {
    SET_AUDIO_MUTED,
    SET_AUDIO_UNMUTE_PERMISSIONS,
    SET_VIDEO_MUTED,
    SET_VIDEO_UNMUTE_PERMISSIONS
} from './actionTypes';
import { setAudioMuted, setCameraFacingMode, setVideoMuted } from './actions';
import {
    CAMERA_FACING_MODE,
    MEDIA_TYPE,
    VIDEO_MUTISM_AUTHORITY
} from './constants';
import { getStartWithAudioMuted, getStartWithVideoMuted } from './functions';
import logger from './logger';
import {
    _AUDIO_INITIAL_MEDIA_STATE,
    _VIDEO_INITIAL_MEDIA_STATE
} from './reducer';

/**
 * Implements the entry point of the middleware of the feature base/media.
 *
 * @param {Store} store - The redux store.
 * @returns {Function}
 */
MiddlewareRegistry.register(store => next => action => {
    switch (action.type) {
    case APP_STATE_CHANGED:
        return _appStateChanged(store, next, action);

    case SET_AUDIO_ONLY:
        return _setAudioOnly(store, next, action);

    case SET_ROOM:
        return _setRoom(store, next, action);

    case TRACK_ADDED: {
        const result = next(action);
        const { track } = action;

        // Don't sync track mute state with the redux store for screenshare
        // since video mute state represents local camera mute state only.
        track.local && track.videoType !== 'desktop'
            && _syncTrackMutedState(store, track);

        return result;
    }

    case SET_AUDIO_MUTED: {
        const state = store.getState();
        const participant = getLocalParticipant(state);

        if (!action.muted && isForceMuted(participant, MEDIA_TYPE.AUDIO, state)) {
            return;
        }
        break;
    }

    case SET_AUDIO_UNMUTE_PERMISSIONS: {
        const { blocked } = action;
        const state = store.getState();
        const tracks = state['features/base/tracks'];
        const isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);

        if (blocked && isAudioMuted) {
            store.dispatch(showWarningNotification({
                descriptionKey: 'notify.audioUnmuteBlockedDescription',
                titleKey: 'notify.audioUnmuteBlockedTitle'
            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
        }
        break;
    }

    case SET_VIDEO_MUTED: {
        const state = store.getState();
        const participant = getLocalParticipant(state);

        if (!action.muted && isForceMuted(participant, MEDIA_TYPE.VIDEO, state)) {
            return;
        }
        break;
    }

    case SET_VIDEO_UNMUTE_PERMISSIONS: {
        const { blocked } = action;
        const state = store.getState();
        const tracks = state['features/base/tracks'];
        const isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);

        if (blocked && isVideoMuted) {
            store.dispatch(showWarningNotification({
                descriptionKey: 'notify.videoUnmuteBlockedDescription',
                titleKey: 'notify.videoUnmuteBlockedTitle'
            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
        }
        break;
    }
    }

    return next(action);
});

/**
 * Adjusts the video muted state based on the app state.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action {@code APP_STATE_CHANGED} which is
 * being dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The value returned by {@code next(action)}.
 */
function _appStateChanged({ dispatch, getState }, next, action) {
    if (navigator.product === 'ReactNative') {
        const { appState } = action;
        const mute = appState !== 'active' && !isLocalVideoTrackDesktop(getState());

        sendAnalytics(createTrackMutedEvent('video', 'background mode', mute));

        dispatch(setVideoMuted(mute, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.BACKGROUND));
    }

    return next(action);
}

/**
 * Adjusts the video muted state based on the audio-only state.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action {@code SET_AUDIO_ONLY} which is
 * being dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The value returned by {@code next(action)}.
 */
function _setAudioOnly({ dispatch }, next, action) {
    const { audioOnly, ensureVideoTrack } = action;

    sendAnalytics(createTrackMutedEvent('video', 'audio-only mode', audioOnly));

    // Make sure we mute both the desktop and video tracks.
    dispatch(setVideoMuted(audioOnly, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY, ensureVideoTrack));

    if (navigator.product !== 'ReactNative') {
        dispatch(setVideoMuted(audioOnly, MEDIA_TYPE.PRESENTER, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY, ensureVideoTrack));
    }

    return next(action);
}

/**
 * Notifies the feature base/media that the action {@link SET_ROOM} is being
 * dispatched within a specific redux {@code store}.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action, {@code SET_ROOM}, which is being
 * dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The new state that is the result of the reduction of the
 * specified {@code action}.
 */
function _setRoom({ dispatch, getState }, next, action) {
    // Figure out the desires/intents i.e. the state of base/media. There are
    // multiple desires/intents ordered by precedence such as server-side
    // config, config overrides in the user-supplied URL, user's own app
    // settings, etc.

    const state = getState();
    const { room } = action;
    const roomIsValid = isRoomValid(room);
    const audioMuted = roomIsValid ? getStartWithAudioMuted(state) : _AUDIO_INITIAL_MEDIA_STATE.muted;
    const videoMuted = roomIsValid ? getStartWithVideoMuted(state) : _VIDEO_INITIAL_MEDIA_STATE.muted;

    sendAnalytics(
        createStartMutedConfigurationEvent('local', audioMuted, videoMuted));
    logger.log(
        `Start muted: ${audioMuted ? 'audio, ' : ''}${
            videoMuted ? 'video' : ''}`);

    // Unconditionally express the desires/expectations/intents of the app and
    // the user i.e. the state of base/media. Eventually, practice/reality i.e.
    // the state of base/tracks will or will not agree with the desires.
    dispatch(setAudioMuted(audioMuted));
    dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
    dispatch(setVideoMuted(videoMuted));

    // startAudioOnly
    //
    // FIXME Technically, the audio-only feature is owned by base/conference,
    // not base/media so the following should be in base/conference.
    // Practically, I presume it was easier to write the source code here
    // because it looks like startWithAudioMuted and startWithVideoMuted.
    //
    // XXX After the introduction of the "Video <-> Voice" toggle on the
    // WelcomePage, startAudioOnly is utilized even outside of
    // conferences/meetings.
    const audioOnly
        = Boolean(
            getPropertyValue(
                state,
                'startAudioOnly',
                /* sources */ {
                    // FIXME Practically, base/config is (really) correct
                    // only if roomIsValid. At the time of this writing,
                    // base/config is overwritten by URL params which leaves
                    // base/config incorrect on the WelcomePage after
                    // leaving a conference which explicitly overwrites
                    // base/config with URL params.
                    config: roomIsValid,

                    // XXX We've already overwritten base/config with
                    // urlParams if roomIsValid. However, settings are more
                    // important than the server-side config. Consequently,
                    // we need to read from urlParams anyway. We also
                    // probably want to read from urlParams when
                    // !roomIsValid.
                    urlParams: true,

                    // The following don't have complications around whether
                    // they are defined or not:
                    jwt: false,
                    settings: true
                }));

    sendAnalytics(createStartAudioOnlyEvent(audioOnly));
    logger.log(`Start audio only set to ${audioOnly.toString()}`);

    dispatch(setAudioOnly(audioOnly, false));

    if (!roomIsValid) {
        dispatch(destroyLocalTracks());
    }

    return next(action);
}

/**
 * Syncs muted state of local media track with muted state from media state.
 *
 * @param {Store} store - The redux store.
 * @param {Track} track - The local media track.
 * @private
 * @returns {void}
 */
function _syncTrackMutedState({ getState }, track) {
    const state = getState()['features/base/media'];
    const mediaType = track.mediaType === MEDIA_TYPE.PRESENTER
        ? MEDIA_TYPE.VIDEO : track.mediaType;
    const muted = Boolean(state[mediaType].muted);

    // XXX If muted state of track when it was added is different from our media
    // muted state, we need to mute track and explicitly modify 'muted' property
    // on track. This is because though TRACK_ADDED action was dispatched it's
    // not yet in redux state and JitsiTrackEvents.TRACK_MUTE_CHANGED may be
    // fired before track gets to state.
    if (track.muted !== muted) {
        sendAnalytics(createSyncTrackStateEvent(track.mediaType, muted));
        logger.log(
            `Sync ${track.mediaType} track muted state to ${
                muted ? 'muted' : 'unmuted'}`);

        track.muted = muted;
        setTrackMuted(track.jitsiTrack, muted);
    }
}
<commit_msg>fix(notifications) Adjust the timeout for unmute blocked notifications.<commit_after>// @flow

import {
    createStartAudioOnlyEvent,
    createStartMutedConfigurationEvent,
    createSyncTrackStateEvent,
    createTrackMutedEvent,
    sendAnalytics
} from '../../analytics';
import { APP_STATE_CHANGED } from '../../mobile/background';
import {
    NOTIFICATION_TIMEOUT_TYPE,
    showWarningNotification
} from '../../notifications';
import { isForceMuted } from '../../participants-pane/functions';
import { SET_AUDIO_ONLY, setAudioOnly } from '../audio-only';
import { isRoomValid, SET_ROOM } from '../conference';
import { getLocalParticipant } from '../participants';
import { MiddlewareRegistry } from '../redux';
import { getPropertyValue } from '../settings';
import {
    destroyLocalTracks,
    isLocalTrackMuted,
    isLocalVideoTrackDesktop,
    setTrackMuted,
    TRACK_ADDED
} from '../tracks';

import {
    SET_AUDIO_MUTED,
    SET_AUDIO_UNMUTE_PERMISSIONS,
    SET_VIDEO_MUTED,
    SET_VIDEO_UNMUTE_PERMISSIONS
} from './actionTypes';
import { setAudioMuted, setCameraFacingMode, setVideoMuted } from './actions';
import {
    CAMERA_FACING_MODE,
    MEDIA_TYPE,
    VIDEO_MUTISM_AUTHORITY
} from './constants';
import { getStartWithAudioMuted, getStartWithVideoMuted } from './functions';
import logger from './logger';
import {
    _AUDIO_INITIAL_MEDIA_STATE,
    _VIDEO_INITIAL_MEDIA_STATE
} from './reducer';

/**
 * Implements the entry point of the middleware of the feature base/media.
 *
 * @param {Store} store - The redux store.
 * @returns {Function}
 */
MiddlewareRegistry.register(store => next => action => {
    switch (action.type) {
    case APP_STATE_CHANGED:
        return _appStateChanged(store, next, action);

    case SET_AUDIO_ONLY:
        return _setAudioOnly(store, next, action);

    case SET_ROOM:
        return _setRoom(store, next, action);

    case TRACK_ADDED: {
        const result = next(action);
        const { track } = action;

        // Don't sync track mute state with the redux store for screenshare
        // since video mute state represents local camera mute state only.
        track.local && track.videoType !== 'desktop'
            && _syncTrackMutedState(store, track);

        return result;
    }

    case SET_AUDIO_MUTED: {
        const state = store.getState();
        const participant = getLocalParticipant(state);

        if (!action.muted && isForceMuted(participant, MEDIA_TYPE.AUDIO, state)) {
            return;
        }
        break;
    }

    case SET_AUDIO_UNMUTE_PERMISSIONS: {
        const { blocked } = action;
        const state = store.getState();
        const tracks = state['features/base/tracks'];
        const isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);

        if (blocked && isAudioMuted) {
            store.dispatch(showWarningNotification({
                descriptionKey: 'notify.audioUnmuteBlockedDescription',
                titleKey: 'notify.audioUnmuteBlockedTitle'
            }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
        }
        break;
    }

    case SET_VIDEO_MUTED: {
        const state = store.getState();
        const participant = getLocalParticipant(state);

        if (!action.muted && isForceMuted(participant, MEDIA_TYPE.VIDEO, state)) {
            return;
        }
        break;
    }

    case SET_VIDEO_UNMUTE_PERMISSIONS: {
        const { blocked } = action;
        const state = store.getState();
        const tracks = state['features/base/tracks'];
        const isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);

        if (blocked && isVideoMuted) {
            store.dispatch(showWarningNotification({
                descriptionKey: 'notify.videoUnmuteBlockedDescription',
                titleKey: 'notify.videoUnmuteBlockedTitle'
            }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
        }
        break;
    }
    }

    return next(action);
});

/**
 * Adjusts the video muted state based on the app state.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action {@code APP_STATE_CHANGED} which is
 * being dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The value returned by {@code next(action)}.
 */
function _appStateChanged({ dispatch, getState }, next, action) {
    if (navigator.product === 'ReactNative') {
        const { appState } = action;
        const mute = appState !== 'active' && !isLocalVideoTrackDesktop(getState());

        sendAnalytics(createTrackMutedEvent('video', 'background mode', mute));

        dispatch(setVideoMuted(mute, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.BACKGROUND));
    }

    return next(action);
}

/**
 * Adjusts the video muted state based on the audio-only state.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action {@code SET_AUDIO_ONLY} which is
 * being dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The value returned by {@code next(action)}.
 */
function _setAudioOnly({ dispatch }, next, action) {
    const { audioOnly, ensureVideoTrack } = action;

    sendAnalytics(createTrackMutedEvent('video', 'audio-only mode', audioOnly));

    // Make sure we mute both the desktop and video tracks.
    dispatch(setVideoMuted(audioOnly, MEDIA_TYPE.VIDEO, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY, ensureVideoTrack));

    if (navigator.product !== 'ReactNative') {
        dispatch(setVideoMuted(audioOnly, MEDIA_TYPE.PRESENTER, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY, ensureVideoTrack));
    }

    return next(action);
}

/**
 * Notifies the feature base/media that the action {@link SET_ROOM} is being
 * dispatched within a specific redux {@code store}.
 *
 * @param {Store} store - The redux store in which the specified {@code action}
 * is being dispatched.
 * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
 * specified {@code action} to the specified {@code store}.
 * @param {Action} action - The redux action, {@code SET_ROOM}, which is being
 * dispatched in the specified {@code store}.
 * @private
 * @returns {Object} The new state that is the result of the reduction of the
 * specified {@code action}.
 */
function _setRoom({ dispatch, getState }, next, action) {
    // Figure out the desires/intents i.e. the state of base/media. There are
    // multiple desires/intents ordered by precedence such as server-side
    // config, config overrides in the user-supplied URL, user's own app
    // settings, etc.

    const state = getState();
    const { room } = action;
    const roomIsValid = isRoomValid(room);
    const audioMuted = roomIsValid ? getStartWithAudioMuted(state) : _AUDIO_INITIAL_MEDIA_STATE.muted;
    const videoMuted = roomIsValid ? getStartWithVideoMuted(state) : _VIDEO_INITIAL_MEDIA_STATE.muted;

    sendAnalytics(
        createStartMutedConfigurationEvent('local', audioMuted, videoMuted));
    logger.log(
        `Start muted: ${audioMuted ? 'audio, ' : ''}${
            videoMuted ? 'video' : ''}`);

    // Unconditionally express the desires/expectations/intents of the app and
    // the user i.e. the state of base/media. Eventually, practice/reality i.e.
    // the state of base/tracks will or will not agree with the desires.
    dispatch(setAudioMuted(audioMuted));
    dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
    dispatch(setVideoMuted(videoMuted));

    // startAudioOnly
    //
    // FIXME Technically, the audio-only feature is owned by base/conference,
    // not base/media so the following should be in base/conference.
    // Practically, I presume it was easier to write the source code here
    // because it looks like startWithAudioMuted and startWithVideoMuted.
    //
    // XXX After the introduction of the "Video <-> Voice" toggle on the
    // WelcomePage, startAudioOnly is utilized even outside of
    // conferences/meetings.
    const audioOnly
        = Boolean(
            getPropertyValue(
                state,
                'startAudioOnly',
                /* sources */ {
                    // FIXME Practically, base/config is (really) correct
                    // only if roomIsValid. At the time of this writing,
                    // base/config is overwritten by URL params which leaves
                    // base/config incorrect on the WelcomePage after
                    // leaving a conference which explicitly overwrites
                    // base/config with URL params.
                    config: roomIsValid,

                    // XXX We've already overwritten base/config with
                    // urlParams if roomIsValid. However, settings are more
                    // important than the server-side config. Consequently,
                    // we need to read from urlParams anyway. We also
                    // probably want to read from urlParams when
                    // !roomIsValid.
                    urlParams: true,

                    // The following don't have complications around whether
                    // they are defined or not:
                    jwt: false,
                    settings: true
                }));

    sendAnalytics(createStartAudioOnlyEvent(audioOnly));
    logger.log(`Start audio only set to ${audioOnly.toString()}`);

    dispatch(setAudioOnly(audioOnly, false));

    if (!roomIsValid) {
        dispatch(destroyLocalTracks());
    }

    return next(action);
}

/**
 * Syncs muted state of local media track with muted state from media state.
 *
 * @param {Store} store - The redux store.
 * @param {Track} track - The local media track.
 * @private
 * @returns {void}
 */
function _syncTrackMutedState({ getState }, track) {
    const state = getState()['features/base/media'];
    const mediaType = track.mediaType === MEDIA_TYPE.PRESENTER
        ? MEDIA_TYPE.VIDEO : track.mediaType;
    const muted = Boolean(state[mediaType].muted);

    // XXX If muted state of track when it was added is different from our media
    // muted state, we need to mute track and explicitly modify 'muted' property
    // on track. This is because though TRACK_ADDED action was dispatched it's
    // not yet in redux state and JitsiTrackEvents.TRACK_MUTE_CHANGED may be
    // fired before track gets to state.
    if (track.muted !== muted) {
        sendAnalytics(createSyncTrackStateEvent(track.mediaType, muted));
        logger.log(
            `Sync ${track.mediaType} track muted state to ${
                muted ? 'muted' : 'unmuted'}`);

        track.muted = muted;
        setTrackMuted(track.jitsiTrack, muted);
    }
}
<|endoftext|>


<commit_before>var sys = require ("sys")
var functional = require ("./functional")

for (fName in functional) if (functional.hasOwnProperty (fName))
    global[fName] = functional[fName]

var tokenize = function (string) {
    var tokens = []
    var parseStack = [tokens]
    var specials = []

    var acceptToken = function (t) { parseStack [0].push (t) }

    var increaseNesting = function (special) {
	var newArr = []
	acceptToken (newArr)
	parseStack.unshift (newArr)
	specials.unshift (special || false)
    }

    var decreaseNesting = function () {
	parseStack.shift ()
	if (specials.shift ()) decreaseNesting ()
	if (parseStack.length === 0)
	    throw new Error (
		"unbalanced parens:\n" +
		    sys.inspect (parseStack))
    }

    var handleSpecial = function (special) {
	if (special === "'") {
	    increaseNesting (true)
	    acceptToken ("quote")
	}
    }

    var handleToken = function (token) {
	var token = token
	var special

	if (token.match (/^[`',]/)) {
	    handleSpecial (token [0])
	    token = token.slice (1)
	}

	if (token === '(') increaseNesting ()
	else if (token === ')') decreaseNesting ()
	else if (token.match (/^-?[0-9.]+$/))
	    acceptToken (parseFloat (token))
	else acceptToken (token)
    }

    string
	.replace (/([^\\])\n/, '$1 ')
	.replace (/\s+\\\n/, "\\n")
	.match (/(;.*)|("([^"]|(\\"))*?[^\\]")|[&']?[*.a-z-]+|[><=!\+\/\*-]+|-?[0-9.]+|([']?\()|\)/g)
	.forEach (handleToken)

    if (parseStack.length > 1) {
	sys.puts (sys.inspect (parseStack[0]))
	throw new Error ("unexpected EOF, probably missing a )")
    }

    return tokens
}

var reprint = function (tokens, nesting) {
    var nesting = nesting || 0
    for (var i=0; i<nesting - 1; i++) sys.print ("\t")
    if (nesting > 0) sys.print ("(")

    tokens.forEach (function (item) {
	if (item.constructor.name === 'Array') {
	    sys.print ("\n")
	    reprint (item, nesting + 1)
	} else {
	    sys.print ("<" + item + ">")
	}
    })
    if (nesting > 0) sys.print (")")
}
var indent = function () {
    return compact (Array.prototype.slice.call (arguments))
	.join("\n")
	.replace (/^/, "\n")
	.replace (/\n/g, "\n  ") + "\n"
}

var constructHash = function (arrayOfArrays) {
    return inject ({}, arrayOfArrays, function (object, item) {
	object [item [0]] = object [item [1]]
	return object
    })
}

var macros = {}

macros['return'] = function (token) {
    if (token && token.constructor.name === "Array" && token[0] === "return")
	return translate (token)
    return "return " + translate (token)
}

macros.let = function (assignments, body) {
    var body = Array.prototype.slice.call (arguments, 1)
    body [body.length - 1] = ['return', body [body.length - 1]]

    var content = indent (
	"var " + map (assignments, function (kv) {
	    return kv [0] + " = " + translate (kv [1])
	}).join(",\n  ") + ";",
	map (body, function (arg) {
	    return translate (arg) + ';'
	}).join("\n")
    )

    return "(function() {" + content + "})();\n"
}

macros.setq = function (name, value) {
    return "var " + translate (name) + " = " + translate (value) + ";\n"
}

macros.statement = function () {
    return macros.call.apply (null, arguments) + ";\n"
}

macros.progn = function (body) {
    var body = Array.prototype.slice.call (arguments)
    body [body.length - 1] = ['return', body [body.length - 1]]

    return map (body, function (arg) {
	return translate (arg) + ';'
    }).join("\n")
}

macros.call = function (fnName) {
    return translate (fnName) + "(" +
	map (
	    Array.prototype.slice.call (arguments, 1),
	    translate
	).join (", ") + ")"
}

macros.defun = function (fnName, arglist, body) {
    return translate (fnName) + " = " +
	macros.lambda.apply (
	    undefined,
	    Array.prototype.slice.call (arguments, 1)
	) + ";\n"
}

macros.macroexpand = function (name) {
    if (macros [name])
	return macros[name].toString ()
    else return "undefined"
}

macros.defmacro = function (name, arglist, body) {
    try {
	macros[name] = eval (macros.lambda.apply (
	    undefined,
	    Array.prototype.slice.call (arguments, 1)
	))
    } catch (e) {
	sys.puts ("error in parsing macro " + name + ":")
	sys.puts (indent (macros.lambda (arglist, body)))
	throw e
    }
}

var joinWith = function (string) {
    var string = string
    return function () {
	return map (
	    Array.prototype.slice.apply (arguments),
	    translate
	).join (" " + string + " ")
    }
}

macros['+'] = joinWith ('+')
macros['concat'] = joinWith ('+')
macros['-'] = joinWith ('-')
macros['*'] = joinWith ('*')
macros['/'] = joinWith ('*')

var transformArgs = function (arglist) {
    var last, args = []
    arglist.forEach (function (arg) {
	if (arg [0] === '&') last = arg.slice (1)
	else {
	    args.push ([last || 'required', arg])
	    last = null
	}
    })

    if (last) throw new Error ("unexpected argument modifier: " + last)

    return args
}

var reverse = macros.reverse = function (arr) {
    var reversed = []
    arr.forEach (function (item) { reversed.unshift (item) })
    return reversed
}

var buildArgsString = function (args, rest) {
    var argsString = "", optionalCount = 0
    args.forEach (function (arg, optionIndex) {
	if (arg [0] === 'optional') {
	    argsString += "if (arguments.length < " +
		(args.length - optionalCount) + ") " +
		"// if " + arg[1] + " is missing" +
		indent (
		    "var " +
			map (
			    args.slice (optionIndex + 1),
			    function (arg, argIndex) {
				return arg[1] + " = " +
				    args [optionIndex + argIndex][1]
			    }
			)
			.reverse ()
			.concat (arg [1] + " = undefined")
			.join (", ") + ';'
		)
	    optionalCount ++
	}
    })

    var argumentCountMismatch = function (msg) {
	return indent ('throw new Error("argument ' +
		       'count mismatch: ' + msg + '");')
    }

    if (rest) {
	if (args.length - optionalCount > 0)
	    argsString += (
		"if (arguments.length < " +
		    (args.length - optionalCount) + ")" +
		    argumentCountMismatch (
			'expected no fewer than ' +
			    (args.length - optionalCount) + ' arguments'
		    )
	    )

	argsString += (
	    "var " + translate (rest [1]) +
		" = Array.prototype.slice.call(arguments, " +
		(args.length) + ");\n"
	)

    } else {
	if (args.length === 0)
	    argsString += (
		'if (arguments.length > 0)' +
		    argumentCountMismatch ('expected no arguments')
	    )

	else if (optionalCount > 0)
	    argsString += (
		'if (arguments.length < ' +
		    (args.length - optionalCount) +
		    ' || arguments.length > ' + args.length + ')' +
		    argumentCountMismatch (
			'expected between ' +
			    (args.length - optionalCount) +
			    ' and ' + args.length + ' arguments'
		    )
	    )
    }

    return argsString
}

var buildCommentString = function (args) {
    if (args.length === 0) return ""
    return "// " + map (args, function (arg) {return reverse(arg).join(":")}).join(" ")
}

macros.lambda = function (arglist, body) {
    var args = transformArgs (arglist)
    var rest = detect (args, function (arg) {return arg [0] === 'rest' })
    var body = Array.prototype.slice.call (arguments, 1)
    var docString

    body [body.length - 1] = ['return', body [body.length - 1]]
    if (typeof body [0] === "string" && body [0].match (/^".*"$/))
	docString = "/* " + eval (body.shift ()) + " */\n"

    var noRestArgs = rest ? args.slice (0, -1) : args
    var argsString = buildArgsString (noRestArgs, rest)
    var commentString = buildCommentString (args)

    return "(function(" +
	map (args, function (arg) {return translate (arg [1])}).join (", ") +
	") { "+
	indent (
	    commentString,
	    docString,
	    argsString,
	    map (body, function (stmt) { return translate (stmt) + ';' }).join ("\n")
	) + "})"
}

macros.map = map

macros.quote = function (item) {
    if (item.constructor.name === "Array")
	return '[' + map (item, macros.quote).join(", ") + ']'
    else if (typeof item === 'number')
	return item
    else return '"' + literal (item) + '"'
}

var literal = function (string) {
    return inject (
	string.replace (/\*/g, '_'),
	string.match (/-(.)/g),
	function (returnString, match) {
	    return returnString.replace (
		match,
		match[1].toUpperCase ()
	    )
	}
    )
}

var translate = function (token, hint) {
    var hint = hint
    if (hint && typeof macros [hint] === 'undefined')
	hint = undefined

    try {
	if (token.constructor.name === 'Array') {
	    if ('undefined' === typeof macros [token [0]])
		return macros [hint || 'call']
		.apply (null, token)
	    else return macros [token [0]]
		.apply (null, token.slice (1))
	} else if (typeof token === 'string' && token.match (/^[*a-z-]+$/))
	    return literal (token)
	else if (typeof token === 'string' && token.match (/^;/))
	    return token.replace (/^;+/, '//')
	else return token
    } catch (e) {
	sys.puts (e.stack)
	sys.print ("Encountered when attempting to process:")
	sys.puts (indent (sys.inspect (token)))
    }
}

var fs = require ("fs")

tokenize (fs.readFileSync ("macros.lisp", 'utf8')).forEach (translate)

process.argv.slice(2).forEach (function (file) {
    tokenize (fs.readFileSync (file, 'utf8'))
	.forEach (function (token) {
	    var line = translate (token, 'statement')
	    if (line) sys.puts (line)
	})
})

<commit_msg>[ remove macros.map ]<commit_after>var sys = require ("sys")
var functional = require ("./functional")

for (fName in functional) if (functional.hasOwnProperty (fName))
    global[fName] = functional[fName]

var tokenize = function (string) {
    var tokens = []
    var parseStack = [tokens]
    var specials = []

    var acceptToken = function (t) { parseStack [0].push (t) }

    var increaseNesting = function (special) {
	var newArr = []
	acceptToken (newArr)
	parseStack.unshift (newArr)
	specials.unshift (special || false)
    }

    var decreaseNesting = function () {
	parseStack.shift ()
	if (specials.shift ()) decreaseNesting ()
	if (parseStack.length === 0)
	    throw new Error (
		"unbalanced parens:\n" +
		    sys.inspect (parseStack))
    }

    var handleSpecial = function (special) {
	if (special === "'") {
	    increaseNesting (true)
	    acceptToken ("quote")
	}
    }

    var handleToken = function (token) {
	var token = token
	var special

	if (token.match (/^[`',]/)) {
	    handleSpecial (token [0])
	    token = token.slice (1)
	}

	if (token === '(') increaseNesting ()
	else if (token === ')') decreaseNesting ()
	else if (token.match (/^-?[0-9.]+$/))
	    acceptToken (parseFloat (token))
	else acceptToken (token)
    }

    string
	.replace (/([^\\])\n/, '$1 ')
	.replace (/\s+\\\n/, "\\n")
	.match (/(;.*)|("([^"]|(\\"))*?[^\\]")|[&']?[*.a-z-]+|[><=!\+\/\*-]+|-?[0-9.]+|([']?\()|\)/g)
	.forEach (handleToken)

    if (parseStack.length > 1) {
	sys.puts (sys.inspect (parseStack[0]))
	throw new Error ("unexpected EOF, probably missing a )")
    }

    return tokens
}

var reprint = function (tokens, nesting) {
    var nesting = nesting || 0
    for (var i=0; i<nesting - 1; i++) sys.print ("\t")
    if (nesting > 0) sys.print ("(")

    tokens.forEach (function (item) {
	if (item.constructor.name === 'Array') {
	    sys.print ("\n")
	    reprint (item, nesting + 1)
	} else {
	    sys.print ("<" + item + ">")
	}
    })
    if (nesting > 0) sys.print (")")
}
var indent = function () {
    return compact (Array.prototype.slice.call (arguments))
	.join("\n")
	.replace (/^/, "\n")
	.replace (/\n/g, "\n  ") + "\n"
}

var constructHash = function (arrayOfArrays) {
    return inject ({}, arrayOfArrays, function (object, item) {
	object [item [0]] = object [item [1]]
	return object
    })
}

var macros = {}

macros['return'] = function (token) {
    if (token && token.constructor.name === "Array" && token[0] === "return")
	return translate (token)
    return "return " + translate (token)
}

macros.let = function (assignments, body) {
    var body = Array.prototype.slice.call (arguments, 1)
    body [body.length - 1] = ['return', body [body.length - 1]]

    var content = indent (
	"var " + map (assignments, function (kv) {
	    return kv [0] + " = " + translate (kv [1])
	}).join(",\n  ") + ";",
	map (body, function (arg) {
	    return translate (arg) + ';'
	}).join("\n")
    )

    return "(function() {" + content + "})();\n"
}

macros.setq = function (name, value) {
    return "var " + translate (name) + " = " + translate (value) + ";\n"
}

macros.statement = function () {
    return macros.call.apply (null, arguments) + ";\n"
}

macros.progn = function (body) {
    var body = Array.prototype.slice.call (arguments)
    body [body.length - 1] = ['return', body [body.length - 1]]

    return map (body, function (arg) {
	return translate (arg) + ';'
    }).join("\n")
}

macros.call = function (fnName) {
    return translate (fnName) + "(" +
	map (
	    Array.prototype.slice.call (arguments, 1),
	    translate
	).join (", ") + ")"
}

macros.defun = function (fnName, arglist, body) {
    return translate (fnName) + " = " +
	macros.lambda.apply (
	    undefined,
	    Array.prototype.slice.call (arguments, 1)
	) + ";\n"
}

macros.macroexpand = function (name) {
    if (macros [name])
	return macros[name].toString ()
    else return "undefined"
}

macros.defmacro = function (name, arglist, body) {
    try {
	macros[name] = eval (macros.lambda.apply (
	    undefined,
	    Array.prototype.slice.call (arguments, 1)
	))
    } catch (e) {
	sys.puts ("error in parsing macro " + name + ":")
	sys.puts (indent (macros.lambda (arglist, body)))
	throw e
    }
}

var joinWith = function (string) {
    var string = string
    return function () {
	return map (
	    Array.prototype.slice.apply (arguments),
	    translate
	).join (" " + string + " ")
    }
}

macros['+'] = joinWith ('+')
macros['concat'] = joinWith ('+')
macros['-'] = joinWith ('-')
macros['*'] = joinWith ('*')
macros['/'] = joinWith ('*')

var transformArgs = function (arglist) {
    var last, args = []
    arglist.forEach (function (arg) {
	if (arg [0] === '&') last = arg.slice (1)
	else {
	    args.push ([last || 'required', arg])
	    last = null
	}
    })

    if (last) throw new Error ("unexpected argument modifier: " + last)

    return args
}

var reverse = macros.reverse = function (arr) {
    var reversed = []
    arr.forEach (function (item) { reversed.unshift (item) })
    return reversed
}

var buildArgsString = function (args, rest) {
    var argsString = "", optionalCount = 0
    args.forEach (function (arg, optionIndex) {
	if (arg [0] === 'optional') {
	    argsString += "if (arguments.length < " +
		(args.length - optionalCount) + ") " +
		"// if " + arg[1] + " is missing" +
		indent (
		    "var " +
			map (
			    args.slice (optionIndex + 1),
			    function (arg, argIndex) {
				return arg[1] + " = " +
				    args [optionIndex + argIndex][1]
			    }
			)
			.reverse ()
			.concat (arg [1] + " = undefined")
			.join (", ") + ';'
		)
	    optionalCount ++
	}
    })

    var argumentCountMismatch = function (msg) {
	return indent ('throw new Error("argument ' +
		       'count mismatch: ' + msg + '");')
    }

    if (rest) {
	if (args.length - optionalCount > 0)
	    argsString += (
		"if (arguments.length < " +
		    (args.length - optionalCount) + ")" +
		    argumentCountMismatch (
			'expected no fewer than ' +
			    (args.length - optionalCount) + ' arguments'
		    )
	    )

	argsString += (
	    "var " + translate (rest [1]) +
		" = Array.prototype.slice.call(arguments, " +
		(args.length) + ");\n"
	)

    } else {
	if (args.length === 0)
	    argsString += (
		'if (arguments.length > 0)' +
		    argumentCountMismatch ('expected no arguments')
	    )

	else if (optionalCount > 0)
	    argsString += (
		'if (arguments.length < ' +
		    (args.length - optionalCount) +
		    ' || arguments.length > ' + args.length + ')' +
		    argumentCountMismatch (
			'expected between ' +
			    (args.length - optionalCount) +
			    ' and ' + args.length + ' arguments'
		    )
	    )
    }

    return argsString
}

var buildCommentString = function (args) {
    if (args.length === 0) return ""
    return "// " + map (args, function (arg) {return reverse(arg).join(":")}).join(" ")
}

macros.lambda = function (arglist, body) {
    var args = transformArgs (arglist)
    var rest = detect (args, function (arg) {return arg [0] === 'rest' })
    var body = Array.prototype.slice.call (arguments, 1)
    var docString

    body [body.length - 1] = ['return', body [body.length - 1]]
    if (typeof body [0] === "string" && body [0].match (/^".*"$/))
	docString = "/* " + eval (body.shift ()) + " */\n"

    var noRestArgs = rest ? args.slice (0, -1) : args
    var argsString = buildArgsString (noRestArgs, rest)
    var commentString = buildCommentString (args)

    return "(function(" +
	map (args, function (arg) {return translate (arg [1])}).join (", ") +
	") { "+
	indent (
	    commentString,
	    docString,
	    argsString,
	    map (body, function (stmt) { return translate (stmt) + ';' }).join ("\n")
	) + "})"
}

macros.quote = function (item) {
    if (item.constructor.name === "Array")
	return '[' + map (item, macros.quote).join(", ") + ']'
    else if (typeof item === 'number')
	return item
    else return '"' + literal (item) + '"'
}

var literal = function (string) {
    return inject (
	string.replace (/\*/g, '_'),
	string.match (/-(.)/g),
	function (returnString, match) {
	    return returnString.replace (
		match,
		match[1].toUpperCase ()
	    )
	}
    )
}

var translate = function (token, hint) {
    var hint = hint
    if (hint && typeof macros [hint] === 'undefined')
	hint = undefined

    try {
	if (token.constructor.name === 'Array') {
	    if ('undefined' === typeof macros [token [0]])
		return macros [hint || 'call']
		.apply (null, token)
	    else return macros [token [0]]
		.apply (null, token.slice (1))
	} else if (typeof token === 'string' && token.match (/^[*a-z-]+$/))
	    return literal (token)
	else if (typeof token === 'string' && token.match (/^;/))
	    return token.replace (/^;+/, '//')
	else return token
    } catch (e) {
	sys.puts (e.stack)
	sys.print ("Encountered when attempting to process:")
	sys.puts (indent (sys.inspect (token)))
    }
}

var fs = require ("fs")

tokenize (fs.readFileSync ("macros.lisp", 'utf8')).forEach (translate)

process.argv.slice(2).forEach (function (file) {
    tokenize (fs.readFileSync (file, 'utf8'))
	.forEach (function (token) {
	    var line = translate (token, 'statement')
	    if (line) sys.puts (line)
	})
})

<|endoftext|>


<commit_before>import m from 'mithril';
import _ from 'underscore';
import moment from 'moment';
import {
    catarse
} from '../api';
import models from '../models';
import dashboardSubscriptionCardDetail from './dashboard-subscription-card-detail';
import subscriptionStatusIcon from './subscription-status-icon';
import paymentMethodIcon from './payment-method-icon';
import subscriptionLastPaymentStatus from './subscription-last-payment-status';
import h from '../h';

const dashboardSubscriptionCard = {
    controller: function(args) {
        const subscription = args.subscription,
            reward = m.prop(),
            toggleDetails = h.toggleProp(false, true),
            user = m.prop();

        if (subscription.user_external_id) {
            const filterUserVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.user_external_id),
                lU = catarse.loaderWithToken(models.userDetail.getRowOptions(filterUserVM.parameters()));

            lU.load().then((data) => {
                user(_.first(data));
            });
        }

        if (subscription.reward_external_id) {
            const filterRewVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.reward_external_id),
                lRew = catarse.loaderWithToken(models.rewardDetail.getRowOptions(filterRewVM.parameters()));

            lRew.load().then((data) => {
                reward(_.first(data));
            });
        }
        return {
            toggleDetails,
            reward,
            user
        };
    },
    view: function(ctrl, args) {
        const subscription = args.subscription,
            user = ctrl.user(),
            cardClass = ctrl.toggleDetails() ? '.card-detailed-open' : '';

        return m(`div${cardClass}`, [m('.card.card-clickable', {
            onclick: ctrl.toggleDetails.toggle
        }, ctrl.user() ?
                m('.w-row', [
                    m('.table-col.w-col.w-col-3',
                        m('.w-row', [
                            m('.w-col.w-col-3',
                                m(`img.u-marginbottom-10.user-avatar[src='${h.useAvatarOrDefault(ctrl.user().profile_img_thumbnail)}']`)
                            ),
                            m('.w-col.w-col-9', [
                                m('.fontsize-smaller.fontweight-semibold.lineheight-tighter',
                                    ctrl.user().name
                                ),
                                m('.fontcolor-secondary.fontsize-smallest',
                                    subscription.user_email
                                )
                            ])
                        ])
                    ),
                    m('.table-col.w-col.w-col-2',
                        m('.fontsize-smaller',
                            _.isEmpty(ctrl.reward()) ? '' : `${ctrl.reward().description.substring(0, 20)}...`
                        )
                    ),
                    m('.table-col.w-col.w-col-1.u-text-center', [
                        m('.fontsize-smaller',
                            `R$${h.formatNumber(subscription.amount / 100, 0, 3)}`
                        ),
                        m('.fontcolor-secondary.fontsize-mini.fontweight-semibold.lineheight-tightest', [
                            m(paymentMethodIcon, {
                                subscription
                            })
                        ])
                    ]),
                    m('.w-col.w-col-2.u-text-center', [
                        m('.fontsize-smaller',
                            `R$${h.formatNumber(subscription.total_paid / 100, 0, 3)}`
                        ),
                        m('.fontcolor-secondary.fontsize-mini.fontweight-semibold.lineheight-tightest',
                            `${subscription.paid_count} meses`
                        )
                    ]),
                    m('.w-col.w-col-2.u-text-center',
                        m(subscriptionLastPaymentStatus, { subscription })
                    ),
                    m('.w-col.w-col-2.u-text-center',
                        m(subscriptionStatusIcon, {
                            subscription
                        })
                    ),
                    m('button.w-inline-block.arrow-admin.fa.fa-chevron-down.fontcolor-secondary')
                ]) : ''
            ),
            ctrl.toggleDetails() ? m(dashboardSubscriptionCardDetail, {
                subscription,
                reward: ctrl.reward(),
                user
            }) : ''
        ]);
    }
};

export default dashboardSubscriptionCard;
<commit_msg>fixing the subscription reward id that should be searched for #163129641<commit_after>import m from 'mithril';
import _ from 'underscore';
import moment from 'moment';
import {
    catarse
} from '../api';
import models from '../models';
import dashboardSubscriptionCardDetail from './dashboard-subscription-card-detail';
import subscriptionStatusIcon from './subscription-status-icon';
import paymentMethodIcon from './payment-method-icon';
import subscriptionLastPaymentStatus from './subscription-last-payment-status';
import h from '../h';

const dashboardSubscriptionCard = {
    controller: function(args) {
        const subscription = args.subscription,
            reward = m.prop(),
            toggleDetails = h.toggleProp(false, true),
            user = m.prop();

        if (subscription.user_external_id) {
            const filterUserVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.user_external_id),
                lU = catarse.loaderWithToken(models.userDetail.getRowOptions(filterUserVM.parameters()));

            lU.load().then((data) => {
                user(_.first(data));
            });
        }

        if (subscription.current_reward_data && subscription.current_reward_data.external_id) {
            const filterRewVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.current_reward_data.external_id),
                lRew = catarse.loaderWithToken(models.rewardDetail.getRowOptions(filterRewVM.parameters()));

            lRew.load().then((data) => {
                reward(_.first(data));
            });
        }
        return {
            toggleDetails,
            reward,
            user
        };
    },
    view: function(ctrl, args) {
        const subscription = args.subscription,
            user = ctrl.user(),
            cardClass = ctrl.toggleDetails() ? '.card-detailed-open' : '';

        return m(`div${cardClass}`, [m('.card.card-clickable', {
            onclick: ctrl.toggleDetails.toggle
        }, ctrl.user() ?
                m('.w-row', [
                    m('.table-col.w-col.w-col-3',
                        m('.w-row', [
                            m('.w-col.w-col-3',
                                m(`img.u-marginbottom-10.user-avatar[src='${h.useAvatarOrDefault(ctrl.user().profile_img_thumbnail)}']`)
                            ),
                            m('.w-col.w-col-9', [
                                m('.fontsize-smaller.fontweight-semibold.lineheight-tighter',
                                    ctrl.user().name
                                ),
                                m('.fontcolor-secondary.fontsize-smallest',
                                    subscription.user_email
                                )
                            ])
                        ])
                    ),
                    m('.table-col.w-col.w-col-2',
                        m('.fontsize-smaller',
                            _.isEmpty(ctrl.reward()) ? '' : `${ctrl.reward().description.substring(0, 20)}...`
                        )
                    ),
                    m('.table-col.w-col.w-col-1.u-text-center', [
                        m('.fontsize-smaller',
                            `R$${h.formatNumber(subscription.amount / 100, 0, 3)}`
                        ),
                        m('.fontcolor-secondary.fontsize-mini.fontweight-semibold.lineheight-tightest', [
                            m(paymentMethodIcon, {
                                subscription
                            })
                        ])
                    ]),
                    m('.w-col.w-col-2.u-text-center', [
                        m('.fontsize-smaller',
                            `R$${h.formatNumber(subscription.total_paid / 100, 0, 3)}`
                        ),
                        m('.fontcolor-secondary.fontsize-mini.fontweight-semibold.lineheight-tightest',
                            `${subscription.paid_count} meses`
                        )
                    ]),
                    m('.w-col.w-col-2.u-text-center',
                        m(subscriptionLastPaymentStatus, { subscription })
                    ),
                    m('.w-col.w-col-2.u-text-center',
                        m(subscriptionStatusIcon, {
                            subscription
                        })
                    ),
                    m('button.w-inline-block.arrow-admin.fa.fa-chevron-down.fontcolor-secondary')
                ]) : ''
            ),
            ctrl.toggleDetails() ? m(dashboardSubscriptionCardDetail, {
                subscription,
                reward: ctrl.reward(),
                user
            }) : ''
        ]);
    }
};

export default dashboardSubscriptionCard;
<|endoftext|>


<commit_before>/**
 * @file DynamicRenderList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import List from '../List';
import Tip from '../Tip';
import Theme from '../Theme';

import SelectMode from '../_statics/SelectMode';
import LIST_SEPARATOR from '../_statics/ListSeparator';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import Calculation from '../_vendors/Calculation';

class DynamicRenderList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: Calculation.getInitValue(props),
            scrollTop: 0
        };

    }

    getIndex = () => {
        const {data, listHeight, itemHeight, scrollBuffer} = this.props,
            {scrollTop} = this.state;
        return Calculation.displayIndexByScrollTop(data, listHeight, itemHeight, scrollTop, scrollBuffer);
    };

    scrollHandler = e => {
        this.setState({
            scrollTop: this.dynamicRenderListEl.scrollTop
        }, () => {
            const {onScroll} = this.props;
            onScroll && onScroll(e);
        });
    };

    changeHandler = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    adjustScroll = () => {
        this.refs.list.adjustScroll();
    };

    componentDidMount() {
        this.dynamicRenderListEl = this.refs.dynamicRenderList;
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: Calculation.getInitValue(nextProps)
            });
        }
    }

    render() {

        const {

                className, style, data, listHeight, itemHeight,

                // not passing down these props
                scrollBuffer,

                ...restProps

            } = this.props,
            {value} = this.state,

            listClassName = classNames('dynamic-render-list', {
                [className]: className
            }),

            scrollerStyle = {
                height: data.length * itemHeight
            },

            index = this.getIndex(),

            filteredData = data && index ? data.slice(index.startWithBuffer, index.stopWithBuffer + 1) : data;

        return (

 {
                     Event.wheelHandler(e, this.props);
                 }}>

                    <List {...restProps}
                          ref="list"
                          style={{transform: `translateY(${index.startWithBuffer * itemHeight}px)`}}
                          data={filteredData}
                          value={value}
                          onChange={this.changeHandler}/>

        );

    }
}

DynamicRenderList.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The theme of the list item.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme of the list item select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * Children passed into the ListItem.
     */
    data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the list button.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the list button.
         */
        style: PropTypes.object,

        /**
         * The theme of the list button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the list button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The list item's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the list button. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the list item will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * If true,the element's ripple effect will be disabled.
         */
        disableTouchRipple: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        tip: PropTypes.string,

        /**
         * The position of tip.
         */
        tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

        /**
         * If true,the item will have center displayed ripple effect.
         */
        rippleDisplayCenter: PropTypes.bool,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a list item touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.string, PropTypes.number, PropTypes.symbol])).isRequired,

    /**
     * The id field name in data. (default: "id")
     */
    idField: PropTypes.string,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the list will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true, the list will be at loading status.
     */
    isLoading: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    shouldPreventContainerScroll: PropTypes.bool,

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * Callback function fired when the list-item touch tap.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when the list-item select.
     */
    onItemSelect: PropTypes.func,

    /**
     * Callback function fired when the list-item deselect.
     */
    onItemDeselect: PropTypes.func,

    /**
     * Callback function fired when the list changed.
     */
    onChange: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func,

    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number

};

DynamicRenderList.defaultProps = {

    theme: Theme.DEFAULT,
    selectTheme: Theme.DEFAULT,

    data: [],

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,
    shouldPreventContainerScroll: true,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    listHeight: 200,
    itemHeight: 40,
    scrollBuffer: 6

};

export default DynamicRenderList;<commit_msg>update DynamicRenderList<commit_after>/**
 * @file DynamicRenderList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import List from '../List';
import Tip from '../Tip';
import Theme from '../Theme';

import SelectMode from '../_statics/SelectMode';
import LIST_SEPARATOR from '../_statics/ListSeparator';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import Calculation from '../_vendors/Calculation';

class DynamicRenderList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: Calculation.getInitValue(props),
            scrollTop: 0
        };

    }

    getIndex = () => {
        const {data, listHeight, itemHeight, scrollBuffer} = this.props,
            {scrollTop} = this.state;
        return Calculation.displayIndexByScrollTop(data, listHeight, itemHeight, scrollTop, scrollBuffer);
    };

    scrollHandler = e => {
        this.setState({
            scrollTop: this.dynamicRenderListEl.scrollTop
        }, () => {
            const {onScroll} = this.props;
            onScroll && onScroll(e);
        });
    };

    changeHandler = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    adjustScroll = () => {
        this.refs.list.adjustScroll();
    };

    componentDidMount() {
        this.dynamicRenderListEl = this.refs.dynamicRenderList;
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: Calculation.getInitValue(nextProps)
            });
        }
    }

    render() {

        const {

                className, style, data, listHeight, itemHeight,

                // not passing down these props
                scrollBuffer,

                ...restProps

            } = this.props,
            {value} = this.state,

            listClassName = classNames('dynamic-render-list', {
                [className]: className
            }),

            scrollerStyle = {
                height: data.length * itemHeight
            },

            index = this.getIndex(),

            filteredData = data && index ? data.slice(index.startWithBuffer, index.stopWithBuffer + 1) : data;

        return (

 Event.wheelHandler(e, this.props)}>

                    <List {...restProps}
                          ref="list"
                          style={{transform: `translateY(${index.startWithBuffer * itemHeight}px)`}}
                          data={filteredData}
                          value={value}
                          onChange={this.changeHandler}/>

        );

    }
}

DynamicRenderList.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The theme of the list item.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme of the list item select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * Children passed into the ListItem.
     */
    data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the list button.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the list button.
         */
        style: PropTypes.object,

        /**
         * The theme of the list button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the list button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The list item's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the list button. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the list item will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * If true,the element's ripple effect will be disabled.
         */
        disableTouchRipple: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        tip: PropTypes.string,

        /**
         * The position of tip.
         */
        tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

        /**
         * If true,the item will have center displayed ripple effect.
         */
        rippleDisplayCenter: PropTypes.bool,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a list item touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.string, PropTypes.number, PropTypes.symbol])).isRequired,

    /**
     * The id field name in data. (default: "id")
     */
    idField: PropTypes.string,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the list will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true, the list will be at loading status.
     */
    isLoading: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    shouldPreventContainerScroll: PropTypes.bool,

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * Callback function fired when the list-item touch tap.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when the list-item select.
     */
    onItemSelect: PropTypes.func,

    /**
     * Callback function fired when the list-item deselect.
     */
    onItemDeselect: PropTypes.func,

    /**
     * Callback function fired when the list changed.
     */
    onChange: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func,

    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number

};

DynamicRenderList.defaultProps = {

    theme: Theme.DEFAULT,
    selectTheme: Theme.DEFAULT,

    data: [],

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,
    shouldPreventContainerScroll: true,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    listHeight: 200,
    itemHeight: 40,
    scrollBuffer: 6

};

export default DynamicRenderList;<|endoftext|>


<commit_before>//Canvas dimensions and margins
var width = 800,
    height = 800;

var margin = {
    top: 50,
    bottom: 50,
    left: 50,
    right: 50,
}

//Creation of a categorical color scale for the nodes according to their group membership (Requires d3 Chromatic library)
var color = d3.scaleOrdinal(d3.schemeDark2);
var colorGroup = ["entidad", "contratista"];
var numberFormat = d3.format(",d");

//Creation of the SVG canvas to draw in
var svgRedContratistas = d3.select("#red_contratistas")
						   .append("svg")
						   .attr("width", width)
						   .attr("height", height)
						   .append("g")
						   .attr("transform", "translate(" + margin.top + ", " + margin.left + ")");

//Redefining the effective drawing area
width = width - margin.left - margin.right;
height = height - margin.top - margin.bottom;

//Creation of the simulation parameters: Creation of the forces that will mandate the simulation
var forceSimulation = d3.forceSimulation()
						.force("collide", d3.forceCollide().radius(function(d) {return 5})) //Prevents nodes from overlapping
						.force("radial", d3.forceRadial(function(d) { return (d.group == "entidad") ? -10 : 300; }).y(height/2).x(width/2)) //Sends contratistas to the outside
						.force("link", d3.forceLink().id(function(d) { return (d.id) })) //Provides link forces to the nodes connected between them
						.force("center", d3.forceCenter((width / 2), (height / 2)));

//Read the JSON formatted data
d3.json("datasets/red_contratistas.json", function(error, data) {
  if (error) throw error;

  //Variables containing nodes and edges
  var nodes = data.nodes;
  var edges = data.edges;

  //Creation of the size scale for the nodes
  var nodeSize = d3.scaleLinear().domain(d3.extent(nodes.map(function(d) { return +d.cuantiaContratos; })))
  							 	 .range([1,20])

  //Adding the nodes to the canvas

  var drawingNodes = svgRedContratistas.selectAll(".node")
  					   .data(nodes)
  					   .enter()
  					   .append("g")
  					   .filter(function(d){ if(d.cuantiaContratos > 2000000000){return this} });

  	  drawingNodes.append("circle")
  	  			  .attr("class","node")
  	  			  .attr("id", function(d) {return d.id})
  	  			  .attr("r", function(d) {return nodeSize(d.cuantiaContratos)})
  	  			  .attr("fill", function(d) {return color(colorGroup.indexOf(d.group))})
  	  			  .attr("stroke", "#fff")
  	  			  .call(d3.drag()
  	  			  	.on("start", dragstarted)
  	  			  	.on("drag", dragged)
  	  			  	.on("end", dragended))
//  	  			  .on("mouseover", mouseOver(.2))
//  	  			  .on("mouseout", mouseOut);

  	  drawingNodes.append("title")
  	  			  .text(function(d) { if(d.group == "contratista") {return "Nombre: " + d.name + "\n" + "Cuantía total acumulada devengada: " + numberFormat(d.cuantiaContratos) + "\n" + "Tipo: Contratista";}
  	  									else {return "Nombre: " + d.name + "\n" + "Cuantía total acumulada otorgada: " + numberFormat(d.cuantiaContratos) + "\n" + "Tipo: Entidad contratante";} });

  //Carrying out the simulation
  forceSimulation.nodes(nodes).on("tick", ticked);
//  forceSimulation.force("link").links(edges);

  //Ticked function to establish the simulation behavior
	function ticked() {
		drawingNodes.attr("transform", positionNode);
        drawingLinks.attr("d", positionLink);

	}

  //Function to define the node position within the boundaries of the SVG canvas
    function positionNode(d) {
      	if (d.x < 0) {
            d.x = 0
        };
        if (d.y < 0) {
            d.y = 0
        };
        if (d.x > width) {
            d.x = width
        };
        if (d.y > height) {
            d.y = height
        };

        return "translate(" + d.x + "," + d.y + ")";
    }

    //Function to draw links between entidades and contratistas
    function positionLink(d) {
        var offset = 30;

        var midpoint_x = (d.source.x + d.target.x) / 2;
        var midpoint_y = (d.source.y + d.target.y) / 2;

        var dx = (d.target.x - d.source.x);
        var dy = (d.target.y - d.source.y);

        var normalise = Math.sqrt((dx * dx) + (dy * dy));

        var offSetX = midpoint_x + offset*(dy/normalise);
        var offSetY = midpoint_y - offset*(dx/normalise);

        return "M" + d.source.x + "," + d.source.y +
            "S" + offSetX + "," + offSetY +
            " " + d.target.x + "," + d.target.y;
    }

   //Functions that define the drag actions
      function dragstarted(d) {
      if (!d3.event.active) forceSimulation.alphaTarget(0.2).restart();
      d.fx = d.x;
      d.fy = d.y;
    }

    function dragged(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    }

    function dragended(d) {
      if (!d3.event.active) forceSimulation.alphaTarget(0.03);
      d.fx = null;
      d.fy = null;
    }

   //Functions related to link placement

    //This function builds a dictionary of links and nodes
    var linkedByIndex = {};
    edges.forEach(function(d) {
        linkedByIndex[d.source + "," + d.target] = 1;
    });

    // check the dictionary to see if nodes are linked
    function isConnected(a, b) {
        return linkedByIndex[a.id + "," + b.id] || linkedByIndex[b.id + "," + a.id] || a.id === b.id;
    }

  //Fits a linear width scale for the links on mouseover
//  var min_width = 0.3,
//      max_width = 5,
//      scale_converter = d3.scaleLinear().domain([d3.min(edges, function(d){return d.weight}),d3.max(edges, function(d){return d.weight})]).range([min_width,max_width]);

    // fade nodes on hover
    function mouseOver(opacity) {
        return function(d) {
            // check all other nodes to see if they're connected
            // to this one. if so, keep the opacity at 1, otherwise
            // fade
            drawingNode.style("stroke-opacity", function(o) {
              thisOpacity = isConnected(d, o) ? 1 : opacity;
                return thisOpacity;
            });
            drawingNode.style("fill-opacity", function(o) {
                thisOpacity = isConnected(d, o) ? 1 : opacity;
                return thisOpacity;
            });
            // also style link accordingly
            drawingLinks.style("stroke-opacity", function(o) {
                return o.source === d || o.target === d ? 1 : opacity;
            });
           // drawingLinks.style("stroke", function(o){
           //     return o.source === d || o.target === d ? color(proteinType.indexOf(o.source.type)) : "#ddd";
           // });
            //drawingLinks.style("stroke-width", function(o){return scale_converter(o.weight)});
        };
    }

    //Restore original colors and opacity after mouse out
        function mouseOut() {
            drawingNode.style("stroke-opacity", 1);
            drawingNode.style("fill-opacity", 1);
            drawingLinks.style("stroke-opacity", 1);
            drawingLinks.style("stroke", "#ddd");
          	drawingLinks.style("stroke-width", 1);
        }

});

<commit_msg>Modifications to the network force layout<commit_after>//Canvas dimensions and margins
var width = 800,
    height = 800;

var margin = {
    top: 50,
    bottom: 50,
    left: 50,
    right: 50,
}

//Creation of a categorical color scale for the nodes according to their group membership (Requires d3 Chromatic library)
var color = d3.scaleOrdinal(d3.schemeDark2);
var colorGroup = ["entidad", "contratista"];
var numberFormat = d3.format(",d");

//Creation of the SVG canvas to draw in
var svgRedContratistas = d3.select("#red_contratistas")
						   .append("svg")
						   .attr("width", width)
						   .attr("height", height)
						   .append("g")
						   .attr("transform", "translate(" + margin.top + ", " + margin.left + ")");

//Redefining the effective drawing area
width = width - margin.left - margin.right;
height = height - margin.top - margin.bottom;

//Creation of the simulation parameters: Creation of the forces that will mandate the simulation
var forceSimulation = d3.forceSimulation()
						.force("collide", d3.forceCollide().radius(function(d) {return 5})) //Prevents nodes from overlapping
						.force("radial", d3.forceRadial(function(d) { return (d.group == "entidad") ? -30 : 200; })//.y(height/2).x(width/2)) //Sends contratistas to the outside
						.force("link", d3.forceLink().id(function(d) { return (d.id) })) //Provides link forces to the nodes connected between them
						.force("center", d3.forceCenter((width / 2), (height / 2)));

//Read the JSON formatted data
d3.json("datasets/red_contratistas.json", function(error, data) {
  if (error) throw error;

  //Variables containing nodes and edges
  var nodes = data.nodes;
  var edges = data.edges;

  //Creation of the size scale for the nodes
  var nodeSize = d3.scaleLinear().domain(d3.extent(nodes.map(function(d) { return +d.cuantiaContratos; })))
  							 	 .range([1,20])

  //Adding the nodes to the canvas

  var drawingNodes = svgRedContratistas.selectAll(".node")
  					   .data(nodes)
  					   .enter()
  					   .append("g")
  					   .filter(function(d){ if(d.cuantiaContratos > 2000000000){return this} });

  	  drawingNodes.append("circle")
  	  			  .attr("class","node")
  	  			  .attr("id", function(d) {return d.id})
  	  			  .attr("r", function(d) {return nodeSize(d.cuantiaContratos)})
  	  			  .attr("fill", function(d) {return color(colorGroup.indexOf(d.group))})
  	  			  .attr("stroke", "#fff")
  	  			  .call(d3.drag()
  	  			  	.on("start", dragstarted)
  	  			  	.on("drag", dragged)
  	  			  	.on("end", dragended))
//  	  			  .on("mouseover", mouseOver(.2))
//  	  			  .on("mouseout", mouseOut);

  	  drawingNodes.append("title")
  	  			  .text(function(d) { if(d.group == "contratista") {return "Nombre: " + d.name + "\n" + "Cuantía total acumulada devengada: " + numberFormat(d.cuantiaContratos) + "\n" + "Tipo: Contratista";}
  	  									else {return "Nombre: " + d.name + "\n" + "Cuantía total acumulada otorgada: " + numberFormat(d.cuantiaContratos) + "\n" + "Tipo: Entidad contratante";} });

  //Carrying out the simulation
  forceSimulation.nodes(nodes).on("tick", ticked);
//  forceSimulation.force("link").links(edges);

  //Ticked function to establish the simulation behavior
	function ticked() {
		drawingNodes.attr("transform", positionNode);
        drawingLinks.attr("d", positionLink);

	}

  //Function to define the node position within the boundaries of the SVG canvas
    function positionNode(d) {
      	if (d.x < 0) {
            d.x = 0
        };
        if (d.y < 0) {
            d.y = 0
        };
        if (d.x > width) {
            d.x = width
        };
        if (d.y > height) {
            d.y = height
        };

        return "translate(" + d.x + "," + d.y + ")";
    }

    //Function to draw links between entidades and contratistas
    function positionLink(d) {
        var offset = 30;

        var midpoint_x = (d.source.x + d.target.x) / 2;
        var midpoint_y = (d.source.y + d.target.y) / 2;

        var dx = (d.target.x - d.source.x);
        var dy = (d.target.y - d.source.y);

        var normalise = Math.sqrt((dx * dx) + (dy * dy));

        var offSetX = midpoint_x + offset*(dy/normalise);
        var offSetY = midpoint_y - offset*(dx/normalise);

        return "M" + d.source.x + "," + d.source.y +
            "S" + offSetX + "," + offSetY +
            " " + d.target.x + "," + d.target.y;
    }

   //Functions that define the drag actions
      function dragstarted(d) {
      if (!d3.event.active) forceSimulation.alphaTarget(0.2).restart();
      d.fx = d.x;
      d.fy = d.y;
    }

    function dragged(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    }

    function dragended(d) {
      if (!d3.event.active) forceSimulation.alphaTarget(0.03);
      d.fx = null;
      d.fy = null;
    }

   //Functions related to link placement

    //This function builds a dictionary of links and nodes
    var linkedByIndex = {};
    edges.forEach(function(d) {
        linkedByIndex[d.source + "," + d.target] = 1;
    });

    // check the dictionary to see if nodes are linked
    function isConnected(a, b) {
        return linkedByIndex[a.id + "," + b.id] || linkedByIndex[b.id + "," + a.id] || a.id === b.id;
    }

  //Fits a linear width scale for the links on mouseover
//  var min_width = 0.3,
//      max_width = 5,
//      scale_converter = d3.scaleLinear().domain([d3.min(edges, function(d){return d.weight}),d3.max(edges, function(d){return d.weight})]).range([min_width,max_width]);

    // fade nodes on hover
    function mouseOver(opacity) {
        return function(d) {
            // check all other nodes to see if they're connected
            // to this one. if so, keep the opacity at 1, otherwise
            // fade
            drawingNode.style("stroke-opacity", function(o) {
              thisOpacity = isConnected(d, o) ? 1 : opacity;
                return thisOpacity;
            });
            drawingNode.style("fill-opacity", function(o) {
                thisOpacity = isConnected(d, o) ? 1 : opacity;
                return thisOpacity;
            });
            // also style link accordingly
            drawingLinks.style("stroke-opacity", function(o) {
                return o.source === d || o.target === d ? 1 : opacity;
            });
           // drawingLinks.style("stroke", function(o){
           //     return o.source === d || o.target === d ? color(proteinType.indexOf(o.source.type)) : "#ddd";
           // });
            //drawingLinks.style("stroke-width", function(o){return scale_converter(o.weight)});
        };
    }

    //Restore original colors and opacity after mouse out
        function mouseOut() {
            drawingNode.style("stroke-opacity", 1);
            drawingNode.style("fill-opacity", 1);
            drawingLinks.style("stroke-opacity", 1);
            drawingLinks.style("stroke", "#ddd");
          	drawingLinks.style("stroke-width", 1);
        }

});

<|endoftext|>