<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import ClassNames from 'classnames';
import Input from '../input';
import events from '../utils/events';
import Chip from '../chip';
import style from './style';

const POSITION = {
 AUTO: 'auto',
 DOWN: 'down',
 UP: 'up'
};

class Autocomplete extends React.Component {
 static propTypes = {
   className: React.PropTypes.string,
   direction: React.PropTypes.oneOf(['auto', 'up', 'down']),
   disabled: React.PropTypes.bool,
   error: React.PropTypes.string,
   label: React.PropTypes.string,
   multiple: React.PropTypes.bool,
   onChange: React.PropTypes.func,
   selectedPosition: React.PropTypes.oneOf(['above', 'below']),
   showSuggestionsWhenValueIsSet: React.PropTypes.bool,
   source: React.PropTypes.any,
   value: React.PropTypes.any
 };

 static defaultProps = {
   className: '',
   direction: 'auto',
   selectedPosition: 'above',
   multiple: true,
   showSuggestionsWhenValueIsSet: false,
   source: {}
 };

 state = {
   direction: this.props.direction,
   focus: false,
   showAllSuggestions: this.props.showSuggestionsWhenValueIsSet,
   query: this.query(this.props.value)
 };

 componentWillReceiveProps (nextProps) {
   if (!this.props.multiple) {
     this.setState({query: nextProps.value});
   }
 }

 shouldComponentUpdate (nextProps, nextState) {
   if (!this.state.focus && nextState.focus && this.props.direction === POSITION.AUTO) {
     const direction = this.calculateDirection();
     if (this.state.direction !== direction) {
       this.setState({ direction });
       return false;
     }
   }
   return true;
 }

 handleChange = (keys, event) => {
   const key = this.props.multiple ? keys : keys[0];
   const query = this.query(key);
   if (this.props.onChange) this.props.onChange(key, event);
   this.setState(
     {focus: false, query, showAllSuggestions: this.props.showSuggestionsWhenValueIsSet},
     () => { this.refs.input.blur(); }
   );
 };

 handleQueryBlur = () => {
   if (this.state.focus) this.setState({focus: false});
 };

 handleQueryChange = (value) => {
   this.setState({query: value, showAllSuggestions: false});
 };

 handleQueryFocus = () => {
   this.refs.suggestions.scrollTop = 0;
   this.setState({active: '', focus: true});
 };

 handleQueryKeyDown = (event) => {
   // Clear query when pressing backspace and showing all suggestions.
   const shouldClearQuery = (
     event.which === 8
     && this.props.showSuggestionsWhenValueIsSet
     && this.state.showAllSuggestions
   );
   if (shouldClearQuery) {
     this.setState({query: ''});
   }
 };

 handleQueryKeyUp = (event) => {
   if (event.which === 13 && this.state.active) this.select(this.state.active, event);
   if (event.which === 27) this.refs.input.blur();
   if ([40, 38].indexOf(event.which) !== -1) {
     const suggestionsKeys = [...this.suggestions().keys()];
     let index = suggestionsKeys.indexOf(this.state.active) + (event.which === 40 ? +1 : -1);
     if (index < 0) index = suggestionsKeys.length - 1;
     if (index >= suggestionsKeys.length) index = 0;
     this.setState({active: suggestionsKeys[index]});
   }
 };

 handleSuggestionHover = (key) => {
   this.setState({active: key});
 };

 calculateDirection () {
   if (this.props.direction === 'auto') {
     const client = ReactDOM.findDOMNode(this.refs.input).getBoundingClientRect();
     const screen_height = window.innerHeight || document.documentElement.offsetHeight;
     const up = client.top > ((screen_height / 2) + client.height);
     return up ? 'up' : 'down';
   } else {
     return this.props.direction;
   }
 }

 query (key) {
   return !this.props.multiple && key ? this.source().get(key) : '';
 }

 suggestions () {
   const suggest = new Map();
   const query = this.state.query.toLowerCase().trim() || '';
   const values = this.values();
   for (const [key, value] of this.source()) {
     const valueMatchesQuery = value.toLowerCase().trim().startsWith(query);
     if (
       (valueMatchesQuery && !values.has(key))
       || (!this.props.multiple && (this.state.showAllSuggestions || valueMatchesQuery))
     ) {
       suggest.set(key, value);
     }
   }
   return suggest;
 }

 source () {
   const { source: src } = this.props;
   if (src.hasOwnProperty('length')) {
     return new Map(src.map((item) => Array.isArray(item) ? [...item] : [item, item]));
   } else {
     return new Map(Object.keys(src).map((key) => [key, src[key]]));
   }
 }

 values () {
   const valueMap = new Map();
   const vals = this.props.multiple ? this.props.value : [this.props.value];
   for (const [k, v] of this.source()) {
     if (vals.indexOf(k) !== -1) valueMap.set(k, v);
   }
   return valueMap;
 }

 select (key, event) {
   events.pauseEvent(event);
   const values = this.values(this.props.value);
   this.handleChange([key, ...values.keys()], event);
 }

 unselect (key, event) {
   if (!this.props.disabled) {
     const values = this.values(this.props.value);
     values.delete(key);
     this.handleChange([...values.keys()], event);
   }
 }

 renderSelected () {
   if (this.props.multiple) {
     const selectedItems = [...this.values()].map(([key, value]) => {
       return (
         <Chip
           key={key}
           className={style.value}
           deletable
           onDeleteClick={this.unselect.bind(this, key)}
         >
           {value}
         </Chip>
       );
     });

     return
{selectedItems}
;
   }
 }

 renderSuggestions () {
   const suggestions = [...this.suggestions()].map(([key, value]) => {
     const className = ClassNames(style.suggestion, {[style.active]: this.state.active === key});
     return (

         {value}

     );
   });

   const className = ClassNames(style.suggestions, {[style.up]: this.state.direction === 'up'});
   return
{suggestions}
;
 }

 render () {
   const {error, label, ...other} = this.props;
   const className = ClassNames(style.root, {
     [style.focus]: this.state.focus
   }, this.props.className);

   return (

       {this.props.selectedPosition === 'above' ? this.renderSelected() : null}
       <Input
         {...other}
         ref='input'
         className={style.input}
         error={error}
         label={label}
         onBlur={this.handleQueryBlur}
         onChange={this.handleQueryChange}
         onFocus={this.handleQueryFocus}
         onKeyDown={this.handleQueryKeyDown}
         onKeyUp={this.handleQueryKeyUp}
         value={this.state.query}
       />
       {this.renderSuggestions()}
       {this.props.selectedPosition === 'below' ? this.renderSelected() : null}

   );
 }
}

export default Autocomplete;
<commit_msg>Refactor autocomplete suggestions method to make it more readable<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import ClassNames from 'classnames';
import Input from '../input';
import events from '../utils/events';
import Chip from '../chip';
import style from './style';

const POSITION = {
 AUTO: 'auto',
 DOWN: 'down',
 UP: 'up'
};

class Autocomplete extends React.Component {
 static propTypes = {
   className: React.PropTypes.string,
   direction: React.PropTypes.oneOf(['auto', 'up', 'down']),
   disabled: React.PropTypes.bool,
   error: React.PropTypes.string,
   label: React.PropTypes.string,
   multiple: React.PropTypes.bool,
   onChange: React.PropTypes.func,
   selectedPosition: React.PropTypes.oneOf(['above', 'below']),
   showSuggestionsWhenValueIsSet: React.PropTypes.bool,
   source: React.PropTypes.any,
   value: React.PropTypes.any
 };

 static defaultProps = {
   className: '',
   direction: 'auto',
   selectedPosition: 'above',
   multiple: true,
   showSuggestionsWhenValueIsSet: false,
   source: {}
 };

 state = {
   direction: this.props.direction,
   focus: false,
   showAllSuggestions: this.props.showSuggestionsWhenValueIsSet,
   query: this.query(this.props.value)
 };

 componentWillReceiveProps (nextProps) {
   if (!this.props.multiple) {
     this.setState({query: nextProps.value});
   }
 }

 shouldComponentUpdate (nextProps, nextState) {
   if (!this.state.focus && nextState.focus && this.props.direction === POSITION.AUTO) {
     const direction = this.calculateDirection();
     if (this.state.direction !== direction) {
       this.setState({ direction });
       return false;
     }
   }
   return true;
 }

 handleChange = (keys, event) => {
   const key = this.props.multiple ? keys : keys[0];
   const query = this.query(key);
   if (this.props.onChange) this.props.onChange(key, event);
   this.setState(
     {focus: false, query, showAllSuggestions: this.props.showSuggestionsWhenValueIsSet},
     () => { this.refs.input.blur(); }
   );
 };

 handleQueryBlur = () => {
   if (this.state.focus) this.setState({focus: false});
 };

 handleQueryChange = (value) => {
   this.setState({query: value, showAllSuggestions: false});
 };

 handleQueryFocus = () => {
   this.refs.suggestions.scrollTop = 0;
   this.setState({active: '', focus: true});
 };

 handleQueryKeyDown = (event) => {
   // Clear query when pressing backspace and showing all suggestions.
   const shouldClearQuery = (
     event.which === 8
     && this.props.showSuggestionsWhenValueIsSet
     && this.state.showAllSuggestions
   );
   if (shouldClearQuery) {
     this.setState({query: ''});
   }
 };

 handleQueryKeyUp = (event) => {
   if (event.which === 13 && this.state.active) this.select(this.state.active, event);
   if (event.which === 27) this.refs.input.blur();
   if ([40, 38].indexOf(event.which) !== -1) {
     const suggestionsKeys = [...this.suggestions().keys()];
     let index = suggestionsKeys.indexOf(this.state.active) + (event.which === 40 ? +1 : -1);
     if (index < 0) index = suggestionsKeys.length - 1;
     if (index >= suggestionsKeys.length) index = 0;
     this.setState({active: suggestionsKeys[index]});
   }
 };

 handleSuggestionHover = (key) => {
   this.setState({active: key});
 };

 calculateDirection () {
   if (this.props.direction === 'auto') {
     const client = ReactDOM.findDOMNode(this.refs.input).getBoundingClientRect();
     const screen_height = window.innerHeight || document.documentElement.offsetHeight;
     const up = client.top > ((screen_height / 2) + client.height);
     return up ? 'up' : 'down';
   } else {
     return this.props.direction;
   }
 }

 query (key) {
   return !this.props.multiple && key ? this.source().get(key) : '';
 }

 suggestions () {
   let suggest = new Map();
   const query = this.state.query.toLowerCase().trim() || '';
   const values = this.values();
   const source = this.source();

   // Suggest any non-set value which matches the query
   if (this.props.multiple) {
     for (const [key, value] of source) {
       if (!values.has(key) && value.toLowerCase().trim().startsWith(query)) {
         suggest.set(key, value);
       }
     }

   // When multiple is false, suggest any value which matches the query if showAllSuggestions is false
   } else if (query && !this.state.showAllSuggestions) {
     for (const [key, value] of source) {
       if (value.toLowerCase().trim().startsWith(query)) {
         suggest.set(key, value);
       }
     }

   // When multiple is false, suggest all values when showAllSuggestions is true
   } else {
     suggest = source;
   }

   return suggest;
 }

 source () {
   const { source: src } = this.props;
   if (src.hasOwnProperty('length')) {
     return new Map(src.map((item) => Array.isArray(item) ? [...item] : [item, item]));
   } else {
     return new Map(Object.keys(src).map((key) => [key, src[key]]));
   }
 }

 values () {
   const valueMap = new Map();
   const vals = this.props.multiple ? this.props.value : [this.props.value];
   for (const [k, v] of this.source()) {
     if (vals.indexOf(k) !== -1) valueMap.set(k, v);
   }
   return valueMap;
 }

 select (key, event) {
   events.pauseEvent(event);
   const values = this.values(this.props.value);
   this.handleChange([key, ...values.keys()], event);
 }

 unselect (key, event) {
   if (!this.props.disabled) {
     const values = this.values(this.props.value);
     values.delete(key);
     this.handleChange([...values.keys()], event);
   }
 }

 renderSelected () {
   if (this.props.multiple) {
     const selectedItems = [...this.values()].map(([key, value]) => {
       return (
         <Chip
           key={key}
           className={style.value}
           deletable
           onDeleteClick={this.unselect.bind(this, key)}
         >
           {value}
         </Chip>
       );
     });

     return
{selectedItems}
;
   }
 }

 renderSuggestions () {
   const suggestions = [...this.suggestions()].map(([key, value]) => {
     const className = ClassNames(style.suggestion, {[style.active]: this.state.active === key});
     return (

         {value}

     );
   });

   const className = ClassNames(style.suggestions, {[style.up]: this.state.direction === 'up'});
   return
{suggestions}
;
 }

 render () {
   const {error, label, ...other} = this.props;
   const className = ClassNames(style.root, {
     [style.focus]: this.state.focus
   }, this.props.className);

   return (

       {this.props.selectedPosition === 'above' ? this.renderSelected() : null}
       <Input
         {...other}
         ref='input'
         className={style.input}
         error={error}
         label={label}
         onBlur={this.handleQueryBlur}
         onChange={this.handleQueryChange}
         onFocus={this.handleQueryFocus}
         onKeyDown={this.handleQueryKeyDown}
         onKeyUp={this.handleQueryKeyUp}
         value={this.state.query}
       />
       {this.renderSuggestions()}
       {this.props.selectedPosition === 'below' ? this.renderSelected() : null}

   );
 }
}

export default Autocomplete;
<|endoftext|>


<commit_before>$(document).ready(function(){ // wait for page to finish loading before executing jQuery code

    noXSS();

    // trigger ajax on CR drop-down to populate revision select
    $("#id_coderesource").on('change', function() {
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(
                "/api/coderesources/" + cr_id + "/revisions/",
                {}, // specify data as an object
                function(result) {
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_driver_revisions").empty().append(options);
                }
            );
        }
        else {
            $("#id_driver_revisions").html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    /* populate CR revision dropdown on selection of CodeResource
     * By *delegating* this event to #dependencyForms rather than each select.coderesource
     * directly, new dynamically-generated selects retain this behaviour. */
    $("#dependencyForms").on('change', 'select.coderesource', function() {
        var suffix = this.id.split('_')[2];
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(// shorthand for $.ajax where datatype is JSON and request method is GET. also parses JSON automatically.
                "/api/coderesources/" + cr_id + "/revisions/", // url
                {}, // specify data as an object
                function (result) { // callback for successful request
                    /* String appends are *much* faster than array joins in JS.
                     * More info at http://jsperf.com/append-string-vs-join-array
                     */
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_revisions_" + suffix).empty().append(options);
                }
            );
        }
        else {
            $("#id_revisions_" + suffix).html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    var dep_coderesource_options = document.getElementById("id_coderesource_0").options,
        numberOfDepForms = $('#dependencyForms > tr').length;

    // modify name attributes for extra input forms received from server
    for (var i = 0; i < numberOfDepForms; i++) {
        $('#id_coderesource_'+i).attr('name', 'coderesource_'+i);
        $('#id_revisions_'+i).attr('name', 'revisions_'+i);
        $('#id_path_'+i).attr('name', 'path_'+i);
        $('#id_filename_'+i).attr('name', 'filename_'+i);
    }

    // query button by id selector
    $("#addDependencyForm").click(function() {
        numberOfDepForms += 1;
        i = numberOfDepForms - 1; // zero-based index
        var $dependencyRow = $('
'),
            $select = $('<select class="coderesource" id="id_coderesource_' + i + '" name="coderesource_' + i + '">');

        for (var j = 0; j < dep_coderesource_options.length; j++) {
            $select.append($('<option>')
                    .attr('value', dep_coderesource_options[j].value)
                    .text(dep_coderesource_options[j].text));
        }

        $dependencyRow.append($('').append($select));
        $dependencyRow.append(
                '<select class="revisions" id="id_revisions_' + i + '" ' +
                'name="revisions_' + i + '">\n' +
                '<option value="" selected="selected">--- select a ' +
                'CodeResource first ---</option></select>	\n');

        // generate char fields
        $dependencyRow.append(
                '<input id="id_path_' + i + '" maxlength="255" ' +
                'name="path_' + i + '" type="text">	\n' +
                '<input id="id_filename_' + i + '" maxlength="255" ' +
                'name="filename_' + i + '" type="text">	\n');

        $('#dependencyForms').find('tr:last').after($dependencyRow);

    });

    $("#removeDependencyForm").click(function() {
        if (numberOfDepForms > 1) {
            numberOfDepForms -= 1;
            $('#dependencyForms').find('tr:last').remove();
        }
    });

    // add or subtract input forms
    var numberOfInputForms = $('#extraInputForms > tr').length;
    var io_cdt_options = document.getElementById("id_compounddatatype_in_0").options;

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfInputForms; i++) {
        $('#id_dataset_name_in_'+i).attr('name', 'dataset_name_in_'+i);
        $('#id_compounddatatype_in_'+i).attr('name', 'compounddatatype_in_'+i);
        $('#id_min_row_in_'+i).attr('name', 'min_row_in_'+i);
        $('#id_max_row_in_'+i).attr('name', 'max_row_in_'+i);
    }

    // append row to table
    $("#addInputForm").click(
        function () {
            numberOfInputForms += 1;
            i = numberOfInputForms - 1; // 0-indexing
            htmlStr = "
";
            htmlStr += ""+numberOfInputForms+"	";

            htmlStr += "<input id=\"id_dataset_name_in_" + i + "\" maxlength=\"128\" name=\"dataset_name_in_" + i + "\" type=\"text\" />	";
            htmlStr += "<select id=\"id_compounddatatype_in_" + i + "\" name=\"compounddatatype_in_" + i + "\">";
            for (var j = 0; j < io_cdt_options.length; j++) {
                htmlStr += "<option value=\"" + io_cdt_options[j].value + "\">" + io_cdt_options[j].text + "</option>";
            }
            htmlStr += "</select>	";
            htmlStr += "<input id=\"id_min_row_in_" + i + "\" class=\"shortIntField\" name=\"min_row_in_" + i + "\" type=\"number\" />	";
            htmlStr += "<input id=\"id_max_row_in_" + i + "\" class=\"shortIntField\" name=\"max_row_in_" + i + "\" type=\"number\" />	";
            htmlStr += "
";

            $('#extraInputForms').find('tr:last').after(htmlStr);
        }
    );
    $("#removeInputForm").click(
        function() {
            if (numberOfInputForms > 1) {
                numberOfInputForms -= 1;
                $('#extraInputForms').find('tr:last').remove();
            }
        }
    );

    // add or subtract output forms
    var numberOfOutputForms = $('#extraOutputForms > tr').length;
    // we can reuse options

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfOutputForms; i++) {
        $('#id_dataset_name_out_'+i).attr('name', 'dataset_name_out_'+i);
        $('#id_compounddatatype_out_'+i).attr('name', 'compounddatatype_out_'+i);
        $('#id_min_row_out_'+i).attr('name', 'min_row_out_'+i);
        $('#id_max_row_out_'+i).attr('name', 'max_row_out_'+i);
    }

    // append row to table
    $("#addOutputForm").click(
        function () {
            numberOfOutputForms += 1;
            i = numberOfOutputForms - 1; // 0-indexing
            htmlStr = "
";
            htmlStr += ""+numberOfOutputForms+"	";

            htmlStr += "<input id=\"id_dataset_name_out_" + i + "\" maxlength=\"128\" name=\"dataset_name_out_" + i + "\" type=\"text\" />	";
            htmlStr += "<select id=\"id_compounddatatype_out_" + i + "\" name=\"compounddatatype_out_" + i + "\">";
            for (var j = 0; j < io_cdt_options.length; j++) {
                htmlStr += "<option value=\"" + io_cdt_options[j].value + "\">" + io_cdt_options[j].text + "</option>";
            }
            htmlStr += "</select>	";
            htmlStr += "<input id=\"id_min_row_out_" + i + "\" class=\"shortIntField\" name=\"min_row_out_" + i + "\" type=\"number\" />	";
            htmlStr += "<input id=\"id_max_row_out_" + i + "\" class=\"shortIntField\" name=\"max_row_out_" + i + "\" type=\"number\" />	";
            htmlStr += "
";

            $('#extraOutputForms').find('tr:last').after(htmlStr);
        }
    );
    $("#removeOutputForm").click(
        function() {
            if (numberOfOutputForms > 1) {
                numberOfOutputForms -= 1;
                $('#extraOutputForms').find('tr:last').remove();
            }
        }
    );

    // Pack help text into an unobtrusive icon
    $('.helptext', 'form').each(function() {
        var $this = $(this);
        $this.wrapInner('').prepend('?');
    });

    $('a[rel="ctrl"]').on('click', function (e) {
        $(this).siblings('.fulltext').show().css({ top: e.pageY, left: e.pageX, 'z-index': 3 });
        setTimeout(function() { $('.fulltext').fadeOut(300); }, 5000);
    });

    // hide Method Family form if a pre-existing family is selected
    $('#id_family').on('change', function() {
        this_family = $(this).val();
        if (this_family === "") {
            $('#id_name').prop('disabled', false);
            $('#id_description').prop('disabled', false);
        } else {
            // TODO: ajax query populates these fields with values from DB
            $('#id_name').prop('disabled', true);
            $('#id_description').prop('disabled', true);
        }
    }).change(); // trigger on load

    // set default MethodFamily name to name of CodeResource
    $("#id_coderesource").on("change", function () {
        $("#id_revision_name").val($(this).children("option:selected").text());
    });
});
<commit_msg>Fix remaining HTML concatenation problems in method_add.js.<commit_after>$(document).ready(function(){ // wait for page to finish loading before executing jQuery code
    "use strict";

    noXSS();

    // trigger ajax on CR drop-down to populate revision select
    $("#id_coderesource").on('change', function() {
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(
                "/api/coderesources/" + cr_id + "/revisions/",
                {}, // specify data as an object
                function(result) {
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_driver_revisions").empty().append(options);
                }
            );
        }
        else {
            $("#id_driver_revisions").html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    /* populate CR revision dropdown on selection of CodeResource
     * By *delegating* this event to #dependencyForms rather than each select.coderesource
     * directly, new dynamically-generated selects retain this behaviour. */
    $("#dependencyForms").on('change', 'select.coderesource', function() {
        var suffix = this.id.split('_')[2];
        cr_id = this.value;
        if (cr_id !== "") {
            $.getJSON(// shorthand for $.ajax where datatype is JSON and request method is GET. also parses JSON automatically.
                "/api/coderesources/" + cr_id + "/revisions/", // url
                {}, // specify data as an object
                function (result) { // callback for successful request
                    /* String appends are *much* faster than array joins in JS.
                     * More info at http://jsperf.com/append-string-vs-join-array
                     */
                    var options = [];
                    $.each(result, function(index, value) {
                        options.push($('<option>').attr('value', value.id).text(
                                value.revision_number + ': ' +
                                value.revision_name));
                    });
                    $("#id_revisions_" + suffix).empty().append(options);
                }
            );
        }
        else {
            $("#id_revisions_" + suffix).html('<option value="">--- select a CodeResource first ---</option>');
        }
    }).change(); // trigger on load

    var dep_coderesource_options = document.getElementById("id_coderesource_0").options,
        numberOfDepForms = $('#dependencyForms > tr').length;

    // modify name attributes for extra input forms received from server
    for (var i = 0; i < numberOfDepForms; i++) {
        $('#id_coderesource_'+i).attr('name', 'coderesource_'+i);
        $('#id_revisions_'+i).attr('name', 'revisions_'+i);
        $('#id_path_'+i).attr('name', 'path_'+i);
        $('#id_filename_'+i).attr('name', 'filename_'+i);
    }

    // query button by id selector
    $("#addDependencyForm").click(function() {
        numberOfDepForms += 1;
        i = numberOfDepForms - 1; // zero-based index
        var $dependencyRow = $('
'),
            $select = $('<select class="coderesource" id="id_coderesource_' + i + '" name="coderesource_' + i + '">');

        for (var j = 0; j < dep_coderesource_options.length; j++) {
            $select.append($('<option>')
                    .attr('value', dep_coderesource_options[j].value)
                    .text(dep_coderesource_options[j].text));
        }

        $dependencyRow.append($('').append($select));
        $dependencyRow.append(
                '<select class="revisions" id="id_revisions_' + i + '" ' +
                'name="revisions_' + i + '">\n' +
                '<option value="" selected="selected">--- select a ' +
                'CodeResource first ---</option></select>	\n');

        // generate char fields
        $dependencyRow.append(
                '<input id="id_path_' + i + '" maxlength="255" ' +
                'name="path_' + i + '" type="text">	\n' +
                '<input id="id_filename_' + i + '" maxlength="255" ' +
                'name="filename_' + i + '" type="text">	\n');

        $('#dependencyForms').find('tr:last').after($dependencyRow);

    });

    $("#removeDependencyForm").click(function() {
        if (numberOfDepForms > 1) {
            numberOfDepForms -= 1;
            $('#dependencyForms').find('tr:last').remove();
        }
    });

    // add or subtract input forms
    var numberOfInputForms = $('#extraInputForms > tr').length;
    var io_cdt_options = document.getElementById("id_compounddatatype_in_0").options;

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfInputForms; i++) {
        $('#id_dataset_name_in_'+i).attr('name', 'dataset_name_in_'+i);
        $('#id_compounddatatype_in_'+i).attr('name', 'compounddatatype_in_'+i);
        $('#id_min_row_in_'+i).attr('name', 'min_row_in_'+i);
        $('#id_max_row_in_'+i).attr('name', 'max_row_in_'+i);
    }

    // append row to table
    $("#addInputForm").click(
        function () {
            numberOfInputForms += 1;
            i = numberOfInputForms - 1; // 0-indexing
            var $inputRow = $('
'),
                $select;
            $inputRow.append(""+numberOfInputForms+"	");

            $inputRow.append("<input id=\"id_dataset_name_in_" + i + "\" maxlength=\"128\" name=\"dataset_name_in_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_in_" + i + "\" name=\"compounddatatype_in_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $inputRow.append($('').append($select));
            $inputRow.append("<input id=\"id_min_row_in_" + i + "\" class=\"shortIntField\" name=\"min_row_in_" + i + "\" type=\"number\" />	");
            $inputRow.append("<input id=\"id_max_row_in_" + i + "\" class=\"shortIntField\" name=\"max_row_in_" + i + "\" type=\"number\" />	");

            $('#extraInputForms').find('tr:last').after($inputRow);
        }
    );
    $("#removeInputForm").click(
        function() {
            if (numberOfInputForms > 1) {
                numberOfInputForms -= 1;
                $('#extraInputForms').find('tr:last').remove();
            }
        }
    );

    // add or subtract output forms
    var numberOfOutputForms = $('#extraOutputForms > tr').length;
    // we can reuse options

    // modify name attributes for extra input forms received from server
    for (i = 0; i < numberOfOutputForms; i++) {
        $('#id_dataset_name_out_'+i).attr('name', 'dataset_name_out_'+i);
        $('#id_compounddatatype_out_'+i).attr('name', 'compounddatatype_out_'+i);
        $('#id_min_row_out_'+i).attr('name', 'min_row_out_'+i);
        $('#id_max_row_out_'+i).attr('name', 'max_row_out_'+i);
    }

    // append row to table
    $("#addOutputForm").click(
        function () {
            numberOfOutputForms += 1;
            i = numberOfOutputForms - 1; // 0-indexing
            var $outputRow = $('
'),
                $select;
            $outputRow.append(""+numberOfOutputForms+"	");

            $outputRow.append("<input id=\"id_dataset_name_out_" + i + "\" maxlength=\"128\" name=\"dataset_name_out_" + i + "\" type=\"text\" />	");
            $select = $("<select id=\"id_compounddatatype_out_" + i + "\" name=\"compounddatatype_out_" + i + "\">");
            for (var j = 0; j < io_cdt_options.length; j++) {
                $select.append($('<option>')
                        .attr('value', io_cdt_options[j].value)
                        .text(io_cdt_options[j].text));
            }
            $outputRow.append($('').append($select));
            $outputRow.append("<input id=\"id_min_row_out_" + i + "\" class=\"shortIntField\" name=\"min_row_out_" + i + "\" type=\"number\" />	");
            $outputRow.append("<input id=\"id_max_row_out_" + i + "\" class=\"shortIntField\" name=\"max_row_out_" + i + "\" type=\"number\" />	");

            $('#extraOutputForms').find('tr:last').after($outputRow);
        }
    );
    $("#removeOutputForm").click(
        function() {
            if (numberOfOutputForms > 1) {
                numberOfOutputForms -= 1;
                $('#extraOutputForms').find('tr:last').remove();
            }
        }
    );

    // Pack help text into an unobtrusive icon
    $('.helptext', 'form').each(function() {
        var $this = $(this);
        $this.wrapInner('').prepend('?');
    });

    $('a[rel="ctrl"]').on('click', function (e) {
        $(this).siblings('.fulltext').show().css({ top: e.pageY, left: e.pageX, 'z-index': 3 });
        setTimeout(function() { $('.fulltext').fadeOut(300); }, 5000);
    });

    // hide Method Family form if a pre-existing family is selected
    $('#id_family').on('change', function() {
        this_family = $(this).val();
        if (this_family === "") {
            $('#id_name').prop('disabled', false);
            $('#id_description').prop('disabled', false);
        } else {
            // TODO: ajax query populates these fields with values from DB
            $('#id_name').prop('disabled', true);
            $('#id_description').prop('disabled', true);
        }
    }).change(); // trigger on load

    // set default MethodFamily name to name of CodeResource
    $("#id_coderesource").on("change", function () {
        $("#id_revision_name").val($(this).children("option:selected").text());
    });
});
<|endoftext|>


<commit_before>var async = require('async'),
    _ = require('underscore'),
    glob = require('glob'),
    fs = require('graceful-fs'),
    path = require('path');

/**
 * generate a map of file operations to perform
 * @type {Function}
 * @param {String} tempDirectory the temporary-directory the source files are located in
 * @param {{ target:String|Object }} resource
 * @param {Function} callback( error, [ { source:String, destination:String, isDirectory:Boolean } ])
 */
module.exports = exports = function( tempDirectory, resource, callback ){
    var params = (typeof resource.target === 'string' ?
        mapSimpleTarget :
        mapComplexTarget
        )( tempDirectory, resource );
    //data structure is: [ [sources], [destinations] ]
    generateMap( tempDirectory, params[0], params[1], resource.exclude, callback );
};

var append = function( pre, val ){ return pre + val; };

//ensure there is a trailing slash on the directory
var trailSlash = function( dir ){
    return dir.lastIndexOf(path.sep) === dir.length -1 ? dir : dir + path.sep;
};

//stat to find if its a directory
//don't report errors cause these are still the raw globs, non-directories wont exist
var isDirectory = function( absGlob, callback ){
    fs.stat( absGlob, function( err, stat ){
        //if its an Error, IGNORE
        callback( null, stat ? stat.isDirectory() : false );
    });
};

/**
 * @private
 * append * * / * wildcard to directory
 * in order to get individual file lists
 * @param {String} cwd the current working directory
 * @param {Array<String>} pathTargets the targets i.e [ 'src/', '*.json' ]
 * @param {Function} callback( pathGlobs )
 */
 var globifyTargets = function( cwd, pathTargets, callback ){
    var absGlobs = pathTargets.map(_.partial(append,cwd));
    async.mapSeries( absGlobs, isDirectory, function( err, isDirs ){
        //never an error
        pathTargets = isDirs.map(function( isDir, i ){
            return isDir ? trailSlash(pathTargets[i]) + '**/*' : pathTargets[i];
        });
        callback( pathTargets );
    });
};

/**
 * @public
 * get the relative paths for all source files from the target keys
 * @param {String} cwd the current working directory for glob-matching
 * @param {Array} globs the strings of patterns to match
 * @param callback( error, sourceMap:Object )
 */
var getRelativeSources = function( cwd, globs, callback ){
    var globContent = function(k,fn){
        glob(k, { cwd: cwd, dot: true }, fn);
    };
    globifyTargets( cwd, globs, function( finalGlobs ){
        async.map(_.map(finalGlobs, _.partial(append,cwd)), globContent, function( err, sources ){
            if( err ){
                callback( err );
                return;
            }
            //remove the cwd from the resolved paths, for a relative-path
            sources = _.map(sources, function(sourceList, i ){
                return _.map( sourceList, function( s, j ){
                    return s.slice(cwd.length);
                });
            });
            callback( null, _.object(finalGlobs, sources) );
        });
    });
};

//if the resource object looks like { target: "destination/" }
var mapSimpleTarget = function( tempDirectory, resource ){
    return [ [''], [resource.target] ];
};

//if the resource object looks like { target: { 'src/' : 'dest/' } }
var mapComplexTarget = function( tempDirectory, resource ){
    return [ _.keys(resource.target), _.values(resource.target) ];
};

//generate a map of operations to perform
var generateMap = function( tempDirectory, sources, destinations, excludes, callback ){
    var resolveMap = function( sourceMap, callback ){
        var i = 0;
        var maps = _.map( sourceMap, function( relSrcs, glob ){
            var destination = destinations[i++];

            return _.map( relSrcs, function(src){
                var absSrc = tempDirectory + src;
                var g = glob;
                //if the glob was a wildcard there will be one level of
                //directory we wish to remove
                if(g.indexOf('**/*') >= 0){
                    g = g.slice(0, g.indexOf('**/*'));
                    src = src.slice(g.length);
                }
                //if its an individual file in the glob, make sure it doesnt end up
                //with a destination like package.json/package.json
                var dest = path.resolve(trailSlash(destination)+src);
                if( dest.lastIndexOf(src+'/'+src) === (dest.length - (src+'/'+src).length) ){
                    dest = dest.slice(0, -('/'+src).length);
                }
                return {
                    source: absSrc,
                    destination: dest,
                    isDirectory: fs.statSync(absSrc).isDirectory()
                };
            });
        });
        callback(null, _.flatten(maps) );
    };

    getRelativeSources( tempDirectory, sources, function( err, sourceMap ){
        if( err ){
            callback(err);
            return;
        }

        if( excludes && excludes.length ){
            getRelativeSources( tempDirectory, excludes, function( err, exclusions ){
                _.each( exclusions, function( excl, target ){
                    var wildCardIndex = target.indexOf('**/*');
                    if( wildCardIndex === target.length - '**/*'.length) {
                        excl.push( target.substr(0, target.indexOf('**/*')-1) );
                    }
                });
                exclusions = _.flatten(_.values(exclusions));
                var filterExclusions = function( src ){
                    return exclusions.indexOf( src ) < 0;
                };
                for( var target in sourceMap ){
                    sourceMap[target] = _.filter( sourceMap[target], filterExclusions );
                }
                resolveMap(sourceMap, callback);
            });
        } else {
            resolveMap(sourceMap, callback);
        }

    });
};

exports.globify = globifyTargets;
exports.getRelativeSources = getRelativeSources;
<commit_msg>fixes createOperationCollection and globs for windows issues related to path separator<commit_after>var async = require('async'),
    _ = require('underscore'),
    glob = require('glob'),
    fs = require('graceful-fs'),
    path = require('path');

/**
 * generate a map of file operations to perform
 * @type {Function}
 * @param {String} tempDirectory the temporary-directory the source files are located in
 * @param {{ target:String|Object }} resource
 * @param {Function} callback( error, [ { source:String, destination:String, isDirectory:Boolean } ])
 */
module.exports = exports = function( tempDirectory, resource, callback ){
    var params = (typeof resource.target === 'string' ?
        mapSimpleTarget :
        mapComplexTarget
        )( tempDirectory, resource );
    //ensure tempDirectory ends with OS-appropriate delimiter
    if(tempDirectory.lastIndexOf(path.sep) !== tempDirectory.length -1){
        tempDirectory += path.sep;
    }
    //data structure is: [ [sources], [destinations] ]
    generateMap( tempDirectory, params[0], params[1], resource.exclude, callback );
};

var append = function( pre, val ){ return pre + val; };

//ensure there is a trailing slash on the directory
var trailSlash = function( dir ){
    return dir.lastIndexOf('/') === dir.length -1 ? dir : dir + '/';
};

//stat to find if its a directory
//don't report errors cause these are still the raw globs, non-directories wont exist
var isDirectory = function( absGlob, callback ){
    fs.stat( absGlob, function( err, stat ){
        //if its an Error, IGNORE
        callback( null, stat ? stat.isDirectory() : false );
    });
};

/**
 * @private
 * append * * / * wildcard to directory
 * in order to get individual file lists
 * @param {String} cwd the current working directory
 * @param {Array<String>} pathTargets the targets i.e [ 'src/', '*.json' ]
 * @param {Function} callback( pathGlobs )
 */
 var globifyTargets = function( cwd, pathTargets, callback ){
    var absGlobs = pathTargets.map(_.partial(append,cwd));
    async.mapSeries( absGlobs, isDirectory, function( err, isDirs ){
        //never an error
        pathTargets = isDirs.map(function( isDir, i ){
            return isDir ? trailSlash(pathTargets[i]) + '**/*' : pathTargets[i];
        });
        callback( pathTargets );
    });
};

/**
 * @public
 * get the relative paths for all source files from the target keys
 * @param {String} cwd the current working directory for glob-matching
 * @param {Array} globs the strings of patterns to match
 * @param callback( error, sourceMap:Object )
 */
var getRelativeSources = function( cwd, globs, callback ){
    var globContent = function(k,fn){
        glob(k, { cwd: cwd, dot: true }, fn);
    };
    globifyTargets( cwd, globs, function( finalGlobs ){
        async.map(_.map(finalGlobs, _.partial(append,cwd)), globContent, function( err, sources ){
            if( err ){
                callback( err );
                return;
            }
            //remove the cwd from the resolved paths, for a relative-path
            sources = _.map(sources, function(sourceList, i ){
                return _.map( sourceList, function( s, j ){
                    return s.slice(cwd.length);
                });
            });
            callback( null, _.object(finalGlobs, sources) );
        });
    });
};

//if the resource object looks like { target: "destination/" }
var mapSimpleTarget = function( tempDirectory, resource ){
    return [ [''], [resource.target] ];
};

//if the resource object looks like { target: { 'src/' : 'dest/' } }
var mapComplexTarget = function( tempDirectory, resource ){
    return [ _.keys(resource.target), _.values(resource.target) ];
};

//generate a map of operations to perform
var generateMap = function( tempDirectory, sources, destinations, excludes, callback ){
    var resolveMap = function( sourceMap, callback ){
        var i = 0;
        var maps = _.map( sourceMap, function( relSrcs, glob ){
            var destination = destinations[i++];

            return _.map( relSrcs, function(src){
                var absSrc = tempDirectory + src;
                var g = glob;
                //if the glob was a wildcard there will be one level of
                //directory we wish to remove
                if(g.indexOf('**/*') >= 0){
                    g = g.slice(0, g.indexOf('**/*'));
                    src = src.slice(g.length);
                }
                //if its an individual file in the glob, make sure it doesnt end up
                //with a destination like package.json/package.json
                var dest = path.resolve(trailSlash(destination)+src);
                var badFilename = src + path.sep + src;
                if( dest.lastIndexOf(badFilename) === (dest.length - badFilename.length) ){
                    dest = dest.slice(0, -(path.sep+src).length);
                }
                return {
                    source: absSrc,
                    destination: dest,
                    isDirectory: fs.statSync(absSrc).isDirectory()
                };
            });
        });
        callback(null, _.flatten(maps) );
    };

    getRelativeSources( tempDirectory, sources, function( err, sourceMap ){
        if( err ){
            callback(err);
            return;
        }

        if( excludes && excludes.length ){
            getRelativeSources( tempDirectory, excludes, function( err, exclusions ){
                _.each( exclusions, function( excl, target ){
                    var wildCardIndex = target.indexOf('**/*');
                    if( wildCardIndex === target.length - '**/*'.length) {
                        excl.push( target.substr(0, target.indexOf('**/*')-1) );
                    }
                });
                exclusions = _.flatten(_.values(exclusions));
                var filterExclusions = function( src ){
                    return exclusions.indexOf( src ) < 0;
                };
                for( var target in sourceMap ){
                    sourceMap[target] = _.filter( sourceMap[target], filterExclusions );
                }
                resolveMap(sourceMap, callback);
            });
        } else {
            resolveMap(sourceMap, callback);
        }

    });
};

exports.globify = globifyTargets;
exports.getRelativeSources = getRelativeSources;
<|endoftext|>


<commit_before>import React from 'react';

class Socials extends React.Component {
    render() {
        return (

Socials

        );
    }
}

export { Socials };
<commit_msg>Update Admin Socials component placeholder<commit_after>import React from 'react';

class Socials extends React.Component {
    render() {
        return (

Socials placeholder

        );
    }
}

export { Socials };
<|endoftext|>


<commit_before>/**
 * @module  dialog
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 */

function parseDict(dict) {
	return {
		cancel: _.indexOf(dict, _.findWhere(dict, { cancel: true })),
		preferred: _.indexOf(dict, _.findWhere(dict, { preferred: true })),
		destructive: _.indexOf(dict, _.findWhere(dict, { destructive: true })),
	};
}

function onClickDict(e, dict, dialog) {
	if (OS_IOS && e.index == e.source.cancel) return;
	if (OS_ANDROID && e.cancel === true) return;

	if (dict != null && _.isObject(dict[+e.index]) && _.isFunction(dict[+e.index].callback)) {
		dict[+e.index].callback.call(dialog, e);
	}
}

/**
 * Create and show an Alert Dialog
 * @param  {String}		title    		The title
 * @param  {String}		message    		The message
 * @param  {Function}	[callback] 		The callback to invokie when clicking **OK**
 * @param  {Object}	 	[ext] 			Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogAlert(title, message, callback, ext) {
	if (OS_ANDROID && _.isEmpty(title)) {
		title = Ti.App.name;
	}

	var dialog = Ti.UI.createAlertDialog(_.extend({
		title: title,
		message: message,
		ok: 'OK'
	}, ext));

	if (_.isFunction(callback)) {
		dialog.addEventListener('click', callback);
	}

	dialog.show();
	return dialog;
}
exports.alert = dialogAlert;

/**
 * Create and show a confirm dialog
 *
 * @param  {String}		title       	The title
 * @param  {String}		message        The message
 * @param  {Object}		dict     		Buttons as Dictionary
 * @param  {Object}		ext 				Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogConfirm(title, message, dict, ext) {
	var dialog = Ti.UI.createAlertDialog(_.extend(parseDict(dict), {
		buttonNames: _.pluck(dict, 'title'),
		title: title,
		message: message
	}, ext));

	dialog.addEventListener('click', function(e) {
		onClickDict(e, dict, dialog);
	});

	dialog.show();
	return dialog;
}
exports.confirm = dialogConfirm;

/**
 * Create and show an Option Dialog
 *
 * @param  {String}		title 			The title
 * @param  {Object}    	dict 				Buttons as Dictionary
 * @param  {Object}		[ext] 			Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogOption(title, dict, ext) {
	var pdict = parseDict(dict);
	if (OS_ANDROID && pdict.cancel !== -1) {
		// Android doesn't need a Cancel button, just hit "Back"
		dict.splice(pdict.cancel, 1);
	}

	var dialog = Ti.UI.createOptionDialog(_.extend(pdict, {
		options: _.pluck(dict, 'title'),
		title: title
	}, ext));

	dialog.addEventListener('click', function(e) {
		onClickDict(e, dict, dialog);
	});

	dialog.show();
	return dialog;
}
exports.option = dialogOption;

/**
 * Create and show a confirm dialog with *Cancel* and *Yes* button.
 *
 * @param  {String}   	title 				The title
 * @param  {String}   	message   			The message
 * @param  {Function} 	[callback]    		The callback to invoke when clicking *Yes*.
 * @param  {String}   	[buttonTitle]		Alternative title for *Yes*.
 * @return {Ti.UI.AlertDialog}
 */
function confirmYes(title, message, callback, buttonTitle) {
	return dialogConfirm(title, message, [
		{
			title: L('cancel', 'Cancel'),
			cancel: true
		},
		{
			title: buttonTitle || L('yes', 'Yes'),
			callback: callback,
			preferred: true
		}
	]);
}
exports.confirmYes = confirmYes;

/**
 * Create a prompt dialog.
 *
 * @param  {String}   	title 				The title
 * @param  {String}   	message   			The message
 * @param  {Object}    	dict 					Buttons as Dictionary
 * @param  {Object}		[ext] 				Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogPrompt(title, message, dict, ext) {
	if (OS_IOS) {

		return dialogConfirm(title, message, dict, _.extend({
			style: Ti.UI.iOS.AlertDialogStyle.PLAIN_TEXT_INPUT
		}, ext));

	} else if (OS_ANDROID) {

		_.each(dict, function(d) {
			if (d.cancel === true || d.callback == null) return;
			d._origCallback = d.callback;
			d.callback = function(e) {
				_.extend(e, { text: this.androidView.value });
				d._origCallback.call(this, e);
			};
		});

		return dialogConfirm(title, message, dict, _.extend({
			androidView: Ti.UI.createTextField({
				value: (ext ? ext.value : '')
			})
		}, ext));

	}
}
exports.prompt = dialogPrompt;

/**
 * Create a checkbox prompt dialog.
 * Android only.
 *
 * @param  {String}   	[title] 	The title.
 * @param  {String}   	[message]   The message.
 * @param  {Object}   	[options] 	The options as an Array of primitive values or Literal objects with title/value. Title can be a primitive or a Literal object of Ti.UI.Label options.
 * @param  {Object}   	[values] 	A list of preselected values.
 * @param  {Object}   	[dict] 		Buttons as Dictionary.
 * @param  {Object}		[ext] 		Extends the `AlertDialog`. The property androidView is ignored.
 * @return {Ti.UI.AlertDialog}
 */
function dialogCheckbox(title, message, options, values, dict, ext) {
	if (OS_IOS) {

		Ti.API.error('Dialog: Dialog.checkbox is not supported yet on iOS');
		return false;

	} else if (OS_ANDROID) {

		var container = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE
		});

		var inner_container = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			top: _.isEmpty(message) ? 20 : 0,
			bottom: _.isEmpty(dict) ? 24 : 0,
			left: 24,
			right: 24,
			layout: 'vertical'
		});

		values = values || [];

		_.each(options, function(item) {
			var value = _.isObject(item) ? item.value : item;
			var title = _.isObject(item) ? item.title : item;

			var item_container = Ti.UI.createView({
				width: Ti.UI.FILL,
				height: 48
			});

			item_container.input = Ti.UI.createSwitch({
				style: Ti.UI.Android.SWITCH_STYLE_CHECKBOX,
				value: values.indexOf(value) >= 0 ? true : false,
				width: Ti.UI.SIZE,
				left: 0,
			});
			item_container.add(item_container.input);

			item_container.add(Ti.UI.createLabel(_.extend({
				left: 36,
				width: Ti.UI.FILL
			}, _.isObject(title) ? title : { text: title })));

			item_container.value = value;

			inner_container.add(item_container);
		});

		container.add(inner_container);

		_.each(dict, function(d) {
			if (d.cancel === true || d.callback == null) return;
			d._origCallback = d.callback;
			d.callback = function(e) {
				var values = [];

				_.each(inner_container.children, function(item) {
					if (item.input.getValue() == true) {
						values.push(item.value);
					}
				});
				_.extend(e, {
					values: values
				});

				d._origCallback.call(this, e);
			};
		});

		return dialogConfirm(title, message, dict, _.extend({
			androidView: container
		}, _.omit(ext, 'androidView')));

	}
}
exports.checkbox = dialogCheckbox;
<commit_msg>Set "canceledOnTouchOutside" to false in Dialog.alert()<commit_after>/**
 * @module  dialog
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 */

function parseDict(dict) {
	return {
		cancel: _.indexOf(dict, _.findWhere(dict, { cancel: true })),
		preferred: _.indexOf(dict, _.findWhere(dict, { preferred: true })),
		destructive: _.indexOf(dict, _.findWhere(dict, { destructive: true })),
	};
}

function onClickDict(e, dict, dialog) {
	if (OS_IOS && e.index == e.source.cancel) return;
	if (OS_ANDROID && e.cancel === true) return;

	if (dict != null && _.isObject(dict[+e.index]) && _.isFunction(dict[+e.index].callback)) {
		dict[+e.index].callback.call(dialog, e);
	}
}

/**
 * Create and show an Alert Dialog
 * @param  {String}		title    		The title
 * @param  {String}		message    		The message
 * @param  {Function}	[callback] 		The callback to invokie when clicking **OK**
 * @param  {Object}	 	[ext] 			Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogAlert(title, message, callback, ext) {
	if (OS_ANDROID && _.isEmpty(title)) {
		title = Ti.App.name;
	}

	var dialog = Ti.UI.createAlertDialog(_.extend({
		title: title,
		message: message,
		ok: 'OK',
		canceledOnTouchOutside: false,
	}, ext));

	if (_.isFunction(callback)) {
		dialog.addEventListener('click', callback);
	}

	dialog.show();
	return dialog;
}
exports.alert = dialogAlert;

/**
 * Create and show a confirm dialog
 *
 * @param  {String}		title       	The title
 * @param  {String}		message        The message
 * @param  {Object}		dict     		Buttons as Dictionary
 * @param  {Object}		ext 				Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogConfirm(title, message, dict, ext) {
	var dialog = Ti.UI.createAlertDialog(_.extend(parseDict(dict), {
		buttonNames: _.pluck(dict, 'title'),
		title: title,
		message: message
	}, ext));

	dialog.addEventListener('click', function(e) {
		onClickDict(e, dict, dialog);
	});

	dialog.show();
	return dialog;
}
exports.confirm = dialogConfirm;

/**
 * Create and show an Option Dialog
 *
 * @param  {String}		title 			The title
 * @param  {Object}    	dict 				Buttons as Dictionary
 * @param  {Object}		[ext] 			Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogOption(title, dict, ext) {
	var pdict = parseDict(dict);
	if (OS_ANDROID && pdict.cancel !== -1) {
		// Android doesn't need a Cancel button, just hit "Back"
		dict.splice(pdict.cancel, 1);
	}

	var dialog = Ti.UI.createOptionDialog(_.extend(pdict, {
		options: _.pluck(dict, 'title'),
		title: title
	}, ext));

	dialog.addEventListener('click', function(e) {
		onClickDict(e, dict, dialog);
	});

	dialog.show();
	return dialog;
}
exports.option = dialogOption;

/**
 * Create and show a confirm dialog with *Cancel* and *Yes* button.
 *
 * @param  {String}   	title 				The title
 * @param  {String}   	message   			The message
 * @param  {Function} 	[callback]    		The callback to invoke when clicking *Yes*.
 * @param  {String}   	[buttonTitle]		Alternative title for *Yes*.
 * @return {Ti.UI.AlertDialog}
 */
function confirmYes(title, message, callback, buttonTitle) {
	return dialogConfirm(title, message, [
		{
			title: L('cancel', 'Cancel'),
			cancel: true
		},
		{
			title: buttonTitle || L('yes', 'Yes'),
			callback: callback,
			preferred: true
		}
	]);
}
exports.confirmYes = confirmYes;

/**
 * Create a prompt dialog.
 *
 * @param  {String}   	title 				The title
 * @param  {String}   	message   			The message
 * @param  {Object}    	dict 					Buttons as Dictionary
 * @param  {Object}		[ext] 				Extends the `AlertDialog`
 * @return {Ti.UI.AlertDialog}
 */
function dialogPrompt(title, message, dict, ext) {
	if (OS_IOS) {

		return dialogConfirm(title, message, dict, _.extend({
			style: Ti.UI.iOS.AlertDialogStyle.PLAIN_TEXT_INPUT
		}, ext));

	} else if (OS_ANDROID) {

		_.each(dict, function(d) {
			if (d.cancel === true || d.callback == null) return;
			d._origCallback = d.callback;
			d.callback = function(e) {
				_.extend(e, { text: this.androidView.value });
				d._origCallback.call(this, e);
			};
		});

		return dialogConfirm(title, message, dict, _.extend({
			androidView: Ti.UI.createTextField({
				value: (ext ? ext.value : '')
			})
		}, ext));

	}
}
exports.prompt = dialogPrompt;

/**
 * Create a checkbox prompt dialog.
 * Android only.
 *
 * @param  {String}   	[title] 	The title.
 * @param  {String}   	[message]   The message.
 * @param  {Object}   	[options] 	The options as an Array of primitive values or Literal objects with title/value. Title can be a primitive or a Literal object of Ti.UI.Label options.
 * @param  {Object}   	[values] 	A list of preselected values.
 * @param  {Object}   	[dict] 		Buttons as Dictionary.
 * @param  {Object}		[ext] 		Extends the `AlertDialog`. The property androidView is ignored.
 * @return {Ti.UI.AlertDialog}
 */
function dialogCheckbox(title, message, options, values, dict, ext) {
	if (OS_IOS) {

		Ti.API.error('Dialog: Dialog.checkbox is not supported yet on iOS');
		return false;

	} else if (OS_ANDROID) {

		var container = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE
		});

		var inner_container = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			top: _.isEmpty(message) ? 20 : 0,
			bottom: _.isEmpty(dict) ? 24 : 0,
			left: 24,
			right: 24,
			layout: 'vertical'
		});

		values = values || [];

		_.each(options, function(item) {
			var value = _.isObject(item) ? item.value : item;
			var title = _.isObject(item) ? item.title : item;

			var item_container = Ti.UI.createView({
				width: Ti.UI.FILL,
				height: 48
			});

			item_container.input = Ti.UI.createSwitch({
				style: Ti.UI.Android.SWITCH_STYLE_CHECKBOX,
				value: values.indexOf(value) >= 0 ? true : false,
				width: Ti.UI.SIZE,
				left: 0,
			});
			item_container.add(item_container.input);

			item_container.add(Ti.UI.createLabel(_.extend({
				left: 36,
				width: Ti.UI.FILL
			}, _.isObject(title) ? title : { text: title })));

			item_container.value = value;

			inner_container.add(item_container);
		});

		container.add(inner_container);

		_.each(dict, function(d) {
			if (d.cancel === true || d.callback == null) return;
			d._origCallback = d.callback;
			d.callback = function(e) {
				var values = [];

				_.each(inner_container.children, function(item) {
					if (item.input.getValue() == true) {
						values.push(item.value);
					}
				});
				_.extend(e, {
					values: values
				});

				d._origCallback.call(this, e);
			};
		});

		return dialogConfirm(title, message, dict, _.extend({
			androidView: container
		}, _.omit(ext, 'androidView')));

	}
}
exports.checkbox = dialogCheckbox;
<|endoftext|>


<commit_before>import CSVExport from './CSVExport';
import MultiSearch from './MultiSearch';
import React, { Component } from 'react';
import TicketTable from '../Tickets/Table';
import { connect } from 'react-redux';

class Table extends Component {

  onCustomFilter(property){
    if(property === 'tags') {
      return (<MultiSearch
                items={this.props.items}
                query={this.props.query}
                onFilter={this.props.search}
              />);
    }
  }

  render() {
    const columns = this.props.fields.map((field) => {
      const column = {
        property: field.name,
        header: {
          label: field.label,
        },
        filterType: field.filterType,
      };

      if (field.filterType === 'custom') {
        column.customFilter = () => {
          return this.onCustomFilter(field.name);
        }
      }

      return column;
    });

    const userColumns = columns.map((field) => field.property).filter((column) => this.props.userColumns[column]);

    return (

        <TicketTable
          id="table-search-items"
          query={this.props.query}
          search={this.props.search}
          tickets={this.props.items}
          toggleColumn={this.props.toggleColumn}
          userColumns={userColumns}
          columns={columns}
        />
        <CSVExport
          items={this.props.items}
          fields={this.props.fields}
          query={this.props.query}
          visibleItems={this.props.visibleItems}
        />

    );
  }
}

const mapStateToProps = state => ({
  items: state.budgets.items,
  fields: state.budgets.fields,
  query: state.budgets.query,
  userColumns: state.budgets.userColumns,
  visibleItems: state.budgets.visibleItems,
});

export default connect(mapStateToProps)(Table);<commit_msg>Reformat<commit_after>import CSVExport from './CSVExport';
import MultiSearch from './MultiSearch';
import React, { Component } from 'react';
import TicketTable from '../Tickets/Table';
import { connect } from 'react-redux';

class Table extends Component {

  onCustomFilter(property){
    if(property === 'tags') {
      return (
        <MultiSearch
          items={this.props.items}
          query={this.props.query}
          onFilter={this.props.search}
        />
      );
    }
  }

  render() {
    const columns = this.props.fields.map((field) => {
      const column = {
        property: field.name,
        header: {
          label: field.label,
        },
        filterType: field.filterType,
      };

      if (field.filterType === 'custom') {
        column.customFilter = () => {
          return this.onCustomFilter(field.name);
        }
      }

      return column;
    });

    const userColumns = columns.map((field) => field.property).filter((column) => this.props.userColumns[column]);

    return (

        <TicketTable
          id="table-search-items"
          query={this.props.query}
          search={this.props.search}
          tickets={this.props.items}
          toggleColumn={this.props.toggleColumn}
          userColumns={userColumns}
          columns={columns}
        />
        <CSVExport
          items={this.props.items}
          fields={this.props.fields}
          query={this.props.query}
          visibleItems={this.props.visibleItems}
        />

    );
  }
}

const mapStateToProps = state => ({
  items: state.budgets.items,
  fields: state.budgets.fields,
  query: state.budgets.query,
  userColumns: state.budgets.userColumns,
  visibleItems: state.budgets.visibleItems,
});

export default connect(mapStateToProps)(Table);<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Item from './Item';
import ItemForm from './Item/Form';

class Budgets extends Component {
	constructor() {
		super();

    this.setEdit  = this.setEdit.bind(this);
    this.handleNewSubmit = this.handleNewSubmit.bind(this);
    this.onEdit   = this.onEdit.bind(this);
    this.onAdd   = this.onAdd.bind(this);
    this.onDelete = this.onDelete.bind(this);

    this.state = {
      items: [
        {
          id: 1,
          summary: "Klevu discovery & calls",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: "Discovery",
            value: 6,
          },
          descriptions: {
            workplan: [
              "Time for communication with Klevu.",
            ],
            budget: [],
            assumptions: [
              "Accounts for one onboarding call."
            ],
            exclusions: [],
          },
          tags: "klevu",
        },
        {
          id: 2,
          summary: "Install Klevu extension",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: 'Dev',
            value: 4,
          },
          descriptions: {
            workplan: [
              "Install Klevu extension using composer.",
            ],
            assumptions: [
              "Install extension once using code provided by Klevu."
            ],
          },
          tags: "klevu",
        },
        {
          id: 3,
          summary: "Configure Klevu flyout",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: 'Dev',
            value: 4,
          },
          descriptions: {
            workplan: [
              "Use Klevu control panel to choose between autocomplete and faceted.",
            ],
            assumptions: [
              "Use one of out of box options provided by Klevu (autocomplete or faceted) without customization.",
            ],
          },
          tags: "klevu",
        },
      ],
      activeEdit: false,
      editItem: {
          summary:  "",
          phase:    "",
          feature:  "",
          budgetHours: {
            column: "",
            value: 0,
          },
          descriptions: {
            workplan: [],
            budget: [],
            assumptions: [],
            exclusions: [],
          },
          tags: "",
      },
    };
  }

  setEdit(bool, itemKey){
    const index = this.indexByKey(itemKey)
    const editItem = this.state.items[index];

    this.setState({
      activeEdit: bool,
      editItem: {
          summary:  editItem.summary,
          phase:    editItem.phase,
          feature:  editItem.feature,
          budgetColumn: editItem.budgetHours.column,
          budgetValue: editItem.budgetHours.value,
          workplan: [editItem.descriptions.workplan],
          budget: [editItem.descriptions.budget],
          assumptions: [editItem.descriptions.assumptions],
          exclusions: [editItem.descriptions.exclusions],
          tags: editItem.tags,
      },
    });
    console.log('Edit: ', this.state.activeEdit);
  }

  indexByKey(key){
    let index = -1;
    let i = 0;
    this.state.items.map(item => (item.summary == key) ? index = i : i++);

    return index;
  }

  handleNewSubmit(item){
    console.log('Item: ', item);
    if (this.state.activeEdit) {
      this.onEdit(item);
    } else {
      this.onAdd(item);
    }
  }

  onAdd(item){
      this.setState({
      items: [
        ...this.state.items,
        item,
      ],
    });
  }

  onEdit(item){
    const index = this.indexByKey(item.summary);

    this.setState({
        items: [
          ...this.state.items.slice(0,index),
          item,
          ...this.state.items.slice(index + 1)
        ],
        activeEdit: false,
        editItem: {
          summary:  "",
          phase:    "",
          feature:  "",
          budgetColumn: "",
          budgetValue: 0,
          workplan: [],
          budget: [],
          assumptions: [],
          exclusions: [],
          tags: "",
      },
      }
    )
    console.log(item.summary + ' edited');
  }

  onDelete(itemId) {
    this.setState({
      items: this.state.items.filter(item => item.id !== itemId),
    });
  }

  render() {
    return (

Budget Tool

            <ItemForm
              onSubmit={this.handleNewSubmit}
              activeEdit={this.state.activeEdit}
              editItem={this.state.editItem}
            />

 Items

            {this.state.items.map(item => (
              <Item
                budgetHours={item.budgetHours}
                descriptions={item.descriptions}
                feature={item.feature}
                key={item.summary}
                phase={item.phase}
                summary={item.summary}
                itemId={item.id}
                tags={item.tags}
                setEdit={this.setEdit}
                onDelete={this.onDelete}
              />
            ))}

    );
  }
}

export default Budgets;
<commit_msg>Pass the entire item as a prop<commit_after>import React, { Component } from 'react';
import Item from './Item';
import ItemForm from './Item/Form';

class Budgets extends Component {
	constructor() {
		super();

    this.setEdit  = this.setEdit.bind(this);
    this.handleNewSubmit = this.handleNewSubmit.bind(this);
    this.onEdit   = this.onEdit.bind(this);
    this.onAdd   = this.onAdd.bind(this);
    this.onDelete = this.onDelete.bind(this);

    this.state = {
      items: [
        {
          id: 1,
          summary: "Klevu discovery & calls",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: "Discovery",
            value: 6,
          },
          descriptions: {
            workplan: [
              "Time for communication with Klevu.",
            ],
            budget: [],
            assumptions: [
              "Accounts for one onboarding call."
            ],
            exclusions: [],
          },
          tags: "klevu",
        },
        {
          id: 2,
          summary: "Install Klevu extension",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: 'Dev',
            value: 4,
          },
          descriptions: {
            workplan: [
              "Install Klevu extension using composer.",
            ],
            assumptions: [
              "Install extension once using code provided by Klevu."
            ],
          },
          tags: "klevu",
        },
        {
          id: 3,
          summary: "Configure Klevu flyout",
          phase: "dev/Klevu",
          feature: "Klevu",
          budgetHours: {
            column: 'Dev',
            value: 4,
          },
          descriptions: {
            workplan: [
              "Use Klevu control panel to choose between autocomplete and faceted.",
            ],
            assumptions: [
              "Use one of out of box options provided by Klevu (autocomplete or faceted) without customization.",
            ],
          },
          tags: "klevu",
        },
      ],
      activeEdit: false,
      editItem: {
          summary:  "",
          phase:    "",
          feature:  "",
          budgetHours: {
            column: "",
            value: 0,
          },
          descriptions: {
            workplan: [],
            budget: [],
            assumptions: [],
            exclusions: [],
          },
          tags: "",
      },
    };
  }

  setEdit(bool, itemKey){
    const index = this.indexByKey(itemKey)
    const editItem = this.state.items[index];

    this.setState({
      activeEdit: bool,
      editItem: {
          summary:  editItem.summary,
          phase:    editItem.phase,
          feature:  editItem.feature,
          budgetColumn: editItem.budgetHours.column,
          budgetValue: editItem.budgetHours.value,
          workplan: [editItem.descriptions.workplan],
          budget: [editItem.descriptions.budget],
          assumptions: [editItem.descriptions.assumptions],
          exclusions: [editItem.descriptions.exclusions],
          tags: editItem.tags,
      },
    });
    console.log('Edit: ', this.state.activeEdit);
  }

  indexByKey(key){
    let index = -1;
    let i = 0;
    this.state.items.map(item => (item.summary == key) ? index = i : i++);

    return index;
  }

  handleNewSubmit(item){
    console.log('Item: ', item);
    if (this.state.activeEdit) {
      this.onEdit(item);
    } else {
      this.onAdd(item);
    }
  }

  onAdd(item){
      this.setState({
      items: [
        ...this.state.items,
        item,
      ],
    });
  }

  onEdit(item){
    const index = this.indexByKey(item.summary);

    this.setState({
        items: [
          ...this.state.items.slice(0,index),
          item,
          ...this.state.items.slice(index + 1)
        ],
        activeEdit: false,
        editItem: {
          summary:  "",
          phase:    "",
          feature:  "",
          budgetColumn: "",
          budgetValue: 0,
          workplan: [],
          budget: [],
          assumptions: [],
          exclusions: [],
          tags: "",
      },
      }
    )
    console.log(item.summary + ' edited');
  }

  onDelete(itemId) {
    this.setState({
      items: this.state.items.filter(item => item.id !== itemId),
    });
  }

  render() {
    return (

Budget Tool

            <ItemForm
              onSubmit={this.handleNewSubmit}
              activeEdit={this.state.activeEdit}
              item={this.state.editItem}
            />

 Items

            {this.state.items.map(item => (
              <Item
                item={item}
                setEdit={this.setEdit}
                onDelete={this.onDelete}
              />
            ))}

    );
  }
}

export default Budgets;
<|endoftext|>


<commit_before>// the eslint "no-unused-expressions" rule is triggered by the `expect`
// assertions in the tests. So, in order to avoid problems with eslint, I'm
// disabling that rule in this file
//
/* eslint-disable no-unused-expressions */

import React from 'react';
import { shallow } from 'enzyme';
import chai from 'chai';
import Dropdown from './Dropdown';

/*
Dropdown Behaviour

+ when the component is initialized
    + no validation error message is displayed (`hasValidated` = false, `isValid` = true or false, depending)
    + the onValidation handler is called with `hasValidated` = false, `isValid` = true or false, `validationMessage` = whatever

+ when the user selects an item from the Dropdown
    + `hasValidated` is set to true
    + the validation error message is display as necessary
    + the onValidation callback is called
    + the onChange callback is called

+ when the user tabs or clicks out of the control
    + `hasValidated` is set to true
    + the validation error message is display as necessary
    + the onValidation callback is called
    + the onChange callback is called
*/

/*
on initialization, the Dropdown component
    should be a div.form-group
    should have a label, if label is set
    should not have a label, if label is not set
    should have a select.form-control
    should have the correct number of option elements (n+1) if includeNull=true
    should have the correct number of option elements (n) if includeNull=false
*/
<commit_msg>added set of specs for markup<commit_after>// the eslint "no-unused-expressions" rule is triggered by the `expect`
// assertions in the tests. So, in order to avoid problems with eslint, I'm
// disabling that rule in this file
//
/* eslint-disable no-unused-expressions */

import React from 'react';
import { shallow } from 'enzyme';
import chai from 'chai';
import Dropdown from './Dropdown';

/*
Dropdown Behaviour

+ when the component is initialized
    + no validation error message is displayed (`hasValidated` = false, `isValid` = true or false, depending)
    + the onValidation handler is called with `hasValidated` = false, `isValid` = true or false, `validationMessage` = whatever

+ when the user selects an item from the Dropdown
    + `hasValidated` is set to true
    + the validation error message is display as necessary
    + the onValidation callback is called
    + the onChange callback is called

+ when the user tabs or clicks out of the control
    + `hasValidated` is set to true
    + the validation error message is display as necessary
    + the onValidation callback is called
    + the onChange callback is called
*/

/*
on initialization, the Dropdown component
    should be a div.form-group
    should have a label, if label is set
    should not have a label, if label is not set
    should have a select.form-control
    should have the correct number of option elements (n+1) if includeNull=true
    should have the correct number of option elements (n) if includeNull=false
*/
describe('on initialization, the Dropdown component', () => {

    // it('should be a div.form-group', () => {});

    // it('should have a label, if label is set', () => {});

    // it('should not have a label, if label is not set', () => {});

    // it('should have a select.form-control', () => {});

    // it('should have the correct number of option elements (n+1) if includeNull=true', () => {});

    // it('should have the correct number of option elements (n) if includeNull=false', () => {});

});
<|endoftext|>


<commit_before>import React from 'react'

import SearchBar from '../../components/SearchBar'
import SideBarMenu from '../../components/SideBarMenu'
import SideBarAccount from '../../components/SideBarAccount'

import logo from './assets/logo.png'

import './Header.scss'

class Header extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      searchBar: false,
      sideBarMenu: false,
      sideBarAccount: false,
      dropDown: null
    }

    this.toggleSearchBar = this.toggleSearchBar.bind(this)
    this.toggleSideBarMenu = this.toggleSideBarMenu.bind(this)
    this.toggleSideBarAccount = this.toggleSideBarAccount.bind(this)
    this.toggleDropdown = this.toggleDropdown.bind(this)
  }

  toggleSearchBar () {
    this.setState({
      searchBar: !this.state.searchBar
    })
  }

  toggleSideBarMenu () {
    document.body.classList.toggle('sidebar-open')
    this.setState({
      sideBarMenu: !this.state.sideBarMenu
    })
  }

  toggleSideBarAccount () {
    document.body.classList.toggle('sidebar-open')
    this.setState({
      sideBarAccount: !this.state.sideBarAccount
    })
  }

  toggleDropdown (id) {
    if (this.state.dropDown === id) {
      this.setState({
        dropDown: null
      })
    } else {
      this.setState({
        dropDown: id
      })
    }
    console.log(id)
  }

  render () {
    return (

              menu

            {/*
 */}

              Home

             this.toggleDropdown('dropdown-1')}>

              Leaderboards

                Raids
                Mythic+

             this.toggleDropdown('dropdown-2')}>

              Recruitment

                Characters
                Guilds

              Parsing

              search

              account

             this.toggleDropdown('dropdown-3')} >

              account

                Manage characters / guilds
                Discord Webhooks
                Settings
                Logout

        <SideBarMenu toggleAction={this.toggleSideBarMenu} isOpen={this.state.sideBarMenu} />
        <SideBarAccount toggleAction={this.toggleSideBarAccount} isOpen={this.state.sideBarAccount} />
        <SearchBar isOpen={this.state.searchBar} />

    )
  }
}

export default Header
<commit_msg>Fix parsing<commit_after>import React from 'react'

import SearchBar from '../../components/SearchBar'
import SideBarMenu from '../../components/SideBarMenu'
import SideBarAccount from '../../components/SideBarAccount'

import logo from './assets/logo.png'

import './Header.scss'

class Header extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      searchBar: false,
      sideBarMenu: false,
      sideBarAccount: false,
      dropDown: null
    }

    this.toggleSearchBar = this.toggleSearchBar.bind(this)
    this.toggleSideBarMenu = this.toggleSideBarMenu.bind(this)
    this.toggleSideBarAccount = this.toggleSideBarAccount.bind(this)
    this.toggleDropdown = this.toggleDropdown.bind(this)
  }

  toggleSearchBar () {
    this.setState({
      searchBar: !this.state.searchBar
    })
  }

  toggleSideBarMenu () {
    document.body.classList.toggle('sidebar-open')
    this.setState({
      sideBarMenu: !this.state.sideBarMenu
    })
  }

  toggleSideBarAccount () {
    document.body.classList.toggle('sidebar-open')
    this.setState({
      sideBarAccount: !this.state.sideBarAccount
    })
  }

  toggleDropdown (id) {
    if (this.state.dropDown === id) {
      this.setState({
        dropDown: null
      })
    } else {
      this.setState({
        dropDown: id
      })
    }
    console.log(id)
  }

  render () {
    return (

              menu

            {/*
 */}

              Home

             this.toggleDropdown('dropdown-1')}>

              Leaderboards

                Raids
                Mythic+

             this.toggleDropdown('dropdown-2')}>

              Recruitment

                Characters
                Guilds

              Parsing

              search

              account

             this.toggleDropdown('dropdown-3')} >

              account

                Manage characters / guilds
                Discord Webhooks
                Settings
                Logout

        <SideBarMenu toggleAction={this.toggleSideBarMenu} isOpen={this.state.sideBarMenu} />
        <SideBarAccount toggleAction={this.toggleSideBarAccount} isOpen={this.state.sideBarAccount} />
        <SearchBar isOpen={this.state.searchBar} />

    )
  }
}

export default Header
<|endoftext|>


<commit_before>import React from 'react';
import { graphql } from 'react-apollo';
import { Route, NavLink } from 'react-router-dom';
import _ from 'lodash';

import { Loading } from 'src/components/Util';

import LangQuery from 'src/gql/lang';

const SLUGS = ['en','fr','de','es','zh'];

const Langs = () => {
	return (

						<Route exact path="/:langSlug([a-z]{2})/:worldSlug([a-z\-]+)" render={({ match }) => {
							const {
								// langSlug,
								worldSlug,
							} = match.params;

							return _.map(SLUGS, slug => <LangWithData key={slug} slug={slug} worldSlug={worldSlug} />);
						}}/>

						<Route exact path="/:langSlug([a-z]{2})" render={({ match }) => {
							// const { langSlug } = match.params;

							return _.map(SLUGS, slug => <LangWithData key={slug} slug={slug} match={match}/>);
						}}/>

	);
};

const Lang = ({ data, worldSlug }) => {
	const { lang, loading } = data;

	if (loading) { return <Loading />; }

	const link = _.without([
		'',
		lang.slug,
		worldSlug ? worldSlug : null,
	], null);

	return (

			<NavLink to={link.join('/')} title={lang.name} className="nav-link" activeClassName="active">
				{lang.label}
			</NavLink>

	);
};

const LangWithData = graphql(LangQuery, {
	options: { shouldBatch: true },
})(Lang);

export default Langs;
<commit_msg>cleanup html<commit_after>import React from 'react';
import { graphql } from 'react-apollo';
import { Route, NavLink } from 'react-router-dom';
import _ from 'lodash';

import { Loading } from 'src/components/Util';

import LangQuery from 'src/gql/lang';

const SLUGS = ['en','fr','de','es','zh'];

const Langs = () => {
	return (

				<Route exact path="/:langSlug([a-z]{2})/:worldSlug([a-z\-]+)" render={({ match }) => {
					const {
						// langSlug,
						worldSlug,
					} = match.params;

					return _.map(SLUGS, slug => <LangWithData key={slug} slug={slug} worldSlug={worldSlug} />);
				}}/>

				<Route exact path="/:langSlug([a-z]{2})" render={({ match }) => {
					// const { langSlug } = match.params;

					return _.map(SLUGS, slug => <LangWithData key={slug} slug={slug} match={match}/>);
				}}/>

	);
};

const Lang = ({ data, worldSlug }) => {
	const { lang, loading } = data;

	if (loading) { return <Loading />; }

	const link = _.without([
		'',
		lang.slug,
		worldSlug ? worldSlug : null,
	], null);

	return (

			<NavLink to={link.join('/')} title={lang.name} className="nav-link" activeClassName="active">
				{lang.label}
			</NavLink>

	);
};

const LangWithData = graphql(LangQuery, {
	options: { shouldBatch: true },
})(Lang);

export default Langs;
<|endoftext|>


<commit_before>const styles = () => ({
  formControl: {
    width: '100%',
  },
});

export default styles;
<commit_msg>Delete styles.js<commit_after><|endoftext|>


<commit_before>import React from 'react';
import request from 'superagent';
import moment from 'moment';

import BuildStore from '../stores/build-store';
import Action from '../actions';
import Loading from './loading';
import {BuildTitle} from './build-list';
import Task from './task';

export default class BuildDetails extends React.Component {

  constructor() {
    super();
    this.state = {build: null};
  }

  get() {
    return BuildStore.getBuild(
      this.props.params.owner,
      this.props.params.name,
      this.props.params.buildNumber
    );
  }

  fetch() {
    Action.getBuild(
      this.props.params.owner + '/' +
      this.props.params.name + '/' +
      this.props.params.buildNumber
    );
    Action.addAlert({
      message: 'We are currently loading new data from the server',
      iconClasses: 'fa fa-spinner fa-pulse',
      key: 'loading-data'
    });
  }

  componentDidMount() {
    BuildStore.addChangeListener(this._onChange.bind(this));
    this.setState({build: this.get()});
    this.fetch();
  }

  componentWillUnmount() {
    BuildStore.removeChangeListener(this._onChange.bind(this));
  }

  _onChange() {
    this.setState({build: this.get()});
  }

  render() {
    var build = this.state.build;

    if (!build) return (<Loading />);

    var tasks = false;
    var state = 'Pending';

    if (build.result) {
      if (!build.result.still_running) {
        state = build.result.succeeded ? 'Success' : 'Failure';
      }

      tasks = this.state.build.result.tasks.map(task => {
        task.key = task.task;
        return (<Task {...task} />)
      });
    }

    if (!build.result || build.result.still_running) {
      clearTimeout(this.fetchTimeout);
      this.fetchTimeout = setTimeout(this.fetch.bind(this), 2000);
    }

    return (

        <BuildTitle {...build} size={2}/>

          Branch: {build.branch}

          Commit hash: {build.sha}

          Author: {build.author}

          Timestamp: {moment(build.start_time).fromNow()}

          State: {state}
          <Coverage result={build.result} />

          {build.message}

{tasks}

    );
  }
}

class Coverage extends React.Component {
  render() {
    if (!this.props.result || !this.props.result.coverage) return false;

    return (

        Coverage: {this.props.result.coverage}

        Coverage difference from last master build: {this.props.result.coverage_diff}

    );
  }
}
<commit_msg>Fix dismissing loading alert on build page<commit_after>import React from 'react';
import request from 'superagent';
import moment from 'moment';

import BuildStore from '../stores/build-store';
import Action from '../actions';
import Loading from './loading';
import {BuildTitle} from './build-list';
import Task from './task';

export default class BuildDetails extends React.Component {

  constructor() {
    super();
    this.state = {build: null, loading: false};
  }

  get() {
    return BuildStore.getBuild(
      this.props.params.owner,
      this.props.params.name,
      this.props.params.buildNumber
    );
  }

  fetch() {
    Action.getBuild(
      this.props.params.owner + '/' +
      this.props.params.name + '/' +
      this.props.params.buildNumber
    );
    Action.addAlert({
      message: 'We are currently loading new data from the server',
      iconClasses: 'fa fa-spinner fa-pulse',
      key: 'loading-data'
    });
  }

  componentDidMount() {
    BuildStore.addChangeListener(this._onChange.bind(this));
    this.setState({build: this.get(), loading: true});
    this.fetch();
  }

  componentWillUnmount() {
    BuildStore.removeChangeListener(this._onChange.bind(this));
  }

  _onChange() {
    this.setState({build: this.get(), loading: BuildStore.isLoading()});
  }

  render() {

    if (!this.state.loading) Action.removeAlert('loading-data');
    var build = this.state.build;

    if (!build) return (<Loading />);

    var tasks = false;
    var state = 'Pending';

    if (build.result) {
      if (!build.result.still_running) {
        state = build.result.succeeded ? 'Success' : 'Failure';
      }

      tasks = this.state.build.result.tasks.map(task => {
        task.key = task.task;
        return (<Task {...task} />);
      });
    }

    if (!build.result || build.result.still_running) {
      clearTimeout(this.fetchTimeout);
      this.fetchTimeout = setTimeout(this.fetch.bind(this), 2000);
    }

    return (

        <BuildTitle {...build} size={2}/>

          Branch: {build.branch}

          Commit hash: {build.sha}

          Author: {build.author}

          Timestamp: {moment(build.start_time).fromNow()}

          State: {state}
          <Coverage result={build.result} />

          {build.message}

{tasks}

    );
  }
}

class Coverage extends React.Component {
  render() {
    if (!this.props.result || !this.props.result.coverage) return false;

    return (

        Coverage: {this.props.result.coverage}

        Coverage difference from last master build: {this.props.result.coverage_diff}

    );
  }
}
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import LoadingSpinner from '../loadingSpinner';
import cx from 'classnames';
import theme from './theme.css';
import uiUtilities from '@teamleader/ui-utilities';

class Button extends PureComponent {
  getSpinnerColor() {
    const { inverse, level } = this.props;

    switch (level) {
      case 'secondary':
        return 'teal';
      case 'outline':
        return inverse ? 'neutral' : 'teal';
      case 'link':
        return inverse ? 'neutral' : 'aqua';
      default:
        return 'neutral';
    }
  }

  getSpinnerTint() {
    const { inverse, level } = this.props;

    switch (level) {
      case 'secondary':
        return 'darkest';
      case 'outline':
        return inverse ? 'lightest' : 'darkest';
      case 'link':
        return inverse ? 'lightest' : 'dark';
      default:
        return 'lightest';
    }
  }

  handleMouseUp = event => {
    this.blur();
    if (this.props.onMouseUp) {
      this.props.onMouseUp(event);
    }
  };

  handleMouseLeave = event => {
    this.blur();
    if (this.props.onMouseLeave) {
      this.props.onMouseLeave(event);
    }
  };

  blur() {
    if (this.buttonNode.blur) {
      this.buttonNode.blur();
    }
  }

  render() {
    const {
      children,
      className,
      level,
      disabled,
      element,
      active,
      fullWidth,
      icon,
      iconPlacement,
      inverse,
      label,
      size,
      type,
      processing,
      ...others
    } = this.props;

    const classNames = cx(
      uiUtilities['reset-box-sizing'],
      uiUtilities['reset-font-smoothing'],
      theme['button-base'],
      theme['button'],
      theme[level],
      theme[size],
      {
        [theme['has-icon-only']]: (!children && !label) || (Array.isArray(children) && !children[0] && !label),
        [theme['is-inverse']]: inverse && (level === 'outline' || level === 'link'),
        [theme['is-disabled']]: disabled,
        [theme['is-full-width']]: fullWidth,
        [theme['is-processing']]: processing,
        [theme['is-active']]: active,
      },
      className,
    );

    const props = {
      ...others,
      ref: node => {
        this.buttonNode = node;
      },
      className: classNames,
      disabled: element === 'button' ? disabled : null,
      element: element,
      onMouseUp: this.handleMouseUp,
      onMouseLeave: this.handleMouseLeave,
      type: element === 'button' ? type : null,
      'data-teamleader-ui': 'button',
    };

    return (
      <Box {...props}>
        {icon && iconPlacement === 'left' && icon}
        {(label || children) && (

            {label}
            {children}

        )}
        {icon && iconPlacement === 'right' && icon}
        {processing && (
          <LoadingSpinner
            className={theme['spinner']}
            color={this.getSpinnerColor()}
            size={size === 'small' ? 'small' : 'medium'}
            tint={this.getSpinnerTint()}
          />
        )}
      </Box>
    );
  }
}

Button.propTypes = {
  /** The content to display inside the button. */
  children: PropTypes.any,
  /** A class name for the button to give custom styles. */
  className: PropTypes.string,
  /** A custom element to be rendered */
  element: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
  /** Determines which kind of button to be rendered. */
  level: PropTypes.oneOf(['outline', 'primary', 'secondary', 'destructive', 'link', 'timer']),
  /** If true, component will be disabled. */
  disabled: PropTypes.bool,
  /** If true, component will be shown in an active state */
  active: PropTypes.bool,
  /** If true, component will take the full width available. */
  fullWidth: PropTypes.bool,
  /** The icon displayed inside the button. */
  icon: PropTypes.element,
  /** The position of the icon inside the button. */
  iconPlacement: PropTypes.oneOf(['left', 'right']),
  /** If true, component will be rendered in inverse mode (only for the levels "link" and "outline"). */
  inverse: PropTypes.bool,
  /** The textual label displayed inside the button. */
  label: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /** Callback function that is fired when mouse leaves the component. */
  onMouseLeave: PropTypes.func,
  /** Callback function that is fired when the mouse button is released. */
  onMouseUp: PropTypes.func,
  /** If true, component will show a loading spinner instead of label or children. */
  processing: PropTypes.bool,
  /** Size of the button. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Type of the button element. */
  type: PropTypes.string,
};

Button.defaultProps = {
  className: '',
  element: 'button',
  fullWidth: false,
  level: 'secondary',
  iconPlacement: 'left',
  inverse: false,
  processing: false,
  size: 'medium',
  type: 'button',
};

export default Button;
<commit_msg>No need to import ui-utilities in JS, we do this already in CSS<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import Box from '../box';
import LoadingSpinner from '../loadingSpinner';
import cx from 'classnames';
import theme from './theme.css';

class Button extends PureComponent {
  getSpinnerColor() {
    const { inverse, level } = this.props;

    switch (level) {
      case 'secondary':
        return 'teal';
      case 'outline':
        return inverse ? 'neutral' : 'teal';
      case 'link':
        return inverse ? 'neutral' : 'aqua';
      default:
        return 'neutral';
    }
  }

  getSpinnerTint() {
    const { inverse, level } = this.props;

    switch (level) {
      case 'secondary':
        return 'darkest';
      case 'outline':
        return inverse ? 'lightest' : 'darkest';
      case 'link':
        return inverse ? 'lightest' : 'dark';
      default:
        return 'lightest';
    }
  }

  handleMouseUp = event => {
    this.blur();
    if (this.props.onMouseUp) {
      this.props.onMouseUp(event);
    }
  };

  handleMouseLeave = event => {
    this.blur();
    if (this.props.onMouseLeave) {
      this.props.onMouseLeave(event);
    }
  };

  blur() {
    if (this.buttonNode.blur) {
      this.buttonNode.blur();
    }
  }

  render() {
    const {
      children,
      className,
      level,
      disabled,
      element,
      active,
      fullWidth,
      icon,
      iconPlacement,
      inverse,
      label,
      size,
      type,
      processing,
      ...others
    } = this.props;

    const classNames = cx(
      theme['reset-box-sizing'],
      theme['reset-font-smoothing'],
      theme['button-base'],
      theme['button'],
      theme[level],
      theme[size],
      {
        [theme['has-icon-only']]: (!children && !label) || (Array.isArray(children) && !children[0] && !label),
        [theme['is-inverse']]: inverse && (level === 'outline' || level === 'link'),
        [theme['is-disabled']]: disabled,
        [theme['is-full-width']]: fullWidth,
        [theme['is-processing']]: processing,
        [theme['is-active']]: active,
      },
      className,
    );

    const props = {
      ...others,
      ref: node => {
        this.buttonNode = node;
      },
      className: classNames,
      disabled: element === 'button' ? disabled : null,
      element: element,
      onMouseUp: this.handleMouseUp,
      onMouseLeave: this.handleMouseLeave,
      type: element === 'button' ? type : null,
      'data-teamleader-ui': 'button',
    };

    return (
      <Box {...props}>
        {icon && iconPlacement === 'left' && icon}
        {(label || children) && (

            {label}
            {children}

        )}
        {icon && iconPlacement === 'right' && icon}
        {processing && (
          <LoadingSpinner
            className={theme['spinner']}
            color={this.getSpinnerColor()}
            size={size === 'small' ? 'small' : 'medium'}
            tint={this.getSpinnerTint()}
          />
        )}
      </Box>
    );
  }
}

Button.propTypes = {
  /** The content to display inside the button. */
  children: PropTypes.any,
  /** A class name for the button to give custom styles. */
  className: PropTypes.string,
  /** A custom element to be rendered */
  element: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
  /** Determines which kind of button to be rendered. */
  level: PropTypes.oneOf(['outline', 'primary', 'secondary', 'destructive', 'link', 'timer']),
  /** If true, component will be disabled. */
  disabled: PropTypes.bool,
  /** If true, component will be shown in an active state */
  active: PropTypes.bool,
  /** If true, component will take the full width available. */
  fullWidth: PropTypes.bool,
  /** The icon displayed inside the button. */
  icon: PropTypes.element,
  /** The position of the icon inside the button. */
  iconPlacement: PropTypes.oneOf(['left', 'right']),
  /** If true, component will be rendered in inverse mode (only for the levels "link" and "outline"). */
  inverse: PropTypes.bool,
  /** The textual label displayed inside the button. */
  label: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /** Callback function that is fired when mouse leaves the component. */
  onMouseLeave: PropTypes.func,
  /** Callback function that is fired when the mouse button is released. */
  onMouseUp: PropTypes.func,
  /** If true, component will show a loading spinner instead of label or children. */
  processing: PropTypes.bool,
  /** Size of the button. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Type of the button element. */
  type: PropTypes.string,
};

Button.defaultProps = {
  className: '',
  element: 'button',
  fullWidth: false,
  level: 'secondary',
  iconPlacement: 'left',
  inverse: false,
  processing: false,
  size: 'medium',
  type: 'button',
};

export default Button;
<|endoftext|>