<commit_before>import Promise from 'native-promise-only';

const url = function(formio) {
  return {
    title: 'Url',
    name: 'url',
    uploadFile: function(file, fileName, dir, progressCallback, url) {
      return new Promise(((resolve, reject) => {
        const data = {
          dir: dir,
          name: fileName,
          file: file
        };

        // Send the file with data.
        const xhr = new XMLHttpRequest();

        if (typeof progressCallback === 'function') {
          xhr.upload.onprogress = progressCallback;
        }

        const fd = new FormData();
        for (const key in data) {
          fd.append(key, data[key]);
        }

        xhr.onload = function() {
          if (xhr.status >= 200 && xhr.status < 300) {
            // Need to test if xhr.response is decoded or not.
            let respData = {};
            try {
              respData = (typeof xhr.response === 'string') ? JSON.parse(xhr.response) : {};
              respData = (respData && respData.data) ? respData.data : respData;
            }
            catch (err) {
              respData = {};
            }

            resolve({
              storage: 'url',
              name: fileName,
              url: `${xhr.responseURL}/${fileName}`,
              size: file.size,
              type: file.type,
              data: respData
            });
          }
          else {
            reject(xhr.response || 'Unable to upload file');
          }
        };

        // Fire on network error.
        xhr.onerror = function() {
          reject(xhr);
        };

        xhr.onabort = function() {
          reject(xhr);
        };

        xhr.open('POST', url);
        const token = formio.getToken();
        if (token) {
          xhr.setRequestHeader('x-jwt-token', token);
        }
        xhr.send(fd);
      }));
    },
    downloadFile: function(file) {
      // Return the original as there is nothing to do.
      return Promise.resolve(file);
    }
  };
};

url.title = 'Url';
export default url;
<commit_msg>Allow url uploads to respond with their own url.<commit_after>import Promise from 'native-promise-only';

const url = function(formio) {
  return {
    title: 'Url',
    name: 'url',
    uploadFile: function(file, fileName, dir, progressCallback, url) {
      return new Promise(((resolve, reject) => {
        const data = {
          dir: dir,
          name: fileName,
          file: file
        };

        // Send the file with data.
        const xhr = new XMLHttpRequest();

        if (typeof progressCallback === 'function') {
          xhr.upload.onprogress = progressCallback;
        }

        const fd = new FormData();
        for (const key in data) {
          fd.append(key, data[key]);
        }

        xhr.onload = function() {
          if (xhr.status >= 200 && xhr.status < 300) {
            // Need to test if xhr.response is decoded or not.
            let respData = {};
            try {
              respData = (typeof xhr.response === 'string') ? JSON.parse(xhr.response) : {};
              respData = (respData && respData.data) ? respData.data : respData;
            }
            catch (err) {
              respData = {};
            }

            const url = respData.hasOwnProperty('url') ? respData.url : `${xhr.responseURL}/${fileName}`;

            resolve({
              storage: 'url',
              name: fileName,
              url,
              size: file.size,
              type: file.type,
              data: respData
            });
          }
          else {
            reject(xhr.response || 'Unable to upload file');
          }
        };

        // Fire on network error.
        xhr.onerror = function() {
          reject(xhr);
        };

        xhr.onabort = function() {
          reject(xhr);
        };

        xhr.open('POST', url);
        const token = formio.getToken();
        if (token) {
          xhr.setRequestHeader('x-jwt-token', token);
        }
        xhr.send(fd);
      }));
    },
    downloadFile: function(file) {
      // Return the original as there is nothing to do.
      return Promise.resolve(file);
    }
  };
};

url.title = 'Url';
export default url;
<|endoftext|>


<commit_before>const {adaPrivateKey, adminPrivateKey} = require('../../page/Authentication/ImportGpgKey/ImportGpgKey.data');
const SeleniumPage = require('../../page/Selenium/Selenium.page');
const RecoverAuthenticationPage = require('../../page/AuthenticationRecover/RecoverAUthentication/RecoverAuthentication.page');
const ShareDialogPage = require('../../page/Share/ShareDialog.page');
const DisplayMainMenuPage = require('../../page/Common/Menu/DisplayMainMenu.page');
const DisplayResourcesWorkspacePage = require('../../page/Resource/DisplayResourcesWorkspace/DisplayResourcesWorkspace.page');
const DisplayResourcesListPage = require('../../page/Resource/DisplayResourcesList/DisplayResourcesList.page');
const DisplayResourceDetailsPage = require('../../page/ResourceDetails/DisplayResourceDetails/DisplayResourceDetails.page');
const DisplayResourceFolderDetailsPage = require('../../page/ResourceFolderDetails/DisplayResourceFolderDetails/DisplayResourceFolderDetails.page');
const FilterResourcesByFoldersPage = require('../../page/Resource/FilterResourcesByFolders/FilterResourcesByFolders.page');
const FilterResourcesByTextPage = require('../../page/Resource/FilterResourcesByText/FilterResourcesByText.page');
const CreateResourcePage = require('../../page/Resource/CreateResource/CreateResource.page');
const CreateResourceFolderPage = require('../../page/ResourceFolder/CreateResourceFolder/CreateResourceFolder.page');
const RenameResourceFolderPage = require('../../page/ResourceFolder/RenameResourceFolder/RenameResourceFolder.page');
const DeleteResourceFolderPage = require('../../page/ResourceFolder/DeleteResourceFolder/DeleteResourceFolder.page');
const FilterResourcesByShortcutsPage = require('../../page/Resource/FilterResourcesByShortcuts/FilterResourcesByShortcuts.page');

describe('password workspace', () => {
  // WARNING : execution order is very important

  after(() => {
    // runs once after the last test in this block
    SeleniumPage.resetInstanceDefault()
  });

  it('As LU I should recover ada account', () => {
    RecoverAuthenticationPage.recover('ada@passbolt.com', adaPrivateKey);
    DisplayMainMenuPage.switchAppIframe();
  });

  it('As LU I should create a new folder', () => {
    DisplayResourcesWorkspacePage.openCreateFolder();
    CreateResourceFolderPage.createFolder('folderParent');
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
  });

  it('As LU I should create a new password', () => {
    DisplayResourcesWorkspacePage.openCreatePassword();
    CreateResourcePage.createPassword('nameA', 'uri', 'ada@passbolt.com', 'secretA', 'description');
  });

  it('As LU I should create a subfolder folder', () => {
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
    DisplayResourcesWorkspacePage.openCreateFolder();
    CreateResourceFolderPage.createFolder('folderChild');
  });

  it('As LU I should create a new password', () => {
    FilterResourcesByFoldersPage.expandFolderSelected();
    FilterResourcesByFoldersPage.selectedFolderNamed('folderChild');
    DisplayResourcesWorkspacePage.openCreatePassword();
    CreateResourcePage.createPassword('nameB', 'uri', 'ada@passbolt.com', 'secretB', 'description');
  });

  it('As LU I should share a password', () => {
    DisplayResourceDetailsPage.openShareResource();
    ShareDialogPage.shareResource('admin@passbolt.com', 'ada@passbolt.com');
  });

  it('As LU I should share a folder', () => {
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
    DisplayResourceFolderDetailsPage.openShareResource();
    ShareDialogPage.shareResource('Accounting', 'ada@passbolt.com');
  });

  it('As LU I should see my passwords share with admin user and accounting group', () => {
    DisplayResourcesListPage.selectedResourceNamed('nameA');
    DisplayResourceDetailsPage.openShareSection();
    DisplayResourceDetailsPage.getShareWithExist('Accounting');
    FilterResourcesByFoldersPage.selectedFolderNamed('folderChild');
    DisplayResourcesListPage.selectedResourceNamed('nameB');
    DisplayResourceDetailsPage.openShareSection();
    DisplayResourceDetailsPage.getShareWithExist('Admin User (admin@passbolt.com)');
    DisplayResourceDetailsPage.getShareWithExist('Accounting');
  });

  it('As LU I should recover admin account', () => {
    RecoverAuthenticationPage.recover('admin@passbolt.com', adminPrivateKey);
    DisplayMainMenuPage.switchAppIframe();
  });

  it('As LU I should filter my resource by shared with me', () => {
    FilterResourcesByShortcutsPage.filterBySharedWithMe();
    DisplayResourcesListPage.selectedResourceNamed('nameB');
  });

  it('As LU I should copy the secret of my password', () => {
    DisplayResourcesListPage.copySecretResource('admin@passbolt.com');
    FilterResourcesByTextPage.pasteClipBoardToVerify('secretB');
  });

  it('As LU I should rename a folder', () => {
    FilterResourcesByFoldersPage.openFolderRenameDialog();
    RenameResourceFolderPage.renameFolder('rename');
  });

  it('As LU I should delete a folder', () => {
    FilterResourcesByFoldersPage.openFolderDeleteDialog();
    DeleteResourceFolderPage.deleteFolder();
  });
});
<commit_msg>Fix open rename/delete folder dialogs<commit_after>const {adaPrivateKey, adminPrivateKey} = require('../../page/Authentication/ImportGpgKey/ImportGpgKey.data');
const SeleniumPage = require('../../page/Selenium/Selenium.page');
const RecoverAuthenticationPage = require('../../page/AuthenticationRecover/RecoverAUthentication/RecoverAuthentication.page');
const ShareDialogPage = require('../../page/Share/ShareDialog.page');
const DisplayMainMenuPage = require('../../page/Common/Menu/DisplayMainMenu.page');
const DisplayResourcesWorkspacePage = require('../../page/Resource/DisplayResourcesWorkspace/DisplayResourcesWorkspace.page');
const DisplayResourcesListPage = require('../../page/Resource/DisplayResourcesList/DisplayResourcesList.page');
const DisplayResourceDetailsPage = require('../../page/ResourceDetails/DisplayResourceDetails/DisplayResourceDetails.page');
const DisplayResourceFolderDetailsPage = require('../../page/ResourceFolderDetails/DisplayResourceFolderDetails/DisplayResourceFolderDetails.page');
const FilterResourcesByFoldersPage = require('../../page/Resource/FilterResourcesByFolders/FilterResourcesByFolders.page');
const FilterResourcesByTextPage = require('../../page/Resource/FilterResourcesByText/FilterResourcesByText.page');
const CreateResourcePage = require('../../page/Resource/CreateResource/CreateResource.page');
const CreateResourceFolderPage = require('../../page/ResourceFolder/CreateResourceFolder/CreateResourceFolder.page');
const RenameResourceFolderPage = require('../../page/ResourceFolder/RenameResourceFolder/RenameResourceFolder.page');
const DeleteResourceFolderPage = require('../../page/ResourceFolder/DeleteResourceFolder/DeleteResourceFolder.page');
const FilterResourcesByShortcutsPage = require('../../page/Resource/FilterResourcesByShortcuts/FilterResourcesByShortcuts.page');

describe('password workspace', () => {
  // WARNING : execution order is very important

  after(() => {
    // runs once after the last test in this block
    SeleniumPage.resetInstanceDefault()
  });

  it('As LU I should recover ada account', () => {
    RecoverAuthenticationPage.recover('ada@passbolt.com', adaPrivateKey);
    DisplayMainMenuPage.switchAppIframe();
  });

  it('As LU I should create a new folder', () => {
    DisplayResourcesWorkspacePage.openCreateFolder();
    CreateResourceFolderPage.createFolder('folderParent');
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
  });

  it('As LU I should create a new password', () => {
    DisplayResourcesWorkspacePage.openCreatePassword();
    CreateResourcePage.createPassword('nameA', 'uri', 'ada@passbolt.com', 'secretA', 'description');
  });

  it('As LU I should create a subfolder folder', () => {
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
    DisplayResourcesWorkspacePage.openCreateFolder();
    CreateResourceFolderPage.createFolder('folderChild');
  });

  it('As LU I should create a new password', () => {
    FilterResourcesByFoldersPage.expandFolderSelected();
    FilterResourcesByFoldersPage.selectedFolderNamed('folderChild');
    DisplayResourcesWorkspacePage.openCreatePassword();
    CreateResourcePage.createPassword('nameB', 'uri', 'ada@passbolt.com', 'secretB', 'description');
  });

  it('As LU I should share a password', () => {
    DisplayResourceDetailsPage.openShareResource();
    ShareDialogPage.shareResource('admin@passbolt.com', 'ada@passbolt.com');
  });

  it('As LU I should share a folder', () => {
    FilterResourcesByFoldersPage.selectedFolderNamed('folderParent');
    DisplayResourceFolderDetailsPage.openShareResource();
    ShareDialogPage.shareResource('Accounting', 'ada@passbolt.com');
  });

  it('As LU I should see my passwords share with admin user and accounting group', () => {
    DisplayResourcesListPage.selectedResourceNamed('nameA');
    DisplayResourceDetailsPage.openShareSection();
    DisplayResourceDetailsPage.getShareWithExist('Accounting');
    FilterResourcesByFoldersPage.selectedFolderNamed('folderChild');
    DisplayResourcesListPage.selectedResourceNamed('nameB');
    DisplayResourceDetailsPage.openShareSection();
    DisplayResourceDetailsPage.getShareWithExist('Admin User (admin@passbolt.com)');
    DisplayResourceDetailsPage.getShareWithExist('Accounting');
  });

  it('As LU I should recover admin account', () => {
    RecoverAuthenticationPage.recover('admin@passbolt.com', adminPrivateKey);
    DisplayMainMenuPage.switchAppIframe();
  });

  it('As LU I should filter my resource by shared with me', () => {
    FilterResourcesByShortcutsPage.filterBySharedWithMe();
    DisplayResourcesListPage.selectedResourceNamed('nameB');
  });

  it('As LU I should copy the secret of my password', () => {
    DisplayResourcesListPage.copySecretResource('admin@passbolt.com');
    FilterResourcesByTextPage.pasteClipBoardToVerify('secretB');
  });

  it('As LU I should rename a folder', () => {
    FilterResourcesByFoldersPage.openRenameResourceFolder();
    RenameResourceFolderPage.renameFolder('rename');
  });

  it('As LU I should delete a folder', () => {
    FilterResourcesByFoldersPage.openDeleteResourceFolder();
    DeleteResourceFolderPage.deleteFolder();
  });
});
<|endoftext|>


<commit_before>var d = require ('dequeue');
var redis = require("redis");
var rClient = redis.createClient();
var dgram = require("dgram");

var FIFO = new d();
var port = 4444;

init();

var udpServer = dgram.createSocket("udp4");

udpServer.on("message",
    function (msg, rinfo) {
        FIFO.push(msg.toString());
    }
);

udpServer.on('error', function (err) {
    console.log("Error server: ", err);
});

udpServer.bind(port);
console.log("Running server: ", port);

function init() {
    while (FIFO.length > 0)
    {
        var msg = FIFO.shift();
        rClient.hset("raw", "data", msg);
        //console.log("msg", msg);
    }
    setImmediate(init);
}<commit_msg>Update UDPefef<commit_after>var d = require ('dequeue');
var redis = require("redis");
var rClient = redis.createClient();
var dgram = require("dgram");

var FIFO = new d();
var port = 4444;

init();

var udpServer = dgram.createSocket("udp4");

udpServer.on("message",
    function (msg, rinfo) {
        FIFO.push(msg.toString());
    }
);

udpServer.on('error', function (err) {
    console.log("Error server: ", err);
});

udpServer.bind(port);
console.log("Running server: ", port);

function init() {
    while (FIFO.length > 0)
    {
        var msg = FIFO.shift();
        rClient.hset("raw", "data"+FIFO.length, msg);
        //console.log("msg", msg);
    }
    setImmediate(init);
}<|endoftext|>


<commit_before>// Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.

define([
    "widgets/js/widget",
    "base/js/utils",
    "jquery",
    "bootstrap",
], function(widget, utils, $){

    var DropdownView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-dropdown');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$buttongroup = $('<div />')
                .addClass('widget_item')
                .addClass('btn-group')
                .appendTo(this.$el);
            this.$droplabel = $('<button />')
                .addClass('btn btn-default')
                .addClass('widget-combo-btn')
                .html(" ")
                .appendTo(this.$buttongroup);
            this.$dropbutton = $('<button />')
                .addClass('btn btn-default')
                .addClass('dropdown-toggle')
                .addClass('widget-combo-carrot-btn')
                .attr('data-toggle', 'dropdown')
                .append($('<span />').addClass("caret"))
                .appendTo(this.$buttongroup);
            this.$droplist = $('<ul />')
                .addClass('dropdown-menu')
                .appendTo(this.$buttongroup);

            this.model.on('change:button_style', function(model, value) {
                this.update_button_style();
            }, this);
            this.update_button_style('');

            // Set defaults.
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */

            if (options === undefined || options.updated_view != this) {
                var selected_item_text = this.model.get('value_name');
                if (selected_item_text.trim().length === 0) {
                    this.$droplabel.html(" ");
                } else {
                    this.$droplabel.text(selected_item_text);
                }

                var items = this.model.get('_value_names');
                var $replace_droplist = $('<ul />')
                    .addClass('dropdown-menu');
                // Copy the style
                $replace_droplist.attr('style', this.$droplist.attr('style'));
                var that = this;
                _.each(items, function(item, i) {
                    var item_button = $('<a href="#"/>')
                        .text(item)
                        .on('click', $.proxy(that.handle_click, that));
                    $replace_droplist.append($('<li />').append(item_button));
                });

                this.$droplist.replaceWith($replace_droplist);
                this.$droplist.remove();
                this.$droplist = $replace_droplist;

                if (this.model.get('disabled')) {
                    this.$buttongroup.attr('disabled','disabled');
                    this.$droplabel.attr('disabled','disabled');
                    this.$dropbutton.attr('disabled','disabled');
                    this.$droplist.attr('disabled','disabled');
                } else {
                    this.$buttongroup.removeAttr('disabled');
                    this.$droplabel.removeAttr('disabled');
                    this.$dropbutton.removeAttr('disabled');
                    this.$droplist.removeAttr('disabled');
                }

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return DropdownView.__super__.update.apply(this);
        },

        update_button_style: function(previous_trait_value) {
            var class_map = {
                primary: ['btn-primary'],
                success: ['btn-success'],
                info: ['btn-info'],
                warning: ['btn-warning'],
                danger: ['btn-danger']
            };
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$droplabel);
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$dropbutton);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name.substring(0, 6) == 'border' || name == 'background' || name == 'color') {
                this.$droplabel.css(name, value);
                this.$dropbutton.css(name, value);
                this.$droplist.css(name, value);
            } else if (name == 'width') {
                this.$droplist.css(name, value);
                this.$droplabel.css(name, value);
            } else if (name == 'padding') {
                this.$droplist.css(name, value);
                this.$buttongroup.css(name, value);
            } else if (name == 'margin') {
                this.$buttongroup.css(name, value);
            } else if (name == 'height') {
                this.$droplabel.css(name, value);
                this.$dropbutton.css(name, value);
            } else if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$droplist.css(name, value);
                this.$droplabel.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).text(), {updated_view: this});
            this.touch();

            // Manually hide the droplist.
            e.stopPropagation();
            e.preventDefault();
            this.$buttongroup.removeClass('open');
        },

    });

    var RadioButtonsView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-radio');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$container = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-radio-box');
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var disabled = this.model.get('disabled');
                var that = this;
                _.each(items, function(item, index) {
                    var item_query = ' :input[data-value="' + encodeURIComponent(item) + '"]';
                    if (that.$el.find(item_query).length === 0) {
                        var $label = $('<label />')
                            .addClass('radio')
                            .text(item)
                            .appendTo(that.$container);

                        $('<input />')
                            .attr('type', 'radio')
                            .addClass(that.model)
                            .val(item)
                            .attr('data-value', encodeURIComponent(item))
                            .prependTo($label)
                            .on('click', $.proxy(that.handle_click, that));
                    }

                    var $item_element = that.$container.find(item_query);
                    if (that.model.get('value_name') == item) {
                        $item_element.prop('checked', true);
                    } else {
                        $item_element.prop('checked', false);
                    }
                    $item_element.prop('disabled', disabled);
                });

                // Remove items that no longer exist.
                this.$container.find('input').each(function(i, obj) {
                    var value = $(obj).val();
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).parent().remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.$label.text(description);
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return RadioButtonsView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$container.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).val(), {updated_view: this});
            this.touch();
        },
    });

    var ToggleButtonsView = widget.DOMWidgetView.extend({
        initialize: function() {
            this._css_state = {};
            ToggleButtonsView.__super__.initialize.apply(this, arguments);
        },

        render: function() {
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-toggle-buttons');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$buttongroup = $('<div />')
                .addClass('btn-group')
                .attr('data-toggle', 'buttons-radio')
                .appendTo(this.$el);

            this.model.on('change:button_style', function(model, value) {
                this.update_button_style();
            }, this);
            this.update_button_style('');
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var disabled = this.model.get('disabled');
                var that = this;
                var item_html;
                _.each(items, function(item, index) {
                    if (item.trim().length === 0) {
                        item_html = " ";
                    } else {
                        item_html = utils.escape_html(item);
                    }
                    var item_query = '[data-value="' + encodeURIComponent(item) + '"]';
                    var $item_element = that.$buttongroup.find(item_query);
                    if (!$item_element.length) {
                        $item_element = $('<button/>')
                            .attr('type', 'button')
                            .addClass('btn btn-default')
                            .html(item_html)
                            .appendTo(that.$buttongroup)
                            .attr('data-value', encodeURIComponent(item))
                            .attr('value', item)
                            .on('click', $.proxy(that.handle_click, that));
                        that.update_style_traits($item_element);
                    }
                    if (that.model.get('value_name') == item) {
                        $item_element.addClass('active');
                    } else {
                        $item_element.removeClass('active');
                    }
                    $item_element.prop('disabled', disabled);
                });

                // Remove items that no longer exist.
                this.$buttongroup.find('button').each(function(i, obj) {
                    var value = $(obj).attr('value');
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.$label.text();
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return ToggleButtonsView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this._css_state[name] = value;
                this.update_style_traits();
            }
        },

        update_style_traits: function(button) {
            for (var name in this._css_state) {
                if (this._css_state.hasOwnProperty(name)) {
                    if (name == 'margin') {
                        this.$buttongroup.css(name, this._css_state[name]);
                    } else if (name != 'width') {
                        if (button) {
                            button.css(name, this._css_state[name]);
                        } else {
                            this.$buttongroup.find('button').css(name, this._css_state[name]);
                        }
                    }
                }
            }
        },

        update_button_style: function(previous_trait_value) {
            var class_map = {
                primary: ['btn-primary'],
                success: ['btn-success'],
                info: ['btn-info'],
                warning: ['btn-warning'],
                danger: ['btn-danger']
            };
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$buttongroup.find('button'));
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).attr('value'), {updated_view: this});
            this.touch();
        },
    });

    var SelectView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-select');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$listbox = $('<select />')
                .addClass('widget-listbox form-control')
                .attr('size', 6)
                .appendTo(this.$el);
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var that = this;
                _.each(items, function(item, index) {
                   var item_query = 'option[data-value="' + encodeURIComponent(item) + '"]';
                    if (that.$listbox.find(item_query).length === 0) {
                        $('<option />')
                            .text(item)
                            .attr('data-value', encodeURIComponent(item))
                            .attr('value_name', item)
                            .appendTo(that.$listbox)
                            .on('click', $.proxy(that.handle_click, that));
                    }
                });

                // Select the correct element
                this.$listbox.val(this.model.get('value_name'));

                // Disable listbox if needed
                var disabled = this.model.get('disabled');
                this.$listbox.prop('disabled', disabled);

                // Remove items that no longer exist.
                this.$listbox.find('option').each(function(i, obj) {
                    var value = $(obj).text();
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return SelectView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$listbox.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).text(), {updated_view: this});
            this.touch();
        },
    });

    return {
        'DropdownView': DropdownView,
        'RadioButtonsView': RadioButtonsView,
        'ToggleButtonsView': ToggleButtonsView,
        'SelectView': SelectView,
    };
});
<commit_msg>don't set bootstrap toggle on ToggleButtonsWidget<commit_after>// Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.

define([
    "widgets/js/widget",
    "base/js/utils",
    "jquery",
    "bootstrap",
], function(widget, utils, $){

    var DropdownView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-dropdown');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$buttongroup = $('<div />')
                .addClass('widget_item')
                .addClass('btn-group')
                .appendTo(this.$el);
            this.$droplabel = $('<button />')
                .addClass('btn btn-default')
                .addClass('widget-combo-btn')
                .html(" ")
                .appendTo(this.$buttongroup);
            this.$dropbutton = $('<button />')
                .addClass('btn btn-default')
                .addClass('dropdown-toggle')
                .addClass('widget-combo-carrot-btn')
                .attr('data-toggle', 'dropdown')
                .append($('<span />').addClass("caret"))
                .appendTo(this.$buttongroup);
            this.$droplist = $('<ul />')
                .addClass('dropdown-menu')
                .appendTo(this.$buttongroup);

            this.model.on('change:button_style', function(model, value) {
                this.update_button_style();
            }, this);
            this.update_button_style('');

            // Set defaults.
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */

            if (options === undefined || options.updated_view != this) {
                var selected_item_text = this.model.get('value_name');
                if (selected_item_text.trim().length === 0) {
                    this.$droplabel.html(" ");
                } else {
                    this.$droplabel.text(selected_item_text);
                }

                var items = this.model.get('_value_names');
                var $replace_droplist = $('<ul />')
                    .addClass('dropdown-menu');
                // Copy the style
                $replace_droplist.attr('style', this.$droplist.attr('style'));
                var that = this;
                _.each(items, function(item, i) {
                    var item_button = $('<a href="#"/>')
                        .text(item)
                        .on('click', $.proxy(that.handle_click, that));
                    $replace_droplist.append($('<li />').append(item_button));
                });

                this.$droplist.replaceWith($replace_droplist);
                this.$droplist.remove();
                this.$droplist = $replace_droplist;

                if (this.model.get('disabled')) {
                    this.$buttongroup.attr('disabled','disabled');
                    this.$droplabel.attr('disabled','disabled');
                    this.$dropbutton.attr('disabled','disabled');
                    this.$droplist.attr('disabled','disabled');
                } else {
                    this.$buttongroup.removeAttr('disabled');
                    this.$droplabel.removeAttr('disabled');
                    this.$dropbutton.removeAttr('disabled');
                    this.$droplist.removeAttr('disabled');
                }

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return DropdownView.__super__.update.apply(this);
        },

        update_button_style: function(previous_trait_value) {
            var class_map = {
                primary: ['btn-primary'],
                success: ['btn-success'],
                info: ['btn-info'],
                warning: ['btn-warning'],
                danger: ['btn-danger']
            };
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$droplabel);
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$dropbutton);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name.substring(0, 6) == 'border' || name == 'background' || name == 'color') {
                this.$droplabel.css(name, value);
                this.$dropbutton.css(name, value);
                this.$droplist.css(name, value);
            } else if (name == 'width') {
                this.$droplist.css(name, value);
                this.$droplabel.css(name, value);
            } else if (name == 'padding') {
                this.$droplist.css(name, value);
                this.$buttongroup.css(name, value);
            } else if (name == 'margin') {
                this.$buttongroup.css(name, value);
            } else if (name == 'height') {
                this.$droplabel.css(name, value);
                this.$dropbutton.css(name, value);
            } else if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$droplist.css(name, value);
                this.$droplabel.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).text(), {updated_view: this});
            this.touch();

            // Manually hide the droplist.
            e.stopPropagation();
            e.preventDefault();
            this.$buttongroup.removeClass('open');
        },

    });

    var RadioButtonsView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-radio');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$container = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-radio-box');
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var disabled = this.model.get('disabled');
                var that = this;
                _.each(items, function(item, index) {
                    var item_query = ' :input[data-value="' + encodeURIComponent(item) + '"]';
                    if (that.$el.find(item_query).length === 0) {
                        var $label = $('<label />')
                            .addClass('radio')
                            .text(item)
                            .appendTo(that.$container);

                        $('<input />')
                            .attr('type', 'radio')
                            .addClass(that.model)
                            .val(item)
                            .attr('data-value', encodeURIComponent(item))
                            .prependTo($label)
                            .on('click', $.proxy(that.handle_click, that));
                    }

                    var $item_element = that.$container.find(item_query);
                    if (that.model.get('value_name') == item) {
                        $item_element.prop('checked', true);
                    } else {
                        $item_element.prop('checked', false);
                    }
                    $item_element.prop('disabled', disabled);
                });

                // Remove items that no longer exist.
                this.$container.find('input').each(function(i, obj) {
                    var value = $(obj).val();
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).parent().remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.$label.text(description);
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return RadioButtonsView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$container.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).val(), {updated_view: this});
            this.touch();
        },
    });

    var ToggleButtonsView = widget.DOMWidgetView.extend({
        initialize: function() {
            this._css_state = {};
            ToggleButtonsView.__super__.initialize.apply(this, arguments);
        },

        render: function() {
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-toggle-buttons');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$buttongroup = $('<div />')
                .addClass('btn-group')
                .appendTo(this.$el);

            this.model.on('change:button_style', function(model, value) {
                this.update_button_style();
            }, this);
            this.update_button_style('');
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var disabled = this.model.get('disabled');
                var that = this;
                var item_html;
                _.each(items, function(item, index) {
                    if (item.trim().length === 0) {
                        item_html = " ";
                    } else {
                        item_html = utils.escape_html(item);
                    }
                    var item_query = '[data-value="' + encodeURIComponent(item) + '"]';
                    var $item_element = that.$buttongroup.find(item_query);
                    if (!$item_element.length) {
                        $item_element = $('<button/>')
                            .attr('type', 'button')
                            .addClass('btn btn-default')
                            .html(item_html)
                            .appendTo(that.$buttongroup)
                            .attr('data-value', encodeURIComponent(item))
                            .attr('value', item)
                            .on('click', $.proxy(that.handle_click, that));
                        that.update_style_traits($item_element);
                    }
                    if (that.model.get('value_name') == item) {
                        $item_element.addClass('active');
                    } else {
                        $item_element.removeClass('active');
                    }
                    $item_element.prop('disabled', disabled);
                });

                // Remove items that no longer exist.
                this.$buttongroup.find('button').each(function(i, obj) {
                    var value = $(obj).attr('value');
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.$label.text();
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return ToggleButtonsView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this._css_state[name] = value;
                this.update_style_traits();
            }
        },

        update_style_traits: function(button) {
            for (var name in this._css_state) {
                if (this._css_state.hasOwnProperty(name)) {
                    if (name == 'margin') {
                        this.$buttongroup.css(name, this._css_state[name]);
                    } else if (name != 'width') {
                        if (button) {
                            button.css(name, this._css_state[name]);
                        } else {
                            this.$buttongroup.find('button').css(name, this._css_state[name]);
                        }
                    }
                }
            }
        },

        update_button_style: function(previous_trait_value) {
            var class_map = {
                primary: ['btn-primary'],
                success: ['btn-success'],
                info: ['btn-info'],
                warning: ['btn-warning'],
                danger: ['btn-danger']
            };
            this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$buttongroup.find('button'));
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).attr('value'), {updated_view: this});
            this.touch();
        },
    });

    var SelectView = widget.DOMWidgetView.extend({
        render : function(){
            /**
             * Called when view is rendered.
             */
            this.$el
                .addClass('widget-hbox widget-select');
            this.$label = $('<div />')
                .appendTo(this.$el)
                .addClass('widget-label')
                .hide();
            this.$listbox = $('<select />')
                .addClass('widget-listbox form-control')
                .attr('size', 6)
                .appendTo(this.$el);
            this.update();
        },

        update : function(options){
            /**
             * Update the contents of this view
             *
             * Called when the model is changed.  The model may have been
             * changed by another view or by a state update from the back-end.
             */
            if (options === undefined || options.updated_view != this) {
                // Add missing items to the DOM.
                var items = this.model.get('_value_names');
                var that = this;
                _.each(items, function(item, index) {
                   var item_query = 'option[data-value="' + encodeURIComponent(item) + '"]';
                    if (that.$listbox.find(item_query).length === 0) {
                        $('<option />')
                            .text(item)
                            .attr('data-value', encodeURIComponent(item))
                            .attr('value_name', item)
                            .appendTo(that.$listbox)
                            .on('click', $.proxy(that.handle_click, that));
                    }
                });

                // Select the correct element
                this.$listbox.val(this.model.get('value_name'));

                // Disable listbox if needed
                var disabled = this.model.get('disabled');
                this.$listbox.prop('disabled', disabled);

                // Remove items that no longer exist.
                this.$listbox.find('option').each(function(i, obj) {
                    var value = $(obj).text();
                    var found = false;
                    _.each(items, function(item, index) {
                        if (item == value) {
                            found = true;
                            return false;
                        }
                    });

                    if (!found) {
                        $(obj).remove();
                    }
                });

                var description = this.model.get('description');
                if (description.length === 0) {
                    this.$label.hide();
                } else {
                    this.typeset(this.$label, description);
                    this.$label.show();
                }
            }
            return SelectView.__super__.update.apply(this);
        },

        update_attr: function(name, value) {
            /**
             * Set a css attr of the widget view.
             */
            if (name == 'padding' || name == 'margin') {
                this.$el.css(name, value);
            } else {
                this.$listbox.css(name, value);
            }
        },

        handle_click: function (e) {
            /**
             * Handle when a value is clicked.
             *
             * Calling model.set will trigger all of the other views of the
             * model to update.
             */
            this.model.set('value_name', $(e.target).text(), {updated_view: this});
            this.touch();
        },
    });

    return {
        'DropdownView': DropdownView,
        'RadioButtonsView': RadioButtonsView,
        'ToggleButtonsView': ToggleButtonsView,
        'SelectView': SelectView,
    };
});
<|endoftext|>


<commit_before>import API from 'src/util/api';
import UI from 'src/util/ui';

import getViewInfo from './getViewInfo';

// ModulePrefsManager is created in the init script
// Any module may have a gear in the settings allowing to change preferences
// the system will either store in Roc or localStorge depending what is available

export class ModulePrefsManager {
  constructor(options = {}) {
    let promises = [];
    if (options.hasRoc) {
      let waitingRoc = new Promise((resolveRoc) => {
        this.resolveRoc = resolveRoc;
      }).then(() => {
        console.log('Roc initialized');
      });
      promises.push(waitingRoc);
    }

    let waitingView = getViewInfo().then((result) => {
      this.viewID = result._id;
    });
    promises.push(waitingView);

    let promiseAll = Promise.all(promises).then(() => {
      this.waiting = () => true;
    });
    this.waiting = () => promiseAll;
  }

  setRoc(roc) {
    this.roc = roc;
    this.resolveRoc();
  }

  async updateSlickGridPrefs(moduleID) {
    await this.waiting();
    const objectStructure = API.getModule(moduleID).data.resurrect()[0];

    const cols = JSON.parse(
      JSON.stringify(API.getModulePreferences(moduleID).cols)
    );
    cols.forEach((item) => {
      if (!item.id) item.id = Math.random();
    });

    await UI.editTable(cols, {
      remove: true,
      dialog: {
        title: 'Configure the columns of the module'
      },
      columns: [
        {
          id: 'id',
          name: 'name',
          jpath: ['name'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'rendererOptions',
          name: 'rendererOptions',
          jpath: ['rendererOptions'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'width',
          name: 'width',
          jpath: ['width'],
          editor: Slick.CustomEditors.NumberValue
        },
        {
          id: 'x',
          name: 'x',
          jpath: ['x'],
          editor: Slick.CustomEditors.Select,
          editorOptions: { choices: 'ab:cd;ef:gh' }
        },
        {
          id: 'jpath',
          name: 'jpath',
          jpath: ['jpath'],
          editor: Slick.CustomEditors.JPathFactory(objectStructure),
          forceType: 'jpath',
          rendererOptions: {
            forceType: 'jpath'
          }
        }
      ]
    });

    cols.forEach((item) => {
      item.formatter = 'typerenderer';
    });
    API.updateModulePreferences(moduleID, {
      cols: JSON.parse(JSON.stringify(cols))
    });

    this.saveModulePrefs(moduleID, { cols });
  }

  async reloadModulePrefs(moduleID) {
    await this.waiting();
    if (this.roc) {
      this.reloadModulePrefsFromRoc(moduleID);
    } else {
      this.reloadModulePrefsFromLocalStorage(moduleID);
    }
  }

  async reloadModulePrefsFromLocalStorage(moduleID) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) return;
    if (moduleID && !prefs[this.viewID][moduleID]) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
    } else {
      for (moduleID in prefs[this.viewID]) {
        API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
      }
    }
  }

  async getRecord() {
    var user = await this.roc.getUser();
    if (!user || !user.username) return undefined;
    return (
      await this.roc.view('entryByOwnerAndId', {
        key: [user.username, ['userModulePrefs', this.viewID]]
      })
    )[0];
  }

  async reloadModulePrefsFromRoc(moduleID) {
    const record = await this.getRecord();
    if (!record) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, record.$content[moduleID]);
    } else {
      for (moduleID in record.$content[moduleID]) {
        API.updateModulePreferences(moduleID, record.$content[moduleID]);
      }
    }
  }

  async saveModulePrefs(moduleID, modulePrefs) {
    await this.waiting();
    if (this.roc) {
      this.saveModulePrefsToRoc(moduleID, modulePrefs);
    } else {
      this.saveModulePrefsToLocalStorage(moduleID, modulePrefs);
    }
  }

  async saveModulePrefsToLocalStorage(moduleID, modulePrefs) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) prefs[this.viewID] = {};
    prefs[this.viewID][moduleID] = modulePrefs;
    localStorage.setItem('viewModulePreferences', JSON.stringify(prefs));
  }

  async saveModulePrefsToRoc(moduleID, modulePrefs) {
    let record = await this.getRecord();
    if (record) {
      record.$content[moduleID] = modulePrefs;
      return this.roc.update(record);
    } else {
      let content = {};
      content[moduleID] = modulePrefs;
      return this.roc.create({
        $id: ['userModulePrefs', this.viewID],
        $content: content,
        $kind: 'userModulePrefs'
      });
    }
  }
}

module.exports = ModulePrefsManager;
<commit_msg>feat: allow to reorder slick grid preferences of module<commit_after>import API from 'src/util/api';
import UI from 'src/util/ui';

import getViewInfo from './getViewInfo';

// ModulePrefsManager is created in the init script
// Any module may have a gear in the settings allowing to change preferences
// the system will either store in Roc or localStorge depending what is available

export class ModulePrefsManager {
  constructor(options = {}) {
    let promises = [];
    if (options.hasRoc) {
      let waitingRoc = new Promise(resolveRoc => {
        this.resolveRoc = resolveRoc;
      }).then(() => {
        console.log('Roc initialized');
      });
      promises.push(waitingRoc);
    }

    let waitingView = getViewInfo().then(result => {
      this.viewID = result._id;
    });
    promises.push(waitingView);

    let promiseAll = Promise.all(promises).then(() => {
      this.waiting = () => true;
    });
    this.waiting = () => promiseAll;
  }

  setRoc(roc) {
    this.roc = roc;
    this.resolveRoc();
  }

  async updateSlickGridPrefs(moduleID) {
    await this.waiting();
    const objectStructure = API.getModule(moduleID).data.resurrect()[0];

    const cols = JSON.parse(
      JSON.stringify(API.getModulePreferences(moduleID).cols)
    );
    cols.forEach(item => {
      if (!item.id) item.id = Math.random();
    });

    await UI.editTable(cols, {
      remove: true,
      reorder: true,
      dialog: {
        title: 'Configure the columns of the module'
      },
      columns: [
        {
          id: 'id',
          name: 'name',
          jpath: ['name'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'rendererOptions',
          name: 'rendererOptions',
          jpath: ['rendererOptions'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'width',
          name: 'width',
          jpath: ['width'],
          editor: Slick.CustomEditors.NumberValue
        },
        {
          id: 'x',
          name: 'x',
          jpath: ['x'],
          editor: Slick.CustomEditors.Select,
          editorOptions: { choices: 'ab:cd;ef:gh' }
        },
        {
          id: 'jpath',
          name: 'jpath',
          jpath: ['jpath'],
          editor: Slick.CustomEditors.JPathFactory(objectStructure),
          forceType: 'jpath',
          rendererOptions: {
            forceType: 'jpath'
          }
        }
      ]
    });

    cols.forEach(item => {
      item.formatter = 'typerenderer';
    });
    API.updateModulePreferences(moduleID, {
      cols: JSON.parse(JSON.stringify(cols))
    });

    this.saveModulePrefs(moduleID, { cols });
  }

  async reloadModulePrefs(moduleID) {
    await this.waiting();
    if (this.roc) {
      this.reloadModulePrefsFromRoc(moduleID);
    } else {
      this.reloadModulePrefsFromLocalStorage(moduleID);
    }
  }

  async reloadModulePrefsFromLocalStorage(moduleID) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) return;
    if (moduleID && !prefs[this.viewID][moduleID]) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
    } else {
      for (moduleID in prefs[this.viewID]) {
        API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
      }
    }
  }

  async getRecord() {
    var user = await this.roc.getUser();
    if (!user || !user.username) return undefined;
    return (
      await this.roc.view('entryByOwnerAndId', {
        key: [user.username, ['userModulePrefs', this.viewID]]
      })
    )[0];
  }

  async reloadModulePrefsFromRoc(moduleID) {
    const record = await this.getRecord();
    if (!record) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, record.$content[moduleID]);
    } else {
      for (moduleID in record.$content[moduleID]) {
        API.updateModulePreferences(moduleID, record.$content[moduleID]);
      }
    }
  }

  async saveModulePrefs(moduleID, modulePrefs) {
    await this.waiting();
    if (this.roc) {
      this.saveModulePrefsToRoc(moduleID, modulePrefs);
    } else {
      this.saveModulePrefsToLocalStorage(moduleID, modulePrefs);
    }
  }

  async saveModulePrefsToLocalStorage(moduleID, modulePrefs) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) prefs[this.viewID] = {};
    prefs[this.viewID][moduleID] = modulePrefs;
    localStorage.setItem('viewModulePreferences', JSON.stringify(prefs));
  }

  async saveModulePrefsToRoc(moduleID, modulePrefs) {
    let record = await this.getRecord();
    if (record) {
      record.$content[moduleID] = modulePrefs;
      return this.roc.update(record);
    } else {
      let content = {};
      content[moduleID] = modulePrefs;
      return this.roc.create({
        $id: ['userModulePrefs', this.viewID],
        $content: content,
        $kind: 'userModulePrefs'
      });
    }
  }
}

module.exports = ModulePrefsManager;
<|endoftext|>


<commit_before>var APIKEY = require('./config.js').key;
var _ = require('underscore.deferred');
var I = require('inflection');
var request = require('request');
var article = require('./lib/indefinite');
var Wordnik = require('wordnik-bb').init(APIKEY);
var apicount = 0;

// fill the blacklist from a file

var fs = require('fs');
var blacklist = [];
try {
  var data = fs.readFileSync('badwords.txt', 'ascii');
  data.split('\n').forEach(function (line) {
    if(line.length>0) {
      blacklist.push(line);
    }
  });
}
catch (err) {
  console.error("There was an error opening the file:");
  console.log(err);
}

var randomWordBucket = [];

var express = require('express'),
  app = express();
app.use(express.logger());
app.listen(3000);
console.log('Express server started on port 3000');

function getCoupletPromise() {

  var coupletDeferred = _.Deferred();
  var coupletPromise = coupletDeferred.promise();

  var word = new Wordnik.Word({
    word: I.singularize(randomWordBucket[Math.floor(Math.random()*randomWordBucket.length)].word),
    params: {
      relationshipTypes: 'rhyme',
      limitPerRelationshipType: 100,
      hasDictionaryDef: true
    }
  });

    //console.log("The model for our random word: ", word);
    // We could also get more info about the random word, in this case, relatedWords that rhyme:
    _.when(word.getRelatedWords(),word.getDefinitions())
      .then(function () {
        apicount+=2;
      if (isBlacklisted(word.id)) {
        coupletDeferred.resolve("");
      }
      if (word.get("relatedWords").length > 0) {
        var wordPos = word.get("definitions")[0].partOfSpeech;
        var first = getLine(word.id, wordPos);
        if (first === "") {
          coupletDeferred.resolve(first);
        }
        else {
          var word2 = word.get("relatedWords")[0].words[Math.floor(Math.random() * word.get("relatedWords")[0].words.length)];
          // quit this couplet if blacklisted word comes up
          if (isBlacklisted(word2)) {
            coupletDeferred.resolve("");
          }

          var posPromise = getPartOfSpeech(word2);
          (function (first, word2) {

            posPromise.done(function (pos) {
              var result = "oops!";
              result = getLine(word2, pos);
              if (result === "") {
                coupletDeferred.resolve(result);
              }
              else {
                var regex = /(<([^>]+)>)/ig;
                coupletDeferred.resolve("
" + first + "\n
" + result + "\nTweet!
");
              }
            });
          })(first, word2);
        }
      }
      else {
        //coupletDeferred.resolve("Sorry. We couldn't find anything that rhymes with " + word.id + "!");
        coupletDeferred.resolve("");
      }
    });
  return coupletDeferred.promise();
}

app.get('/', function (req, res) {

  var cypher = "";
  // get a bunch of random words so we don't have to call the API every time
  var url = "http://api.wordnik.com//v4/words.json/randomWords?includePartOfSpeech=noun,adjective,verb-transitive&excludePartOfSpeech=proper-noun,proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&minCorpusCount=4000&hasDictionaryDef=true&limit=1000&api_key=" + APIKEY;
  var rwDeferred = _.Deferred();
  var randomWordPromise = rwDeferred.promise();
  request({
    url: url
  }, function (error, response, body) {
    apicount++;
    if (JSON.parse(body).message === "exceeded access limits") {
      console.log("We're over the access limit, nooo!");
      rwDeferred.reject(error);
    }
    else if (!error && response.statusCode === 200) {
      //console.log(JSON.parse(body).word);
      //console.log(I.singularize(JSON.parse(body).word));
      rwDeferred.resolve(JSON.parse(body));

    }
    else {
      rwDeferred.reject(error);
    }
  });

  randomWordPromise.done(function(words) {
    //console.log(words.length);
    randomWordBucket = words;

    var stuffToDo = [];
    for (var i = 0; i < 12; i++) {
      var cp = getCoupletPromise();
      cp.done(function (couplet) {
        if (couplet !== "") {
          cypher += (couplet);
        }
      });
      stuffToDo.push(cp);
    }

    _.when(stuffToDo).done(function () {
      //console.log(cypher);
      //console.log('*drops the mic*');
      cypher += "
*drops the mic*

Yo, reload for more!
how it works | source code | thank u based Wordnik";
      res.send('<!doctype html><title>RapBot: a Freestyle 80s Battle Rap Generator</title>
RapBot

freestyle 80s battle rap generator by Darius Kazemi

' + cypher + '
');
      console.log("count: ",apicount);

    });

  });
});

function getPartOfSpeech(wordId) {
  // accepts a word string
  var word = new Wordnik.Word({
    word: wordId,
    params: {
      includeSuggestions: true
    }
  });
  var deferred = _.Deferred();
  word.getDefinitions()
    .then(function (word) {
      apicount++;
    deferred.resolve(word.get("definitions")[0].partOfSpeech);
  });
  return deferred.promise();
}

function ladiesFellas() {
  return (Math.random() < 0.5) ? "ladies" : "fellas";
}

function womanMan() {
  return (Math.random() < 0.5) ? "woman" : "man";
}

function sistasHomies() {
  return (Math.random() < 0.5) ? "sistas" : "homies";
}

function sheHe() {
  return (Math.random() < 0.5) ? "she" : "he";
}

function w(word) {
  return "" + word + "";
}

function getLine(word, pos) {

  var result = "Oops, we didn't account for something.";

  if (pos === 'adjective') {
    var pre = [
      "You can try and battle me, but you're too ",
      "I make the MCs in the place wish that they were ",
      "My rhymes blow your mind and you think it's ",
      "My sweet-ass rhymes make your " + womanMan() + " feel ",
      "Now I'm gonna tell you why you ain't ",
      "You'll never beat me 'cause I'm so ",
      "If you're gonna battle me, then you gotta be ",
      "When I rock a mic you know I rock it real ",
      "If a rapper tries to step I'm gonna get ",
      "When I'm on the stage the " + ladiesFellas() + " get ",
      "I'm smooth, you'll never catch me acting "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'noun') {
    var a = article(word) + " ";
    var pre = [
      "I'm the illest MC to ever rock the ",
      "When I'm on the mic you realize you're " + a,
      "My rhymes bring the power like a raging ",
      "If you can't handle this then you're nothing but " + a,
      "When I come to a battle I'm strapped with " + a,
      "When you battle me it's like you battle " + a,
      "Every other MC is a sucker ",
      "There's nobody like me 'cause I'm the greatest ",
      "You hear my freestyle and you drop your ",
      "My flow and my style both blow away the ",
      "My posse's got my back and my " + sistasHomies() + " got my ",
      "Sweeter than molasses, and stronger than " + a,
      "Try to step to me and I'mma wreck your ",
      "Wherever I go, people give me some ",
      "You're nothin' but a scrub, word to your ",
      "I'm a lyricist, I'm a microphone ",
      "I write my rhymes while I chill in my ",
      "They called me a new jack, but I'm a new ",
      "Master of the game, I'm the rap ",
      "I know what you want, what you want's " + a,
      "My DJ is the backup and I'm the "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(I.singularize(word));
  }
  else if (pos === 'proper-noun') {
    var a = article(word) + " ";
    var pre = [
      "I'm playing you and your best friend ",
      "I know how to charm a " + womanMan() + ", just ask your friend ",
      "I've battled every MC, every Tom, Dick, and ",
      "You wish you had a DJ like DJ "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(I.singularize(word));
  }
  else if (pos === 'adverb') {
    var a = article(word) + " ";
    var pre = [
      "You know I rock the mic ",
      "Everybody knows I treat all the " + ladiesFellas() + " ",
      "Everybody in the club looks at me so "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'verb-transitive') {
    var a = article(word) + " ";
    var pre = [
      "My rhyme profile makes the " + ladiesFellas() + " ",
      "My DJ is the greatest, " + sheHe() + " makes the beat ",
      "Listen to my rhyme, let your mind "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'interjection') {
    result = "*skratch solo* ... (" + word[0] + "-" + word[0] + "-" + w(word) + "!)";
  }
  else {
    result = "";
  }

  return result;

}

function isBlacklisted(data) {
  var result = false;
  for (var i=0;i<blacklist.length;i++) {
    if (data.indexOf(blacklist[i]) >= 0) {
      result = true;
    }
  }
  return result;
}

<commit_msg>API calls per page now down to 20 from 35, stbut right now there's no accounting for proper nouns<commit_after>var APIKEY = require('./config.js').key;
var _ = require('underscore.deferred');
var I = require('inflection');
var request = require('request');
var article = require('./lib/indefinite');
var Wordnik = require('wordnik-bb').init(APIKEY);
var apicount = 0;

// fill the blacklist from a file

var fs = require('fs');
var blacklist = [];
try {
  var data = fs.readFileSync('badwords.txt', 'ascii');
  data.split('\n').forEach(function (line) {
    if(line.length>0) {
      blacklist.push(line);
    }
  });
}
catch (err) {
  console.error("There was an error opening the file:");
  console.log(err);
}

var randomWords = {
  noun: [],
  adj: [],
  verb: []
};

var express = require('express'),
  app = express();
app.use(express.logger());
app.listen(3000);
console.log('Express server started on port 3000');

function getCoupletPromise() {

  var coupletDeferred = _.Deferred();
  var coupletPromise = coupletDeferred.promise();
  var randomWordType, randomWordPos;
  //console.log(randomWords.noun.length);
  var rnd = Math.random();
  if (rnd < 0.4) {
    randomWordType = randomWords.noun;
    randomWordPos = 'noun';
  }
  else if (rnd >= 0.4 && rnd <= 0.8) {
    randomWordType = randomWords.adj;
    randomWordPos = 'adjective';
  }
  else {
    randomWordType = randomWords.verb;
    randomWordPos = 'verb-transitive';
  }

  var word = new Wordnik.Word({
    word: I.singularize(randomWordType[Math.floor(Math.random()*randomWordType.length)].word),
    params: {
      relationshipTypes: 'rhyme',
      limitPerRelationshipType: 100,
      hasDictionaryDef: true
    }
  });

    //console.log("The model for our random word: ", word);
    // We could also get more info about the random word, in this case, relatedWords that rhyme:
    _.when(word.getRelatedWords())
      .then(function () {
        apicount+=1;
      if (isBlacklisted(word.id)) {
        coupletDeferred.resolve("");
      }
      if (word.get("relatedWords").length > 0) {
        var wordPos = randomWordPos;
        var first = getLine(word.id, wordPos);
        if (first === "") {
          coupletDeferred.resolve(first);
        }
        else {
          var word2 = word.get("relatedWords")[0].words[Math.floor(Math.random() * word.get("relatedWords")[0].words.length)];
          // quit this couplet if blacklisted word comes up
          if (isBlacklisted(word2)) {
            coupletDeferred.resolve("");
          }

          var posPromise = getPartOfSpeech(word2);
          (function (first, word2) {

            posPromise.done(function (pos) {
              var result = "oops!";
              result = getLine(word2, pos);
              if (result === "") {
                coupletDeferred.resolve(result);
              }
              else {
                var regex = /(<([^>]+)>)/ig;
                coupletDeferred.resolve("
" + first + "\n
" + result + "\nTweet!
");
              }
            });
          })(first, word2);
        }
      }
      else {
        //coupletDeferred.resolve("Sorry. We couldn't find anything that rhymes with " + word.id + "!");
        coupletDeferred.resolve("");
      }
    });
  return coupletDeferred.promise();
}

app.get('/', function (req, res) {

  var cypher = "";
  // get a bunch of random words so we don't have to call the API every time
  var randomWordNounPromise = getRandomWordsPromise('noun');
  var randomWordAdjPromise = getRandomWordsPromise('adjective');
  var randomWordVerbPromise = getRandomWordsPromise('verb-transitive');

  _.when(randomWordNounPromise,randomWordAdjPromise,randomWordVerbPromise).done(function() {
    var stuffToDo = [];
    for (var i = 0; i < 12; i++) {
      var cp = getCoupletPromise();
      cp.done(function (couplet) {
        if (couplet !== "") {
          cypher += (couplet);
        }
      });
      stuffToDo.push(cp);
    }

    _.when(stuffToDo).done(function () {
      //console.log(cypher);
      //console.log('*drops the mic*');
      cypher += "
*drops the mic*

Yo, reload for more!
how it works | source code | thank u based Wordnik";
      res.send('<!doctype html><title>RapBot: a Freestyle 80s Battle Rap Generator</title>
RapBot

freestyle 80s battle rap generator by Darius Kazemi

' + cypher + '
');
      console.log("count: ",apicount);

    });

  });
});

function getPartOfSpeech(wordId) {
  // accepts a word string
  var word = new Wordnik.Word({
    word: wordId,
    params: {
      includeSuggestions: true
    }
  });
  var deferred = _.Deferred();
  word.getDefinitions()
    .then(function (word) {
      apicount++;
    deferred.resolve(word.get("definitions")[0].partOfSpeech);
  });
  return deferred.promise();
}

function ladiesFellas() {
  return (Math.random() < 0.5) ? "ladies" : "fellas";
}

function womanMan() {
  return (Math.random() < 0.5) ? "woman" : "man";
}

function sistasHomies() {
  return (Math.random() < 0.5) ? "sistas" : "homies";
}

function sheHe() {
  return (Math.random() < 0.5) ? "she" : "he";
}

function w(word) {
  return "" + word + "";
}

function getLine(word, pos) {

  var result = "Oops, we didn't account for something.";

  if (pos === 'adjective') {
    var pre = [
      "You can try and battle me, but you're too ",
      "I make the MCs in the place wish that they were ",
      "My rhymes blow your mind and you think it's ",
      "My sweet-ass rhymes make your " + womanMan() + " feel ",
      "Now I'm gonna tell you why you ain't ",
      "You'll never beat me 'cause I'm so ",
      "If you're gonna battle me, then you gotta be ",
      "When I rock a mic you know I rock it real ",
      "If a rapper tries to step I'm gonna get ",
      "When I'm on the stage the " + ladiesFellas() + " get ",
      "I'm smooth, you'll never catch me acting "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'noun') {
    var a = article(word) + " ";
    var pre = [
      "I'm the illest MC to ever rock the ",
      "When I'm on the mic you realize you're " + a,
      "My rhymes bring the power like a raging ",
      "If you can't handle this then you're nothing but " + a,
      "When I come to a battle I'm strapped with " + a,
      "When you battle me it's like you battle " + a,
      "Every other MC is a sucker ",
      "There's nobody like me 'cause I'm the greatest ",
      "You hear my freestyle and you drop your ",
      "My flow and my style both blow away the ",
      "My posse's got my back and my " + sistasHomies() + " got my ",
      "Sweeter than molasses, and stronger than " + a,
      "Try to step to me and I'mma wreck your ",
      "Wherever I go, people give me some ",
      "You're nothin' but a scrub, word to your ",
      "I'm a lyricist, I'm a microphone ",
      "I write my rhymes while I chill in my ",
      "They called me a new jack, but I'm a new ",
      "Master of the game, I'm the rap ",
      "I know what you want, what you want's " + a,
      "My DJ is the backup and I'm the "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(I.singularize(word));
  }
  else if (pos === 'proper-noun') {
    var a = article(word) + " ";
    var pre = [
      "I'm playing you and your best friend ",
      "I know how to charm a " + womanMan() + ", just ask your friend ",
      "I've battled every MC, every Tom, Dick, and ",
      "You wish you had a DJ like DJ "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(I.singularize(word));
  }
  else if (pos === 'adverb') {
    var a = article(word) + " ";
    var pre = [
      "You know I rock the mic ",
      "Everybody knows I treat all the " + ladiesFellas() + " ",
      "Everybody in the club looks at me so "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'verb-transitive') {
    var a = article(word) + " ";
    var pre = [
      "My rhyme profile makes the " + ladiesFellas() + " ",
      "My DJ is the greatest, " + sheHe() + " makes the beat ",
      "Listen to my rhyme, let your mind "
      ];
    result = pre[Math.floor(Math.random() * pre.length)] + w(word);
  }
  else if (pos === 'interjection') {
    result = "*skratch solo* ... (" + word[0] + "-" + word[0] + "-" + w(word) + "!)";
  }
  else {
    result = "";
  }

  return result;

}

function isBlacklisted(data) {
  var result = false;
  for (var i=0;i<blacklist.length;i++) {
    if (data.indexOf(blacklist[i]) >= 0) {
      result = true;
    }
  }
  return result;
}

function getRandomWordsPromise(pos) {
  var url = "http://api.wordnik.com//v4/words.json/randomWords?includePartOfSpeech="+pos+"&excludePartOfSpeech=proper-noun,proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&minCorpusCount=4000&hasDictionaryDef=true&limit=1000&api_key=" + APIKEY;
  var rwDeferred = _.Deferred();
  var randomWordNounPromise = rwDeferred.promise();
  request({
    url: url
  }, function (error, response, body) {
    apicount++;
    if (JSON.parse(body).message === "exceeded access limits") {
      console.log("We're over the access limit, nooo!");
      rwDeferred.reject(error);
    }
    else if (!error && response.statusCode === 200) {
      //console.log(JSON.parse(body).word);
      //console.log(I.singularize(JSON.parse(body).word));
      rwDeferred.resolve(JSON.parse(body));
    }
    else {
      rwDeferred.reject(error);
    }
  });

  (function(pos) {
    randomWordNounPromise.done(function(words) {
      console.log("!!",words.length);
      if (pos === "noun") {
        randomWords.noun = words;
      }
      if (pos === "adjective") {
        randomWords.adj = words;
      }
      if (pos === "verb-transitive") {
        randomWords.verb = words;
      }
    });
  })(pos);

  return randomWordNounPromise;
}
<|endoftext|>


<commit_before>'use strict';

const RtmClient = require('@slack/client').RtmClient,
  CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS,
  RTM_EVENTS = require('@slack/client').RTM_EVENTS,
  MemoryDataStore = require('@slack/client').MemoryDataStore,
  EventEmitter = require('events').EventEmitter,
  util = require('util'),
  log = require('winston'),
  _ = require('lodash');

class JiraBot extends EventEmitter {
  constructor(config) {
    super();

    log.info('Creating new JiraBot instance');

    this.config = config;

    this.issueKeysRegex = new RegExp('(' + config.watchTicketPrefixes.join('|') + ')-\\d+', 'g');

    this.slack = new RtmClient(config.apiToken, {
      dataStore: new MemoryDataStore()
    });

    this.slack.on(CLIENT_EVENTS.RTM.AUTHENTICATED, this._onOpen.bind(this));
    this.slack.on(RTM_EVENTS.MESSAGE, this._onMessage.bind(this));
  }

  login() {
    this.slack.start();
  }

  sendMessage(...args) {
    this.slack.sendMessage.apply(this.slack, args);
  }

  sendTyping(...args) {
    this.slack.sendTyping.apply(this.slack, args);
  }

  _onOpen(rtmStartData) {
    log.info(`Connected to Slack. You are @${rtmStartData.self.name} of "${rtmStartData.team.name}" team`);
  }

  _onMessage(message) {
    const text = message.text;

    const channel = this.slack.dataStore.getGroupById(message.channel);
    const user = this.slack.dataStore.getUserById(message.user);
    let issueKeys;

    if (message.type !== 'message'
      || message.user === this.slack.activeUserId
      || !text
      || this.config.allowChannels.indexOf(channel.name) === -1) {
      return;
    }

    if (text.match(/hello/i) && (text.search(`<@${this.slack.activeUserId}>`) !== -1)) {
      this.slack.sendMessage(`@${user.name} hello :)`, message.channel);
    }

    issueKeys = text.match(this.issueKeysRegex) || [];

    if (issueKeys.length) {
      _.uniq(issueKeys).forEach((issueKey) => {
        log.info(`Found Jira issue key ${issueKey} in channel #${channel.name} from user @${user.name}`);

        this.emit('ticketKeyFound', issueKey, channel);
      });
    }
  }
}

module.exports = JiraBot;
<commit_msg>Fix getting channel/group name. Code cleanup.<commit_after>'use strict';

const RtmClient = require('@slack/client').RtmClient,
  CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS,
  RTM_EVENTS = require('@slack/client').RTM_EVENTS,
  MemoryDataStore = require('@slack/client').MemoryDataStore,
  EventEmitter = require('events').EventEmitter,
  util = require('util'),
  log = require('winston'),
  _ = require('lodash');

class JiraBot extends EventEmitter {
  constructor(config) {
    super();

    log.info('Creating new JiraBot instance');

    this.config = config;

    this.issueKeysRegex = new RegExp('(' + config.watchTicketPrefixes.join('|') + ')-\\d+', 'g');

    this.slack = new RtmClient(config.apiToken, {
      dataStore: new MemoryDataStore()
    });

    this.slack.on(CLIENT_EVENTS.RTM.AUTHENTICATED, this._onOpen.bind(this));
    this.slack.on(RTM_EVENTS.MESSAGE, this._onMessage.bind(this));
  }

  login() {
    this.slack.start();
  }

  sendMessage(...args) {
    this.slack.sendMessage.apply(this.slack, args);
  }

  sendTyping(...args) {
    this.slack.sendTyping.apply(this.slack, args);
  }

  _onOpen(rtmStartData) {
    log.info(`Connected to Slack. You are @${rtmStartData.self.name} of "${rtmStartData.team.name}" team`);
  }

  _onMessage(message) {
    const channel = this._getChannelById(message.channel);
    const user = this.slack.dataStore.getUserById(message.user);

    if (this._isSelfMessage(message) || !this._isMessageFromAllowedChannel(message) || message.text == null) {
      return;
    }

    this._respondToHello(message);

    this._getIssueKeysFromMessage(message).forEach((issueKey) => {
      log.info(`Found Jira issue key ${issueKey} in channel #${channel.name} from user @${user.name}`);

      this.emit('ticketKeyFound', issueKey, channel);
    });
  }

  _isSelfMessage(message) {
    return message.user === this.slack.activeUserId;
  }

  _isMessageFromAllowedChannel(message) {
    const channel = this._getChannelById(message.channel);
    return this.config.allowChannels.indexOf(channel.name) !== -1;
  }

  _getIssueKeysFromMessage(message) {
    return _.uniq(message.text.match(this.issueKeysRegex) || []);
  }

  _respondToHello(message) {
    if (message.text.match(/hello/i) && (message.text.search(`<@${this.slack.activeUserId}>`) !== -1)) {
      const user = this.slack.dataStore.getUserById(message.user);
      this.slack.sendMessage(`Hello @${user.name}!`, message.channel);
    }
  }

  _getChannelById(channelId) {
    const dataStore = this.slack.dataStore;
    return dataStore.getGroupById(channelId) || dataStore.getChannelById(channelId);
  }
}

module.exports = JiraBot;
<|endoftext|>


<commit_before>"use strict";
const path = require('path');
const express = require('express');
const proxy = require('http-proxy-middleware');
const compression = require('compression');

function run_fork() {
    const port = process.env.PORT || 5000;
    const app = express();

    app.use(compression());

    const projectPath = path.dirname(__dirname);
    const staticPath = path.join(projectPath, 'browser-bundle');
    app.use(express.static(staticPath));
    app.use('/api', proxy({target: 'http://localhost:3000'}));
    app.get('*', (req, res) => {
      res.sendFile(path.join(projectPath, '/browser-bundle', 'index.html'));
    });

    app.listen(port, (err) => {
        if (err) {
            console.log(err);
        }
        console.info('==> 🌎 Listening on port %s. Open up http://0.0.0.0:%s/ in your browser.', port, port);
    });
}

module.exports = run_fork;<commit_msg>fix project path variable<commit_after>"use strict";
const path = require('path');
const express = require('express');
const proxy = require('http-proxy-middleware');
const compression = require('compression');

function run_fork() {
    const port = process.env.PORT || 5000;
    const app = express();

    app.use(compression());

    const projectPath = path.dirname(path.dirname(__dirname));
    const staticPath = path.join(projectPath, 'browser-bundle');
    app.use(express.static(staticPath));
    app.use('/api', proxy({target: 'http://localhost:3000'}));
    app.get('*', (req, res) => {
      res.sendFile(path.join(projectPath, '/browser-bundle', 'index.html'));
    });

    app.listen(port, (err) => {
        if (err) {
            console.log(err);
        }
        console.info('==> 🌎 Listening on port %s. Open up http://0.0.0.0:%s/ in your browser.', port, port);
    });
}

module.exports = run_fork;<|endoftext|>


<commit_before>/**
 * MIX fis conf file
 *
 * @author  Yang,junlong at 2016-06-22 10:12:17 build.
 * @version $Id$
 */

// 基础配置信息 命名空间
fis.config.merge({
    //namespace: 'mix',
    project : {
        // 使用project.exclude排除某些后缀 svn、cvs默认已排除
        exclude : [/\.(tar|rar|psd|jar|bat|sh|md|git|bak)$/i, /^\/mix\/lib\/est/i]
    }
});

fis.config.merge({
	// 插件安装
    modules: {
        parser: {
            less: 'less',
        },
        postprocessor: {
            js: 'jswrapper, require-async'
            //html: 'amd'
        },
        postpackager: 'modjs'
    },
    // 插件配置
    settings : {
        postprocessor : {
            jswrapper: {
                type: 'amd'
            }
        },
        postpackager: {
        	modjs: {
        		subpath: 'pkg/map.js',
                useType: false
        	}
        }
    },

    roadmap : {
        ext : {
            less : 'css'
        },
        path : [
            {
                reg: /LICENSE/i,
                release: false
            },
            {
                reg: 'server.conf',
                release: '/WEB-INF/server.conf'
            },
            {
                reg: /^\/app\/index\.html$/i,
                isMod: true,
                useMap: false,
                release: '/index.html'
            },
            {
                // .html|css 后缀的文件不加入map.json
                reg: /^.*(.+\.(?:html|css))$/i,
                useMap: false
            },
            {
                reg: /^(?!.*mod.js).*$/i,
                isMod: true
            },
            {
                // default
                reg: /^.+$/,
                release: '/static/$&'
            }
        ]
    }
});

// limit jello command
if (fis.require.prefixes[0] != 'fis') {
    //fis.log.error('Please use the `fis` command!\nUsage: jello release -wL');
}

// stdout.write some info...
process.stdout.write('\n β start complie '.yellow +fis.config.get('namespace')+' project ...\n'.yellow);
<commit_msg>修改fis 配置<commit_after>/**
 * MIX fis conf file
 *
 * @author  Yang,junlong at 2016-06-22 10:12:17 build.
 * @version $Id$
 */

// 基础配置信息 命名空间
fis.config.merge({
    //namespace: 'mix',
    project : {
        // 使用project.exclude排除某些后缀 svn、cvs默认已排除
        exclude : [/\.(tar|rar|psd|jar|bat|sh|md|git|bak)$/i, /^\/mix\/lib\/est/i]
    }
});

fis.config.merge({
	// 插件安装
    modules: {
        parser: {
            less: 'less',
        },
        postprocessor: {
            js: 'jswrapper, require-async'
            //html: 'amd'
        },
        postpackager: 'modjs'
    },
    // 插件配置
    settings : {
        postprocessor : {
            jswrapper: {
                type: 'amd'
            }
        },
        postpackager: {
        	modjs: {
        		subpath: 'pkg/map.js',
                useType: false
        	}
        }
    },

    roadmap : {
        ext : {
            less : 'css'
        },
        path : [
            {
                reg: /LICENSE/i,
                release: false
            },
            {
                reg: 'server.conf',
                release: '/WEB-INF/server.conf'
            },
            {
                reg: /^\/app\/index\.html$/i,
                isMod: true,
                useMap: false,
                release: '/index.html'
            },
            {
                // .html|css 后缀的文件不加入map.json
                reg: /^.*(.+\.(?:html|css))$/i,
                useMap: true,
                url: '/static$&',
                release: '/static$&'
            },
            {
                reg: /^(?!.*mod.js)(.*$)/i,
                isMod: true,
                url: '/static$1',
                release: '/static$1'
            },
            {
                // default
                reg: /^.+$/,
                url: '/static$&',
                release: '/static$&'
            }
        ]
    }
});

fis.emitter.once('fis-conf:loaded', function() {
    if (process.title.split(/\s/)[3] == 'output') {
        fis.config.set('roadmap.path', [
            {
                reg: /LICENSE/i,
                release: false
            },
            {
                reg: 'server.conf',
                release: '/WEB-INF/server.conf'
            },
            {
                reg: /^\/app\/index\.html$/i,
                isMod: true,
                useMap: false,
                release: '/index.html'
            },
            {
                // .html|css 后缀的文件不加入map.json
                reg: /^.*(.+\.(?:html|css))$/i,
                useMap: true,
                url: './static$&',
                release: './static$&'
            },
            {
                reg: /^(?!.*mod.js)(.*$)/i,
                isMod: true,
                url: '/mix-dashboard/static$1',
                release: '/static$1'
            },
            {
                // default
                reg: /^.+$/,
                url: '/mix-dashboard/static$&',
                release: '/static$&'
            }
        ]);
    }
});

// limit jello command
if (fis.require.prefixes[0] != 'fis') {
    //fis.log.error('Please use the `fis` command!\nUsage: jello release -wL');
}

// stdout.write some info...
process.stdout.write('\n β start complie '.yellow +fis.config.get('namespace')+' project ...\n'.yellow);
<|endoftext|>