<commit_before>const Component = require('./ComponentImage');
const OComponent = require('./Component');
const yt = 'yt';
const vi = 'vi';

module.exports = Component.extend(
  {
    defaults: {
      ...Component.prototype.defaults,
      type: 'video',
      tagName: 'video',
      videoId: '',
      void: 0,
      provider: '', // on change of provider, traits are switched
      ytUrl: 'https://www.youtube.com/embed/',
      viUrl: 'https://player.vimeo.com/video/',
      loop: 0,
      muted: 0,
      autoplay: 0,
      controls: 1,
      color: '',
      sources: [],
      attributes: { allowfullscreen: 'allowfullscreen' },
      toolbar: OComponent.prototype.defaults.toolbar
    },

    initialize(o, opt) {
      var traits = [];
      var prov = this.get('provider');
      switch (prov) {
        case yt:
          traits = this.getYoutubeTraits();
          break;
        case vi:
          traits = this.getVimeoTraits();
          break;
        default:
          traits = this.getSourceTraits();
      }
      if (this.get('src')) this.parseFromSrc();
      this.set('traits', traits);
      Component.prototype.initialize.apply(this, arguments);
      this.listenTo(this, 'change:provider', this.updateTraits);
      this.listenTo(this, 'change:videoId', this.updateSrc);
    },

    initToolbar(...args) {
      OComponent.prototype.initToolbar.apply(this, args);
    },

    /**
     * Set attributes by src string
     */
    parseFromSrc() {
      var prov = this.get('provider');
      var uri = this.parseUri(this.get('src'));
      var qr = uri.query;
      switch (prov) {
        case yt:
        case vi:
          var videoId = uri.pathname.split('/').pop();
          this.set('videoId', videoId);
          if (qr.autoplay) this.set('autoplay', 1);
          if (qr.loop) this.set('loop', 1);
          if (parseInt(qr.controls) === 0) this.set('controls', 0);
          if (qr.color) this.set('color', qr.color);
          break;
        default:
      }
    },

    /**
     * Update src on change of video ID
     * @private
     */
    updateSrc() {
      var prov = this.get('provider');
      switch (prov) {
        case yt:
          this.set('src', this.getYoutubeSrc());
          break;
        case vi:
          this.set('src', this.getVimeoSrc());
          break;
      }
    },

    /**
     * Returns object of attributes for HTML
     * @return {Object}
     * @private
     */
    getAttrToHTML(...args) {
      var attr = Component.prototype.getAttrToHTML.apply(this, args);
      var prov = this.get('provider');
      switch (prov) {
        case yt:
        case vi:
          break;
        default:
          if (this.get('loop')) attr.loop = 'loop';
          if (this.get('autoplay')) attr.autoplay = 'autoplay';
          if (this.get('controls')) attr.controls = 'controls';
      }
      return attr;
    },

    /**
     * Update traits by provider
     * @private
     */
    updateTraits() {
      var prov = this.get('provider');
      var traits = this.getSourceTraits();
      switch (prov) {
        case yt:
          this.set('tagName', 'iframe');
          traits = this.getYoutubeTraits();
          break;
        case vi:
          this.set('tagName', 'iframe');
          traits = this.getVimeoTraits();
          break;
        default:
          this.set('tagName', 'video');
      }
      this.loadTraits(traits);
      this.em.trigger('change:selectedComponent');
    },

    // Listen provider change and switch traits, in TraitView listen traits change

    /**
     * Return the provider trait
     * @return {Object}
     * @private
     */
    getProviderTrait() {
      return {
        type: 'select',
        label: 'Provider',
        name: 'provider',
        changeProp: 1,
        value: this.get('provider'),
        options: [
          { value: 'so', name: 'HTML5 Source' },
          { value: yt, name: 'Youtube' },
          { value: vi, name: 'Vimeo' }
        ]
      };
    },

    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getSourceTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Source',
          name: 'src',
          placeholder: 'eg. ./media/video.mp4',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait(),
        this.getControlsTrait()
      ];
    },
    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getYoutubeTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Video ID',
          name: 'videoId',
          placeholder: 'eg. jNQXAC9IVRw',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait(),
        this.getControlsTrait()
      ];
    },

    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getVimeoTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Video ID',
          name: 'videoId',
          placeholder: 'eg. 123456789',
          changeProp: 1
        },
        {
          label: 'Color',
          name: 'color',
          placeholder: 'eg. FF0000',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait(),
        this.getControlsTrait()
      ];
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getAutoplayTrait() {
      return {
        type: 'checkbox',
        label: 'Autoplay',
        name: 'autoplay',
        changeProp: 1
      };
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getLoopTrait() {
      return {
        type: 'checkbox',
        label: 'Loop',
        name: 'loop',
        changeProp: 1
      };
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getControlsTrait() {
      return {
        type: 'checkbox',
        label: 'Controls',
        name: 'controls',
        changeProp: 1
      };
    },

    /**
     * Returns url to youtube video
     * @return {string}
     * @private
     */
    getYoutubeSrc() {
      const id = this.get('videoId');
      let url = this.get('ytUrl');
      url += id + '?';
      url += this.get('autoplay') ? '&autoplay=1' : '';
      url += !this.get('controls') ? '&controls=0&showinfo=0' : '';
      // Loop works only with playlist enabled
      // https://stackoverflow.com/questions/25779966/youtube-iframe-loop-doesnt-work
      url += this.get('loop') ? `&loop=1&playlist=${id}` : '';
      return url;
    },

    /**
     * Returns url to vimeo video
     * @return {string}
     * @private
     */
    getVimeoSrc() {
      var url = this.get('viUrl');
      url += this.get('videoId') + '?';
      url += this.get('autoplay') ? '&autoplay=1' : '';
      url += this.get('loop') ? '&loop=1' : '';
      url += !this.get('controls') ? '&title=0&portrait=0&badge=0' : '';
      url += this.get('color') ? '&color=' + this.get('color') : '';
      return url;
    }
  },
  {
    /**
     * Detect if the passed element is a valid component.
     * In case the element is valid an object abstracted
     * from the element will be returned
     * @param {HTMLElement}
     * @return {Object}
     * @private
     */
    isComponent(el) {
      var result = '';
      var isYtProv = /youtube\.com\/embed/.test(el.src);
      var isViProv = /player\.vimeo\.com\/video/.test(el.src);
      var isExtProv = isYtProv || isViProv;
      if (el.tagName == 'VIDEO' || (el.tagName == 'IFRAME' && isExtProv)) {
        result = { type: 'video' };
        if (el.src) result.src = el.src;
        if (isExtProv) {
          if (isYtProv) result.provider = yt;
          else if (isViProv) result.provider = vi;
        }
      }
      return result;
    }
  }
);
<commit_msg>Remove controls option for Vimeo videos as it's only for PRO users. Closes #977<commit_after>const Component = require('./ComponentImage');
const OComponent = require('./Component');
const yt = 'yt';
const vi = 'vi';

module.exports = Component.extend(
  {
    defaults: {
      ...Component.prototype.defaults,
      type: 'video',
      tagName: 'video',
      videoId: '',
      void: 0,
      provider: '', // on change of provider, traits are switched
      ytUrl: 'https://www.youtube.com/embed/',
      viUrl: 'https://player.vimeo.com/video/',
      loop: 0,
      muted: 0,
      autoplay: 0,
      controls: 1,
      color: '',
      sources: [],
      attributes: { allowfullscreen: 'allowfullscreen' },
      toolbar: OComponent.prototype.defaults.toolbar
    },

    initialize(o, opt) {
      var traits = [];
      var prov = this.get('provider');
      switch (prov) {
        case yt:
          traits = this.getYoutubeTraits();
          break;
        case vi:
          traits = this.getVimeoTraits();
          break;
        default:
          traits = this.getSourceTraits();
      }
      if (this.get('src')) this.parseFromSrc();
      this.set('traits', traits);
      Component.prototype.initialize.apply(this, arguments);
      this.listenTo(this, 'change:provider', this.updateTraits);
      this.listenTo(this, 'change:videoId', this.updateSrc);
    },

    initToolbar(...args) {
      OComponent.prototype.initToolbar.apply(this, args);
    },

    /**
     * Set attributes by src string
     */
    parseFromSrc() {
      var prov = this.get('provider');
      var uri = this.parseUri(this.get('src'));
      var qr = uri.query;
      switch (prov) {
        case yt:
        case vi:
          var videoId = uri.pathname.split('/').pop();
          this.set('videoId', videoId);
          if (qr.autoplay) this.set('autoplay', 1);
          if (qr.loop) this.set('loop', 1);
          if (parseInt(qr.controls) === 0) this.set('controls', 0);
          if (qr.color) this.set('color', qr.color);
          break;
        default:
      }
    },

    /**
     * Update src on change of video ID
     * @private
     */
    updateSrc() {
      var prov = this.get('provider');
      switch (prov) {
        case yt:
          this.set('src', this.getYoutubeSrc());
          break;
        case vi:
          this.set('src', this.getVimeoSrc());
          break;
      }
    },

    /**
     * Returns object of attributes for HTML
     * @return {Object}
     * @private
     */
    getAttrToHTML(...args) {
      var attr = Component.prototype.getAttrToHTML.apply(this, args);
      var prov = this.get('provider');
      switch (prov) {
        case yt:
        case vi:
          break;
        default:
          if (this.get('loop')) attr.loop = 'loop';
          if (this.get('autoplay')) attr.autoplay = 'autoplay';
          if (this.get('controls')) attr.controls = 'controls';
      }
      return attr;
    },

    /**
     * Update traits by provider
     * @private
     */
    updateTraits() {
      var prov = this.get('provider');
      var traits = this.getSourceTraits();
      switch (prov) {
        case yt:
          this.set('tagName', 'iframe');
          traits = this.getYoutubeTraits();
          break;
        case vi:
          this.set('tagName', 'iframe');
          traits = this.getVimeoTraits();
          break;
        default:
          this.set('tagName', 'video');
      }
      this.loadTraits(traits);
      this.em.trigger('change:selectedComponent');
    },

    // Listen provider change and switch traits, in TraitView listen traits change

    /**
     * Return the provider trait
     * @return {Object}
     * @private
     */
    getProviderTrait() {
      return {
        type: 'select',
        label: 'Provider',
        name: 'provider',
        changeProp: 1,
        value: this.get('provider'),
        options: [
          { value: 'so', name: 'HTML5 Source' },
          { value: yt, name: 'Youtube' },
          { value: vi, name: 'Vimeo' }
        ]
      };
    },

    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getSourceTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Source',
          name: 'src',
          placeholder: 'eg. ./media/video.mp4',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait(),
        this.getControlsTrait()
      ];
    },
    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getYoutubeTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Video ID',
          name: 'videoId',
          placeholder: 'eg. jNQXAC9IVRw',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait(),
        this.getControlsTrait()
      ];
    },

    /**
     * Return traits for the source provider
     * @return {Array<Object>}
     * @private
     */
    getVimeoTraits() {
      return [
        this.getProviderTrait(),
        {
          label: 'Video ID',
          name: 'videoId',
          placeholder: 'eg. 123456789',
          changeProp: 1
        },
        {
          label: 'Color',
          name: 'color',
          placeholder: 'eg. FF0000',
          changeProp: 1
        },
        this.getAutoplayTrait(),
        this.getLoopTrait()
      ];
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getAutoplayTrait() {
      return {
        type: 'checkbox',
        label: 'Autoplay',
        name: 'autoplay',
        changeProp: 1
      };
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getLoopTrait() {
      return {
        type: 'checkbox',
        label: 'Loop',
        name: 'loop',
        changeProp: 1
      };
    },

    /**
     * Return object trait
     * @return {Object}
     * @private
     */
    getControlsTrait() {
      return {
        type: 'checkbox',
        label: 'Controls',
        name: 'controls',
        changeProp: 1
      };
    },

    /**
     * Returns url to youtube video
     * @return {string}
     * @private
     */
    getYoutubeSrc() {
      const id = this.get('videoId');
      let url = this.get('ytUrl');
      url += id + '?';
      url += this.get('autoplay') ? '&autoplay=1' : '';
      url += !this.get('controls') ? '&controls=0&showinfo=0' : '';
      // Loop works only with playlist enabled
      // https://stackoverflow.com/questions/25779966/youtube-iframe-loop-doesnt-work
      url += this.get('loop') ? `&loop=1&playlist=${id}` : '';
      return url;
    },

    /**
     * Returns url to vimeo video
     * @return {string}
     * @private
     */
    getVimeoSrc() {
      var url = this.get('viUrl');
      url += this.get('videoId') + '?';
      url += this.get('autoplay') ? '&autoplay=1' : '';
      url += this.get('loop') ? '&loop=1' : '';
      url += !this.get('controls') ? '&title=0&portrait=0&badge=0' : '';
      url += this.get('color') ? '&color=' + this.get('color') : '';
      return url;
    }
  },
  {
    /**
     * Detect if the passed element is a valid component.
     * In case the element is valid an object abstracted
     * from the element will be returned
     * @param {HTMLElement}
     * @return {Object}
     * @private
     */
    isComponent(el) {
      var result = '';
      var isYtProv = /youtube\.com\/embed/.test(el.src);
      var isViProv = /player\.vimeo\.com\/video/.test(el.src);
      var isExtProv = isYtProv || isViProv;
      if (el.tagName == 'VIDEO' || (el.tagName == 'IFRAME' && isExtProv)) {
        result = { type: 'video' };
        if (el.src) result.src = el.src;
        if (isExtProv) {
          if (isYtProv) result.provider = yt;
          else if (isViProv) result.provider = vi;
        }
      }
      return result;
    }
  }
);
<|endoftext|>


<commit_before>var Terrain = {

    create: function(scene, camera, renderer) {
        var axes = new THREE.AxisHelper(100);
        scene.add(axes);

        var geometry = new THREE.PlaneGeometry(60, 60, 9, 9);
        var material = new THREE.MeshBasicMaterial({
            color: 0x333333,
            wireframe: true
        });
        var plane = new THREE.Mesh(geometry, material);
        scene.add(plane);
        // this.controls = new THREE.TrackballControls(camera);
        document.getElementById('webgl1').appendChild(renderer.domElement);
        this.render();
    },

    render: function() {
        this.controls.update();
        requestAnimationFrame(this.render);
        renderer.render(scene, camera);
    }
};
Terrain.test();
// exports.module = Terrain;<commit_msg>remove test code =)<commit_after>var Terrain = {

    create: function(scene, camera, renderer) {
        var axes = new THREE.AxisHelper(100);
        scene.add(axes);

        var geometry = new THREE.PlaneGeometry(60, 60, 9, 9);
        var material = new THREE.MeshBasicMaterial({
            color: 0x333333,
            wireframe: true
        });
        var plane = new THREE.Mesh(geometry, material);
        scene.add(plane);
        // this.controls = new THREE.TrackballControls(camera);
        document.getElementById('webgl1').appendChild(renderer.domElement);
        this.render();
    },

    render: function() {
        this.controls.update();
        requestAnimationFrame(this.render);
        renderer.render(scene, camera);
    }
};
exports.module = Terrain;<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2013  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// WidgetModel, WidgetView, and WidgetManager
//============================================================================
/**
 * Base Widget classes
 * @module IPython
 * @namespace IPython
 * @submodule widget
 */

(function () {
    "use strict";

    // Use require.js 'define' method so that require.js is intelligent enough to
    // syncronously load everything within this file when it is being 'required'
    // elsewhere.
    define(["underscore",
             "backbone",
            ], function (underscore, backbone) {

        //--------------------------------------------------------------------
        // WidgetManager class
        //--------------------------------------------------------------------
        var WidgetManager = function () {
            this.comm_manager = null;
            this.widget_model_types = {};
            this.widget_view_types = {};
            this._model_instances = {};

            Backbone.sync = function (method, model, options, error) {
                var result = model._handle_sync(method, options);
                if (options.success) {
                  options.success(result);
                }
            };
        };

        WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
            this.comm_manager = comm_manager;

            // Register already-registered widget model types with the comm manager.
            for (var widget_model_name in this.widget_model_types) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
        };

        WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
            // Register the widget with the comm manager.  Make sure to pass this object's context
            // in so `this` works in the call back.
            if (this.comm_manager !== null) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
            this.widget_model_types[widget_model_name] = widget_model_type;
        };

        WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
            this.widget_view_types[widget_view_name] = widget_view_type;
        };
	WidgetManager.prototype.handle_msg = function(msg, model) {
	    var method = msg.content.data.method;
	    switch (method) {
		case 'display':
		    var cell = this.get_msg_cell(msg.parent_header.msg_id);
		    if (cell === null) {
			console.log("Could not determine where the display" +
				    " message was from.  Widget will not be displayed");
		    } else {
			var view = this.create_view(model,
						    msg.content.data.view_name, cell);
			if (view !== undefined
			    && cell.widget_subarea !== undefined
			    && cell.widget_subarea !== null) {
                            cell.widget_area.show();
                            cell.widget_subarea.append(view.$el);
			}
		    }
		    break;
		case 'set_snapshot':
                    var cell = this.get_msg_cell(msg.parent_header.msg_id);
                    cell.metadata.snapshot = msg.content.data.snapshot;
                    break;
	    }
	}

	WidgetManager.prototype.create_view = function(model, view_name, cell) {
	    view_name = view_name || model.get('default_view_name');
            var ViewType = this.widget_view_types[view_name];
            if (ViewType !== undefined && ViewType !== null) {
                var view = new ViewType({model: model, widget_manager: this, cell: cell});
                view.render();
		model.views.push(view);
		/*
                // jng: Handle when the view element is remove from the page.
		// observe the view destruction event and do this.  We may need
		// to override the view's remove method to trigger this event.
                var that = this;
                view.$el.on("remove", function () {
                    var index = that.views.indexOf(view);
                    if (index > -1) {
                        that.views.splice(index, 1);
                    }
                    view.remove(); // Clean-up view

                    // Close the comm if there are no views left.
                    if (that.views.length() === 0) {
			//jng: trigger comm close event
                        }

                        if (that.comm !== undefined) {
                            that.comm.close();
                            delete that.comm.model; // Delete ref so GC will collect widget model.
                            delete that.comm;
                        }
                        delete that.widget_id; // Delete id from model so widget manager cleans up.
                    });
		*/
                return view;
            }
        },

        WidgetManager.prototype.get_msg_cell = function (msg_id) {
	    var cell = null;
            // First, check to see if the msg was triggered by cell execution.
            if (IPython.notebook !== undefined && IPython.notebook !== null) {
                cell = IPython.notebook.get_msg_cell(msg_id);
            }
	    if (cell !== null) {
		return cell
	    }
            // Second, check to see if a get_cell callback was defined
            // for the message.  get_cell callbacks are registered for
            // widget messages, so this block is actually checking to see if the
            // message was triggered by a widget.
            var kernel = this.get_kernel();
            if (kernel !== undefined && kernel !== null) {
                var callbacks = kernel.get_callbacks_for_msg(msg_id);
                if (callbacks !== undefined &&
                    callbacks.iopub !== undefined &&
                    callbacks.iopub.get_cell !== undefined) {

                    return callbacks.iopub.get_cell();
                }
            }

            // Not triggered by a cell or widget (no get_cell callback
            // exists).
            return null;
        };

        WidgetManager.prototype.get_model = function (widget_id) {
            var model = this._model_instances[widget_id];
            if (model !== undefined && model.id == widget_id) {
                return model;
            }
            return null;
        };

        WidgetManager.prototype.get_kernel = function () {
            if (this.comm_manager === null) {
                return null;
            } else {
                return this.comm_manager.kernel;
            }
        };

        WidgetManager.prototype.on_create_widget = function (callback) {
            this._create_widget_callback = callback;
        };

        WidgetManager.prototype._handle_create_widget = function (widget_model) {
            if (this._create_widget_callback) {
                try {
                    this._create_widget_callback(widget_model);
                } catch (e) {
                    console.log("Exception in WidgetManager callback", e, widget_model);
                }
            }
        };

        WidgetManager.prototype._handle_comm_open = function (comm, msg) {
            var widget_type_name = msg.content.target_name;
            var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
            this._model_instances[comm.comm_id] = widget_model;
            this._handle_create_widget(widget_model);
        };

        //--------------------------------------------------------------------
        // Init code
        //--------------------------------------------------------------------
        IPython.WidgetManager = WidgetManager;
        if (IPython.widget_manager === undefined || IPython.widget_manager === null) {
            IPython.widget_manager = new WidgetManager();
        }

        return IPython.widget_manager;
    });
}());
<commit_msg>Delete the snapshot message handler<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2013  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// WidgetModel, WidgetView, and WidgetManager
//============================================================================
/**
 * Base Widget classes
 * @module IPython
 * @namespace IPython
 * @submodule widget
 */

(function () {
    "use strict";

    // Use require.js 'define' method so that require.js is intelligent enough to
    // syncronously load everything within this file when it is being 'required'
    // elsewhere.
    define(["underscore",
             "backbone",
            ], function (underscore, backbone) {

        //--------------------------------------------------------------------
        // WidgetManager class
        //--------------------------------------------------------------------
        var WidgetManager = function () {
            this.comm_manager = null;
            this.widget_model_types = {};
            this.widget_view_types = {};
            this._model_instances = {};

            Backbone.sync = function (method, model, options, error) {
                var result = model._handle_sync(method, options);
                if (options.success) {
                  options.success(result);
                }
            };
        };

        WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
            this.comm_manager = comm_manager;

            // Register already-registered widget model types with the comm manager.
            for (var widget_model_name in this.widget_model_types) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
        };

        WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
            // Register the widget with the comm manager.  Make sure to pass this object's context
            // in so `this` works in the call back.
            if (this.comm_manager !== null) {
                this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
            }
            this.widget_model_types[widget_model_name] = widget_model_type;
        };

        WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
            this.widget_view_types[widget_view_name] = widget_view_type;
        };
	WidgetManager.prototype.handle_msg = function(msg, model) {
	    var method = msg.content.data.method;
	    switch (method) {
		case 'display':
		    var cell = this.get_msg_cell(msg.parent_header.msg_id);
		    if (cell === null) {
			console.log("Could not determine where the display" +
				    " message was from.  Widget will not be displayed");
		    } else {
			var view = this.create_view(model,
						    msg.content.data.view_name, cell);
			if (view !== undefined
			    && cell.widget_subarea !== undefined
			    && cell.widget_subarea !== null) {
                            cell.widget_area.show();
                            cell.widget_subarea.append(view.$el);
			}
		    }
		    break;
	    }
	}

	WidgetManager.prototype.create_view = function(model, view_name, cell) {
	    view_name = view_name || model.get('default_view_name');
            var ViewType = this.widget_view_types[view_name];
            if (ViewType !== undefined && ViewType !== null) {
                var view = new ViewType({model: model, widget_manager: this, cell: cell});
                view.render();
		model.views.push(view);
		/*
                // jng: Handle when the view element is remove from the page.
		// observe the view destruction event and do this.  We may need
		// to override the view's remove method to trigger this event.
                var that = this;
                view.$el.on("remove", function () {
                    var index = that.views.indexOf(view);
                    if (index > -1) {
                        that.views.splice(index, 1);
                    }
                    view.remove(); // Clean-up view

                    // Close the comm if there are no views left.
                    if (that.views.length() === 0) {
			//jng: trigger comm close event
                        }

                        if (that.comm !== undefined) {
                            that.comm.close();
                            delete that.comm.model; // Delete ref so GC will collect widget model.
                            delete that.comm;
                        }
                        delete that.widget_id; // Delete id from model so widget manager cleans up.
                    });
		*/
                return view;
            }
        },

        WidgetManager.prototype.get_msg_cell = function (msg_id) {
	    var cell = null;
            // First, check to see if the msg was triggered by cell execution.
            if (IPython.notebook !== undefined && IPython.notebook !== null) {
                cell = IPython.notebook.get_msg_cell(msg_id);
            }
	    if (cell !== null) {
		return cell
	    }
            // Second, check to see if a get_cell callback was defined
            // for the message.  get_cell callbacks are registered for
            // widget messages, so this block is actually checking to see if the
            // message was triggered by a widget.
            var kernel = this.get_kernel();
            if (kernel !== undefined && kernel !== null) {
                var callbacks = kernel.get_callbacks_for_msg(msg_id);
                if (callbacks !== undefined &&
                    callbacks.iopub !== undefined &&
                    callbacks.iopub.get_cell !== undefined) {

                    return callbacks.iopub.get_cell();
                }
            }

            // Not triggered by a cell or widget (no get_cell callback
            // exists).
            return null;
        };

        WidgetManager.prototype.get_model = function (widget_id) {
            var model = this._model_instances[widget_id];
            if (model !== undefined && model.id == widget_id) {
                return model;
            }
            return null;
        };

        WidgetManager.prototype.get_kernel = function () {
            if (this.comm_manager === null) {
                return null;
            } else {
                return this.comm_manager.kernel;
            }
        };

        WidgetManager.prototype.on_create_widget = function (callback) {
            this._create_widget_callback = callback;
        };

        WidgetManager.prototype._handle_create_widget = function (widget_model) {
            if (this._create_widget_callback) {
                try {
                    this._create_widget_callback(widget_model);
                } catch (e) {
                    console.log("Exception in WidgetManager callback", e, widget_model);
                }
            }
        };

        WidgetManager.prototype._handle_comm_open = function (comm, msg) {
            var widget_type_name = msg.content.target_name;
            var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
            this._model_instances[comm.comm_id] = widget_model;
            this._handle_create_widget(widget_model);
        };

        //--------------------------------------------------------------------
        // Init code
        //--------------------------------------------------------------------
        IPython.WidgetManager = WidgetManager;
        if (IPython.widget_manager === undefined || IPython.widget_manager === null) {
            IPython.widget_manager = new WidgetManager();
        }

        return IPython.widget_manager;
    });
}());
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Axis from '../Axis';

class XAxis extends Component {

  static propTypes = {
    type: PropTypes.string,
    getChart: PropTypes.func.isRequired // Provided by ChartProvider
  };

  render () {
    let { getChart, ...rest } = this.props;
    const chart = getChart();
    const type = (chart.getType() === 'stockChart') ? 'datetime' : 'linear';

    return (
      <Axis type={type} {...rest} isX />
    );
  }
}

export default XAxis;
<commit_msg>Enforce ID of XAxis if stock chart<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Axis from '../Axis';

class XAxis extends Component {

  static propTypes = {
    type: PropTypes.string,
    getChart: PropTypes.func.isRequired // Provided by ChartProvider
  };

  render () {
    let { getChart, id, ...rest } = this.props;
    const chart = getChart();
    const isStockChart = chart.getType() === 'stockChart';
    const type = isStockChart ? 'datetime' : 'linear';
    const axisId = isStockChart ? 'xAxis' : id;

    return (
      <Axis type={type} {...rest} id={axisId} isX />
    );
  }
}

export default XAxis;
<|endoftext|>


<commit_before>describe('When a <NavLink> is active', () => {
  it('applies its activeClassName')
  it('applies its activeStyle')
})

describe('When a <NavLink> is not active', () => {
  it('does not apply its activeClassName')
  it('does not apply its activeStyle')
})
<commit_msg>NavLink tests (#4421)<commit_after>import expect from 'expect'
import React from 'react'
import ReactDOM from 'react-dom'
import MemoryRouter from 'react-router/MemoryRouter'
import NavLink from '../NavLink'

describe('NavLink', () => {
  const node = document.createElement('div')

  afterEach(() => {
    ReactDOM.unmountComponentAtNode(node)
  })

  describe('When a <NavLink> is active', () => {
    it('applies its activeClassName', () => {
      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink to='/pizza' activeClassName='active'>Pizza!</NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.className).toContain('active')
    })

    it('applies its activeStyle', () => {
      const defaultStyle = { color: 'black' }
      const activeStyle = { color: 'red' }

      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink
            to='/pizza'
            style={defaultStyle}
            activeStyle={activeStyle}
            >
            Pizza!
          </NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.style.color).toBe(activeStyle.color)
    })
  })

  describe('When a <NavLink> is not active', () => {
    it('does not apply its activeClassName', () => {
      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink to='/salad' activeClassName='active'>Salad?</NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.className).toNotContain('active')
    })

    it('does not apply its activeStyle', () => {
      const defaultStyle = { color: 'black' }
      const activeStyle = { color: 'red' }

      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink
            to='/salad'
            style={defaultStyle}
            activeStyle={activeStyle}
            >
            Salad?
          </NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.style.color).toBe(defaultStyle.color)
    })
  })

  describe('isActive', () => {
    const activeExact = (match, location) => !!match && match.isExact

    it('applies active props when isActive returns true', () => {
      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink
            to='/pizza'
            activeClassName='active'
            isActive={activeExact}
            >
            Pizza!
          </NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.className).toContain('active')
    })

    it('does not apply active props when isActive returns false', () => {
      ReactDOM.render((
        <MemoryRouter initialEntries={['/pizza']}>
          <NavLink
            to='/pizza/anchovies'
            activeClassName='active'
            isActive={activeExact}
            >
            Pizza!
          </NavLink>
        </MemoryRouter>
      ), node)
      const a = node.getElementsByTagName('a')[0]
      expect(a.className).toNotContain('active')
    })
  })

})
<|endoftext|>


<commit_before>module.exports.name = 'userJoin';
module.exports.events = ['JOIN'];
let EWBF = null;
let JHO = null;
let DDJLog = null;
const EJLX_BAN_EMOJI_ID = '423687199385452545';
const LOCKDOWN_ROLE_ID = '259181555803619329';
module.exports.initialize = async (json, server) => {
  server.newUsers = [];
  if (!json || !json['newUsers']) return;
  server.newUsers = json['newUsers'];
  if (server.guild.id == '189571157446492161') {
    server.invites = await server.guild.fetchInvites(); // Cleanup when saving...?
    EWBF = server.guild.channels.get('277384105245802497');
    JHO = server.guild.channels.get('189571157446492161');
  } else if (server.guild.id == '453115403829248010') {
    server.invites = await server.guild.fetchInvites(); // Cleanup when saving...?
    DDJLog = server.guild.channels.get('453125855523241984');
  }
};
module.exports.isAllowed = () => {
  return true;
};

const Discord = require('discord.js');
const EPOCH = 1420070400000;
const Long = require('long');

function generateSnowflake(date) {
  function pad(v, n, c = '0') {
    return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n);
  }
  let BINARY = `${pad((date.getTime() - EPOCH).toString(2), 42)}0000100000000000000000`;
  return Long.fromString(BINARY, 2).toString();
}

function generateDiffStr(diffMillis) {
  const absDiff = Math.abs(diffMillis);
  const [hr, min] = [Math.floor(absDiff / 3600000), Math.floor(absDiff / 60000) % 60];
  return `${hr ? `${hr} hr ` : ''}${min} mins`;
}

function joinNotif(member, inv) {
  let embed = new Discord.RichEmbed();
  embed.description = `📥 **${member.user.tag}** has \`joined\` the server. (${member.id})`;
  embed.setFooter(`User Join (${member.guild.memberCount})\nLink: ${inv[0]} from ${inv[1].inviter.username}`, member.user.avatarURL);
  embed.setTimestamp();
  embed.setColor(0x84a332);
  return embed;
}

async function bparker(member, inv) {
  const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
  const username = member.user.username;
  let likelihood = 0;
  const diffNow = new Date() - date;
  if (diffNow < 600000) { // less than 10 minutes old
    likelihood += 4;
  }
  if (inv[0] === 'japanese') likelihood++; // jp link
  if ((username.includes('Lexy') && username.includes('Maria')) || username === 'OaklandRaiders') likelihood += 5;
  if (likelihood === 10) {
    await member.ban({ days: 1, reason: 'Auto BAN bparker'});
    setTimeout(async () => {
      let msgs = await JHO.fetchMessages({limit: 30});
      for (let [, msg] of msgs) {
        if (msg.author.id == '159985870458322944' && msg.mentions.users.has(member.id)) { // delete mee6 welcome
          msg.delete();
        }
        if (msg.author.id === '270366726737231884' && msg.content.includes(`Welcome ${username}`)) { // delete Rai welcome
          msg.delete();
        }
      }
    }, 3000);
    return true;
  }
  return false;
}

async function sendLockdownNotif(member, inv, lockdown, welcome) {
  const embed = new Discord.RichEmbed();
  const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
  let likelihood = 0;
  const diffNow = new Date() - date;
  const diffThen = lockdown.after ? new Date(lockdown.after) - date : null;
  const diffNowStr = generateDiffStr(diffNow);
  const regexp = lockdown.regex && new RegExp(lockdown.regex, lockdown.ignoreCase && 'i');
  if (diffNow < 600000) { // less than 10 minutes old
    likelihood += 4;
  } else if (diffNow < 86400000) { // less than a day old
    likelihood += 2;
  } else if (diffNow < 604800000) { // less than a week old
    likelihood++;
  }
  if (diffThen && diffThen < 0) likelihood += 2; // after the specified time
  if (lockdown.link && inv[0] === lockdown.link) likelihood++; // same link
  if (regexp && regexp.test(member.user.username)) likelihood += 3; // regex name
  const max = 4 + (lockdown.after ? 2 : 0) + (lockdown.link ? 1 : 0) + (lockdown.regex ? 3 : 0);

  const createdStr = `Account created **${diffNowStr}** ago${diffThen ? ` and **${generateDiffStr(diffThen)}** ${diffThen > 0 ? 'before' : 'after'} the specified time\n` : '\n'}`;
  const linkStr = lockdown.link && inv[0] === lockdown.link ? `Used the same link \`${inv[0]}\` from ${inv[1].inviter.username}\n` : '';
  const regexStr = regexp && regexp.test(member.user.username) ? `Username matched the regex: \`${lockdown.regex}\`\n` : '';
  embed.title = 'New User Alert';
  embed.description = `**${member.user.tag}** has \`joined\` the server. (${member.id}) ${member}\n\n${createdStr}${linkStr}${regexStr}Suspicious Level: **${likelihood}**/${max}\n${likelihood !== 0 && likelihood !== 10 ? `\nMods and **WP** can react with ✅ if you think this user is not suspicious, or <:ban:${EJLX_BAN_EMOJI_ID}> **twice** (triple click) to ban.` : ''}`;
  embed.setFooter(`User Join (${member.guild.memberCount})\nLink: ${inv[0]} from ${inv[1].inviter.username}`, member.user.avatarURL);
  embed.setTimestamp();
  embed.setColor(0x84a332);
  const banEmoji = member.guild.emojis.get(EJLX_BAN_EMOJI_ID);
  if (likelihood <= 3) { // not suspicious
    welcome && await member.removeRole(LOCKDOWN_ROLE_ID);
    welcome && await JHO.send(welcome);
    return;
  } else if (likelihood === 10 && welcome) {
    await member.ban({ days: 1, reason: 'Auto BAN. Matched all criteria.'});
    await EWBF.send({ embed });
    return;
  }
  const msg = await EWBF.send({ embed });

  await msg.react('✅');
  await msg.react(banEmoji);

  const filter = (reaction) => reaction.emoji.name === '✅' || (reaction.emoji.name === 'ban' && reaction.emoji.id === EJLX_BAN_EMOJI_ID);
  const banReacted = new Set();
  const collector = msg.createReactionCollector(filter, { time: 10 * 60 * 1000 }); // 10 minutes
  collector.on('collect', async (r) => {
    if (r.emoji.name === '✅') {
      welcome && await member.removeRole(LOCKDOWN_ROLE_ID);
      welcome && await JHO.send(welcome);
      collector.stop();
    } else {
      if (banReacted.has(r.users.lastKey())) {
        await member.ban({ days: 1, reason: `Banned by ${r.users.last()} during lockdown`});
        collector.stop();
      } else {
        r.users.forEach((user, userID) => banReacted.add(userID));
      }
    }
  });

  collector.on('end', () => {
    msg.clearReactions();
  });
}

async function postLogs(member, server) {
  const newInvites = await server.guild.fetchInvites();
  let inv = null;
  for (let [k, v] of newInvites) {
    let old = server.invites.get(k);
    if (old) {
      if (old.uses < v.uses) {
        inv = [k, v];
        break;
      }
    } else if (v.uses > 0) {
      inv = [k, v];
      break;
    }
  }
  server.invites = newInvites;
  if (inv === null) inv = ['japanese', { inviter: { username: 'vanityURL' } }];
  console.log(`${member.user.username} joined with ${inv[0]}`);
  if (inv[0] === 'NJJCYVD') {
    const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
    const diff = date - new Date(server.lastmag);
    if (diff > 0) {
      const m = Math.floor(diff / (60 * 1000));
      const hr = Math.floor(m / 60);
      const min = m % 60;
      const avatarURL = member.user.avatarURL;
      if (avatarURL && avatarURL.includes('cdn.discordapp.com/avatars')) {
          const embed = new Discord.RichEmbed();
          embed.setTitle(`${member.user.tag} (${member.id}) might be magmikan aka リア充先輩 aka じぇい`)
          embed.setDescription(`Account created: ${hr} hrs ${min} mins after the last time magmikan was banned, and he has an avatar already`);
          embed.setFooter(`Account created: `, avatarURL);
          embed.setTimestamp(date);
          EWBF.send({ embed });
      }
    }
  }

  if (await bparker(member, inv)) return;

  let welcome = `Welcome ${member} to the English-Japanese Language Exchange. Please read the rules first If you have any questions feel free to message one of the Mods!  Tell us what your native language is and we'll get you properly tagged with a colored name.\n\n`;
  welcome += `${member}さん、ようこそEnglish-Japanese Language Exchangeへ!\nあなたの母語を教えてください!\n質問があれば、何でも遠慮なく聞いてくださいね。このチャンネルには日本語と英語で投稿できます。よろしくお願いします！ <@&357449148405907456>`;

  if (server.lockdown) {
    await member.addRole(LOCKDOWN_ROLE_ID);
    await sendLockdownNotif(member, inv, server.lockdown, welcome);
    return;
  } else if (server.quickban) {
    await sendLockdownNotif(member, inv, server.quickban, null);
  } else if (member.guild.members.get('270366726737231884').presence.status == 'offline') { // rybot
    let embed = joinNotif(member, inv);
    EWBF.send({ embed });
  } else {
    setTimeout(async () => {
      let joinedSnowflake = generateSnowflake(member.joinedAt);
      let msgs = await EWBF.fetchMessages({limit: 20, after: joinedSnowflake});
      for (let [, msg] of msgs) {
        if (msg.author.id == '270366726737231884' && msg.embeds.length && msg.embeds[0].description.includes(member.id)) {
          return;
        }
      }
      let embed = joinNotif(member, inv);
      EWBF.send({embed});
    }, 5000);
  }

  if (member.guild.members.get('159985870458322944').presence.status == 'offline') { // mee6
    JHO.send(welcome);
  } else {
    setTimeout(async () => {
      let msgs = await JHO.fetchMessages({limit: 50});
      for (let [, msg] of msgs) {
        if (msg.author.id == '159985870458322944' && msg.mentions.members.has(member.id)) {
          return;
        }
      }
      JHO.send(welcome);
    }, 5000);
  }
}

async function postLogsDDJ(member, server) {
  let newInvites = await server.guild.fetchInvites();
  let inv = null;
  for (let [k, v] of newInvites) {
    let old = server.invites.get(k);
    if (old) {
      if (old.uses < v.uses) {
        inv = [k, v];
        break;
      }
    } else if (v.uses > 0) {
      inv = [k, v];
      break;
    }
  }
  server.invites = newInvites;
  let embed = joinNotif(member, inv);
  DDJLog.send({embed});
}
module.exports.process = async (member, server) => {
  if (server.newUsers.unshift(member.id) > 3) server.newUsers.pop();
  if (member.guild.id == '189571157446492161')
    setTimeout(() => postLogs(member, server), 500);
  if (member.guild.id == '453115403829248010')
    setTimeout(() => postLogsDDJ(member, server), 500);
};
<commit_msg>temp anti raid<commit_after>module.exports.name = 'userJoin';
module.exports.events = ['JOIN'];
let EWBF = null;
let JHO = null;
let DDJLog = null;
const EJLX_BAN_EMOJI_ID = '423687199385452545';
const LOCKDOWN_ROLE_ID = '259181555803619329';
module.exports.initialize = async (json, server) => {
  server.newUsers = [];
  if (!json || !json['newUsers']) return;
  server.newUsers = json['newUsers'];
  if (server.guild.id == '189571157446492161') {
    server.invites = await server.guild.fetchInvites(); // Cleanup when saving...?
    EWBF = server.guild.channels.get('277384105245802497');
    JHO = server.guild.channels.get('189571157446492161');
  } else if (server.guild.id == '453115403829248010') {
    server.invites = await server.guild.fetchInvites(); // Cleanup when saving...?
    DDJLog = server.guild.channels.get('453125855523241984');
  }
};
module.exports.isAllowed = () => {
  return true;
};

const tempList = '687373983787778090,687367734471950383,683378103736729648,683379768300666908,687719049383247904,687769173614526471,688146624173965319,687810824080719898,687732351136301080,688121689175097360,688144158052843551,688153832869331021,688117574239649925,688130662888243352,687372556290097182,688161999519219722,684126052980883578,687752330153820207,688140949053767729,687729355895734293,688118381903216691,688099979784356022,687373930343694440,687727528374304777,687092262777520191,683367888672784415,686327347343130630,688109684888043520,683388942321451022,688130113245937829,687372351029116939,684689716574158848,684649182493278243,688132617962651913,688126044632514574,687065022165549110,688158719741394959,687363365835636806,687737549321797664,684120586083237958,688097139901202453,688161249816608769,687726887719534684,686327003712192531,688173430746775567,68810968488804352,68821158354092036,688121631608143878,688115974490161211,688119855475589149,688114038219079800,688068704105267203,688140368767746146,688138166233858056,683823821152845825'.split(',');

const Discord = require('discord.js');
const EPOCH = 1420070400000;
const Long = require('long');

function generateSnowflake(date) {
  function pad(v, n, c = '0') {
    return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n);
  }
  let BINARY = `${pad((date.getTime() - EPOCH).toString(2), 42)}0000100000000000000000`;
  return Long.fromString(BINARY, 2).toString();
}

function generateDiffStr(diffMillis) {
  const absDiff = Math.abs(diffMillis);
  const [hr, min] = [Math.floor(absDiff / 3600000), Math.floor(absDiff / 60000) % 60];
  return `${hr ? `${hr} hr ` : ''}${min} mins`;
}

function joinNotif(member, inv) {
  let embed = new Discord.RichEmbed();
  embed.description = `📥 **${member.user.tag}** has \`joined\` the server. (${member.id})`;
  embed.setFooter(`User Join (${member.guild.memberCount})\nLink: ${inv[0]} from ${inv[1].inviter.username}`, member.user.avatarURL);
  embed.setTimestamp();
  embed.setColor(0x84a332);
  return embed;
}

async function bparker(member, inv) {
  const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
  const username = member.user.username;
  let likelihood = 0;
  const diffNow = new Date() - date;
  if (diffNow < 600000) { // less than 10 minutes old
    likelihood += 4;
  }
  if (inv[0] === 'japanese') likelihood++; // jp link
  if ((username.includes('Lexy') && username.includes('Maria')) || username === 'OaklandRaiders') likelihood += 5;
  if (likelihood === 10) {
    await member.ban({ days: 1, reason: 'Auto BAN bparker'});
    setTimeout(async () => {
      let msgs = await JHO.fetchMessages({limit: 30});
      for (let [, msg] of msgs) {
        if (msg.author.id == '159985870458322944' && msg.mentions.users.has(member.id)) { // delete mee6 welcome
          msg.delete();
        }
        if (msg.author.id === '270366726737231884' && msg.content.includes(`Welcome ${username}`)) { // delete Rai welcome
          msg.delete();
        }
      }
    }, 3000);
    return true;
  }
  return false;
}

async function sendLockdownNotif(member, inv, lockdown, welcome) {
  const embed = new Discord.RichEmbed();
  const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
  let likelihood = 0;
  const diffNow = new Date() - date;
  const diffThen = lockdown.after ? new Date(lockdown.after) - date : null;
  const diffNowStr = generateDiffStr(diffNow);
  const regexp = lockdown.regex && new RegExp(lockdown.regex, lockdown.ignoreCase && 'i');
  if (diffNow < 600000) { // less than 10 minutes old
    likelihood += 4;
  } else if (diffNow < 86400000) { // less than a day old
    likelihood += 2;
  } else if (diffNow < 604800000) { // less than a week old
    likelihood++;
  }
  if (diffThen && diffThen < 0) likelihood += 2; // after the specified time
  if (lockdown.link && inv[0] === lockdown.link) likelihood++; // same link
  if (regexp && regexp.test(member.user.username)) likelihood += 3; // regex name
  const max = 4 + (lockdown.after ? 2 : 0) + (lockdown.link ? 1 : 0) + (lockdown.regex ? 3 : 0);

  const createdStr = `Account created **${diffNowStr}** ago${diffThen ? ` and **${generateDiffStr(diffThen)}** ${diffThen > 0 ? 'before' : 'after'} the specified time\n` : '\n'}`;
  const linkStr = lockdown.link && inv[0] === lockdown.link ? `Used the same link \`${inv[0]}\` from ${inv[1].inviter.username}\n` : '';
  const regexStr = regexp && regexp.test(member.user.username) ? `Username matched the regex: \`${lockdown.regex}\`\n` : '';
  embed.title = 'New User Alert';
  embed.description = `**${member.user.tag}** has \`joined\` the server. (${member.id}) ${member}\n\n${createdStr}${linkStr}${regexStr}Suspicious Level: **${likelihood}**/${max}\n${likelihood !== 0 && likelihood !== 10 ? `\nMods and **WP** can react with ✅ if you think this user is not suspicious, or <:ban:${EJLX_BAN_EMOJI_ID}> **twice** (triple click) to ban.` : ''}`;
  embed.setFooter(`User Join (${member.guild.memberCount})\nLink: ${inv[0]} from ${inv[1].inviter.username}`, member.user.avatarURL);
  embed.setTimestamp();
  embed.setColor(0x84a332);
  const banEmoji = member.guild.emojis.get(EJLX_BAN_EMOJI_ID);
  if (likelihood <= 3) { // not suspicious
    welcome && await member.removeRole(LOCKDOWN_ROLE_ID);
    welcome && await JHO.send(welcome);
    return;
  } else if (likelihood === 10 && welcome) {
    await member.ban({ days: 1, reason: 'Auto BAN. Matched all criteria.'});
    await EWBF.send({ embed });
    return;
  }
  const msg = await EWBF.send({ embed });

  await msg.react('✅');
  await msg.react(banEmoji);

  const filter = (reaction) => reaction.emoji.name === '✅' || (reaction.emoji.name === 'ban' && reaction.emoji.id === EJLX_BAN_EMOJI_ID);
  const banReacted = new Set();
  const collector = msg.createReactionCollector(filter, { time: 10 * 60 * 1000 }); // 10 minutes
  collector.on('collect', async (r) => {
    if (r.emoji.name === '✅') {
      welcome && await member.removeRole(LOCKDOWN_ROLE_ID);
      welcome && await JHO.send(welcome);
      collector.stop();
    } else {
      if (banReacted.has(r.users.lastKey())) {
        await member.ban({ days: 1, reason: `Banned by ${r.users.last()} during lockdown`});
        collector.stop();
      } else {
        r.users.forEach((user, userID) => banReacted.add(userID));
      }
    }
  });

  collector.on('end', () => {
    msg.clearReactions();
  });
}

async function postLogs(member, server) {
  const newInvites = await server.guild.fetchInvites();
  let inv = null;
  for (let [k, v] of newInvites) {
    let old = server.invites.get(k);
    if (old) {
      if (old.uses < v.uses) {
        inv = [k, v];
        break;
      }
    } else if (v.uses > 0) {
      inv = [k, v];
      break;
    }
  }
  server.invites = newInvites;
  if (inv === null) inv = ['japanese', { inviter: { username: 'vanityURL' } }];
  console.log(`${member.user.username} joined with ${inv[0]}`);
  if (inv[0] === 'NJJCYVD') {
    const date = Discord.SnowflakeUtil.deconstruct(member.id).date;
    const diff = date - new Date(server.lastmag);
    if (diff > 0) {
      const m = Math.floor(diff / (60 * 1000));
      const hr = Math.floor(m / 60);
      const min = m % 60;
      const avatarURL = member.user.avatarURL;
      if (avatarURL && avatarURL.includes('cdn.discordapp.com/avatars')) {
          const embed = new Discord.RichEmbed();
          embed.setTitle(`${member.user.tag} (${member.id}) might be magmikan aka リア充先輩 aka じぇい`)
          embed.setDescription(`Account created: ${hr} hrs ${min} mins after the last time magmikan was banned, and he has an avatar already`);
          embed.setFooter(`Account created: `, avatarURL);
          embed.setTimestamp(date);
          EWBF.send({ embed });
      }
    }
  }

  if (await bparker(member, inv)) return;

  let welcome = `Welcome ${member} to the English-Japanese Language Exchange. Please read the rules first If you have any questions feel free to message one of the Mods!  Tell us what your native language is and we'll get you properly tagged with a colored name.\n\n`;
  welcome += `${member}さん、ようこそEnglish-Japanese Language Exchangeへ!\nあなたの母語を教えてください!\n質問があれば、何でも遠慮なく聞いてくださいね。このチャンネルには日本語と英語で投稿できます。よろしくお願いします！ <@&357449148405907456>`;

  if (server.lockdown) {
    await member.addRole(LOCKDOWN_ROLE_ID);
    await sendLockdownNotif(member, inv, server.lockdown, welcome);
    return;
  } else if (server.quickban) {
    await sendLockdownNotif(member, inv, server.quickban, null);
  } else if (member.guild.members.get('270366726737231884').presence.status == 'offline') { // rybot
    let embed = joinNotif(member, inv);
    EWBF.send({ embed });
  } else {
    setTimeout(async () => {
      let joinedSnowflake = generateSnowflake(member.joinedAt);
      let msgs = await EWBF.fetchMessages({limit: 20, after: joinedSnowflake});
      for (let [, msg] of msgs) {
        if (msg.author.id == '270366726737231884' && msg.embeds.length && msg.embeds[0].description.includes(member.id)) {
          return;
        }
      }
      let embed = joinNotif(member, inv);
      EWBF.send({embed});
    }, 5000);
  }

  if (member.guild.members.get('159985870458322944').presence.status == 'offline') { // mee6
    JHO.send(welcome);
  } else {
    setTimeout(async () => {
      let msgs = await JHO.fetchMessages({limit: 50});
      for (let [, msg] of msgs) {
        if (msg.author.id == '159985870458322944' && msg.mentions.members.has(member.id)) {
          if (tempList.includes(member.id)) { // delete raider's welcome message
            await msg.delete();
          }
          return;
        }
      }
      JHO.send(welcome);
    }, 5000);
  }
}

async function postLogsDDJ(member, server) {
  let newInvites = await server.guild.fetchInvites();
  let inv = null;
  for (let [k, v] of newInvites) {
    let old = server.invites.get(k);
    if (old) {
      if (old.uses < v.uses) {
        inv = [k, v];
        break;
      }
    } else if (v.uses > 0) {
      inv = [k, v];
      break;
    }
  }
  server.invites = newInvites;
  let embed = joinNotif(member, inv);
  DDJLog.send({embed});
}
module.exports.process = async (member, server) => {
  if (server.newUsers.unshift(member.id) > 3) server.newUsers.pop();
  if (tempList.includes(member.id)) {
    await member.ban({ days: 1, reason: 'raid'});
  }
  if (member.guild.id == '189571157446492161')
    setTimeout(() => postLogs(member, server), 500);
  if (member.guild.id == '453115403829248010')
    setTimeout(() => postLogsDDJ(member, server), 500);
};
<|endoftext|>


<commit_before>import React, {Component, useState} from 'react'
import {
  FormControlLabel,
  Checkbox,
  FormGroup,
  Box,
  Typography,
  Divider,
  Grid,
  RadioGroup,
  Radio,
  Avatar,
  Button
} from '@material-ui/core'

import Moment from 'react-moment';
import SegmentManager from '../../components/segmentManager'
import { parseJwt, generateJWT } from '../../components/segmentManager/jwt'

import { PREDICATES_SEARCH} from '../../graphql/mutations'
 import graphql from '../../graphql/client'
 import gravatar from '../../shared/gravatar'

export default function InboundSettings({settings, update}){
  const [state, setState] = React.useState({
    enable_inbound: true,
    visitors_enabled: true,
    users_enabled: true,
    users_radio: "all",
    visitorsPredicates: [],
    visitors_radio: "all",
    usersPredicates: [],
  });

  const handleChange = name => event => {
    setState({ ...state, [name]: event.target.checked });
  };

  function setPredicates(name, value){
    setState({ ...state, [name]: value });
  }

  function handleSubmit(){
    const {
      enable_inbound, users_radio, usersPredicates,
      visitors_radio, visitors_enabled, visitorsPredicates
    } = state

    const data = {
      app: {
        inbound_settings: {
          enabled: enable_inbound,
          users: {
            enabled_segment: users_radio,
            predicates: usersPredicates
          },
          visitors: {
            enabled_segment: visitors_radio,
            predicates: visitorsPredicates
          }
        }
      }
    }
    update(data)
  }

  return (

      <Typography variant={"h4"}>
        Control inbound conversations and the launcher
      </Typography>

      <Typography variant={"subtitle2"}>
        Control who can send you messages and where they see the launcher
      </Typography>

      <Typography variant={"h5"}>
        New conversations button
      </Typography>

      <Grid container>
        <FormControlLabel
          control={
            <Checkbox
              checked={state.enable_inbound}
              onChange={handleChange('enable_inbound')}
              value={state.enable_inbound}
              color="primary"
            />
          }
          label="Let people start new inbound conversations with you"
        />
      </Grid>

      <Typography variant={"caption"}>
        When this is turned off, people can only reply to the outbound messages  you send.
      </Typography>

      <Divider/>

      <Typography variant={"h5"}>
        visibility
      </Typography>

      <Typography variant={"body1"}>
        Control who sees the standard Messenger launcher on your website.
      </Typography>

      <Typography variant={"body1"}>
        Any messages you send will still be delivered.
      </Typography>

      <Typography variant={"body1"}>
        On the web, show the standard Messenger launcher to:
        Users
      </Typography>

      <Divider/>

      <AppSegmentManager
        app={settings}
        label={"Users"}
        namespace={"users"}
        all={"All Users"}
        checked={state.users_enabled}
        updateChecked={handleChange}
        predicates={state.usersPredicates}
        setPredicates={setPredicates}
        radioValue={state.users_radio}
        some={"Users who match certain data"}
      />

      <Divider/>

      <AppSegmentManager
        app={settings}
        label={"Visitors"}
        all={"All Visitors"}
        namespace="visitors"
        checked={state.visitors_enabled}
        updateChecked={handleChange}
        predicates={state.visitorsPredicates}
        setPredicates={setPredicates}
        radioValue={state.visitors_radio}
        some={"Visitors who match certain data"}
      />

      <Typography variant="caption">
        This doesn’t affect the outbound messages you send.
      </Typography>

      <Button onClick={handleSubmit}
        variant={"contained"} color={"primary"}>
        Save
      </Button>

  )
}

function AppSegmentManager({
  app,
  label,
  all,
  some,
  checked,
  updateChecked,
  namespace,
  predicates,
  setPredicates,
  radioValue
}){

  //const [checked, setChecked]= useState(checked)
  //const [radioValue, setRadioValue] = useState("all")
  //const [predicates, setPredicates] = useState([])

  function handleChange(e){
    updateChecked(e)
    //setChecked(!checked)
  }

  function handleChangeRadio(e){
    setPredicates(`${namespace}_radio`, e.target.value)
  }

  function updatePredicates(data, cb){
    setPredicates(`${namespace}Predicates`, data.segments)
    cb && cb()
  }

  console.log("predicates ", namespace, predicates)

  return (

    <Grid container>
      <FormControlLabel
        control={
          <Checkbox
            checked={checked}
            onChange={updateChecked(`${namespace}_enabled`)}
            value={checked}
            color="primary"
          />
        }
        label={label}
      />

      <RadioGroup
        //aria-label="gender"
        //name="gender1"
        //className={classes.group}
        disabled={!checked}
        value={radioValue}
        onChange={handleChangeRadio}
      >

        <FormControlLabel
          disabled={!checked}
          value="all"
          control={<Radio />}
          label={all}
        />

        <FormControlLabel
          disabled={!checked}
          value="some"
          control={<Radio />}
          label={some}
        />

        {
          checked && radioValue === "some" ?
          <AppSegment
            app={app}
            data={{ segments: predicates }}
            updateData={updatePredicates}
          /> : null
        }

      </RadioGroup>

    </Grid>

  )
}

class AppSegment extends Component {

  constructor(props) {
    super(props)
    this.state = {
      jwt: null,
      app_users: [],
      search: false,
      meta: {}
    }
  }
  componentDidMount() {
    /*this.props.actions.fetchAppSegment(
      this.props.app.segments[0].id
    )*/

    this.search()
  }

  updateData = (data, cb) => {
    const newData = Object.assign({}, this.props.data, { segments: data.data })
    this.props.updateData(newData, cb ? cb() : null)
  }

  updatePredicate = (data, cb) => {
    const jwtToken = generateJWT(data)
    //console.log(parseJwt(jwtToken))
    if (cb)
      cb(jwtToken)
    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt), this.search))
  }

  addPredicate = (data, cb) => {

    const pending_predicate = {
      attribute: data.name,
      comparison: null,
      type: data.type,
      value: data.value
    }

    const new_predicates = this.props.data.segments.concat(pending_predicate)
    const jwtToken = generateJWT(new_predicates)
    //console.log(parseJwt(jwtToken))
    if (cb)
      cb(jwtToken)

    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt)))
  }

  deletePredicate(data) {
    const jwtToken = generateJWT(data)
    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt), this.search))
  }

  search = (page) => {

    this.setState({ searching: true })
    // jwt or predicates from segment
    //console.log(this.state.jwt)
    const data = this.state.jwt ? parseJwt(this.state.jwt).data : this.props.data.segments
    const predicates_data = {
      data: {
        predicates: data.filter((o) => o.comparison)
      }
    }

    graphql(PREDICATES_SEARCH, {
      appKey: this.props.app.key,
      search: predicates_data,
      page: page || 1,
      per: 5,
    },{
      success: (data) => {
        const appUsers = data.predicatesSearch.appUsers
        this.setState({
          app_users: appUsers.collection,
          meta: appUsers.meta,
          searching: false
        })
      },
      error: (error) => {
        debugger
      }
    })
  }

  showUserDrawer = (o)=>{
    this.props.dispatch(
      toggleDrawer({ rightDrawer: true }, ()=>{
        this.props.dispatch(getAppUser(o.id))
      })
    )
  }

  render() {
    return <SegmentManager {...this.props}
      loading={this.state.searching}
      predicates={this.props.data.segments}
      meta={this.state.meta}
      collection={this.state.app_users}
      updatePredicate={this.updatePredicate.bind(this)}
      addPredicate={this.addPredicate.bind(this)}
      deletePredicate={this.deletePredicate.bind(this)}
      search={this.search.bind(this)}

      loading={this.props.searching}
      columns={[

        {name: 'id', title: 'id', hidden: true},
        {field: 'email', title: 'email',
          render: row => (row ?

 this.showUserDrawer(row) }>

                  <Avatar
                    name={row.email}
                    size="medium"
                    src={gravatar(row.email)}
                  />

              <Typography>{row.name || row.displayName}</Typography>

           : undefined)
        },
        {field: 'lastVisitedAt',
          title: 'lastVisitedAt',
          render: row => (row ? <Moment fromNow>
                                        {row.lastVisitedAt}
                                      </Moment> : undefined)
        },
        {field: 'state', title: 'state'},
        {field: 'online', title: 'online'},
        {field: 'lat',  title: 'lat'},
        {field: 'lng',  title: 'lng'},
        {field: 'postal', title: 'postal'},
        {field: 'browser', title: 'browser'},
        {field: 'referrer', title: 'referrer'},
        {field: 'os', title: 'os'},
        {field: 'osVersion', title: 'osVersion'},
        {field: 'lang', title: 'lang'},

      ]}

      defaultHiddenColumnNames={
        ['id',
        'state',
        'online',
        'lat',
        'lng',
        'postal',
        'browserLanguage',
        'referrer',
        'os',
        'osVersion',
        'lang'
        ]}
      //selection [],
      tableColumnExtensions={[
        //{ columnName: 'id', width: 150 },
        { columnName: 'email', width: 250 },
        { columnName: 'lastVisitedAt', width: 120 },
        { columnName: 'os', width: 100 },
        { columnName: 'osVersion', width: 100 },
        { columnName: 'state', width: 80 },
        { columnName: 'online', width: 80 },
        //{ columnName: 'amount', align: 'right', width: 140 },
      ]}
      leftColumns={ ['email']}
      rightColumns={ ['online']}
      //toggleMapView={this.toggleMapView}
      //map_view={this.state.map_view}
      //enableMapView={true}
    >
      { /*
        this.state.jwt ?
          <Button isLoading={false}
            appearance={'link'}
            onClick={this.handleSave}>

            {" "}
            Save Segment
          </Button> : null
      */
      }

    </SegmentManager>
  }
}<commit_msg>Update InboundSettings.js<commit_after>import React, {Component, useState} from 'react'
import {
  FormControlLabel,
  Checkbox,
  FormGroup,
  Box,
  Typography,
  Divider,
  Grid,
  RadioGroup,
  Radio,
  Avatar,
  Button
} from '@material-ui/core'

import Moment from 'react-moment';
import SegmentManager from '../../components/segmentManager'
import { parseJwt, generateJWT } from '../../components/segmentManager/jwt'

import { PREDICATES_SEARCH} from '../../graphql/mutations'
 import graphql from '../../graphql/client'
 import gravatar from '../../shared/gravatar'

export default function InboundSettings({settings, update}){
  const [state, setState] = React.useState({
    enable_inbound: true,
    visitors_enabled: true,
    users_enabled: true,
    users_radio: "all",
    visitorsPredicates: [],
    visitors_radio: "all",
    usersPredicates: [],
  });

  const handleChange = name => event => {
    setState({ ...state, [name]: event.target.checked });
  };

  function setPredicates(name, value){
    setState({ ...state, [name]: value });
  }

  function handleSubmit(){
    const {
      enable_inbound, users_radio, usersPredicates,
      visitors_radio, visitors_enabled, visitorsPredicates
    } = state

    const data = {
      app: {
        inbound_settings: {
          enabled: enable_inbound,
          users: {
            enabled_segment: users_radio,
            predicates: usersPredicates
          },
          visitors: {
            enabled_segment: visitors_radio,
            predicates: visitorsPredicates
          }
        }
      }
    }
    update(data)
  }

  return (

      <Typography variant={"h4"}>
        Control inbound conversations and the launcher
      </Typography>

      <Typography variant={"subtitle2"}>
        Control who can send you messages and where they see the launcher
      </Typography>

      <Typography variant={"h5"}>
        New conversations button
      </Typography>

      <Grid container>
        <FormControlLabel
          control={
            <Checkbox
              checked={state.enable_inbound}
              onChange={handleChange('enable_inbound')}
              value={state.enable_inbound}
              color="primary"
            />
          }
          label="Let people start new inbound conversations with you"
        />
      </Grid>

      <Typography variant={"caption"}>
        When this is turned off, people can only reply to the outbound messages  you send.
      </Typography>

      <Divider/>

      <Typography variant={"h5"}>
        visibility
      </Typography>

      <Typography variant={"body1"}>
        Control who sees the standard Messenger launcher on your website.
      </Typography>

      <Typography variant={"body1"}>
        Any messages you send will still be delivered.
      </Typography>

      <Typography variant={"body1"}>
        On the web, show the standard Messenger launcher to:
        Users
      </Typography>

      <Divider/>

      <AppSegmentManager
        app={settings}
        label={"Users"}
        namespace={"users"}
        all={"All Users"}
        checked={state.users_enabled}
        updateChecked={handleChange}
        predicates={state.usersPredicates}
        setPredicates={setPredicates}
        radioValue={state.users_radio}
        some={"Users who match certain data"}
      />

      <Divider/>

      <AppSegmentManager
        app={settings}
        label={"Visitors"}
        all={"All Visitors"}
        namespace="visitors"
        checked={state.visitors_enabled}
        updateChecked={handleChange}
        predicates={state.visitorsPredicates}
        setPredicates={setPredicates}
        radioValue={state.visitors_radio}
        some={"Visitors who match certain data"}
      />

      <Typography variant="caption">
        This doesn’t affect the outbound messages you send.
      </Typography>

      <Button onClick={handleSubmit}
        variant={"contained"} color={"primary"}>
        Save
      </Button>

  )
}

function AppSegmentManager({
  app,
  label,
  all,
  some,
  checked,
  updateChecked,
  namespace,
  predicates,
  setPredicates,
  radioValue
}){

  //const [checked, setChecked]= useState(checked)
  //const [radioValue, setRadioValue] = useState("all")
  //const [predicates, setPredicates] = useState([])

  function handleChange(e){
    updateChecked(e)
    //setChecked(!checked)
  }

  function handleChangeRadio(e){
    setPredicates(`${namespace}_radio`, e.target.value)
  }

  function updatePredicates(data, cb){
    setPredicates(`${namespace}Predicates`, data.segments)
    cb && cb()
  }

  return (

    <Grid container>

      <Grid item sm={6}>
        <FormControlLabel
          control={
            <Checkbox
              checked={checked}
              onChange={updateChecked(`${namespace}_enabled`)}
              value={checked}
              color="primary"
            />
          }
          label={label}
        />
      </Grid>

      <Grid item={6}>
        <RadioGroup
          //aria-label="gender"
          //name="gender1"
          //className={classes.group}
          disabled={!checked}
          value={radioValue}
          onChange={handleChangeRadio}
        >

          <FormControlLabel
            disabled={!checked}
            value="all"
            control={<Radio />}
            label={all}
          />

          <FormControlLabel
            disabled={!checked}
            value="some"
            control={<Radio />}
            label={some}
          />

        </RadioGroup>
      </Grid>

      <Grid item sm={12}>
        {
          checked && radioValue === "some" ?
          <AppSegment
            app={app}
            data={{ segments: predicates }}
            updateData={updatePredicates}
          /> : null
        }
      </Grid>

    </Grid>

  )
}

class AppSegment extends Component {

  constructor(props) {
    super(props)
    this.state = {
      jwt: null,
      app_users: [],
      search: false,
      meta: {}
    }
  }
  componentDidMount() {
    /*this.props.actions.fetchAppSegment(
      this.props.app.segments[0].id
    )*/

    this.search()
  }

  updateData = (data, cb) => {
    const newData = Object.assign({}, this.props.data, { segments: data.data })
    this.props.updateData(newData, cb ? cb() : null)
  }

  updatePredicate = (data, cb) => {
    const jwtToken = generateJWT(data)
    //console.log(parseJwt(jwtToken))
    if (cb)
      cb(jwtToken)
    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt), this.search))
  }

  addPredicate = (data, cb) => {

    const pending_predicate = {
      attribute: data.name,
      comparison: null,
      type: data.type,
      value: data.value
    }

    const new_predicates = this.props.data.segments.concat(pending_predicate)
    const jwtToken = generateJWT(new_predicates)
    //console.log(parseJwt(jwtToken))
    if (cb)
      cb(jwtToken)

    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt)))
  }

  deletePredicate(data) {
    const jwtToken = generateJWT(data)
    this.setState({ jwt: jwtToken }, () => this.updateData(parseJwt(this.state.jwt), this.search))
  }

  search = (page) => {

    this.setState({ searching: true })
    // jwt or predicates from segment
    //console.log(this.state.jwt)
    const data = this.state.jwt ? parseJwt(this.state.jwt).data : this.props.data.segments
    const predicates_data = {
      data: {
        predicates: data.filter((o) => o.comparison)
      }
    }

    graphql(PREDICATES_SEARCH, {
      appKey: this.props.app.key,
      search: predicates_data,
      page: page || 1,
      per: 5,
    },{
      success: (data) => {
        const appUsers = data.predicatesSearch.appUsers
        this.setState({
          app_users: appUsers.collection,
          meta: appUsers.meta,
          searching: false
        })
      },
      error: (error) => {
        debugger
      }
    })
  }

  showUserDrawer = (o)=>{
    this.props.dispatch(
      toggleDrawer({ rightDrawer: true }, ()=>{
        this.props.dispatch(getAppUser(o.id))
      })
    )
  }

  render() {
    return <SegmentManager {...this.props}
      loading={this.state.searching}
      predicates={this.props.data.segments}
      meta={this.state.meta}
      collection={this.state.app_users}
      updatePredicate={this.updatePredicate.bind(this)}
      addPredicate={this.addPredicate.bind(this)}
      deletePredicate={this.deletePredicate.bind(this)}
      search={this.search.bind(this)}

      loading={this.props.searching}
      columns={[

        {name: 'id', title: 'id', hidden: true},
        {field: 'email', title: 'email',
          render: row => (row ?

 this.showUserDrawer(row) }>

                  <Avatar
                    name={row.email}
                    size="medium"
                    src={gravatar(row.email)}
                  />

              <Typography>{row.name || row.displayName}</Typography>

           : undefined)
        },
        {field: 'lastVisitedAt',
          title: 'lastVisitedAt',
          render: row => (row ? <Moment fromNow>
                                        {row.lastVisitedAt}
                                      </Moment> : undefined)
        },
        {field: 'state', title: 'state'},
        {field: 'online', title: 'online'},
        {field: 'lat',  title: 'lat'},
        {field: 'lng',  title: 'lng'},
        {field: 'postal', title: 'postal'},
        {field: 'browser', title: 'browser'},
        {field: 'referrer', title: 'referrer'},
        {field: 'os', title: 'os'},
        {field: 'osVersion', title: 'osVersion'},
        {field: 'lang', title: 'lang'},

      ]}

      defaultHiddenColumnNames={
        ['id',
        'state',
        'online',
        'lat',
        'lng',
        'postal',
        'browserLanguage',
        'referrer',
        'os',
        'osVersion',
        'lang'
        ]}
      //selection [],
      tableColumnExtensions={[
        //{ columnName: 'id', width: 150 },
        { columnName: 'email', width: 250 },
        { columnName: 'lastVisitedAt', width: 120 },
        { columnName: 'os', width: 100 },
        { columnName: 'osVersion', width: 100 },
        { columnName: 'state', width: 80 },
        { columnName: 'online', width: 80 },
        //{ columnName: 'amount', align: 'right', width: 140 },
      ]}
      leftColumns={ ['email']}
      rightColumns={ ['online']}
      //toggleMapView={this.toggleMapView}
      //map_view={this.state.map_view}
      //enableMapView={true}
    >
      { /*
        this.state.jwt ?
          <Button isLoading={false}
            appearance={'link'}
            onClick={this.handleSave}>

            {" "}
            Save Segment
          </Button> : null
      */
      }

    </SegmentManager>
  }
}<|endoftext|>