<commit_before>/*
 * RailsAdmin filtering select @VERSION
 *
 * Based on the combobox example from jQuery UI documentation
 * http://jqueryui.com/demos/autocomplete/#combobox
 *
 * License
 *
 * http://www.railsadmin.org
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.ui.autocomplete.js
 */
(function ($) {
    $.widget &&
    $.widget("ra.filteringSelect", {
        options: {
            createQuery: function (query) {
                return {query: query};
            },
            minLength: 0,
            searchDelay: 200,
            remote_source: null,
            source: null,
            xhr: false
        },

        _create: function () {
            var self = this,
                select = this.element.hide(),
                selected = select.children(":selected"),
                value = selected.val() ? selected.text() : "";

            if (this.options.xhr) {
                this.options.source = this.options.remote_source;
            } else {
                this.options.source = select.children("option").map(function () {
                    return {label: $(this).text(), value: this.value};
                }).toArray();
            }
            var filtering_select = $('

')
            var input = this.input = $('<input type="text">')
                .val(value)
                .addClass("form-control ra-filtering-select-input")
                .attr('style', select.attr('style'))
                .show()
                .autocomplete({
                    delay: this.options.searchDelay,
                    minLength: this.options.minLength,
                    source: this._getSourceFunction(this.options.source),
                    select: function (event, ui) {
                        var option = $('<option></option>').attr('value', ui.item.id).attr('selected', 'selected').text(ui.item.value);
                        select.html(option);
                        select.trigger("change", ui.item.id);
                        self._trigger("selected", event, {
                            item: option
                        });
                        $(self.element.parents('.controls')[0]).find('.update').removeClass('disabled');
                    },
                    change: function (event, ui) {
                        if (!ui.item) {
                            var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
                                valid = false;
                            select.children("option").each(function () {
                                if ($(this).text().match(matcher)) {
                                    this.selected = valid = true;
                                    return false;
                                }
                            });
                            if (!valid || $(this).val() == '') {
                                //Patch for enum_edit
                                if (select.attr('data-enum_edit')) {
                                    var option = $('<option></option>').attr('value', event.currentTarget.value).attr('selected', 'selected').text(event.currentTarget.value);
                                    select.html(option);
                                }
                                else {
                                    //remove invalid value, as it didn't match anything
                                    $(this).val(null);
                                    select.html($('<option value="" selected="selected"></option>'));
                                    input.data("ui-autocomplete").term = "";
                                    $(self.element.parents('.controls')[0]).find('.update').addClass('disabled');
                                }
                                return false;
                            }
                        }
                    }
                })
                .keyup(function () {
                    /* Clear select options and trigger change if selected item is deleted */
                    if ($(this).val().length == 0) {
                        select.html($('<option value="" selected="selected"></option>'));
                        select.trigger("change");
                    }
                })

            if (select.attr('placeholder'))
                input.attr('placeholder', select.attr('placeholder'))

            input.data("ui-autocomplete")._renderItem = function (ul, item) {
                return $("

")
                    .data("ui-autocomplete-item", item)
                    .append($("").html(item.html || item.id))
                    .appendTo(ul);
            };

            var button = this.button = $(' ')
                .click(function () {
                    if (select.prop('disabled')) return;
                    // close if already visible
                    if (input.autocomplete("widget").is(":visible")) {
                        input.autocomplete("close");
                        return;
                    }

                    // pass empty string as value to search for, displaying all results
                    input.autocomplete("search", "");
                    input.focus();
                });

            filtering_select.append(input).append(button).insertAfter(select);

            select.on('disabled', function (e) {
                input.prop('disabled', true);
                button.find('button').prop('disabled', true);
            });
            select.on('enabled', function (e) {
                input.prop('disabled', false);
                button.find('button').prop('disabled', false);
            });
        },

        _getResultSet: function (request, data, xhr) {
            var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
            var highlighter = function (label, word) {
                if (word.length > 0) {
                    return $.map(label.split(word), function (el, i) {
                        return $('').text(el).html();
                    }).join($('').text(word)[0].outerHTML);
                } else {
                    return $('').text(label).html();
                }
            };

            return $.map(data, function (el, i) {
                // match regexp only for local requests, remote ones are already filtered, and label may not contain filtered term.
                if ((el.id || el.value) && (xhr || matcher.test(el.label))) {
                    return {
                        html: highlighter(el.label || el.id, request.term),
                        value: el.label || el.id,
                        id: el.id || el.value
                    };
                }
            });
        },

        _getSourceFunction: function (source) {

            var self = this,
                requestIndex = 0;

            if ($.isArray(source)) {

                return function (request, response) {
                    response(self._getResultSet(request, source, false));
                };

            } else if (typeof source === "string") {

                return function (request, response) {

                    if (this.xhr) {
                        this.xhr.abort();
                    }

                    this.xhr = $.ajax({
                        url: source,
                        data: self.options.createQuery(request.term),
                        dataType: "json",
                        autocompleteRequest: ++requestIndex,
                        select: null,
                        get_ui_widget: function () {
                            var ui = null, $label, $icon, $siblings,
                                id = this.url.match(/source_object_id=(.+)&/)[1];
                            $('select[data-options]').each(function (index) {
                                if ($(this).data('options').remote_source.match(id).length > 0) {
                                    ui = $(this);
                                }
                            });
                            $siblings = ui.siblings();
                            $label = $siblings.find('label.btn');
                            $icon = $siblings.find('label.btn span:first');
                            return {label: $label, icon: $icon};
                        },
                        beforeSend: function () {
                            var select = this.select = this.get_ui_widget();
                            if (select) {
                                select.label.removeClass('btn-danger').addClass('btn-info');
                                select.icon.removeClass().addClass('fa fa-spinner fa-spin');
                            }
                            console.log('Before init the request');
                        },
                        success: function (data, status) {
                            var select = this.select;
                            if (this.autocompleteRequest === requestIndex) {
                                response(self._getResultSet(request, data, true));

                            }
                            if (select) {
                                select.label.removeClass('btn-danger').addClass('btn-info');
                                select.icon.removeClass().addClass('caret');
                            }
                            console.log('Completed the request');
                        },
                        error: function () {
                            var select = this.select;
                            if (this.autocompleteRequest === requestIndex) {
                                response([]);
                            }
                            if (select) {
                                select.label.removeClass('btn-info').addClass('btn-danger');
                                select.icon.removeClass().addClass('fa fa-times');
                            }
                            console.log('An error happened with the request');
                        }
                    });
                };

            } else {

                return source;
            }
        },

        destroy: function () {
            this.input.remove();
            this.button.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);
<commit_msg>Fixed bug at request status indicator to filtered select<commit_after>/*
 * RailsAdmin filtering select @VERSION
 *
 * Based on the combobox example from jQuery UI documentation
 * http://jqueryui.com/demos/autocomplete/#combobox
 *
 * License
 *
 * http://www.railsadmin.org
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.ui.autocomplete.js
 */
(function ($) {
    $.widget &&
    $.widget("ra.filteringSelect", {
        options: {
            createQuery: function (query) {
                return {query: query};
            },
            minLength: 0,
            searchDelay: 200,
            remote_source: null,
            source: null,
            xhr: false
        },

        _create: function () {
            var self = this,
                select = this.element.hide(),
                selected = select.children(":selected"),
                value = selected.val() ? selected.text() : "";

            if (this.options.xhr) {
                this.options.source = this.options.remote_source;
            } else {
                this.options.source = select.children("option").map(function () {
                    return {label: $(this).text(), value: this.value};
                }).toArray();
            }
            var filtering_select = $('

')
            var input = this.input = $('<input type="text">')
                .val(value)
                .addClass("form-control ra-filtering-select-input")
                .attr('style', select.attr('style'))
                .show()
                .autocomplete({
                    delay: this.options.searchDelay,
                    minLength: this.options.minLength,
                    source: this._getSourceFunction(this.options.source),
                    select: function (event, ui) {
                        var option = $('<option></option>').attr('value', ui.item.id).attr('selected', 'selected').text(ui.item.value);
                        select.html(option);
                        select.trigger("change", ui.item.id);
                        self._trigger("selected", event, {
                            item: option
                        });
                        $(self.element.parents('.controls')[0]).find('.update').removeClass('disabled');
                    },
                    change: function (event, ui) {
                        if (!ui.item) {
                            var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
                                valid = false;
                            select.children("option").each(function () {
                                if ($(this).text().match(matcher)) {
                                    this.selected = valid = true;
                                    return false;
                                }
                            });
                            if (!valid || $(this).val() == '') {
                                //Patch for enum_edit
                                if (select.attr('data-enum_edit')) {
                                    var option = $('<option></option>').attr('value', event.currentTarget.value).attr('selected', 'selected').text(event.currentTarget.value);
                                    select.html(option);
                                }
                                else {
                                    //remove invalid value, as it didn't match anything
                                    $(this).val(null);
                                    select.html($('<option value="" selected="selected"></option>'));
                                    input.data("ui-autocomplete").term = "";
                                    $(self.element.parents('.controls')[0]).find('.update').addClass('disabled');
                                }
                                return false;
                            }
                        }
                    }
                })
                .keyup(function () {
                    /* Clear select options and trigger change if selected item is deleted */
                    if ($(this).val().length == 0) {
                        select.html($('<option value="" selected="selected"></option>'));
                        select.trigger("change");
                    }
                })

            if (select.attr('placeholder'))
                input.attr('placeholder', select.attr('placeholder'))

            input.data("ui-autocomplete")._renderItem = function (ul, item) {
                return $("

")
                    .data("ui-autocomplete-item", item)
                    .append($("").html(item.html || item.id))
                    .appendTo(ul);
            };

            var button = this.button = $(' ')
                .click(function () {
                    if (select.prop('disabled')) return;
                    // close if already visible
                    if (input.autocomplete("widget").is(":visible")) {
                        input.autocomplete("close");
                        return;
                    }

                    // pass empty string as value to search for, displaying all results
                    input.autocomplete("search", "");
                    input.focus();
                });

            filtering_select.append(input).append(button).insertAfter(select);

            select.on('disabled', function (e) {
                input.prop('disabled', true);
                button.find('button').prop('disabled', true);
            });
            select.on('enabled', function (e) {
                input.prop('disabled', false);
                button.find('button').prop('disabled', false);
            });
        },

        _getResultSet: function (request, data, xhr) {
            var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
            var highlighter = function (label, word) {
                if (word.length > 0) {
                    return $.map(label.split(word), function (el, i) {
                        return $('').text(el).html();
                    }).join($('').text(word)[0].outerHTML);
                } else {
                    return $('').text(label).html();
                }
            };

            return $.map(data, function (el, i) {
                // match regexp only for local requests, remote ones are already filtered, and label may not contain filtered term.
                if ((el.id || el.value) && (xhr || matcher.test(el.label))) {
                    return {
                        html: highlighter(el.label || el.id, request.term),
                        value: el.label || el.id,
                        id: el.id || el.value
                    };
                }
            });
        },

        _getSourceFunction: function (source) {

            var self = this,
                requestIndex = 0;

            if ($.isArray(source)) {

                return function (request, response) {
                    response(self._getResultSet(request, source, false));
                };

            } else if (typeof source === "string") {

                return function (request, response) {

                    if (this.xhr) {
                        this.xhr.abort();
                    }

                    this.xhr = $.ajax({
                        url: source,
                        data: self.options.createQuery(request.term),
                        dataType: "json",
                        autocompleteRequest: ++requestIndex,
                        select: null,
                        get_ui_widget: function () {
                            var ui = null, $label, $icon, $siblings,
                                id = this.url.match(/source_object_id=(.+)&/)[1],
                                field = this.url.match(/\/(.+)\?/)[1];

                            $('select[data-options]').each(function (index) {
                                if ($(this).data('options').remote_source.match(id)) {
                                    if ($(this).data('options').remote_source.match(field)) {
                                        ui = $(this);
                                        return false;
                                    }
                                }
                            });
                            $siblings = ui.siblings();
                            $label = $siblings.find('label.btn');
                            $icon = $siblings.find('label.btn span:first');
                            return {label: $label, icon: $icon};
                        },
                        beforeSend: function () {
                            var select = this.select = this.get_ui_widget();
                            if (select) {
                                select.label.removeClass('btn-danger').addClass('btn-info');
                                select.icon.removeClass().addClass('fa fa-spinner fa-spin');
                            }
                            console.log('Before init the request');
                        },
                        success: function (data, status) {
                            var select = this.select;
                            if (this.autocompleteRequest === requestIndex) {
                                response(self._getResultSet(request, data, true));

                            }
                            if (select) {
                                select.label.removeClass('btn-danger').addClass('btn-info');
                                select.icon.removeClass().addClass('caret');
                            }
                            console.log('Completed the request');
                        },
                        error: function () {
                            var select = this.select;
                            if (this.autocompleteRequest === requestIndex) {
                                response([]);
                            }
                            if (select) {
                                select.label.removeClass('btn-info').addClass('btn-danger');
                                select.icon.removeClass().addClass('fa fa-times');
                            }
                            console.log('An error happened with the request');
                        }
                    });
                };

            } else {

                return source;
            }
        },

        destroy: function () {
            this.input.remove();
            this.button.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * View for a back button.
 *
 * @author Andrey Zelenkov (Mlearner)
 */

define( function( require ) {
  "use strict";

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var YellowButton = require( 'FRACTION_MATCHER/view/YellowButton' );
  var Image = require( 'SCENERY/nodes/Image' );

  var backImage = require( 'image!FRACTION_MATCHER/images/back-button.png' );

  function BackButton( options, callback ) {
    Node.call( this, options );

    this.addChild( new YellowButton( {
      labelWidth: backImage.width,
      labelHeight: backImage.height,
      label: new Image( backImage ),
      callback: callback
    } ) );
  }

  return inherit( Node, BackButton );
} );
<commit_msg>added // images comment for require statement<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * View for a back button.
 *
 * @author Andrey Zelenkov (Mlearner)
 */

define( function( require ) {
  "use strict";

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var YellowButton = require( 'FRACTION_MATCHER/view/YellowButton' );
  var Image = require( 'SCENERY/nodes/Image' );

  // images
  var backImage = require( 'image!FRACTION_MATCHER/images/back-button.png' );

  function BackButton( options, callback ) {
    Node.call( this, options );

    this.addChild( new YellowButton( {
      labelWidth: backImage.width,
      labelHeight: backImage.height,
      label: new Image( backImage ),
      callback: callback
    } ) );
  }

  return inherit( Node, BackButton );
} );
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Relay from 'react-relay';

import TypedTransition from '../core/TypedTransition';

import Title from '../components/Title';
import PhoneList from '../components/PhoneList';
import AddModal from '../components/AddModal';
import EditModal from '../components/EditModal';

import AddPhoneMutation from '../mutations/AddPhoneMutation';
import RemovePhoneMutation from '../mutations/RemovePhoneMutation';
import UpdatePhoneMutation from '../mutations/UpdatePhoneMutation';

class PhoneView extends Component {

  constructor(props) {
    super(props);
    this.state = {
      modalVisible: false,
      editModalVisible: false,
      editingPhone: {
        phoneId: false,
        phoneModel: false,
      },
    };
  }

  handleModal = (modalVisible) => {
    this.setState({
      modalVisible,
    });
  };

  handleEditModal = (editModalVisible, phoneId, phoneModel) => {
    this.setState({
      editModalVisible,
      editingPhone: {
        phoneId,
        phoneModel,
      },
    });
  };

  renderModal() {
    const { modalVisible } = this.state;
    const { viewer } = this.props;

    if (!modalVisible) {
      return null;
    }

    return (
      <AddModal viewer={viewer} handleModal={this.handleModal}/>
    );
  }

  renderEditModal() {
    const { editModalVisible, editingPhone } = this.state;
    const { viewer } = this.props;

    if (!editModalVisible) {
      return null;
    }

    return (
      <EditModal
        viewer={viewer}
        editingPhone={editingPhone}
        handleEditModal={this.handleEditModal}
      />
    );
  }

  render() {
    const { viewer } = this.props;

    return (

        {this.renderModal()}
        {this.renderEditModal()}

            <Title text="Relay Phones - Demo Application" />

              view source

            <PhoneList
              viewer={viewer}
              handleModal={this.handleModal}
              handleEditModal={this.handleEditModal}
            />

    );
  }
}

const Style = {
  container: {
    marginTop: '40px',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  innerContainer: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
  },
};

export function path() {
  return '/phone';
}

PhoneView.contextTypes = TypedTransition.contextTypes();

export default Relay.createContainer(PhoneView, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        ${AddPhoneMutation.getFragment('viewer')}
        ${RemovePhoneMutation.getFragment('viewer')}
        ${UpdatePhoneMutation.getFragment('viewer')}
        phones(first: 908098879) {
          edges {
            node {
              phoneId
              model
              image
            },
          },
        },
      }
    `,
  },
});
<commit_msg>Test console.log<commit_after>import React, { Component } from 'react';
import Relay from 'react-relay';

import TypedTransition from '../core/TypedTransition';

import Title from '../components/Title';
import PhoneList from '../components/PhoneList';
import AddModal from '../components/AddModal';
import EditModal from '../components/EditModal';

import AddPhoneMutation from '../mutations/AddPhoneMutation';
import RemovePhoneMutation from '../mutations/RemovePhoneMutation';
import UpdatePhoneMutation from '../mutations/UpdatePhoneMutation';

class PhoneView extends Component {

  constructor(props) {
    super(props);
    this.state = {
      modalVisible: false,
      editModalVisible: false,
      editingPhone: {
        phoneId: false,
        phoneModel: false,
      },
    };
  }

  handleModal = (modalVisible) => {
    console.log('handleModal');
    this.setState({
      modalVisible,
    });
  };

  handleEditModal = (editModalVisible, phoneId, phoneModel) => {
    this.setState({
      editModalVisible,
      editingPhone: {
        phoneId,
        phoneModel,
      },
    });
  };

  renderModal() {
    const { modalVisible } = this.state;
    const { viewer } = this.props;

    if (!modalVisible) {
      return null;
    }

    return (
      <AddModal viewer={viewer} handleModal={this.handleModal}/>
    );
  }

  renderEditModal() {
    const { editModalVisible, editingPhone } = this.state;
    const { viewer } = this.props;

    if (!editModalVisible) {
      return null;
    }

    return (
      <EditModal
        viewer={viewer}
        editingPhone={editingPhone}
        handleEditModal={this.handleEditModal}
      />
    );
  }

  render() {
    const { viewer } = this.props;

    return (

        {this.renderModal()}
        {this.renderEditModal()}

            <Title text="Relay Phones - Demo Application" />

              view source

            <PhoneList
              viewer={viewer}
              handleModal={this.handleModal}
              handleEditModal={this.handleEditModal}
            />

    );
  }
}

const Style = {
  container: {
    marginTop: '40px',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  innerContainer: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
  },
};

export function path() {
  return '/phone';
}

PhoneView.contextTypes = TypedTransition.contextTypes();

export default Relay.createContainer(PhoneView, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        ${AddPhoneMutation.getFragment('viewer')}
        ${RemovePhoneMutation.getFragment('viewer')}
        ${UpdatePhoneMutation.getFragment('viewer')}
        phones(first: 908098879) {
          edges {
            node {
              phoneId
              model
              image
            },
          },
        },
      }
    `,
  },
});
<|endoftext|>


<commit_before>var widget_settimer = {
    _settimer: null,
    elements: null,

    drawDial: function () {
        var c = this.g, // context
        a = this.arc(this.cv), // Arc
        r = 1;

        c.lineWidth = this.lineWidth;
        c.lineCap = this.lineCap;
        if (this.o.bgColor !== "none") {
            c.beginPath();
            c.strokeStyle = this.o.bgColor;
            c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);
            c.stroke();
        }

        var tick_w = (2 * Math.PI) / 360;
        var step =  (this.o.max - this.o.min) / this.angleArc;
        var acAngle = ((this.o.isValue - this.o.min) / step) + this.startAngle;
        var dist = this.o.tickdistance || 4;

        // draw ticks
        for (tick = this.startAngle; tick < this.endAngle + 0.00001; tick+=tick_w*dist) {
            i = step * (tick-this.startAngle)+this.o.min;

            c.beginPath();
            c.strokeStyle = this.o.tkColor;//'#4477ff';

            w = tick_w;
            w *= (c.strokeStyle != this.o.tkColor) ? 2 : 1;

            c.arc( this.xy, this.xy, this.radius, tick, tick+w , false);
            c.stroke();
        }

        // draw selection cursor
        c.beginPath();
        c.strokeStyle = this.o.hdColor;
        c.lineWidth = this.lineWidth * 2;
        c.arc(this.xy, this.xy, this.radius-this.lineWidth/2, a.s, a.e, a.d);
        c.stroke();

        return false;
    },
    init: function () {
        _settimer=this;
        _settimer.elements = $('div[data-type="settimer"]');
        _settimer.elements.each(function(index) {
            var device = $(this).data('device');
            $(this).data('get', $(this).data('get') || 'STATE');
            readings[$(this).data('get')] = true;

            $(this).data('cmd', $(this).data('cmd')||'set');
            $(this).data('off', $(this).data('off')||'off');

            var container = $('
').appendTo($(this));

            var buttons = $('
').appendTo(container);
            var button_set = $('
').appendTo(buttons);
            var button_off = $('
').appendTo(buttons);

            var knobs = $('
').appendTo(container);
            var knob_hour_wrap = $('
').appendTo(knobs);
            var knob_hour = $('<input class="widget_settimer_hour" />', {
                type: 'text',
                value: $(this).attr('data-initvalue')||'0',
                disabled : true,
            }).appendTo(knob_hour_wrap);

            var knob_min_wrap = $('
').appendTo(knobs);
            var knob_min = $('<input class="widget_settimer_minute" />', {
                type: 'text',
                value: $(this).attr('data-initvalue')||'0',
                disabled : true,
            }).appendTo(knob_min_wrap);

            knob_hour.knob({
                'min': 0,
                'max': 23,
                'lastValue': 0,
                'height':120,
                'width':120,
                'angleOffset': $(this).attr('data-angleoffset')?$(this).attr('data-angleoffset')*1:-120,
                'angleArc': $(this).attr('data-anglearc')?$(this).attr('data-anglearc')*1:240,
                'bgColor': $(this).data('bgcolor') || 'transparent',
                'fgColor': $(this).data('fgcolor') || '#cccccc',
                'tkColor': $(this).data('tkcolor') || '#696969',
                'hdColor': $(this).data('hdcolor') || '#aa6900',
                'thickness': .25,
                'tickdistance': 20,
                'cursor': 6,
                'touchPosition': 'left',
                'draw' : _settimer.drawDial,
                'readOnly' : $(this).hasClass('readonly'),
            });
            knob_min.knob({
                'min': 0,
                'max': 59,
                'lastValue': 0,
                'height':120,
                'width':120,
                'angleOffset': $(this).attr('data-angleoffset')?$(this).attr('data-angleoffset')*1:-120,
                'angleArc': $(this).attr('data-anglearc')?$(this).attr('data-anglearc')*1:240,
                'bgColor': $(this).data('bgcolor') || 'transparent',
                'fgColor': $(this).data('fgcolor') || '#cccccc',
                'tkColor': $(this).data('tkcolor') || '#696969',
                'hdColor': $(this).data('hdcolor') || '#aa6900',
                'thickness': .25,
                'tickdistance': 10,
                'cursor': 6,
                'touchPosition': 'left',
                'draw' : _settimer.drawDial,
                'readOnly' : $(this).hasClass('readonly'),
            });

            button_set.famultibutton({
                backgroundIcon: 'fa-circle',
                offBackgroundColor: '#aa6900',
                icon: 'fa-clock-o',
                offColor: '#2a2a2a',
                mode: 'push',
                // Called in toggle on state.
                toggleOn: function( ) {
                    var parent = $(this).parents('div[data-type="settimer"]');
                    var knob_hour = parent.find('input[class=widget_settimer_hour]');
                    var knob_min = parent.find('input[class=widget_settimer_minute]');
                    var hour = knob_hour.val();
                    var min = knob_min.val();

                    hour = hour<10?'0'+hour:hour;
                    min = min<10?'0'+min:min;

                    var v = hour+':'+min;
                    if(hour==parent.data('off') || min==parent.data('off') ) {
                        v = parent.data('off');
                    }

                    var cmd = [parent.data('cmd'), device, parent.data('set'), v].join(' ');
                    setFhemStatus(cmd);
                    if( device && typeof device != "undefined") {
                        TOAST && $.toast(cmd);
                    }
                },
            });

            button_off.famultibutton({
                backgroundIcon: 'fa-circle',
                icon: 'fa-power-off',
                mode: 'push',
                // Called in toggle on state.
                toggleOn: function( ) {
                    var parent = $(this).parents('div[data-type="settimer"]');
                    var cmd = [parent.data('cmd'), device, parent.data('set'), parent.data('off')].join(' ');
                    console.log(cmd);
                    setFhemStatus(cmd);
                    if( device && typeof device != "undefined") {
                        TOAST && $.toast(cmd);
                    }
                },
            });
        });
    },
    update: function (dev,par) {
        var deviceElements;
        if ( dev == '*' )
            deviceElements= _settimer.elements;
        else
            deviceElements= _settimer.elements.filter('div[data-device="'+dev+'"]');

        deviceElements.each(function(index) {
            if ( $(this).data('get')==par || par =='*'){
                var val = getDeviceValue( $(this), 'get' );
                var knob_hour = $(this).find('input[class=widget_settimer_hour]');
                var knob_min = $(this).find('input[class=widget_settimer_minute]');
                if (val){
                    var v = val.split(':');
                    var hour = v[0];
                    var min = v[0]=='off'?v[0]:v[1];

                    if ( knob_hour.val() != hour ){
                        knob_hour.val( hour ).trigger('change');
                        knob_hour.val( hour );
                    }
                    if ( knob_min.val() != min ){
                        knob_min.val( min ).trigger('change');
                        knob_min.val( min );
                    }
                }
                knob_hour.css({visibility:'visible'});
                knob_min.css({visibility:'visible'});
            }
        });
    }
};
<commit_msg>data-reading added; some bugfixes<commit_after>var widget_settimer = {
    _settimer: null,
    elements: null,

    drawDial: function () {
        var c = this.g, // context
        a = this.arc(this.cv), // Arc
        r = 1;

        c.lineWidth = this.lineWidth;
        c.lineCap = this.lineCap;
        if (this.o.bgColor !== "none") {
            c.beginPath();
            c.strokeStyle = this.o.bgColor;
            c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);
            c.stroke();
        }

        var tick_w = (2 * Math.PI) / 360;
        var step =  (this.o.max - this.o.min) / this.angleArc;
        var acAngle = ((this.o.isValue - this.o.min) / step) + this.startAngle;
        var dist = this.o.tickdistance || 4;

        // draw ticks
        for (tick = this.startAngle; tick < this.endAngle + 0.00001; tick+=tick_w*dist) {
            i = step * (tick-this.startAngle)+this.o.min;

            c.beginPath();
            c.strokeStyle = this.o.tkColor;//'#4477ff';

            w = tick_w;
            w *= (c.strokeStyle != this.o.tkColor) ? 2 : 1;

            c.arc( this.xy, this.xy, this.radius, tick, tick+w , false);
            c.stroke();
        }

        // draw selection cursor
        c.beginPath();
        c.strokeStyle = this.o.hdColor;
        c.lineWidth = this.lineWidth * 2;
        c.arc(this.xy, this.xy, this.radius-this.lineWidth/2, a.s, a.e, a.d);
        c.stroke();

        return false;
    },
    init: function () {
        _settimer=this;
        _settimer.elements = $('div[data-type="settimer"]');
        _settimer.elements.each(function(index) {
            var device = $(this).data('device');
            $(this).data('get', $(this).data('get') || $(this).data('reading') || 'STATE');
            readings[$(this).data('get')] = true;
            $(this).data('set', $(this).data('reading'));
            $(this).data('cmd', $(this).data('cmd')||($(this).data('reading')?'setreading':'set'));
            $(this).data('off', $(this).data('off')||'off');

            var container = $('
').appendTo($(this));

            var buttons = $('
').appendTo(container);
            var button_set = $('
').appendTo(buttons);
            var button_off = $('
').appendTo(buttons);

            var knobs = $('
').appendTo(container);
            var knob_hour_wrap = $('
').appendTo(knobs);
            var knob_hour = $('<input class="widget_settimer_hour" />', {
                type: 'text',
                value: $(this).attr('data-initvalue')||'0',
                disabled : true,
            }).appendTo(knob_hour_wrap);

            var knob_min_wrap = $('
').appendTo(knobs);
            var knob_min = $('<input class="widget_settimer_minute" />', {
                type: 'text',
                value: $(this).attr('data-initvalue')||'0',
                disabled : true,
            }).appendTo(knob_min_wrap);

            knob_hour.knob({
                'min': 0,
                'max': 23,
                'lastValue': 0,
                'height':120,
                'width':120,
                'angleOffset': $(this).attr('data-angleoffset')?$(this).attr('data-angleoffset')*1:-120,
                'angleArc': $(this).attr('data-anglearc')?$(this).attr('data-anglearc')*1:240,
                'bgColor': $(this).data('bgcolor') || 'transparent',
                'fgColor': $(this).data('fgcolor') || '#cccccc',
                'tkColor': $(this).data('tkcolor') || '#696969',
                'hdColor': $(this).data('hdcolor') || '#aa6900',
                'thickness': .25,
                'tickdistance': 20,
                'cursor': 6,
                'touchPosition': 'left',
                'draw' : _settimer.drawDial,
                'readOnly' : $(this).hasClass('readonly'),
            });
            knob_min.knob({
                'min': 0,
                'max': 59,
                'lastValue': 0,
                'height':120,
                'width':120,
                'angleOffset': $(this).attr('data-angleoffset')?$(this).attr('data-angleoffset')*1:-120,
                'angleArc': $(this).attr('data-anglearc')?$(this).attr('data-anglearc')*1:240,
                'bgColor': $(this).data('bgcolor') || 'transparent',
                'fgColor': $(this).data('fgcolor') || '#cccccc',
                'tkColor': $(this).data('tkcolor') || '#696969',
                'hdColor': $(this).data('hdcolor') || '#aa6900',
                'thickness': .25,
                'tickdistance': 10,
                'cursor': 6,
                'touchPosition': 'left',
                'draw' : _settimer.drawDial,
                'readOnly' : $(this).hasClass('readonly'),
            });

            button_set.famultibutton({
                backgroundIcon: 'fa-circle',
                offBackgroundColor: '#aa6900',
                icon: 'fa-clock-o',
                offColor: '#2a2a2a',
                mode: 'push',
                // Called in toggle on state.
                toggleOn: function( ) {
                    var parent = $(this).parents('div[data-type="settimer"]');
                    var knob_hour = parent.find('input[class=widget_settimer_hour]');
                    var knob_min = parent.find('input[class=widget_settimer_minute]');
                    var hour = knob_hour.val()*1;
                    var min = knob_min.val()*1;

                    hour = hour<10?'0'+hour:hour;
                    min = min<10?'0'+min:min;

                    var v = hour+':'+min;
                    if(hour==parent.data('off') || min==parent.data('off') ) {
                        v = parent.data('off');
                    }

                    var cmd = [parent.data('cmd'), device, parent.data('set'), v].join(' ');
                    setFhemStatus(cmd);
                    if( device && typeof device != "undefined") {
                        TOAST && $.toast(cmd);
                    }
                },
            });

            button_off.famultibutton({
                backgroundIcon: 'fa-circle',
                icon: 'fa-power-off',
                mode: 'push',
                // Called in toggle on state.
                toggleOn: function( ) {
                    var parent = $(this).parents('div[data-type="settimer"]');
                    var cmd = [parent.data('cmd'), device, parent.data('set'), parent.data('off')].join(' ');
                    console.log(cmd);
                    setFhemStatus(cmd);
                    if( device && typeof device != "undefined") {
                        TOAST && $.toast(cmd);
                    }
                },
            });
        });
    },
    update: function (dev,par) {
        var deviceElements;
        if ( dev == '*' )
            deviceElements= _settimer.elements;
        else
            deviceElements= _settimer.elements.filter('div[data-device="'+dev+'"]');

        deviceElements.each(function(index) {
            if ( $(this).data('get')==par || par =='*'){
                var val = getDeviceValue( $(this), 'get' );
                var knob_hour = $(this).find('input[class=widget_settimer_hour]');
                var knob_min = $(this).find('input[class=widget_settimer_minute]');
                if (val){
                    var v = val.split(':');
                    var hour = v[0];
                    var min = v[0]=='off'?v[0]:v[1];

                    if ( knob_hour.val() != hour ){
                        knob_hour.val( hour ).trigger('change');
                        knob_hour.val( hour );
                    }
                    if ( knob_min.val() != min ){
                        knob_min.val( min ).trigger('change');
                        knob_min.val( min );
                    }
                }
                knob_hour.css({visibility:'visible'});
                knob_min.css({visibility:'visible'});
            }
        });
    }
};
<|endoftext|>


<commit_before>'use strict';
const assert = require('assert');
const extractDomain = require('./index');

const urls = [
    'https://www.npmjs.com/package/extract-domain',
    'http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'https://npmjs.com/package/extract-domain',
    'http://example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'http://www.so.many.sub.domains.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'http://user:password@example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'ftp://example.org/resource.txt'
];

const expected = [
    'npmjs.com',
    'example.com',
    'npmjs.com',
    'example.org'
];

describe('extract domain', () => {
    it('should extract given domain from string without sub domain', () => {
        assert.equal(extractDomain(urls[3]), expected[1]);
        assert.equal(extractDomain(urls[1]), expected[1]);
    });

    it('should extract given domain from string', () => {
        assert.equal(extractDomain(urls[1]), expected[1]);

        assert.equal(extractDomain(urls[0]), expected[0]);
    });

    it('should extract given domain from an array of strings', () => {
        const domains = extractDomain(urls);

        domains.map(domain => assert(expected.indexOf(domain) > -1));
    });

    it('should return empty string if it is not a domain', () => {
        assert.equal(extractDomain('/i.am/just.astring//7test'), '');
    });

    it('should throw syntax error exception if the argument is not string nor array', () => {
        try {
            extractDomain('{}');
        } catch (e) {
            assert.equal(e.name, 'TypeError');

            assert.equal(
                e.message,
                'The given URL is not a string. Please verify your string|array.'
            );
        }
    });

    it('should throw syntax error exception if the array value is not a string', () => {
        try {
            extractDomain([ [ 'wow' ] ]);
        } catch (e) {
            assert.equal(e.name, 'TypeError');

            assert.equal(
                e.message,
                'The given URL is not a string. Please verify your string|array.'
            );
        }
    });
});
<commit_msg>update tests<commit_after>'use strict';
const assert = require('assert');
const extractDomain = require('./index');

const urls = [
    'https://www.npmjs.com/package/extract-domain',
    'http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'https://npmjs.com/package/extract-domain',
    'http://example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'http://www.so.many.sub.domains.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'http://user:password@example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument',
    'ftp://example.org/resource.txt'
];

const expected = [
    'npmjs.com',
    'example.com',
    'npmjs.com',
    'example.org'
];

describe('extract domain', () => {
    it('should extract given domain from string', () => {
        assert.equal(extractDomain(urls[1]), expected[1]);

        assert.equal(extractDomain(urls[0]), expected[0]);
    });

    it('should extract given domain from an array of strings', () => {
        const domains = extractDomain(urls);

        domains.map(domain => assert(expected.indexOf(domain) > -1));
    });

    it('should return empty string if it is not a domain', () => {
        assert.equal(extractDomain('/i.am/just.astring//7test'), '');
    });

    it('should throw syntax error exception if the argument is not string nor array', () => {
        try {
            extractDomain('{}');
        } catch (e) {
            assert.equal(e.name, 'TypeError');

            assert.equal(
                e.message,
                'The given URL is not a string. Please verify your string|array.'
            );
        }
    });

    it('should throw syntax error exception if the array value is not a string', () => {
        try {
            extractDomain([ [ 'wow' ] ]);
        } catch (e) {
            assert.equal(e.name, 'TypeError');

            assert.equal(
                e.message,
                'The given URL is not a string. Please verify your string|array.'
            );
        }
    });
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name                OLog
// @namespace           http://www.olog.com/
// @description         OLog Userscript
// @include             http://s*-*.ogame.gameforge.com/game/*
// @grant               GM_xmlhttpRequest
// ==/UserScript==

"use strict";

var menuTable = document.getElementById("menuTable");

var oLogLi = document.createElement("li");
oLogLi.onfocus = function(c) {
    if (b(c.target).closest(".dropdown").length == 0) {
        b(".currentlySelected a").removeClass("hover");
        b(".currentlySelected").removeClass("focus");
    }
}

var oLogAnchor = document.createElement("a");
oLogAnchor.className = "menubutton"
oLogAnchor.href = "#"
oLogAnchor.onclick = function() {
    alert("OLog Settings");
}

var oLogSpan = document.createElement("span");
oLogSpan.className = "textlabel"

var oLogText = document.createTextNode("OLog Settings");

oLogSpan.appendChild(oLogText);
oLogAnchor.appendChild(oLogSpan);
oLogLi.appendChild(oLogAnchor);
menuTable.appendChild(oLogLi);

var page = getWindowVariable("currentPage");

if (page === "messages") {
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            for(var i = 0; i < mutation.addedNodes.length; i++) {
                var node = mutation.addedNodes[i];
                if (node.localName === "ul" && node.classList.contains("tab_inner")) {
                    //send all messages at once such that all SR keys can be sent at once to the server
                    processMessageNodes(node.querySelectorAll(".msg"));
                }
            }
        });
    });

    observer.observe(document, { childList: true, subtree: true });
}

function processMessageNodes(nodes) {
    var reportKeys = {
        sr: [],     //spy report
        cr: [],     //combat report
        rr: [],     //recycle report
        mr: []      //missile report
    };

    for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        var apiElement = node.querySelector(".icon_apikey");
        if (apiElement !== null) {
            var key = node.querySelector(".icon_apikey").title;
            var type = key.substring(0, 2);
            if (reportKeys.hasOwnProperty(type)) {
                reportKeys[type].push(key);
            }
        }
    }

    console.log(reportKeys);

    postData({
        endpoint: "keys",
        data: {
            reportKeys: reportKeys
        }
    });
}

function postData(object) {
    addPlayerData(object.data);
    console.log(JSON.stringify(object.data));
    GM_xmlhttpRequest({
        method: "POST",
        url: "http://localhost:8080/api/userscript/" + object.endpoint,
        data: JSON.stringify(object.data),
        headers: {
            "Content-Type": "application/json"
        },
        onload: function(response) {
            console.log("load");
        },
        onerror: function(response) {
            console.log("error");
        }
    });
}

function addPlayerData(data) {
    data.server = getWindowVariable("constants.language");
    data.universe = getWindowVariable("constants.name");
    data.playerId = getWindowVariable("playerId");
    data.playerName = getWindowVariable("playerName");
}

/**
 * Returns a global variable.
 *
 * Needed because a @grant other than none puts the script
 * in a separate scope.
 *
 * @param {string} name The name of the global variable.
 */
function getWindowVariable(name) {
    return window.eval(name);
}<commit_msg>The settings page now shows an empty page and renders correctly in the menu bar.<commit_after>// ==UserScript==
// @name                OLog
// @namespace           http://www.olog.com/
// @description         OLog Userscript
// @include             http://s*-*.ogame.gameforge.com/game/*
// @grant               GM_xmlhttpRequest
// ==/UserScript==

"use strict";

var menuTable = document.getElementById("menuTable");

var oLogLi = document.createElement("li");
oLogLi.onfocus = function(c) {
    if (b(c.target).closest(".dropdown").length == 0) {
        b(".currentlySelected a").removeClass("hover");
        b(".currentlySelected").removeClass("focus");
    }
}

var oLogAnchor = document.createElement("a");
oLogAnchor.className = "menubutton"
oLogAnchor.href = "#"
oLogAnchor.onclick = function() {
    var menuTableLiList = menuTable.querySelectorAll("li");
    for (var i = 0; i < menuTableLiList.length; i++) {
        console.log(menuTableLiList[i]);
        console.log(menuTableLiList[i].querySelector(".menubutton"));
        console.log(menuTableLiList[i].querySelector(".menubutton").classList);
        menuTableLiList[i].querySelector(".menubutton").classList.remove("selected");
    }

    oLogAnchor.classList.add("selected");

    var inhaltDiv = document.getElementById("inhalt");
    while (inhaltDiv.firstChild) {
        inhaltDiv.removeChild(inhaltDiv.firstChild);
    }
}

var oLogSpan = document.createElement("span");
oLogSpan.className = "textlabel"

var oLogText = document.createTextNode("OLog Settings");

oLogSpan.appendChild(oLogText);
oLogAnchor.appendChild(oLogSpan);
oLogLi.appendChild(oLogAnchor);
menuTable.appendChild(oLogLi);

var page = getWindowVariable("currentPage");

if (page === "messages") {
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            for(var i = 0; i < mutation.addedNodes.length; i++) {
                var node = mutation.addedNodes[i];
                if (node.localName === "ul" && node.classList.contains("tab_inner")) {
                    //send all messages at once such that all SR keys can be sent at once to the server
                    processMessageNodes(node.querySelectorAll(".msg"));
                }
            }
        });
    });

    observer.observe(document, { childList: true, subtree: true });
}

function processMessageNodes(nodes) {
    var reportKeys = {
        sr: [],     //spy report
        cr: [],     //combat report
        rr: [],     //recycle report
        mr: []      //missile report
    };

    for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        var apiElement = node.querySelector(".icon_apikey");
        if (apiElement !== null) {
            var key = node.querySelector(".icon_apikey").title;
            var type = key.substring(0, 2);
            if (reportKeys.hasOwnProperty(type)) {
                reportKeys[type].push(key);
            }
        }
    }

    console.log(reportKeys);

    postData({
        endpoint: "keys",
        data: {
            reportKeys: reportKeys
        }
    });
}

function postData(object) {
    addPlayerData(object.data);
    console.log(JSON.stringify(object.data));
    GM_xmlhttpRequest({
        method: "POST",
        url: "http://localhost:8080/api/userscript/" + object.endpoint,
        data: JSON.stringify(object.data),
        headers: {
            "Content-Type": "application/json"
        },
        onload: function(response) {
            console.log("load");
        },
        onerror: function(response) {
            console.log("error");
        }
    });
}

function addPlayerData(data) {
    data.server = getWindowVariable("constants.language");
    data.universe = getWindowVariable("constants.name");
    data.playerId = getWindowVariable("playerId");
    data.playerName = getWindowVariable("playerName");
}

/**
 * Returns a global variable.
 *
 * Needed because a @grant other than none puts the script
 * in a separate scope.
 *
 * @param {string} name The name of the global variable.
 */
function getWindowVariable(name) {
    return window.eval(name);
}<|endoftext|>


<commit_before>'use strict';

module.exports = (XIBLE, EXPRESS_APP) => {
  const XibleRegistryWrapper = require('xible-registry-wrapper');
  const fsExtra = require('fs-extra');
  const os = require('os');

  const registryUrl = XIBLE.Config.getValue('registry.url');
  if (!registryUrl) {
    throw new Error('"registry.url" not found in config');
  }

  const xibleRegistry = new XibleRegistryWrapper(registryUrl);

  // the tmp path for downloading this node
  const TMP_REGISTRY_DIR = `${os.tmpdir() || '/tmp'}/xible-registry-`;
  console.log(os.tmpdir());

  function cleanUp(tmpRegDir) {
    if (!tmpRegDir) {
      return Promise.resolve();
    }

    return new Promise((resolve, reject) => {
      // remove the tmp dir
      fsExtra.remove(tmpRegDir, (err) => {
        if (err) {
          reject(err);
          return;
        }

        resolve();
      });
    });
  }

  /**
  * Installs a flow from a registry.
  * @param {String} altName The name to publish the flow with. Defaults to the flow name.
  * @returns {Promise}
  */
  xibleRegistry.Flow.prototype.install = function flowInstall(altName) {
    if (!XIBLE.Config.getValue('registry.flows.allowinstall')) {
      return Promise.reject('Your config does not allow to install flows from the registry');
    }

    let flowPath = XIBLE.Config.getValue('flows.path');
    if (!flowPath) {
      return Promise.reject('no "flows.path" configured');
    }
    flowPath = XIBLE.resolvePath(flowPath);

    if (altName) {
      if (!XIBLE.Flow.validateId(altName)) {
        return Promise.reject('flow _id/name cannot contain reserved/unsave characters');
      }
      this._id = altName;
      this.name = altName;
    }

    // remove fields specifically for the registry
    delete this.publishUserName;
    delete this.publishDate;

    return new Promise((resolve, reject) => {
      // write
      const flowDestPath = `${flowPath}/${this._id}.json`;
      fsExtra.writeFile(flowDestPath, JSON.stringify(this, null, '\t'), (err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  };

  /**
  * Installs a nodepack from a registry.
  * @returns {Promise}
  */
  xibleRegistry.NodePack.prototype.install = function nodePackInstall() {
    if (!XIBLE.Config.getValue('registry.nodepacks.allowinstall')) {
      return Promise.reject('Your config does not allow to install nodepacks from the registry');
    }

    let tmpRegDir;
    let nodePath = XIBLE.Config.getValue('nodes.path');
    if (!nodePath) {
      return Promise.reject('no "nodes.path" configured');
    }
    nodePath = XIBLE.resolvePath(nodePath);

    // get the registrydata
    return this.getRegistryData()
    .then((registryData) => {
      if (!registryData.name) {
        return Promise.reject(`No "name" field found in the registry data for node "${this.name}"`);
      }

      return this.getTarballUrl()
      .then(tarballUrl => new Promise((resolve, reject) => {
        // check if the tarbalUrl is safe
        if (encodeURI(tarballUrl) !== tarballUrl) {
          reject(new Error('Package URL contains potentially unsafe characters'));
          return;
        }

        // create the tmp dir
        fsExtra.mkdtemp(TMP_REGISTRY_DIR, (err, mTmpRegDir) => {
          tmpRegDir = mTmpRegDir;
          if (err) {
            reject(err);
            return;
          }

          // create a package.json so npm knows where the root lies
          // remove the dependencies from the package so npm doesn't get confused
          const packageJson = require(`${__dirname}/../../package.json`);
          delete packageJson.dependencies;
          delete packageJson.devDependencies;

          // write off package.json
          fsExtra.writeFile(`${tmpRegDir}/package.json`, JSON.stringify(packageJson), (createPackageJsonErr) => {
            if (createPackageJsonErr) {
              reject(createPackageJsonErr);
              return;
            }

            // fork npm to install the registry url
            const fork = require('child_process').spawn;
            const npm = fork('npm', ['install', '--no-save', tarballUrl], {
              cwd: tmpRegDir,
              shell: true
            });

            npm.on('error', npmErr => reject(npmErr));

            npm.on('exit', (exitCode) => {
              if (exitCode) {
                reject(`exited with code: ${exitCode}`);
                return;
              }

              // specify the dir where this node will be installed
              const nodeDestDir = `${nodePath}/${this.name}`;

              // when success, resolve
              const onSuccess = () => XIBLE.Node
              .initFromPath(nodeDestDir)
              .then(() => cleanUp(tmpRegDir))
              .then(() => {
                // see if we can/need to reinit flows that are not runnable
                const flows = XIBLE.getFlows();
                for (const flowId in flows) {
                  if (!flows[flowId].runnable) {
                    flows[flowId].initJson(flows[flowId].json);
                  }
                }
              })
              .then(resolve)
              .catch((onSuccessErr) => {
                reject(onSuccessErr);
              });

              // remove existing node directory
              fsExtra.emptyDir(nodeDestDir, (removeExistingNodeErr) => {
                if (removeExistingNodeErr) {
                  reject(removeExistingNodeErr);
                  return;
                }

                // first move the node itself
                fsExtra.move(`${tmpRegDir}/node_modules/${registryData.name}`, nodeDestDir, {
                  overwrite: true
                }, (moveNodeErr) => {
                  if (moveNodeErr) {
                    reject(moveNodeErr);
                    return;
                  }

                  // check if there's anything left in node_modules
                  fsExtra.readdir(`${tmpRegDir}/node_modules`, (remainingNodeModulesErr, files) => {
                    if (remainingNodeModulesErr) {
                      reject(remainingNodeModulesErr);
                      return;
                    }

                    if (!files.length) {
                      onSuccess();
                      return;
                    }

                    // move the rest of the node_modules
                    fsExtra.move(`${tmpRegDir}/node_modules`, `${nodeDestDir}/node_modules`, {
                      overwrite: true
                    }, (moveNodeModulesErr) => {
                      if (moveNodeModulesErr) {
                        reject(moveNodeModulesErr);
                        return;
                      }

                      onSuccess();
                    });
                  });
                });
              });
            });

            npm.stdout.on('data', (data) => {
              console.log(data.toString());
            });

            npm.stderr.on('data', (data) => {
              console.log(data.toString());
            });
          });
        });
      }));
    })
    .catch(err =>
      cleanUp(tmpRegDir)
      .then(() => Promise.reject(err))
      .catch(() => Promise.reject(err))
    );
  };

  if (EXPRESS_APP) {
    require('./routes.js')(xibleRegistry, XIBLE, EXPRESS_APP);
  }

  return {
    Registry: xibleRegistry
  };
};
<commit_msg>removed debug console.log<commit_after>'use strict';

module.exports = (XIBLE, EXPRESS_APP) => {
  const XibleRegistryWrapper = require('xible-registry-wrapper');
  const fsExtra = require('fs-extra');
  const os = require('os');

  const registryUrl = XIBLE.Config.getValue('registry.url');
  if (!registryUrl) {
    throw new Error('"registry.url" not found in config');
  }

  const xibleRegistry = new XibleRegistryWrapper(registryUrl);

  // the tmp path for downloading this node
  const TMP_REGISTRY_DIR = `${os.tmpdir() || '/tmp'}/xible-registry-`;

  function cleanUp(tmpRegDir) {
    if (!tmpRegDir) {
      return Promise.resolve();
    }

    return new Promise((resolve, reject) => {
      // remove the tmp dir
      fsExtra.remove(tmpRegDir, (err) => {
        if (err) {
          reject(err);
          return;
        }

        resolve();
      });
    });
  }

  /**
  * Installs a flow from a registry.
  * @param {String} altName The name to publish the flow with. Defaults to the flow name.
  * @returns {Promise}
  */
  xibleRegistry.Flow.prototype.install = function flowInstall(altName) {
    if (!XIBLE.Config.getValue('registry.flows.allowinstall')) {
      return Promise.reject('Your config does not allow to install flows from the registry');
    }

    let flowPath = XIBLE.Config.getValue('flows.path');
    if (!flowPath) {
      return Promise.reject('no "flows.path" configured');
    }
    flowPath = XIBLE.resolvePath(flowPath);

    if (altName) {
      if (!XIBLE.Flow.validateId(altName)) {
        return Promise.reject('flow _id/name cannot contain reserved/unsave characters');
      }
      this._id = altName;
      this.name = altName;
    }

    // remove fields specifically for the registry
    delete this.publishUserName;
    delete this.publishDate;

    return new Promise((resolve, reject) => {
      // write
      const flowDestPath = `${flowPath}/${this._id}.json`;
      fsExtra.writeFile(flowDestPath, JSON.stringify(this, null, '\t'), (err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  };

  /**
  * Installs a nodepack from a registry.
  * @returns {Promise}
  */
  xibleRegistry.NodePack.prototype.install = function nodePackInstall() {
    if (!XIBLE.Config.getValue('registry.nodepacks.allowinstall')) {
      return Promise.reject('Your config does not allow to install nodepacks from the registry');
    }

    let tmpRegDir;
    let nodePath = XIBLE.Config.getValue('nodes.path');
    if (!nodePath) {
      return Promise.reject('no "nodes.path" configured');
    }
    nodePath = XIBLE.resolvePath(nodePath);

    // get the registrydata
    return this.getRegistryData()
    .then((registryData) => {
      if (!registryData.name) {
        return Promise.reject(`No "name" field found in the registry data for node "${this.name}"`);
      }

      return this.getTarballUrl()
      .then(tarballUrl => new Promise((resolve, reject) => {
        // check if the tarbalUrl is safe
        if (encodeURI(tarballUrl) !== tarballUrl) {
          reject(new Error('Package URL contains potentially unsafe characters'));
          return;
        }

        // create the tmp dir
        fsExtra.mkdtemp(TMP_REGISTRY_DIR, (err, mTmpRegDir) => {
          tmpRegDir = mTmpRegDir;
          if (err) {
            reject(err);
            return;
          }

          // create a package.json so npm knows where the root lies
          // remove the dependencies from the package so npm doesn't get confused
          const packageJson = require(`${__dirname}/../../package.json`);
          delete packageJson.dependencies;
          delete packageJson.devDependencies;

          // write off package.json
          fsExtra.writeFile(`${tmpRegDir}/package.json`, JSON.stringify(packageJson), (createPackageJsonErr) => {
            if (createPackageJsonErr) {
              reject(createPackageJsonErr);
              return;
            }

            // fork npm to install the registry url
            const fork = require('child_process').spawn;
            const npm = fork('npm', ['install', '--no-save', tarballUrl], {
              cwd: tmpRegDir,
              shell: true
            });

            npm.on('error', npmErr => reject(npmErr));

            npm.on('exit', (exitCode) => {
              if (exitCode) {
                reject(`exited with code: ${exitCode}`);
                return;
              }

              // specify the dir where this node will be installed
              const nodeDestDir = `${nodePath}/${this.name}`;

              // when success, resolve
              const onSuccess = () => XIBLE.Node
              .initFromPath(nodeDestDir)
              .then(() => cleanUp(tmpRegDir))
              .then(() => {
                // see if we can/need to reinit flows that are not runnable
                const flows = XIBLE.getFlows();
                for (const flowId in flows) {
                  if (!flows[flowId].runnable) {
                    flows[flowId].initJson(flows[flowId].json);
                  }
                }
              })
              .then(resolve)
              .catch((onSuccessErr) => {
                reject(onSuccessErr);
              });

              // remove existing node directory
              fsExtra.emptyDir(nodeDestDir, (removeExistingNodeErr) => {
                if (removeExistingNodeErr) {
                  reject(removeExistingNodeErr);
                  return;
                }

                // first move the node itself
                fsExtra.move(`${tmpRegDir}/node_modules/${registryData.name}`, nodeDestDir, {
                  overwrite: true
                }, (moveNodeErr) => {
                  if (moveNodeErr) {
                    reject(moveNodeErr);
                    return;
                  }

                  // check if there's anything left in node_modules
                  fsExtra.readdir(`${tmpRegDir}/node_modules`, (remainingNodeModulesErr, files) => {
                    if (remainingNodeModulesErr) {
                      reject(remainingNodeModulesErr);
                      return;
                    }

                    if (!files.length) {
                      onSuccess();
                      return;
                    }

                    // move the rest of the node_modules
                    fsExtra.move(`${tmpRegDir}/node_modules`, `${nodeDestDir}/node_modules`, {
                      overwrite: true
                    }, (moveNodeModulesErr) => {
                      if (moveNodeModulesErr) {
                        reject(moveNodeModulesErr);
                        return;
                      }

                      onSuccess();
                    });
                  });
                });
              });
            });

            npm.stdout.on('data', (data) => {
              console.log(data.toString());
            });

            npm.stderr.on('data', (data) => {
              console.log(data.toString());
            });
          });
        });
      }));
    })
    .catch(err =>
      cleanUp(tmpRegDir)
      .then(() => Promise.reject(err))
      .catch(() => Promise.reject(err))
    );
  };

  if (EXPRESS_APP) {
    require('./routes.js')(xibleRegistry, XIBLE, EXPRESS_APP);
  }

  return {
    Registry: xibleRegistry
  };
};
<|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;
var sinon = require('sinon');
var m = require('./index');

describe('validate-commit-msg.js', function() {
  var originalLog, originalError;
  var errors = [];
  var logs = [];

  var VALID = true;
  var INVALID = false;

  beforeEach(function() {
    errors.length = 0;
    logs.length = 0;
    originalLog = console.log;
    originalError = console.error;
    console.error = fakeError;
    console.log = fakeLog;

    sinon.spy(console, 'error');
    sinon.spy(console, 'log');

    function fakeError(msg) {
      errors.push(msg.replace(/\x1B\[\d+m/g, '')); // uncolor
    }

    function fakeLog(msg) {
      logs.push(msg.replace(/\x1B\[\d+m/g, '')); // uncolor
    }
  });

  describe('validateMessage', function() {

    it('should be valid', function() {
      expect(m.validateMessage('fixup! fix($compile): something')).to.equal(VALID);
      expect(m.validateMessage('fix($compile): something')).to.equal(VALID);
      expect(m.validateMessage('feat($location): something')).to.equal(VALID);
      expect(m.validateMessage('docs($filter): something')).to.equal(VALID);
      expect(m.validateMessage('style($http): something')).to.equal(VALID);
      expect(m.validateMessage('refactor($httpBackend): something')).to.equal(VALID);
      expect(m.validateMessage('test($resource): something')).to.equal(VALID);
      expect(m.validateMessage('chore($controller): something')).to.equal(VALID);
      expect(m.validateMessage('chore(foo-bar): something')).to.equal(VALID);
      expect(m.validateMessage('chore(*): something')).to.equal(VALID);
      expect(m.validateMessage('chore(guide/location): something')).to.equal(VALID);
      expect(m.validateMessage('revert(foo): something')).to.equal(VALID);
      expect(m.validateMessage('custom(baz): something')).to.equal(VALID);
      expect(errors).to.deep.equal([]);
    });

    it('should validate 100 characters length', function() {
      var msg = "fix($compile): something super mega extra giga tera long, maybe even longer and longer and longer... ";

      expect(m.validateMessage(msg)).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: is longer than 100 characters !']);
    });

    it('should work fine with a bigger body', function() {
      var message = [
        'chore(build): something',
        '', // BLANK_LINE
        'Something longer that is more descriptive',
        '', // BLANK LINE
        'Closes #14',
        'BREAKING CHANGE: Something is totally broken :-('
      ].join('\n');
      expect(m.validateMessage(message)).to.equal(VALID);
      expect(errors).to.deep.equal([]);
    });

    it('should validate "<type>(<scope>): <subject>" format', function() {
      var msg = 'not correct format';

      expect(m.validateMessage(msg)).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" ! was: not correct format']);
    });

    it('should validate type', function() {
      expect(m.validateMessage('weird($filter): something')).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: "weird" is not allowed type !']);
    });

    it('should allow empty scope', function() {
      expect(m.validateMessage('fix: blablabla')).to.equal(VALID);
    });

    it('should allow dot in scope', function() {
      expect(m.validateMessage('chore(mocks.$httpBackend): something')).to.equal(VALID);
    });

    it('should ignore msg prefixed with "WIP: "', function() {
      expect(m.validateMessage('WIP: stuff')).to.equal(VALID);
    });
  });

  afterEach(function() {
    console.log = originalLog;
    console.error = originalError;
  });
});

<commit_msg>test(WIP): Update the WIP test to omit colon<commit_after>'use strict';

var expect = require('chai').expect;
var sinon = require('sinon');
var m = require('./index');

describe('validate-commit-msg.js', function() {
  var originalLog, originalError;
  var errors = [];
  var logs = [];

  var VALID = true;
  var INVALID = false;

  beforeEach(function() {
    errors.length = 0;
    logs.length = 0;
    originalLog = console.log;
    originalError = console.error;
    console.error = fakeError;
    console.log = fakeLog;

    sinon.spy(console, 'error');
    sinon.spy(console, 'log');

    function fakeError(msg) {
      errors.push(msg.replace(/\x1B\[\d+m/g, '')); // uncolor
    }

    function fakeLog(msg) {
      logs.push(msg.replace(/\x1B\[\d+m/g, '')); // uncolor
    }
  });

  describe('validateMessage', function() {

    it('should be valid', function() {
      expect(m.validateMessage('fixup! fix($compile): something')).to.equal(VALID);
      expect(m.validateMessage('fix($compile): something')).to.equal(VALID);
      expect(m.validateMessage('feat($location): something')).to.equal(VALID);
      expect(m.validateMessage('docs($filter): something')).to.equal(VALID);
      expect(m.validateMessage('style($http): something')).to.equal(VALID);
      expect(m.validateMessage('refactor($httpBackend): something')).to.equal(VALID);
      expect(m.validateMessage('test($resource): something')).to.equal(VALID);
      expect(m.validateMessage('chore($controller): something')).to.equal(VALID);
      expect(m.validateMessage('chore(foo-bar): something')).to.equal(VALID);
      expect(m.validateMessage('chore(*): something')).to.equal(VALID);
      expect(m.validateMessage('chore(guide/location): something')).to.equal(VALID);
      expect(m.validateMessage('revert(foo): something')).to.equal(VALID);
      expect(m.validateMessage('custom(baz): something')).to.equal(VALID);
      expect(errors).to.deep.equal([]);
    });

    it('should validate 100 characters length', function() {
      var msg = "fix($compile): something super mega extra giga tera long, maybe even longer and longer and longer... ";

      expect(m.validateMessage(msg)).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: is longer than 100 characters !']);
    });

    it('should work fine with a bigger body', function() {
      var message = [
        'chore(build): something',
        '', // BLANK_LINE
        'Something longer that is more descriptive',
        '', // BLANK LINE
        'Closes #14',
        'BREAKING CHANGE: Something is totally broken :-('
      ].join('\n');
      expect(m.validateMessage(message)).to.equal(VALID);
      expect(errors).to.deep.equal([]);
    });

    it('should validate "<type>(<scope>): <subject>" format', function() {
      var msg = 'not correct format';

      expect(m.validateMessage(msg)).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" ! was: not correct format']);
    });

    it('should validate type', function() {
      expect(m.validateMessage('weird($filter): something')).to.equal(INVALID);
      expect(errors).to.deep.equal(['INVALID COMMIT MSG: "weird" is not allowed type !']);
    });

    it('should allow empty scope', function() {
      expect(m.validateMessage('fix: blablabla')).to.equal(VALID);
    });

    it('should allow dot in scope', function() {
      expect(m.validateMessage('chore(mocks.$httpBackend): something')).to.equal(VALID);
    });

    it('should ignore msg prefixed with "WIP "', function() {
      expect(m.validateMessage('WIP stuff')).to.equal(VALID);
    });
  });

  afterEach(function() {
    console.log = originalLog;
    console.error = originalError;
  });
});

<|endoftext|>