<commit_before>/* globals _, Backbone, DiscussionTopicMenuView, DiscussionUtil, Thread */
(function() {
    'use strict';
    var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) {
            for (var key in parent) {
                if (__hasProp.call(parent, key)) {
                    child[key] = parent[key];
                }
            }
            function ctor() {
                this.constructor = child;
            }

            ctor.prototype = parent.prototype;
            child.prototype = new ctor();
            child.__super__ = parent.prototype;
            return child;
        };

    if (typeof Backbone !== 'undefined' && Backbone !== null) {
        this.NewPostView = (function(_super) {
            __extends(NewPostView, _super);

            function NewPostView() {
                var self = this;
                this.updateStyles = function() {
                    return NewPostView.prototype.updateStyles.apply(self, arguments);
                };
                this.resetForm = function() {
                    return NewPostView.prototype.resetForm.apply(self, arguments);
                };
                return NewPostView.__super__.constructor.apply(this, arguments);
            }

            NewPostView.prototype.initialize = function(options) {
                var _ref;
                this.mode = options.mode || 'inline';
                if ((_ref = this.mode) !== 'tab' && _ref !== 'inline') {
                    throw new Error('invalid mode: ' + this.mode);
                }
                this.course_settings = options.course_settings;
                this.is_commentable_cohorted = options.is_commentable_cohorted;
                this.topicId = options.topicId;
            };

            NewPostView.prototype.render = function() {
                var context, threadTypeTemplate;
                context = _.clone(this.course_settings.attributes);
                _.extend(context, {
                    cohort_options: this.getCohortOptions(),
                    is_commentable_cohorted: this.is_commentable_cohorted,
                    mode: this.mode,
                    form_id: this.mode + (this.topicId ? '-' + this.topicId : '')
                });
                this.$el.html(_.template($('#new-post-template').html())(context));
                threadTypeTemplate = _.template($('#thread-type-template').html());
                if ($('.js-group-select').prop('disabled')) {
                    $('.group-selector-wrapper').addClass('disabled');
                }
                this.addField(threadTypeTemplate({
                    form_id: _.uniqueId('form-')
                }));
                if (this.isTabMode()) {
                    this.topicView = new DiscussionTopicMenuView({
                        topicId: this.topicId,
                        course_settings: this.course_settings
                    });
                    this.topicView.on('thread:topic_change', this.toggleGroupDropdown);
                    this.addField(this.topicView.render());
                }
                return DiscussionUtil.makeWmdEditor(this.$el, $.proxy(this.$, this), 'js-post-body');
            };

            NewPostView.prototype.addField = function(fieldView) {
                return this.$('.forum-new-post-form-wrapper').append(fieldView);
            };

            NewPostView.prototype.isTabMode = function() {
                return this.mode === 'tab';
            };

            NewPostView.prototype.getCohortOptions = function() {
                var userCohortId;
                if (this.course_settings.get('is_cohorted') && DiscussionUtil.isPrivilegedUser()) {
                    userCohortId = $('#discussion-container').data('user-cohort-id');
                    return _.map(this.course_settings.get('cohorts'), function(cohort) {
                        return {
                            value: cohort.id,
                            text: cohort.name,
                            selected: cohort.id === userCohortId
                        };
                    });
                } else {
                    return null;
                }
            };

            NewPostView.prototype.events = {
                'keypress .forum-new-post-form input:not(.wmd-input)': function(event) {
                    return DiscussionUtil.ignoreEnterKey(event);
                },
                'submit .forum-new-post-form': 'createPost',
                'change .post-option-input': 'postOptionChange',
                'click .cancel': 'cancel',
                'click  .add-post-cancel': 'cancel',
                'reset .forum-new-post-form': 'updateStyles'
            };

            NewPostView.prototype.toggleGroupDropdown = function($target) {
                if ($target.data('cohorted')) {
                    $('.js-group-select').prop('disabled', false);
                    return $('.group-selector-wrapper').removeClass('disabled');
                } else {
                    $('.js-group-select').val('').prop('disabled', true);
                    return $('.group-selector-wrapper').addClass('disabled');
                }
            };

            NewPostView.prototype.postOptionChange = function(event) {
                var $optionElem, $target;
                $target = $(event.target);
                $optionElem = $target.closest('.post-option');
                if ($target.is(':checked')) {
                    return $optionElem.addClass('is-enabled');
                } else {
                    return $optionElem.removeClass('is-enabled');
                }
            };

            NewPostView.prototype.createPost = function(event) {
                var anonymous, anonymousToPeers, body, follow, group, threadType, title, topicId, url,
                    self = this;
                event.preventDefault();
                threadType = this.$('.input-radio:checked').val();
                title = this.$('.js-post-title').val();
                body = this.$('.js-post-body').find('.wmd-input').val();
                group = this.$('.js-group-select option:selected').attr('value');
                anonymous = false || this.$('.js-anon').is(':checked');
                anonymousToPeers = false || this.$('.js-anon-peers').is(':checked');
                follow = false || this.$('input[name=follow]').is(':checked');
                topicId = this.isTabMode() ? this.topicView.getCurrentTopicId() : this.topicId;
                url = DiscussionUtil.urlFor('create_thread', topicId);
                return DiscussionUtil.safeAjax({
                    $elem: $(event.target),
                    $loading: event ? $(event.target) : void 0,
                    url: url,
                    type: 'POST',
                    dataType: 'json',
                    data: {
                        thread_type: threadType,
                        title: title,
                        body: body,
                        anonymous: anonymous,
                        anonymous_to_peers: anonymousToPeers,
                        auto_subscribe: follow,
                        group_id: group
                    },
                    error: DiscussionUtil.formErrorHandler(this.$('.post-errors')),
                    success: function(response) {
                        var thread;
                        thread = new Thread(response.content);
                        self.$el.addClass('is-hidden');
                        self.resetForm();
                        self.trigger('newPost:createPost');
                        return self.collection.add(thread);
                    }
                });
            };

            NewPostView.prototype.formModified = function() {
                var postBodyHasContent = this.$('.js-post-body').find('.wmd-input').val() !== '',
                    titleHasContent = this.$('.js-post-title').val() !== '';
                return postBodyHasContent || titleHasContent;
            };

            NewPostView.prototype.cancel = function(event) {
                event.preventDefault();
                if (this.formModified()) {
                    if (!confirm(gettext('Your post will be discarded.'))) {  // eslint-disable-line no-alert
                        return;
                    }
                }
                this.trigger('newPost:cancel');
                this.resetForm();
            };

            NewPostView.prototype.resetForm = function() {
                var $general;
                this.$('.forum-new-post-form')[0].reset();
                DiscussionUtil.clearFormErrors(this.$('.post-errors'));
                this.$('.wmd-preview p').html('');
                if (this.isTabMode()) {
                    $general = this.$('.post-topic option:contains(General)');
                    this.topicView.setTopic($general || this.$('button.topic-title').first());
                }
            };

            NewPostView.prototype.updateStyles = function() {
                var self = this;
                return setTimeout(function() { return self.$('.post-option-input').trigger('change'); }, 1);
            };

            return NewPostView;
        })(Backbone.View);
    }
}).call(window);
<commit_msg>Discussion Selector fixes. TNL-6648<commit_after>/* globals _, Backbone, DiscussionTopicMenuView, DiscussionUtil, Thread */
(function() {
    'use strict';
    var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) {
            for (var key in parent) {
                if (__hasProp.call(parent, key)) {
                    child[key] = parent[key];
                }
            }
            function ctor() {
                this.constructor = child;
            }

            ctor.prototype = parent.prototype;
            child.prototype = new ctor();
            child.__super__ = parent.prototype;
            return child;
        };

    if (typeof Backbone !== 'undefined' && Backbone !== null) {
        this.NewPostView = (function(_super) {
            __extends(NewPostView, _super);

            function NewPostView() {
                var self = this;
                this.updateStyles = function() {
                    return NewPostView.prototype.updateStyles.apply(self, arguments);
                };
                this.resetForm = function() {
                    return NewPostView.prototype.resetForm.apply(self, arguments);
                };
                return NewPostView.__super__.constructor.apply(this, arguments);
            }

            NewPostView.prototype.initialize = function(options) {
                var _ref;
                this.mode = options.mode || 'inline';
                if ((_ref = this.mode) !== 'tab' && _ref !== 'inline') {
                    throw new Error('invalid mode: ' + this.mode);
                }
                this.course_settings = options.course_settings;
                this.is_commentable_cohorted = options.is_commentable_cohorted;
                this.topicId = options.topicId;
            };

            NewPostView.prototype.render = function() {
                var context, threadTypeTemplate;
                context = _.clone(this.course_settings.attributes);
                _.extend(context, {
                    cohort_options: this.getCohortOptions(),
                    is_commentable_cohorted: this.is_commentable_cohorted,
                    mode: this.mode,
                    form_id: this.mode + (this.topicId ? '-' + this.topicId : '')
                });
                this.$el.html(_.template($('#new-post-template').html())(context));
                threadTypeTemplate = _.template($('#thread-type-template').html());
                if ($('.js-group-select').prop('disabled')) {
                    $('.group-selector-wrapper').addClass('disabled');
                }
                this.addField(threadTypeTemplate({
                    form_id: _.uniqueId('form-')
                }));
                if (this.isTabMode()) {
                    this.topicView = new DiscussionTopicMenuView({
                        topicId: this.topicId,
                        course_settings: this.course_settings
                    });
                    this.topicView.on('thread:topic_change', this.toggleGroupDropdown);
                    this.addField(this.topicView.render());
                }
                return DiscussionUtil.makeWmdEditor(this.$el, $.proxy(this.$, this), 'js-post-body');
            };

            NewPostView.prototype.addField = function(fieldView) {
                return this.$('.forum-new-post-form-wrapper').append(fieldView);
            };

            NewPostView.prototype.isTabMode = function() {
                return this.mode === 'tab';
            };

            NewPostView.prototype.getCohortOptions = function() {
                var userCohortId;
                if (this.course_settings.get('is_cohorted') && DiscussionUtil.isPrivilegedUser()) {
                    userCohortId = $('#discussion-container').data('user-cohort-id');
                    return _.map(this.course_settings.get('cohorts'), function(cohort) {
                        return {
                            value: cohort.id,
                            text: cohort.name,
                            selected: cohort.id === userCohortId
                        };
                    });
                } else {
                    return null;
                }
            };

            NewPostView.prototype.events = {
                'keypress .forum-new-post-form input:not(.wmd-input)': function(event) {
                    return DiscussionUtil.ignoreEnterKey(event);
                },
                'submit .forum-new-post-form': 'createPost',
                'change .post-option-input': 'postOptionChange',
                'click .cancel': 'cancel',
                'click  .add-post-cancel': 'cancel',
                'reset .forum-new-post-form': 'updateStyles'
            };

            NewPostView.prototype.toggleGroupDropdown = function($target) {
                if ($target.data('cohorted')) {
                    $('.js-group-select').prop('disabled', false);
                    return $('.group-selector-wrapper').removeClass('disabled');
                } else {
                    $('.js-group-select').val('').prop('disabled', true);
                    return $('.group-selector-wrapper').addClass('disabled');
                }
            };

            NewPostView.prototype.postOptionChange = function(event) {
                var $optionElem, $target;
                $target = $(event.target);
                $optionElem = $target.closest('.post-option');
                if ($target.is(':checked')) {
                    return $optionElem.addClass('is-enabled');
                } else {
                    return $optionElem.removeClass('is-enabled');
                }
            };

            NewPostView.prototype.createPost = function(event) {
                var anonymous, anonymousToPeers, body, follow, group, threadType, title, topicId, url,
                    self = this;
                event.preventDefault();
                threadType = this.$('.input-radio:checked').val();
                title = this.$('.js-post-title').val();
                body = this.$('.js-post-body').find('.wmd-input').val();
                group = this.$('.js-group-select option:selected').attr('value');
                anonymous = false || this.$('input[name=anonymous]').is(':checked');
                anonymousToPeers = false || this.$('input[name=anonymous_to_peers]').is(':checked');
                follow = false || this.$('input[name=follow]').is(':checked');
                topicId = this.isTabMode() ? this.topicView.getCurrentTopicId() : this.topicId;
                url = DiscussionUtil.urlFor('create_thread', topicId);
                return DiscussionUtil.safeAjax({
                    $elem: $(event.target),
                    $loading: event ? $(event.target) : void 0,
                    url: url,
                    type: 'POST',
                    dataType: 'json',
                    data: {
                        thread_type: threadType,
                        title: title,
                        body: body,
                        anonymous: anonymous,
                        anonymous_to_peers: anonymousToPeers,
                        auto_subscribe: follow,
                        group_id: group
                    },
                    error: DiscussionUtil.formErrorHandler(this.$('.post-errors')),
                    success: function(response) {
                        var thread;
                        thread = new Thread(response.content);
                        self.$el.addClass('is-hidden');
                        self.resetForm();
                        self.trigger('newPost:createPost');
                        return self.collection.add(thread);
                    }
                });
            };

            NewPostView.prototype.formModified = function() {
                var postBodyHasContent = this.$('.js-post-body').find('.wmd-input').val() !== '',
                    titleHasContent = this.$('.js-post-title').val() !== '';
                return postBodyHasContent || titleHasContent;
            };

            NewPostView.prototype.cancel = function(event) {
                event.preventDefault();
                if (this.formModified()) {
                    if (!confirm(gettext('Your post will be discarded.'))) {  // eslint-disable-line no-alert
                        return;
                    }
                }
                this.trigger('newPost:cancel');
                this.resetForm();
            };

            NewPostView.prototype.resetForm = function() {
                var $general;
                this.$('.forum-new-post-form')[0].reset();
                DiscussionUtil.clearFormErrors(this.$('.post-errors'));
                this.$('.wmd-preview p').html('');
                if (this.isTabMode()) {
                    $general = this.$('.post-topic option:contains(General)');
                    this.topicView.setTopic($general || this.$('button.topic-title').first());
                }
            };

            NewPostView.prototype.updateStyles = function() {
                var self = this;
                return setTimeout(function() { return self.$('.post-option-input').trigger('change'); }, 1);
            };

            return NewPostView;
        })(Backbone.View);
    }
}).call(window);
<|endoftext|>


<commit_before>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Simple
 *
 * @fileoverview
 *
 * @suppress {checkTypes}
 */

goog.provide('Simple');

goog.require('vf2js.components.Application');
goog.require('vf2js.components.Button');

/**
 * @constructor
 * @extends {vf2js.components.Application}
 */
Simple = function() {
  goog.base(this);

  /**
   * @private
   * @type {vf2js.components.Button}
   */
  this.$ID0;

  /**
   * @private
   * @type {Array}
   */
  this.mxmldd;

  /**
   * @private
   * @type {Array}
   */
  this.mxmldp;
};
goog.inherits(Simple, vf2js.components.Application);

/**
 * Metadata
 *
 * @type {Object.<string, Array.<Object>>}
 */
Simple.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'Simple', qName: 'Simple' }] };

/**
 * @override
 * @return {Array} the Array of UI element descriptors.
 */
Simple.prototype.get_MXMLProperties = function()
{
  if (this.mxmldp == undefined)
  {
    /** @type {Array} */
    var arr = goog.base(this, 'get_MXMLProperties');
    /** @type {Array} */
    var data = [
1,
'mxmlContentFactory',
false,
[vf2js.components.Button, 2, '_id', true, '$ID0', 'label', true, 'hello', 0, 0, null],
0,
0
];

    if (arr)
      this.mxmldp = arr.concat(data);
    else
      this.mxmldp = data;
  }
  return this.mxmldp;
};

<commit_msg>Updated test expectation.<commit_after>/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Simple
 *
 * @fileoverview
 *
 * @suppress {checkTypes}
 */

goog.provide('Simple');

goog.require('vf2js.components.Application');
goog.require('vf2js.components.Button');

/**
 * @constructor
 * @extends {vf2js.components.Application}
 */
Simple = function() {
  goog.base(this);

  /**
   * @private
   * @type {vf2js.components.Button}
   */
  this.$ID0;

  /**
   * @private
   * @type {Array}
   */
  this.mxmldd;

  /**
   * @private
   * @type {Array}
   */
  this.mxmldp;
};
goog.inherits(Simple, vf2js.components.Application);

/**
 * Metadata
 *
 * @type {Object.<string, Array.<Object>>}
 */
Simple.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'Simple', qName: 'Simple' }] };

/**
 * @override
 * @return {Array} the Array of UI element descriptors.
 */
Simple.prototype.get_MXMLProperties = function()
{
  if (this.mxmldp == undefined)
  {
    /** @type {Array} */
    var arr = goog.base(this, 'get_MXMLProperties');
    /** @type {Array} */
    var data = [
1,
vf2js.components.Button,
2,
'_id',
true,
'$ID0',
'label',
true,
'hello',
0,
0,
null0,
0
];

    if (arr)
      this.mxmldp = arr.concat(data);
    else
      this.mxmldp = data;
  }
  return this.mxmldp;
};

<|endoftext|>


<commit_before>import React from 'react';
import FocusTrap from 'focus-trap-react';
import {Button, Container, Form, Modal, Icon, Segment, Grid, TextArea, Input, Label} from 'semantic-ui-react';
import {FormattedMessage, defineMessages} from 'react-intl';
import {connectToStores} from 'fluxible-addons-react';
import ContentStore from '../../../../stores/ContentStore';
import UserProfileStore from '../../../../stores/UserProfileStore';

class EmbedModal extends React.Component {
    constructor(props) {
        super(props);

        this.defaultWidthValue = 800;
        this.defaultHeightValue = 400;

        this.state = {
            modalOpen: false,
            activeTrap: false,
            width: this.defaultWidthValue,
            height: this.defaultHeightValue,
            href: null
        };

        this.handleEmbed = this.handleEmbed.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.unmountTrap = this.unmountTrap.bind(this);

        this.messages = defineMessages({
            embedModal_header:{
                id:'embedModal.embedModal_embedHeader',
                defaultMessage: 'Embed deck'
            },
            embedModal_embedButton:{
                id:'embedModal.embedModal_embedButton',
                defaultMessage: 'Embed'
            },
            embedModal_cancelButton:{
                id:'embedModal.embedModal_cancelButton',
                defaultMessage: 'Cancel'
            },
            embedModal_sizeLabel:{
                id:'embedModal.embedModal_sizeLabel',
                defaultMessage: 'Size'
            }
        });
    }

    handleEmbed() {
        this.setState({
            modalOpen:true,
            activeTrap:true
        });
        // TODO: implement.
    }

    handleChange() {
        var widthInput = $('#embedModalWidth');
        var heightInput = $('#embedModalHeight');

        this.setState({
            width: widthInput.val() || this.defaultWidthValue,
            height: heightInput.val() || this.defaultHeightValue,
            href: window.location.href
        });
    }

    handleClose(){
        $('#app').attr('aria-hidden', 'false');
        this.setState({
            modalOpen: false,
            activeTrap: false
        });
    }

    unmountTrap() {
        if(this.state.activeTrap){
            this.setState({ activeTrap: false });
            $('#app').attr('aria-hidden','false');
        }
    }

    render() {
        return(
            <Modal
                    trigger={
                        <Button icon="code"
                                color="grey"
                                type="button"
                                onClick={this.handleEmbed}
                                content={this.context.intl.formatMessage(this.messages.embedModal_embedButton)}/>
                    }
                    open={this.state.modalOpen}
                    onOpen={this.handleChange}
                    onClose={this.handleClose}
                    id="embedModal"
                    aria-labelledby="embedModalHeader"
                    aria-describedby="embedModalDescription"
                    aria-hidden = {!this.state.modalOpen}
                    role="dialog"
                    tabIndex="0">
                <FocusTrap
                        id="focus-trap-embedModal"
                        className = "header"
                        active={this.state.activeTrap}
                        focusTrapOptions={{
                            onDeactivate: this.unmountTrap,
                            clickOutsideDeactivates: true ,
                            initialFocus: '#embedModalDescription'
                        }}>
                    <Modal.Header className="ui center aligned" id="embedModalHeader">

                            {this.context.intl.formatMessage(this.messages.embedModal_header)}

                    </Modal.Header>
                    <Modal.Content>
                        <Container>
                            <Segment color="blue" textAlign="center" padded>
                                <Segment>
                                    <Form.Field>

                                            {this.context.intl.formatMessage(this.messages.embedModal_sizeLabel)}

                                        <Input id="embedModalWidth"
                                                placeholder={this.defaultWidthValue}
                                                onChange={this.handleChange}/>
                                        x
                                        <Input id="embedModalHeight"
                                                placeholder={this.defaultHeightValue}
                                                onChange={this.handleChange}/>
                                    </Form.Field>
                                    <Form.Field>
                                        <TextArea id="embedModalDescription"
                                                label="description"
                                                autoHeight={true}
                                                value={''}/>
                                    </Form.Field>
                                    <Modal.Actions>
                                        <Button icon="remove"
                                                color="red"
                                                type="button"
                                                onClick={this.handleClose}
                                                content={this.context.intl.formatMessage(this.messages.embedModal_cancelButton)}/>
                                    </Modal.Actions>
                                </Segment>
                            </Segment>
                        </Container>
                    </Modal.Content>
                </FocusTrap>
            </Modal>
        );
    }

}

EmbedModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

EmbedModal = connectToStores(EmbedModal,[ContentStore, UserProfileStore], (context, props) => {
    return{
        ContentStore : context.getStore(ContentStore).getState(),
        UserProfileStore : context.getStore(UserProfileStore).getState()
    };
});

export default EmbedModal;
<commit_msg>Changed the labels to 'Width of embedded content' and 'Height of embedded content'. Wrapped the fields into a form to apply the semantic-ui-react styles on them.<commit_after>import React from 'react';
import FocusTrap from 'focus-trap-react';
import {Button, Container, Form, Modal, Icon, Segment, Grid, TextArea, Input, Label} from 'semantic-ui-react';
import {FormattedMessage, defineMessages} from 'react-intl';
import {connectToStores} from 'fluxible-addons-react';
import ContentStore from '../../../../stores/ContentStore';
import UserProfileStore from '../../../../stores/UserProfileStore';

class EmbedModal extends React.Component {
    constructor(props) {
        super(props);

        this.defaultWidthValue = 800;
        this.defaultHeightValue = 400;

        this.state = {
            modalOpen: false,
            activeTrap: false,
            width: this.defaultWidthValue,
            height: this.defaultHeightValue,
            href: null
        };

        this.handleEmbed = this.handleEmbed.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.unmountTrap = this.unmountTrap.bind(this);

        this.messages = defineMessages({
            embedModal_header:{
                id:'embedModal.embedModal_embedHeader',
                defaultMessage: 'Embed deck'
            },
            embedModal_embedButton:{
                id:'embedModal.embedModal_embedButton',
                defaultMessage: 'Embed'
            },
            embedModal_cancelButton:{
                id:'embedModal.embedModal_cancelButton',
                defaultMessage: 'Cancel'
            },
            embedModal_widthLabel:{
                id:'embedModal.embedModal_widthLabel',
                defaultMessage: 'Width of embedded content'
            },
            embedModal_heightLabel:{
                id:'embedModal.embedModal_heightLabel',
                defaultMessage: 'Height of embedded content'
            },
        });
    }

    handleEmbed() {
        this.setState({
            modalOpen:true,
            activeTrap:true
        });
        // TODO: implement.
    }

    handleChange() {
        var widthInput = $('#embedModalWidth');
        var heightInput = $('#embedModalHeight');

        this.setState({
            width: widthInput.val() || this.defaultWidthValue,
            height: heightInput.val() || this.defaultHeightValue,
            href: window.location.href
        });
    }

    handleClose(){
        $('#app').attr('aria-hidden', 'false');
        this.setState({
            modalOpen: false,
            activeTrap: false
        });
    }

    unmountTrap() {
        if(this.state.activeTrap){
            this.setState({ activeTrap: false });
            $('#app').attr('aria-hidden','false');
        }
    }

    render() {
        return(
            <Modal
                    trigger={
                        <Button icon="code"
                                color="grey"
                                type="button"
                                onClick={this.handleEmbed}
                                content={this.context.intl.formatMessage(this.messages.embedModal_embedButton)}/>
                    }
                    open={this.state.modalOpen}
                    onOpen={this.handleChange}
                    onClose={this.handleClose}
                    id="embedModal"
                    aria-labelledby="embedModalHeader"
                    aria-describedby="embedModalDescription"
                    aria-hidden = {!this.state.modalOpen}
                    role="dialog"
                    tabIndex="0">
                <FocusTrap
                        id="focus-trap-embedModal"
                        className = "header"
                        active={this.state.activeTrap}
                        focusTrapOptions={{
                            onDeactivate: this.unmountTrap,
                            clickOutsideDeactivates: true ,
                            initialFocus: '#embedModalDescription'
                        }}>
                    <Modal.Header className="ui center aligned" id="embedModalHeader">

                            {this.context.intl.formatMessage(this.messages.embedModal_header)}

                    </Modal.Header>
                    <Modal.Content>
                        <Container>
                            <Segment color="blue" textAlign="center" padded>
                                <Segment>
                                    <form className="ui form">
                                        <Form.Field>

                                                {this.context.intl.formatMessage(this.messages.embedModal_widthLabel)}

                                            <Input id="embedModalWidth"
                                                    placeholder={this.defaultWidthValue}
                                                    onChange={this.handleChange}/>

                                                {this.context.intl.formatMessage(this.messages.embedModal_heightLabel)}

                                            <Input id="embedModalHeight"
                                                    placeholder={this.defaultHeightValue}
                                                    onChange={this.handleChange}/>
                                        </Form.Field>
                                        <Form.Field>
                                            <textarea id="embedModalDescription"
                                                    ref="embedModalDescription"
                                                    label="description"
                                                    autoHeight={true}
                                                    value={''}/>
                                        </Form.Field>
                                        <Modal.Actions>
                                            <Button icon="remove"
                                                    color="red"
                                                    type="button"
                                                    onClick={this.handleClose}
                                                    content={this.context.intl.formatMessage(this.messages.embedModal_cancelButton)}/>
                                        </Modal.Actions>
                                    </form>
                                </Segment>
                            </Segment>
                        </Container>
                    </Modal.Content>
                </FocusTrap>
            </Modal>
        );
    }

}

EmbedModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

EmbedModal = connectToStores(EmbedModal,[ContentStore, UserProfileStore], (context, props) => {
    return{
        ContentStore : context.getStore(ContentStore).getState(),
        UserProfileStore : context.getStore(UserProfileStore).getState()
    };
});

export default EmbedModal;
<|endoftext|>


<commit_before>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2011 Purdue University. All rights reserved.
 * @license     http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

HUB.Groups = {
	jQuery: jq,

	initialize: function()
	{
		//
		HUB.Groups.membershipNotifications();

		//verify wanting to cancel from group
		HUB.Groups.confirmCancelMembership();

		//confirm messages
		HUB.Groups.confirmLeaveArea();

		//logo picker to show logo picked in preview
		HUB.Groups.customizePickLogo();

		//show or hide custom content box
		HUB.Groups.customizeOverviewContent();

		//group page preview in lightbox
		HUB.Groups.customizePreviewPage();

		//hide all empty paragraphs generated from wiki
		//HUB.Groups.fixEmptyParagraphs();

		//toggle between public and private group desc
		HUB.Groups.togglePublicPrivateDescription();

		//special groups
		HUB.Groups.specialGroups();

		//scrolling asset browser
		HUB.Groups.scrollingAssetBrowser();

		//group availablity checker
		HUB.Groups.groupIdAvailability();

		//group menu alert fixer
		HUB.Groups.groupMenuFix();
	},

	//-----

	groupMenuFix: function()
	{
		var $ = this.jQuery;

		$("#page_menu li").each(function(index){
			var meta = $(this).find(".meta"),
				metawidth = meta.outerWidth(true),
				alrt = $(this).find(".alrt");

			if(alrt.length)
			{
				if(metawidth > 20)
				{
					alrt.css("right", 33+(metawidth-20));
				}
				else if(metawidth < 20 && metawidth != 0)
				{
					alrt.css("right", 33-(20-metawidth));
				}
			}
		});
	},

	//-----

	membershipNotifications: function()
	{
		var $ = this.jQuery;

		var content = "",
			invites = $(".invites"),
			requests = $(".requests");

		if(invites.length)
		{
			invites.addClass("hide");
			content += invites.html();
		}

		if(requests.length)
		{
			requests.addClass("hide");
			content += requests.html();
		}

		if(content != "")
		{
			var timeout = setTimeout(function() {
				$.fancybox({
					autoSize:false,
					width: 600,
					height: 'auto',
					content: content,
					tpl: {
						wrap:'

'
					},
					beforeload: function() {
						invites.toggleClass("hide");
						requests.toggleClass("hide");
					}
				});
			}, 2000);
		}
	},

	//-----

	fixEmptyParagraphs: function()
	{
		var $ = this.jQuery;

		$('p').each(function(i, el) {
			var text = el.innerHTML;
			if(escape(text) == '%3Cbr%3E%0A' || text == "") {
				el.addClass('hide');
			}
		});
	},

	//-----

	togglePublicPrivateDescription: function()
	{
		var $ = this.jQuery;

		var publicDesc = $("#public"),
			privateDesc = $("#private"),
			toggleSwitch = $("#toggle_description");

		if(toggleSwitch.length)
		{
			toggleSwitch.removeClass('hide');

			toggleSwitch.bind("click", function(e) {
				e.preventDefault();

				if(publicDesc.hasClass("hide"))
				{
					toggleSwitch.html('Show Private Description (-)');
				}
				else
				{
					toggleSwitch.html('Show Public Description (+)');
				}

				publicDesc.toggleClass("hide");
				privateDesc.toggleClass("hide");
			});
		}
	},

	//-----

	confirmCancelMembership: function()
	{
		var $ = this.jQuery;

		$(".cancel_group_membership").live('click', function(e) {
			e.preventDefault();

			var answer = confirm('Are you sure you would like to cancel your group membership?');
			if(answer)
			{
				window.location = this.href;
			}
		});
	},

	//-----

	confirmLeaveArea: function()
	{
		var $ = this.jQuery;

		$('.leave_area').bind('click', function(e) {
			e.preventDefault();

			var question = $(this).attr('rel'),
				answer = confirm(question);

			if(answer) {
				window.location = this.href;
			}
		});
	},

	//-----

	customizePickLogo: function()
	{
		var $ = this.jQuery;

		var logo = "",
			logoSelecter = $("#group_logo");

		if(logoSelecter.length)
		{
			logoSelecter.bind("change", function(e) {

				if(this.value == "")
				{
					logo = '';
				}
				else
				{
					logo = '';
				}

				$("#logo_picked").html(logo)
			});
		}
	},

	//-----

	customizeOverviewContent: function()
	{
		var $ = this.jQuery;

		var overview = $('#overview_content'),
			customOverview = $('#group_overview_type_custom').attr("checked");

		if(overview.length)
		{
			if(!customOverview)
			{
				overview.addClass("hide-left");
			}

			$("input[type=radio]").bind("click", function(e){
				$('p.side-by-side').removeClass('checked');
				$(this).parents(".side-by-side").addClass("checked");
				if(this.value == 1)
				{
					overview.removeClass('hide-left');
				}
				else
				{
					overview.addClass('hide-left');
				}
			});
		}
	},

	//-----

	customizePreviewPage: function()
	{
		var $ = this.jQuery;

		$('.quick-view').fancybox({
			type: 'inline',
			width: 600,
			height: 'auto',
			autoSize: false,
			fitToView: false,
			titleShow: false
		});
	},

	//-----

	scrollingAssetBrowser: function()
	{
		var $ = this.jQuery;

		var topBox = $("#top_box"),
			bottomBox = $("#bottom_box"),
			assetBox = $("#asset_browser"),
			max = 0, pos = 0;

		assetBox
			.css('width', ($(assetBox.parent()).width() - 10) + 'px')
			.css('padding', '10px');

		if(assetBox.length)
		{
			if(topBox.length && bottomBox.length)
			{
				max = (bottomBox.position().top + bottomBox.outerHeight(true)) - assetBox.outerHeight(true);
				pos = $(document).scrollTop() - 200;

				if( pos > 0 && pos < max)
				{
					assetBox.stop().animate({
						"top": pos
					});
				}
			}
			else
			{
				console.log('Missing needed DOM elements to make assest browser scroll.');
			}
		}
	},

	//-----

	specialGroups: function()
	{
		var $ = this.jQuery;

		$("#special-group-tab").on("click", function(event){
			$("#special-group-pane").slideToggle('slow', function() {
				$("#special-group-tab").toggleClass('active');
			});
			event.preventDefault();
		});

		var wh = $(window).height(),
			ph = $("#page_container").height();
		if(ph < wh)
		{
			//$("#page_container").css("height", wh);
			//$("#page_container_inner").css("height", wh);
		}
	},

	//-----

	groupIdAvailability: function()
	{
		var $ = this.jQuery;
		$("#group_cn_field")
			.on("keydown", function(event) {
				$('.available, .not-available').remove();
			})
			.on("keyup", function(event) {
				$.ajax({
					url: 'index.php?option=com_groups&task=groupavailability&no_html=1',
					data: { 'group' : $(this).val() },
					success: function(data) {
						var availability = jQuery.parseJSON(data);
						if(availability)
						{
							if(availability.available)
							{
								if(!$('.available').length)
								{
									$("#group_cn_field").after('Group Available');
								}
								$('.not-available').remove();
							}
							else
							{
								$(".available").remove();
								if(!$('.not-available').length)
								{
									$("#group_cn_field").after('Group Not Available');
								}
							}
						}
					}
				});
			});
	}
}

//-----------------------------------------------------------

jQuery(document).ready(function($){
	HUB.Groups.initialize();
});

//-----------------------------------------------------------

jQuery(window).scroll(function($){
	HUB.Groups.scrollingAssetBrowser();
});<commit_msg>[COM_GROUPS] Fixed issue with IE not have window.console object.<commit_after>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2011 Purdue University. All rights reserved.
 * @license     http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

HUB.Groups = {
	jQuery: jq,

	initialize: function()
	{
		//
		HUB.Groups.membershipNotifications();

		//verify wanting to cancel from group
		HUB.Groups.confirmCancelMembership();

		//confirm messages
		HUB.Groups.confirmLeaveArea();

		//logo picker to show logo picked in preview
		HUB.Groups.customizePickLogo();

		//show or hide custom content box
		HUB.Groups.customizeOverviewContent();

		//group page preview in lightbox
		HUB.Groups.customizePreviewPage();

		//hide all empty paragraphs generated from wiki
		//HUB.Groups.fixEmptyParagraphs();

		//toggle between public and private group desc
		HUB.Groups.togglePublicPrivateDescription();

		//special groups
		HUB.Groups.specialGroups();

		//scrolling asset browser
		HUB.Groups.scrollingAssetBrowser();

		//group availablity checker
		HUB.Groups.groupIdAvailability();

		//group menu alert fixer
		HUB.Groups.groupMenuFix();
	},

	//-----

	groupMenuFix: function()
	{
		var $ = this.jQuery;

		$("#page_menu li").each(function(index){
			var meta = $(this).find(".meta"),
				metawidth = meta.outerWidth(true),
				alrt = $(this).find(".alrt");

			if(alrt.length)
			{
				if(metawidth > 20)
				{
					alrt.css("right", 33+(metawidth-20));
				}
				else if(metawidth < 20 && metawidth != 0)
				{
					alrt.css("right", 33-(20-metawidth));
				}
			}
		});
	},

	//-----

	membershipNotifications: function()
	{
		var $ = this.jQuery;

		var content = "",
			invites = $(".invites"),
			requests = $(".requests");

		if(invites.length)
		{
			invites.addClass("hide");
			content += invites.html();
		}

		if(requests.length)
		{
			requests.addClass("hide");
			content += requests.html();
		}

		if(content != "")
		{
			var timeout = setTimeout(function() {
				$.fancybox({
					autoSize:false,
					width: 600,
					height: 'auto',
					content: content,
					tpl: {
						wrap:'

'
					},
					beforeload: function() {
						invites.toggleClass("hide");
						requests.toggleClass("hide");
					}
				});
			}, 2000);
		}
	},

	//-----

	fixEmptyParagraphs: function()
	{
		var $ = this.jQuery;

		$('p').each(function(i, el) {
			var text = el.innerHTML;
			if(escape(text) == '%3Cbr%3E%0A' || text == "") {
				el.addClass('hide');
			}
		});
	},

	//-----

	togglePublicPrivateDescription: function()
	{
		var $ = this.jQuery;

		var publicDesc = $("#public"),
			privateDesc = $("#private"),
			toggleSwitch = $("#toggle_description");

		if(toggleSwitch.length)
		{
			toggleSwitch.removeClass('hide');

			toggleSwitch.bind("click", function(e) {
				e.preventDefault();

				if(publicDesc.hasClass("hide"))
				{
					toggleSwitch.html('Show Private Description (-)');
				}
				else
				{
					toggleSwitch.html('Show Public Description (+)');
				}

				publicDesc.toggleClass("hide");
				privateDesc.toggleClass("hide");
			});
		}
	},

	//-----

	confirmCancelMembership: function()
	{
		var $ = this.jQuery;

		$(".cancel_group_membership").live('click', function(e) {
			e.preventDefault();

			var answer = confirm('Are you sure you would like to cancel your group membership?');
			if(answer)
			{
				window.location = this.href;
			}
		});
	},

	//-----

	confirmLeaveArea: function()
	{
		var $ = this.jQuery;

		$('.leave_area').bind('click', function(e) {
			e.preventDefault();

			var question = $(this).attr('rel'),
				answer = confirm(question);

			if(answer) {
				window.location = this.href;
			}
		});
	},

	//-----

	customizePickLogo: function()
	{
		var $ = this.jQuery;

		var logo = "",
			logoSelecter = $("#group_logo");

		if(logoSelecter.length)
		{
			logoSelecter.bind("change", function(e) {

				if(this.value == "")
				{
					logo = '';
				}
				else
				{
					logo = '';
				}

				$("#logo_picked").html(logo)
			});
		}
	},

	//-----

	customizeOverviewContent: function()
	{
		var $ = this.jQuery;

		var overview = $('#overview_content'),
			customOverview = $('#group_overview_type_custom').attr("checked");

		if(overview.length)
		{
			if(!customOverview)
			{
				overview.addClass("hide-left");
			}

			$("input[type=radio]").bind("click", function(e){
				$('p.side-by-side').removeClass('checked');
				$(this).parents(".side-by-side").addClass("checked");
				if(this.value == 1)
				{
					overview.removeClass('hide-left');
				}
				else
				{
					overview.addClass('hide-left');
				}
			});
		}
	},

	//-----

	customizePreviewPage: function()
	{
		var $ = this.jQuery;

		$('.quick-view').fancybox({
			type: 'inline',
			width: 600,
			height: 'auto',
			autoSize: false,
			fitToView: false,
			titleShow: false
		});
	},

	//-----

	scrollingAssetBrowser: function()
	{
		var $ = this.jQuery;

		var topBox = $("#top_box"),
			bottomBox = $("#bottom_box"),
			assetBox = $("#asset_browser"),
			max = 0, pos = 0;

		assetBox
			.css('width', ($(assetBox.parent()).width() - 10) + 'px')
			.css('padding', '10px');

		if(assetBox.length)
		{
			if(topBox.length && bottomBox.length)
			{
				max = (bottomBox.position().top + bottomBox.outerHeight(true)) - assetBox.outerHeight(true);
				pos = $(document).scrollTop() - 200;

				if( pos > 0 && pos < max)
				{
					assetBox.stop().animate({
						"top": pos
					});
				}
			}
			else
			{
				if (window.console) console.log('Missing needed DOM elements to make assest browser scroll.');
			}
		}
	},

	//-----

	specialGroups: function()
	{
		var $ = this.jQuery;

		$("#special-group-tab").on("click", function(event){
			$("#special-group-pane").slideToggle('slow', function() {
				$("#special-group-tab").toggleClass('active');
			});
			event.preventDefault();
		});

		var wh = $(window).height(),
			ph = $("#page_container").height();
		if(ph < wh)
		{
			//$("#page_container").css("height", wh);
			//$("#page_container_inner").css("height", wh);
		}
	},

	//-----

	groupIdAvailability: function()
	{
		var $ = this.jQuery;
		$("#group_cn_field")
			.on("keydown", function(event) {
				$('.available, .not-available').remove();
			})
			.on("keyup", function(event) {
				$.ajax({
					url: 'index.php?option=com_groups&task=groupavailability&no_html=1',
					data: { 'group' : $(this).val() },
					success: function(data) {
						var availability = jQuery.parseJSON(data);
						if(availability)
						{
							if(availability.available)
							{
								if(!$('.available').length)
								{
									$("#group_cn_field").after('Group Available');
								}
								$('.not-available').remove();
							}
							else
							{
								$(".available").remove();
								if(!$('.not-available').length)
								{
									$("#group_cn_field").after('Group Not Available');
								}
							}
						}
					}
				});
			});
	}
}

//-----------------------------------------------------------

jQuery(document).ready(function($){
	HUB.Groups.initialize();
});

//-----------------------------------------------------------

jQuery(window).scroll(function($){
	HUB.Groups.scrollingAssetBrowser();
});<|endoftext|>


<commit_before>//Dependencies.
let assign = require('object-assign');
let keys = require('lodash/object/keys');
let {clone, isEqual} = require('lodash/lang');

const ALL = 'ALL';

let _buildPagination = (pageInfos) => {
    return {
        page: pageInfos.page || 0,
        skip: pageInfos.skip || 0
    }
};
let _buildOrderAndSort = (pageInfos) => {
    if (pageInfos.order) {
        let result = {};
        result.sortFieldName = pageInfos.order.key;
        if (pageInfos.order.order) {
            result.sortDesc = pageInfos.order.order.toLowerCase() === 'desc';
        }
        return result;
    } else {
        return {
            sortFieldName: '',
            sortDesc: false
        }
    }
};
let _buildFacets = (facets) => {
    return keys(facets).map((selectedFacetKey) => {
        let selectedFacet = facets[selectedFacetKey];
        return {
            key: selectedFacetKey,
            value: selectedFacet.key
        };
    });
};
let _parseUnscopedResponse = (data, context) => {
    return ({
        map: data.groups,
        facet: _parseFacets(data.facets),
        pageInfos: _parsePageInfos(data, context)
    });
};

let _parseScopedResponse = (data, context) => {
    return ({
        map: data.groups || {[context.scope]: data.list},
        facet: _parseFacets(data.facets),
        pageInfos: _parsePageInfos(data, context)
    });
};
let _parseFacets = (facets) => {
    return keys(facets).reduce((formattedFacets, serverFacetKey) => {
        let serverFacetData = facets[serverFacetKey];
        formattedFacets[serverFacetKey] = keys(serverFacetData).reduce((facetData, serverFacetItemKey) => {
            let serverFacetItemValue = serverFacetData[serverFacetItemKey];
            facetData[serverFacetItemKey] = {
                label: serverFacetItemKey,
                count: serverFacetItemValue
            };
            return facetData;
        }, {});
        return formattedFacets;
    }, {});
};

let _dispatchResult = (data) => {
    Focus.dispatcher.handleServerAction({
        data,
        type: 'update'
    });
};

let _parsePageInfos = (data, context) => {
    return {
        currentPage: context.page,
        perPage: 50,
        totalRecords: data.totalCount
    }
};

module.exports = function(config){
  /**
   * Builded search action.
   * @param  {object} options - The options used to build the service, it should have the following structure:
   * ```javascript
   * {
   * 	criteria:{
   * 		query: 'The query typed by the user'
   * 		scope: 'The selected scope'
   * 	},
   * 	pageInfos: { //All this informations will be use to transform the data given the query, this will be passed into the URL.
   * 		page: 'The wanted page',
   * 		skip: 'Number of results to skip',
   * 		sortBy: 'The information on wich the data is sorted', // This is **OPTIONAL**
   * 		sortAsc: 'Is the sort ascending or descending, boolean'
   * 	},
   * 	group: 'On which FACET should we group' // This is **OPTIONAL**
   * 	selectedFacets: 'An object with the selected facets', // This is **OPTIONAL**
   * 	previousData: 'An object chich contains the previous data' // This is **OPTIONAL**.
   * 							It will be used only when the action is triggered by a pagination action such as a scroll or a pagination.
   * 	service:{
   * 		scope: "function which launch the scope search"
   * 		unScope: "function whoch launch the unscoped search"
   * 	}
   * }
   * ```
   * @return {function} - The builded search action.
   */
  return function searchAction(options){
    options = options || {};
    let {scope, query} = options.criteria; //Cannot be read from the store ?
    if(scope === ALL){
      //Call the search action.
      options.service.scope(options);
    }else{
      //The component which call the serice should be know if it has all the data.
      if(options.previousData){ //Maybe rename pagination or something like that.
        options.service.unScope(options).then((response)=>{
            // Read the previous data from options.previous;
            return response;
        });
        //Read the totalCount

      }
      //The search is unscoped.

    }
  };
};
<commit_msg>[search action] Fix error between options and config<commit_after>//Dependencies.
let assign = require('object-assign');
let keys = require('lodash/object/keys');
let {clone, isEqual} = require('lodash/lang');

const ALL = 'ALL';

let _buildPagination = (pageInfos) => {
    return {
        page: pageInfos.page || 0,
        skip: pageInfos.skip || 0
    }
};
let _buildOrderAndSort = (pageInfos) => {
    if (pageInfos.order) {
        let result = {};
        result.sortFieldName = pageInfos.order.key;
        if (pageInfos.order.order) {
            result.sortDesc = pageInfos.order.order.toLowerCase() === 'desc';
        }
        return result;
    } else {
        return {
            sortFieldName: '',
            sortDesc: false
        }
    }
};
let _buildFacets = (facets) => {
    return keys(facets).map((selectedFacetKey) => {
        let selectedFacet = facets[selectedFacetKey];
        return {
            key: selectedFacetKey,
            value: selectedFacet.key
        };
    });
};
let _parseUnscopedResponse = (data, context) => {
    return ({
        map: data.groups,
        facet: _parseFacets(data.facets),
        pageInfos: _parsePageInfos(data, context)
    });
};

let _parseScopedResponse = (data, context) => {
    return ({
        map: data.groups || {[context.scope]: data.list},
        facet: _parseFacets(data.facets),
        pageInfos: _parsePageInfos(data, context)
    });
};
let _parseFacets = (facets) => {
    return keys(facets).reduce((formattedFacets, serverFacetKey) => {
        let serverFacetData = facets[serverFacetKey];
        formattedFacets[serverFacetKey] = keys(serverFacetData).reduce((facetData, serverFacetItemKey) => {
            let serverFacetItemValue = serverFacetData[serverFacetItemKey];
            facetData[serverFacetItemKey] = {
                label: serverFacetItemKey,
                count: serverFacetItemValue
            };
            return facetData;
        }, {});
        return formattedFacets;
    }, {});
};

let _dispatchResult = (data) => {
    Focus.dispatcher.handleServerAction({
        data,
        type: 'update'
    });
};

let _parsePageInfos = (data, context) => {
    return {
        currentPage: context.page,
        perPage: 50,
        totalRecords: data.totalCount
    }
};

module.exports = function(config){
  /**
   * Builded search action.
   * @param  {object} options - The options used to build the service, it should have the following structure:
   * ```javascript
   * {
   * 	criteria:{
   * 		query: 'The query typed by the user'
   * 		scope: 'The selected scope'
   * 	},
   * 	pageInfos: { //All this informations will be use to transform the data given the query, this will be passed into the URL.
   * 		page: 'The wanted page',
   * 		skip: 'Number of results to skip',
   * 		sortBy: 'The information on wich the data is sorted', // This is **OPTIONAL**
   * 		sortAsc: 'Is the sort ascending or descending, boolean'
   * 	},
   * 	group: 'On which FACET should we group' // This is **OPTIONAL**
   * 	selectedFacets: 'An object with the selected facets', // This is **OPTIONAL**
   * 	previousData: 'An object chich contains the previous data' // This is **OPTIONAL**.
   * 							It will be used only when the action is triggered by a pagination action such as a scroll or a pagination.
   * 	service:{
   * 		scope: "function which launch the scope search"
   * 		unScope: "function whoch launch the unscoped search"
   * 	}
   * }
   * ```
   * @return {function} - The builded search action.
   */
  return function searchAction(options){
    options = options || {};
    let {scope, query} = options.criteria; //Cannot be read from the store ?
    if(scope === ALL){
      //Call the search action.
      options.service.scope(options);
    }else{
      //The component which call the serice should be know if it has all the data.
      if(options.previousData){ //Maybe rename pagination or something like that.
        config.service.unScope(options).then((response)=>{
            // Read the previous data from options.previous;
            return response;
        });
        //Read the totalCount

      }
      //The search is unscoped.

    }
  };
};
<|endoftext|>


<commit_before>import React from 'react'

import md from 'components/md'
import CSS from './css'
import Keyframes from './keyframes'
import InjectGlobal from './inject-global'
import WithTheme from './with-theme'

const Helpers = () => md`
  <SectionLayout title="Helpers">
  ## Helpers

  ${<CSS />}

  ${<Keyframes />}

  ${<InjectGlobal />}

  ${<WithTheme />}
`

export default Helpers
<commit_msg>Fix api/helpers page<commit_after>import React from 'react'

import md from 'components/md'
import CSS from './css'
import Keyframes from './keyframes'
import InjectGlobal from './inject-global'
import WithTheme from './with-theme'

const Helpers = () => md`
  ## Helpers

  ${<CSS />}

  ${<Keyframes />}

  ${<InjectGlobal />}

  ${<WithTheme />}
`

export default Helpers
<|endoftext|>


<commit_before>/**

 Copyright 2015 Covistra Technologies Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
var _ = require('lodash');
var EE = require('eventemitter2').EventEmitter2;
var util = require('util');
var Path = require('path');
var requireDirectory = require('require-directory');
var P = require('bluebird');

module.exports = function(server, log, config) {

    var socketManager = server.plugins['covistra-socket'].socketManager;

    var Channel = require('./channel')(server, log, config);

    function ChannelManager() {
        this.channels = {};
        EE.call(this);

        // Register our messages in the underlying socket system
        socketManager.registerGlobalHandler('subscribe', this.onSubscribe, { scope: this });
        socketManager.registerGlobalHandler('unsubscribe', this.onUnsubscribe, { scope: this });
    }

    util.inherits(ChannelManager, EE);

    ChannelManager.prototype.onSubscribe = function(msg) {
        var _this = this;
        if(!_.isArray(msg.data)) {
            msg.data = [msg.data];
        }

        // Loop through each provided channel spec
        _.each(msg.data, function(channelKey) {
            var channel = _this.getChannel(channelKey);
            if(channel) {
                channel.subscribe(msg.context.client);
            }
        });

    };

    ChannelManager.prototype.onUnsubscribe = function(msg) {
        var _this = this;
        if(!_.isArray(msg.data)) {
            msg.data = [msg.data];
        }

        // Loop through each provided channel specs
        _.each(msg.data, function(channelKey) {
            var channel = _this.getChannel(channelKey);
            if(channel) {
                channel.unsubscribe(msg.context.client);
            }
        });

    };

    ChannelManager.prototype.openChannel = function(key, options) {
        log.debug("ChannelManager.openChannel", key);
        var channel = this.channels[key];
        if(!channel) {
            channel = new Channel(key, options);
            this.channels[key] = channel;
            this.emit('channel-opened', channel);
            return channel;
        }
        else {
            log.warn("Trying to create a channel with an existing key. Reusing existing channel");
            return channel;
        }
    };

    ChannelManager.prototype.closeChannel = function(key) {
        var channel = this.channels[key];
        if(channel) {
            delete this.channels[key];
            this.emit('channel-closed', channel);
        }
        else {
            log.error("Cannot close channel %s. Not found", key);
        }
    };

    ChannelManager.prototype.getChannel = function(key) {
        return this.channels[key];
    };

    ChannelManager.prototype.listChannels = function(options) {
        return _.values(this.channels);
    };

    ChannelManager.prototype.subscribe = function(channelKey, client) {
        var channel = this.channels[channelKey];
        if(channel) {
            return channel.subscribe(client);
        }
        else {
            throw new Error("unknown-channel:"+channelKey);
        }
    };

    ChannelManager.prototype.unsubscribe = function(channelKey, client) {
        var channel = this.channels[channelKey];
        if(channel) {
            return channel.unsubscribe(client);
        }
        else {
            throw new Error("unknown-channel:"+channelKey);
        }
    };

    ChannelManager.discover = P.method(function() {
        var _this = this;

        if(arguments.length > 1) {
            path = Array.prototype.slice.call(arguments).join("/");
        }
        else if(_.isArray(path)) {
            path = path.join("/");
        }

        log.debug("Registering all events located in path:", Path.resolve(path));
        return requireDirectory(module, Path.resolve(path), {
            visit: function(factory, filename) {
                log.trace("Loading event", filename);
                var event = factory(server, config, log);
                log.debug("Registering event on channel", event.channel);
                _this.subscribe(event.channel, event.handler);
            },
            include: /event\.js$/
        });

    });

    return new ChannelManager();
};
<commit_msg>Correct discover method declaration<commit_after>/**

 Copyright 2015 Covistra Technologies Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
var _ = require('lodash');
var EE = require('eventemitter2').EventEmitter2;
var util = require('util');
var Path = require('path');
var requireDirectory = require('require-directory');
var P = require('bluebird');

module.exports = function(server, log, config) {

    var socketManager = server.plugins['covistra-socket'].socketManager;

    var Channel = require('./channel')(server, log, config);

    function ChannelManager() {
        this.channels = {};
        EE.call(this);

        // Register our messages in the underlying socket system
        socketManager.registerGlobalHandler('subscribe', this.onSubscribe, { scope: this });
        socketManager.registerGlobalHandler('unsubscribe', this.onUnsubscribe, { scope: this });
    }

    util.inherits(ChannelManager, EE);

    ChannelManager.prototype.onSubscribe = function(msg) {
        var _this = this;
        if(!_.isArray(msg.data)) {
            msg.data = [msg.data];
        }

        // Loop through each provided channel spec
        _.each(msg.data, function(channelKey) {
            var channel = _this.getChannel(channelKey);
            if(channel) {
                channel.subscribe(msg.context.client);
            }
        });

    };

    ChannelManager.prototype.onUnsubscribe = function(msg) {
        var _this = this;
        if(!_.isArray(msg.data)) {
            msg.data = [msg.data];
        }

        // Loop through each provided channel specs
        _.each(msg.data, function(channelKey) {
            var channel = _this.getChannel(channelKey);
            if(channel) {
                channel.unsubscribe(msg.context.client);
            }
        });

    };

    ChannelManager.prototype.openChannel = function(key, options) {
        log.debug("ChannelManager.openChannel", key);
        var channel = this.channels[key];
        if(!channel) {
            channel = new Channel(key, options);
            this.channels[key] = channel;
            this.emit('channel-opened', channel);
            return channel;
        }
        else {
            log.warn("Trying to create a channel with an existing key. Reusing existing channel");
            return channel;
        }
    };

    ChannelManager.prototype.closeChannel = function(key) {
        var channel = this.channels[key];
        if(channel) {
            delete this.channels[key];
            this.emit('channel-closed', channel);
        }
        else {
            log.error("Cannot close channel %s. Not found", key);
        }
    };

    ChannelManager.prototype.getChannel = function(key) {
        return this.channels[key];
    };

    ChannelManager.prototype.listChannels = function(options) {
        return _.values(this.channels);
    };

    ChannelManager.prototype.subscribe = function(channelKey, client) {
        var channel = this.channels[channelKey];
        if(channel) {
            return channel.subscribe(client);
        }
        else {
            throw new Error("unknown-channel:"+channelKey);
        }
    };

    ChannelManager.prototype.unsubscribe = function(channelKey, client) {
        var channel = this.channels[channelKey];
        if(channel) {
            return channel.unsubscribe(client);
        }
        else {
            throw new Error("unknown-channel:"+channelKey);
        }
    };

    ChannelManager.prototype.discover = P.method(function() {
        var _this = this;

        if(arguments.length > 1) {
            path = Array.prototype.slice.call(arguments).join("/");
        }
        else if(_.isArray(path)) {
            path = path.join("/");
        }

        log.debug("Registering all events located in path:", Path.resolve(path));
        return requireDirectory(module, Path.resolve(path), {
            visit: function(factory, filename) {
                log.trace("Loading event", filename);
                var event = factory(server, config, log);
                log.debug("Registering event on channel", event.channel);
                _this.subscribe(event.channel, event.handler);
            },
            include: /event\.js$/
        });

    });

    return new ChannelManager();
};
<|endoftext|>


<commit_before>/* jshint esversion: 6 */
/* global process */
const Nacl = require('tweetnacl/nacl-fast');

// XXX npm "os" and "child_process"

// TODO if this process is using too much CPU, we can use "cluster" to add load balancing to this code
//console.log('New child process', process.pid);
process.on('message', function (data) {
    //console.log('In process', process.pid);
    //console.log(+new Date(), "Message received by subprocess");
    if (!data || !data.key || !data.msg || !data.txid) {
        return void process.send({
            error:'E_INVAL'
        });
    }
    const txid = data.txid;

    var signedMsg;
    try {
        signedMsg = Nacl.util.decodeBase64(data.msg);
    } catch (e) {
        return void process.send({
            txid: txid,
            error: 'E_BAD_MESSAGE',
        });
    }

    var validateKey;
    try {
        validateKey = Nacl.util.decodeBase64(data.key);
    } catch (e) {
        return void process.send({
            txid: txid,
            error:'E_BADKEY'
        });
    }
    // validate the message
    const validated = Nacl.sign.open(signedMsg, validateKey);
    if (!validated) {
        return void process.send({
            txid: txid,
            error:'FAILED'
        });
    }
    process.send({
        txid: txid,
    });
});
<commit_msg>remove an XXX<commit_after>/* jshint esversion: 6 */
/* global process */
const Nacl = require('tweetnacl/nacl-fast');

// TODO if this process is using too much CPU, we can use "cluster" to add load balancing to this code
//console.log('New child process', process.pid);
process.on('message', function (data) {
    //console.log('In process', process.pid);
    //console.log(+new Date(), "Message received by subprocess");
    if (!data || !data.key || !data.msg || !data.txid) {
        return void process.send({
            error:'E_INVAL'
        });
    }
    const txid = data.txid;

    var signedMsg;
    try {
        signedMsg = Nacl.util.decodeBase64(data.msg);
    } catch (e) {
        return void process.send({
            txid: txid,
            error: 'E_BAD_MESSAGE',
        });
    }

    var validateKey;
    try {
        validateKey = Nacl.util.decodeBase64(data.key);
    } catch (e) {
        return void process.send({
            txid: txid,
            error:'E_BADKEY'
        });
    }
    // validate the message
    const validated = Nacl.sign.open(signedMsg, validateKey);
    if (!validated) {
        return void process.send({
            txid: txid,
            error:'FAILED'
        });
    }
    process.send({
        txid: txid,
    });
});
<|endoftext|>


<commit_before>var express    = require('express');
var redis      = require('redis');
var request    = require('request');
var _          = require('underscore');
var config     = require('./server/config');
var Bitcoind   = require('./server/bitcoind');
var RedisDB    = require('./server/db/redis');
var sockjs     = require('sockjs');
var http       = require('http');
var https      = require('https');
var fs         = require('fs');

var server     = express();

var db = new RedisDB();
db.connect();

var bitcoind = new Bitcoind(config.bitcoind);

var listener = sockjs.createServer({log: function(severity, message) {}});

function listUnspent(addresses, callback) {
  bitcoind.rpc('listunspent', [0, 99999999999999, addresses], function(err, btcres) {
    if(err) {
      return callback(err);
    }

    var unspent = [];

    for(var i=0;i<btcres.length; i++) {
      unspent.push({
        hash:          btcres[i].txid,
        vout:          btcres[i].vout,
        address:       btcres[i].address,
        scriptPubKey:  btcres[i].scriptPubKey,
        amount:        btcres[i].amount,
        confirmations: btcres[i].confirmations
      });
    }

    callback(undefined, unspent);
  });
};

listener.on('connection', function(conn) {
    conn.on('data', function(message) {
      var req = JSON.parse(message);

      if(req.method == 'listUnspent')
        listUnspent(req.addresses, function(err, unspent) {
          if(err)
            conn.write(JSON.stringify(err));
          else
            conn.write(JSON.stringify({method: 'listUnspent', result: unspent}));
        });
    });
});

server.use(express.json());
server.use(express.urlencoded());
server.use(express.static('public'));
server.use(function(err, req, res, next){
  console.error(err.stack);
  res.send({error: true});
});

server.get('/api/wallet', function(req,res) {
  db.getWallet(req.query.serverKey, function(err, wallet) {
    if(wallet)
      return res.send({wallet: wallet});

    if(err)
      console.log("Wallet Get Error: "+err);

    res.send({result: 'error', message: 'Wallet not found'});
  });
});

server.post('/api/wallet/delete', function(req, res) {
  db.delete(req.body.serverKey, function(err, deleted) {
    if(deleted == true)
      res.send({result: 'success'});
    else
      res.send({result: 'notfound'});
  });
});

function saveWallet(req, res) {
  db.set(req.body.serverKey, req.body.payload, function(err, data) {
    if(err) {
      if(err == 'outOfSync') {
        return res.send({result: 'outOfSync', wallet: data.wallet});
      } else {
        return res.send(errorMessage("Database error: "+JSON.stringify(err)));
      }
    } else {
      res.send({result: 'ok'});
    }
  });
};

function saveWalletAndAddresses(req, res) {
  if(req.body.address) {
    bitcoind.rpc('importaddress', [req.body.address, req.body.serverKey, false], function(err, btcres) {
      if(err)
        return res.send({messages: [err.message]});

      saveWallet(req, res);
    });
  } else if(req.body.importAddresses) {
    var batch = [];

    for(var i=0;i<req.body.importAddresses.length;i++)
      batch.push({method: 'importaddress', params: [req.body.importAddresses[i], req.body.serverKey, true], id: i});

    bitcoind.batch(batch, function(err, btcres) {
      if(err)
        return btcres.send({messages: [err.message]});

      saveWallet(req, res);
    });
  } else {
    saveWallet(req, res);
  }
}

function registerAddresses(addresses, callback) {
  var isNew = false;

  if(typeof addresses == 'string') {
    isNew = true;
    var addresses = [addresses];
  }

  bitcoind.rpc('importaddress', [addresses, null, isNew], function(err, btcres) {
    if(err)
      return callback(err.message);

    callback(null, true)
  });
}

function errorResponse(errors) {
  if(typeof errors == 'string')
    errors = [errors];
  return {messages: errors};
}

server.post('/api/wallet', function(req,res) {
  db.getWallet(req.body.serverKey, function(err, wallet) {
    if(err) {
      console.log('Database error: '+err);
      return res.send(errorResponse('There was a server error, please try again later.'));
    }

    // New wallet
    if(!req.body.override) {
      if(wallet)
        return res.send({result: 'exists', wallet: wallet});

      if(req.body.payload.email != undefined)
        db.checkEmailExists(req.body.payload.email, function(err, response) {
          if(response == true)
            return res.send({result: 'error', messages: ['Email address already exists']});
          else
            return saveWalletAndAddresses(req, res);
        });
    }

    return saveWalletAndAddresses(req, res);
  });
});

server.get('/api/weighted_prices', function(req, res) {
  /*
    For testing offline:
    res.send([{code: 'USD', rate: 40.00}]);
    return;
  */
  try {
    request({uri: config.pricesUrl, method: 'GET'}, function (error, pricesResponse, body) {
      if (!error && pricesResponse.statusCode == 200) {
        res.send(JSON.parse(body));
      } else {
        res.send({error: 'cannot connect to the weighted prices API'});
      }
      return;
    });
  } catch(err)  {
    console.log(err);
    res.send({error: 'cannot connect to the weighted prices API'});
  }
});

server.post('/api/tx/unspent', function(req,res) {
  listUnspent(req.body.addresses, function(err, unspent) {
    if(err)
      return res.send({error: 'bitcoinNode'});

    res.send({unspent: unspent});
  });
});

server.post('/api/tx/details', function(req,res) {
  var i = 0;
  var queries = [];

  if(!req.body.txHashes) {
    res.send([]);
    return;
  }

  for(i=0;i<req.body.txHashes.length;i++) {
    queries.push({method: 'gettransaction', params: [req.body.txHashes[i]]});
  }

  bitcoind.batch(queries, function(err, results) {
    if(err) console.log(err);
    var txes = _.map(results, function(result) {
      result = result.result;
      return {
        hash: result.txid,
        time: result.time,
        amount: result.amount,
        fee: result.fee,
        confirmations: result.confirmations,
        blockhash: result.blockhash,
        blockindex: result.blockindex,
        blocktime: result.blocktime
      };
    });

    res.send(txes);
  });
});

server.post('/api/tx/send', function(req, res) {
  bitcoind.rpc('sendrawtransaction', [req.body.tx], function(err, btcres) {
    if(err)
      return res.send({messages: ['Bitcoind error: '+err]});
    res.send({hash: btcres});
  });
});

if(config.httpsPort || config.sslKey || config.sslCert) {
  var httpsServer = https.createServer({
    key: fs.readFileSync(config.sslKey, 'utf8'),
    cert: fs.readFileSync(config.sslCert, 'utf8')
  }, server);

  listener.installHandlers(httpsServer, {prefix:'/listener'});
  module.exports.httpsServer = httpsServer;

  module.exports.httpServer = http.createServer(function(req, res) {
    var host = req.headers.host;
    if(typeof host == "undefined")
      return res.end();
    res.statusCode = 302;
    var host = req.headers.host;
    var hostname = host.match(/:/g) ? host.slice(0, host.indexOf(":")) : host;
    res.setHeader('Location', 'https://'+hostname+':'+config.httpsPort+'/');
    res.end();
  });
} else {
  console.log('Warning: You are not running in SSL mode!');

  var httpServer = http.createServer(server);
  listener.installHandlers(httpServer, {prefix:'/listener'});
  module.exports.httpServer = httpServer;
}

module.exports.config = config;
module.exports.server = server;<commit_msg>fix bug for missing tx<commit_after>var express    = require('express');
var redis      = require('redis');
var request    = require('request');
var _          = require('underscore');
var config     = require('./server/config');
var Bitcoind   = require('./server/bitcoind');
var RedisDB    = require('./server/db/redis');
var sockjs     = require('sockjs');
var http       = require('http');
var https      = require('https');
var fs         = require('fs');

var server     = express();

var db = new RedisDB();
db.connect();

var bitcoind = new Bitcoind(config.bitcoind);

var listener = sockjs.createServer({log: function(severity, message) {}});

function listUnspent(addresses, callback) {
  bitcoind.rpc('listunspent', [0, 99999999999999, addresses], function(err, btcres) {
    if(err) {
      return callback(err);
    }

    var unspent = [];

    for(var i=0;i<btcres.length; i++) {
      unspent.push({
        hash:          btcres[i].txid,
        vout:          btcres[i].vout,
        address:       btcres[i].address,
        scriptPubKey:  btcres[i].scriptPubKey,
        amount:        btcres[i].amount,
        confirmations: btcres[i].confirmations
      });
    }

    callback(undefined, unspent);
  });
};

listener.on('connection', function(conn) {
    conn.on('data', function(message) {
      var req = JSON.parse(message);

      if(req.method == 'listUnspent')
        listUnspent(req.addresses, function(err, unspent) {
          if(err)
            conn.write(JSON.stringify(err));
          else
            conn.write(JSON.stringify({method: 'listUnspent', result: unspent}));
        });
    });
});

server.use(express.json());
server.use(express.urlencoded());
server.use(express.static('public'));
server.use(function(err, req, res, next){
  console.error(err.stack);
  res.send({error: true});
});

server.get('/api/wallet', function(req,res) {
  db.getWallet(req.query.serverKey, function(err, wallet) {
    if(wallet)
      return res.send({wallet: wallet});

    if(err)
      console.log("Wallet Get Error: "+err);

    res.send({result: 'error', message: 'Wallet not found'});
  });
});

server.post('/api/wallet/delete', function(req, res) {
  db.delete(req.body.serverKey, function(err, deleted) {
    if(deleted == true)
      res.send({result: 'success'});
    else
      res.send({result: 'notfound'});
  });
});

function saveWallet(req, res) {
  db.set(req.body.serverKey, req.body.payload, function(err, data) {
    if(err) {
      if(err == 'outOfSync') {
        return res.send({result: 'outOfSync', wallet: data.wallet});
      } else {
        return res.send(errorMessage("Database error: "+JSON.stringify(err)));
      }
    } else {
      res.send({result: 'ok'});
    }
  });
};

function saveWalletAndAddresses(req, res) {
  if(req.body.address) {
    bitcoind.rpc('importaddress', [req.body.address, req.body.serverKey, false], function(err, btcres) {
      if(err)
        return res.send({messages: [err.message]});

      saveWallet(req, res);
    });
  } else if(req.body.importAddresses) {
    var batch = [];

    for(var i=0;i<req.body.importAddresses.length;i++)
      batch.push({method: 'importaddress', params: [req.body.importAddresses[i], req.body.serverKey, true], id: i});

    bitcoind.batch(batch, function(err, btcres) {
      if(err)
        return btcres.send({messages: [err.message]});

      saveWallet(req, res);
    });
  } else {
    saveWallet(req, res);
  }
}

function registerAddresses(addresses, callback) {
  var isNew = false;

  if(typeof addresses == 'string') {
    isNew = true;
    var addresses = [addresses];
  }

  bitcoind.rpc('importaddress', [addresses, null, isNew], function(err, btcres) {
    if(err)
      return callback(err.message);

    callback(null, true)
  });
}

function errorResponse(errors) {
  if(typeof errors == 'string')
    errors = [errors];
  return {messages: errors};
}

server.post('/api/wallet', function(req,res) {
  db.getWallet(req.body.serverKey, function(err, wallet) {
    if(err) {
      console.log('Database error: '+err);
      return res.send(errorResponse('There was a server error, please try again later.'));
    }

    // New wallet
    if(!req.body.override) {
      if(wallet)
        return res.send({result: 'exists', wallet: wallet});

      if(req.body.payload.email != undefined)
        db.checkEmailExists(req.body.payload.email, function(err, response) {
          if(response == true)
            return res.send({result: 'error', messages: ['Email address already exists']});
          else
            return saveWalletAndAddresses(req, res);
        });
    }

    return saveWalletAndAddresses(req, res);
  });
});

server.get('/api/weighted_prices', function(req, res) {
  /*
    For testing offline:
    res.send([{code: 'USD', rate: 40.00}]);
    return;
  */
  try {
    request({uri: config.pricesUrl, method: 'GET'}, function (error, pricesResponse, body) {
      if (!error && pricesResponse.statusCode == 200) {
        res.send(JSON.parse(body));
      } else {
        res.send({error: 'cannot connect to the weighted prices API'});
      }
      return;
    });
  } catch(err)  {
    console.log(err);
    res.send({error: 'cannot connect to the weighted prices API'});
  }
});

server.post('/api/tx/unspent', function(req,res) {
  listUnspent(req.body.addresses, function(err, unspent) {
    if(err)
      return res.send({error: 'bitcoinNode'});

    res.send({unspent: unspent});
  });
});

server.post('/api/tx/details', function(req,res) {
  var i = 0;
  var queries = [];

  if(!req.body.txHashes) {
    res.send([]);
    return;
  }

  for(i=0;i<req.body.txHashes.length;i++) {
    queries.push({method: 'gettransaction', params: [req.body.txHashes[i]]});
  }

  bitcoind.batch(queries, function(err, results) {
    if(err) console.log(err);

    var txes = [];

    for(var i=0; i<results.length;i++) {
      var result = results[i].result;
      if(result == null)
        continue;

      txes.push({
        hash: result.txid,
        time: result.time,
        amount: result.amount,
        fee: result.fee,
        confirmations: result.confirmations,
        blockhash: result.blockhash,
        blockindex: result.blockindex,
        blocktime: result.blocktime
      });
    }

    res.send(txes);
  });
});

server.post('/api/tx/send', function(req, res) {
  bitcoind.rpc('sendrawtransaction', [req.body.tx], function(err, btcres) {
    if(err)
      return res.send({messages: ['Bitcoind error: '+err]});
    res.send({hash: btcres});
  });
});

if(config.httpsPort || config.sslKey || config.sslCert) {
  var httpsServer = https.createServer({
    key: fs.readFileSync(config.sslKey, 'utf8'),
    cert: fs.readFileSync(config.sslCert, 'utf8')
  }, server);

  listener.installHandlers(httpsServer, {prefix:'/listener'});
  module.exports.httpsServer = httpsServer;

  module.exports.httpServer = http.createServer(function(req, res) {
    var host = req.headers.host;
    if(typeof host == "undefined")
      return res.end();
    res.statusCode = 302;
    var host = req.headers.host;
    var hostname = host.match(/:/g) ? host.slice(0, host.indexOf(":")) : host;
    res.setHeader('Location', 'https://'+hostname+':'+config.httpsPort+'/');
    res.end();
  });
} else {
  console.log('Warning: You are not running in SSL mode!');

  var httpServer = http.createServer(server);
  listener.installHandlers(httpServer, {prefix:'/listener'});
  module.exports.httpServer = httpServer;
}

module.exports.config = config;
module.exports.server = server;<|endoftext|>


<commit_before>'use strict';

var adduser   = module.exports = {};
var asks      = require('asks');
var lang      = require('../util/lang');

var REGEX_IS_EMAIL = /^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+\/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i;

var PROMPT_SCHEMAS = [{
  name: 'username',
  type: 'input',
  message: 'username',
  validate: function(username) {
    var done = this.async();

    if (username.toLowerCase() !== username) {
      return done('username must be lowercase.');
    }

    if (~encodeURIComponent(username).indexOf("%")) {
      return done('username cannot contain any non-urlsafe characters.')
    }

    done(true);
  }
}, {
  name: 'password',
  type: 'password',
  message: 'password',
  validate: function(password) {
    var done = this.async();

    if (!password) {
      return done('password is required');
    }

    done(true);
  }
}, {
  name: 'email',
  type: 'input',
  message: 'email',
  validate: function(email) {
    var done = this.async();

    if (!email) {
      return done('email is required');
    }

    if (!REGEX_IS_EMAIL.test(email)) {
      return done('invalid email.')
    }

    done(true);
  }
}];

function simple_clone(obj) {
  var ret = {};
  var key;

  for (key in obj) {
    ret[key] = obj[key];
  }

  return ret;
}

// 1. new user
// username:
// password:

// 2. change password
// password:

// @param {Object} options
// - username: {string=}
// - password: {string=}
adduser.run = function(options, callback) {

  // If the command 'adduser' is called from the restful service, username and password must be specified
  if (options._http) {
    if (!options.username || !options.password) {
      return callback('username or password is not specified.');
    }
  }

  var schemas = [];
  var defaults = {};
  var skipped = {};

  var profile = this.profile;

  PROMPT_SCHEMAS.forEach(function(schema) {
    var key = schema.name;

    // get the existing user info from config
    var saved = profile.get(key);

    if (saved) {
      schema.default = saved;
    }

    // store the saved
    defaults[key] = saved;

    // If process.argv already contains a certain key, skip it
    if (options[key]) {
      skipped[key] = options[key];
      return;
    }

    schema = simple_clone(schema);

    schemas.push(schema);
  });

  var self = this;

  asks.prompt(schemas, function(result) {
    lang.mix(result, skipped, false);

    // if the username to add is different from the current username, `signup`
    if (
      options.signup ||
      result.username !== defaults.username ||
      result.password !== defaults.password
    ) {
      result.signup = true;
    }

    result = defaults;

    self.add(result, callback);
  });
};

// @param {Object} options
// - username
// - email
// - password
// - signup
adduser.add = function(options, callback) {
  var neuropil = this.neuropil;

  this.logger.info('{{cyan Add user}} ...');

  var self = this;
  neuropil.adduser(options, function(err, res, json) {
    if (err) {
      return callback(err, res, json);
    }

    var profile = self.profile;
    PROMPT_SCHEMAS.forEach(function(schema) {
      var key = schema.name;
      profile.set(key, options[key]);
    });

    // encrypt and hash password and username
    profile.encrypt();
    callback(err, res, json);
  });
};<commit_msg>command/adduser: fixes old errors; #364<commit_after>'use strict';

var adduser   = module.exports = {};
var asks      = require('asks');
var lang      = require('../util/lang');

var REGEX_IS_EMAIL = /^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+\/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i;

var PROMPT_SCHEMAS = [{
  name: 'username',
  type: 'input',
  message: 'username',
  validate: function(username) {
    var done = this.async();

    if (username.toLowerCase() !== username) {
      return done('username must be lowercase.');
    }

    if (~encodeURIComponent(username).indexOf("%")) {
      return done('username cannot contain any non-urlsafe characters.')
    }

    done(true);
  }
}, {
  name: 'password',
  type: 'password',
  message: 'password',
  validate: function(password) {
    var done = this.async();

    if (!password) {
      return done('password is required');
    }

    done(true);
  }
}, {
  name: 'email',
  type: 'input',
  message: 'email',
  validate: function(email) {
    var done = this.async();

    if (!email) {
      return done('email is required');
    }

    if (!REGEX_IS_EMAIL.test(email)) {
      return done('invalid email.')
    }

    done(true);
  }
}];

function simple_clone(obj) {
  var ret = {};
  var key;

  for (key in obj) {
    ret[key] = obj[key];
  }

  return ret;
}

// 1. new user
// username:
// password:

// 2. change password
// password:

// @param {Object} options
// - username: {string=}
// - password: {string=}
adduser.run = function(options, callback) {

  // If the command 'adduser' is called from the restful service, username and password must be specified
  if (options._http) {
    if (!options.username || !options.password) {
      return callback('username or password is not specified.');
    }
  }

  var schemas = [];
  var defaults = {};
  var skipped = {};

  var profile = this.profile;

  PROMPT_SCHEMAS.forEach(function(schema) {
    var key = schema.name;

    // get the existing user info from config
    var saved = profile.get(key);

    if (saved) {
      schema.default = saved;
    }

    // store the saved
    defaults[key] = saved;

    // If process.argv already contains a certain key, skip it
    if (options[key]) {
      skipped[key] = options[key];
      return;
    }

    schema = simple_clone(schema);

    schemas.push(schema);
  });

  var self = this;

  asks.prompt(schemas, function(result) {
    lang.mix(result, skipped, false);

    // if the username to add is different from the current username, `signup`
    if (
      options.signup ||
      result.username !== defaults.username ||
      result.password !== defaults.password
    ) {
      result.signup = true;
    }

    self.add(result, callback);
  });
};

// @param {Object} options
// - username
// - email
// - password
// - signup
adduser.add = function(options, callback) {
  var neuropil = this.neuropil;

  this.logger.info('{{cyan Add user}} ...');

  var self = this;
  neuropil.adduser(options, function(err, res, json) {
    if (err) {
      return callback(err, res, json);
    }

    var profile = self.profile;
    PROMPT_SCHEMAS.forEach(function(schema) {
      var key = schema.name;
      profile.set(key, options[key]);
    });

    // encrypt and hash password and username
    profile.encrypt();
    callback(err, res, json);
  });
};<|endoftext|>