<commit_before>var currentLocation;
var apiFilter = "allAPIs";
var statsEnabled = isDataPublishingEnabled();

//setting default date
var to = new Date();
var from = new Date(to.getTime() - 1000 * 60 * 60 * 24 * 30);

currentLocation=window.location.pathname;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getFirstAccessTime",currentLocation:currentLocation  },
        function (json) {

            if (!json.error) {

                if( json.usage && json.usage.length > 0){
                    var d = new Date();
                    from = new Date(json.usage[0].year, json.usage[0].month-1, json.usage[0].day);
                    var currentDay = new Date(d.getFullYear(), d.getMonth(), d.getDate(),d.getHours(),d.getMinutes());

                    //day picker
                    $('#today-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-86400000);
                    });

                    //hour picker
                    $('#hour-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-3600000);
                    })

                    //week picker
                    $('#week-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-604800000);
                    })

                    //month picker
                    $('#month-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-(604800000*4));
                    });

                    $('#date-range').click(function(){
                         $(this).removeClass('active');
                    });

                    //date picker
                    $('#date-range').daterangepicker({
                          timePicker: true,
                          timePickerIncrement: 30,
                          format: 'YYYY-MM-DD h:mm',
                          opens: 'left',
                    });

                    $("#apiFilter").change(function (e) {
                    	apiFilter = this.value;
                    	drawAPIResponseFaultCountChart(from,to,apiFilter);
                    });

                    $('#date-range').on('apply.daterangepicker', function(ev, picker) {
                       btnActiveToggle(this);
                       from = convertTimeString(picker.startDate);
                       to = convertTimeString(picker.endDate);
                       var fromStr = from.split(" ");
                       var toStr = to.split(" ");
                       var dateStr = fromStr[0] + " " + fromStr[1] + " to " + toStr[0] + " " + toStr[1] + "";
                       $("#date-range span").html(dateStr);
                       drawAPIResponseFaultCountChart(from,to,apiFilter);
                    });

                    getDateTime(to,from);

                    $('#date-range').click(function (event) {
                    event.stopPropagation();
                    });

                    $('body').on('click', '.btn-group button', function (e) {
                        $(this).siblings().removeClass('active');
                        $(this).addClass('active');
                    });

                }

                else if (json.usage && json.usage.length == 0 && statsEnabled) {
                    $('.stat-page').html("");
                    showNoDataAnalyticsMsg();
                }

                else{
                    $('.stat-page').html("");
                    showEnableAnalyticsMsg();
                }
            }
            else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");

var drawAPIResponseFaultCountTable = function(from,to){
    var fromDate = from;
    var toDate = to;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getAPIResponseFaultCount", currentLocation:currentLocation,fromDate:fromDate,toDate:toDate, apiFilter:apiFilter},
        function (json) {
            if (!json.error) {
                $('#apiFaultyTable').find("tr:gt(0)").remove();
                var length = json.usage.length;
                $('#noData').empty();
                $('#tableContainer').empty();

                if(length>0){

                $('div#apiFaultyTable_wrapper.dataTables_wrapper.no-footer').remove();
                var chart;
                var $dataTable =$('

');

                $dataTable.append($('

'+
                                        '' + i18n.t("API")+ '	'+
                                        '' + i18n.t("Version") + '	'+
                                        '' + i18n.t("Count")+ '	'+
                                        '' + i18n.t("Percentage")+ '	'+
                                    '

'));

                for (var i = 0; i < json.usage.length; i++) {
                    $dataTable.append($('
' + json.usage[i].apiName + '	' + json.usage[i].version + '	' + json.usage[i].count + '	' + Math.round(json.usage[i].faultPercentage * 100) / 100 +'%
'));
                }

                $('#tableContainer').append($dataTable);
                $('#tableContainer').show();
                $('#apiFaultyTable').datatables_extended({
                     "order": [
                        [ 3, "desc" ]
                     ],
                     "fnDrawCallback": function(){
                         if(this.fnSettings().fnRecordsDisplay()<=$("#apiFaultyTable_length option:selected" ).val()
                         || $("#apiFaultyTable_length option:selected" ).val()==-1)
                             $('#apiFaultyTable_paginate').hide();
                         else
                             $('#apiFaultyTable_paginate').show();
                     },
                });
                //$('select').css('width','80px');

                }else if (length == 0) {
                    $('#tableContainer').hide();
                    $('div#apiFaultyTable_wrapper.dataTables_wrapper.no-footer').remove();
                    $('#noData').append($('

'+i18n.t("No Data Available")+'

'));
                }

            } else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");
}

var drawAPIResponseFaultCountChart = function(from,to){
    var fromDate = from;
    var toDate = to;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getAPIResponseFaultCount",currentLocation:currentLocation,fromDate:fromDate,toDate:toDate,apiFilter:apiFilter },
        function (json) {
            $('#spinner').hide();
            if (!json.error) {
                var length = json.usage.length,s1 = [];
                $('#chartContainer').empty();
                $('#noData').empty();

                if (length > 0) {
                    var faultData = [];
                    var data=[];

                    //chart data
                    for (var i = 0; i < length; i++) {
                        faultData.push({x:i, y:parseFloat(json.usage[i].count), label: json.usage[i].apiName +" v"+json.usage[i].version});
                        data.push({x:i, y:parseFloat(json.usage[i].totalRequestCount)-parseFloat(json.usage[i].count), label: json.usage[i].apiName});
                    }

                    var dataStructure = [
                        {
                            "key": "Success",
                            "values": data
                        },{
                            "key": "Fault",
                            "values": faultData
                        }];

                    (function (data) {
                    var colorRangeArray=["#4aa3df","#e74c3c"];
                        var colors = d3.scale.ordinal()
                           .range(colorRangeArray);
                        keyColor = function (d, i) {
                            return colors(d.key)
                        };

                        var chart;
                        nv.addGraph(function () {
                            chart = nv.models.stackedAreaChart().margin({left:80,right:50})
                                .x(function (d) {
                                return d.x
                            })
                                .y(function (d) {
                                return d.y
                            })
                                .color(keyColor)
                                .useInteractiveGuideline(true);

                            if (dataStructure[0].values.length > 4) chart.margin({bottom: 160});

                            var labels = [];
                            for(var i =0;i<dataStructure[0].values.length;i++){
                                labels.push(dataStructure[0].values[i].label)
                            }

                            chart.xAxis
                                .axisLabel('APIs')
                                .tickFormat(function (d, i) {
                                return labels[i];
                            });
                            chart.xAxis.tickValues(dataStructure[0].values.map( function(d){return d.x;}));
                            if (dataStructure[0].values.length > 4) chart.xAxis.rotateLabels(-45);

                            chart.yAxis.axisLabel('Total Hits');
                            chart.yAxis.tickFormat(d3.format(',d'));

                            d3.select('#faultyCountChart svg')
                              .datum(data)
                              .transition().duration(0)
                              .call(chart);

                            nv.utils.windowResize(chart.update);
                            return chart;
                      });
                    })(dataStructure);
                    $('#chartContainer').append($('
<svg style="height:500px;"></svg>
'));
                    $('#chartContainer').show();
                    $('#faultyCountChart svg').show();

                    drawAPIResponseFaultCountTable(fromDate,toDate);

                } else {
                    $('#tableContainer').hide();
                    $('#chartContainer').hide();
                    $('#noData').html('');
                    $('#noData').append($('

'+i18n.t("No Data Available")+'

'));
                }

            } else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");
}

function getDateTime(currentDay,fromDay){
    to = convertTimeString(currentDay);
    from = convertTimeString(fromDay);
    var toDate = to.split(" ");
    var fromDate = from.split(" ");
    var dateStr= fromDate[0]+" "+fromDate[1]+" to "+toDate[0]+" "+toDate[1]+"";
    $("#date-range span").html(dateStr);
    $('#date-range').data('daterangepicker').setStartDate(from);
    $('#date-range').data('daterangepicker').setEndDate(to);
    drawAPIResponseFaultCountChart(from,to);
}
<commit_msg>Fix faulty invocation chart's tooltip and xaxis labelling<commit_after>var currentLocation;
var apiFilter = "allAPIs";
var statsEnabled = isDataPublishingEnabled();

//setting default date
var to = new Date();
var from = new Date(to.getTime() - 1000 * 60 * 60 * 24 * 30);

currentLocation=window.location.pathname;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getFirstAccessTime",currentLocation:currentLocation  },
        function (json) {

            if (!json.error) {

                if( json.usage && json.usage.length > 0){
                    var d = new Date();
                    from = new Date(json.usage[0].year, json.usage[0].month-1, json.usage[0].day);
                    var currentDay = new Date(d.getFullYear(), d.getMonth(), d.getDate(),d.getHours(),d.getMinutes());

                    //day picker
                    $('#today-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-86400000);
                    });

                    //hour picker
                    $('#hour-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-3600000);
                    })

                    //week picker
                    $('#week-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-604800000);
                    })

                    //month picker
                    $('#month-btn').on('click',function(){
                        getDateTime(currentDay,currentDay-(604800000*4));
                    });

                    $('#date-range').click(function(){
                         $(this).removeClass('active');
                    });

                    //date picker
                    $('#date-range').daterangepicker({
                          timePicker: true,
                          timePickerIncrement: 30,
                          format: 'YYYY-MM-DD h:mm',
                          opens: 'left',
                    });

                    $("#apiFilter").change(function (e) {
                    	apiFilter = this.value;
                    	drawAPIResponseFaultCountChart(from,to,apiFilter);
                    });

                    $('#date-range').on('apply.daterangepicker', function(ev, picker) {
                       btnActiveToggle(this);
                       from = convertTimeString(picker.startDate);
                       to = convertTimeString(picker.endDate);
                       var fromStr = from.split(" ");
                       var toStr = to.split(" ");
                       var dateStr = fromStr[0] + " " + fromStr[1] + " to " + toStr[0] + " " + toStr[1] + "";
                       $("#date-range span").html(dateStr);
                       drawAPIResponseFaultCountChart(from,to,apiFilter);
                    });

                    getDateTime(to,from);

                    $('#date-range').click(function (event) {
                    event.stopPropagation();
                    });

                    $('body').on('click', '.btn-group button', function (e) {
                        $(this).siblings().removeClass('active');
                        $(this).addClass('active');
                    });

                }

                else if (json.usage && json.usage.length == 0 && statsEnabled) {
                    $('.stat-page').html("");
                    showNoDataAnalyticsMsg();
                }

                else{
                    $('.stat-page').html("");
                    showEnableAnalyticsMsg();
                }
            }
            else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");

var drawAPIResponseFaultCountTable = function(from,to){
    var fromDate = from;
    var toDate = to;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getAPIResponseFaultCount", currentLocation:currentLocation,fromDate:fromDate,toDate:toDate, apiFilter:apiFilter},
        function (json) {
            if (!json.error) {
                $('#apiFaultyTable').find("tr:gt(0)").remove();
                var length = json.usage.length;
                $('#noData').empty();
                $('#tableContainer').empty();

                if(length>0){

                $('div#apiFaultyTable_wrapper.dataTables_wrapper.no-footer').remove();
                var chart;
                var $dataTable =$('

');

                $dataTable.append($('

'+
                                        '' + i18n.t("API")+ '	'+
                                        '' + i18n.t("Version") + '	'+
                                        '' + i18n.t("Count")+ '	'+
                                        '' + i18n.t("Percentage")+ '	'+
                                    '

'));

                for (var i = 0; i < json.usage.length; i++) {
                    $dataTable.append($('
' + json.usage[i].apiName + '	' + json.usage[i].version + '	' + json.usage[i].count + '	' + Math.round(json.usage[i].faultPercentage * 100) / 100 +'%
'));
                }

                $('#tableContainer').append($dataTable);
                $('#tableContainer').show();
                $('#apiFaultyTable').datatables_extended({
                     "order": [
                        [ 3, "desc" ]
                     ],
                     "fnDrawCallback": function(){
                         if(this.fnSettings().fnRecordsDisplay()<=$("#apiFaultyTable_length option:selected" ).val()
                         || $("#apiFaultyTable_length option:selected" ).val()==-1)
                             $('#apiFaultyTable_paginate').hide();
                         else
                             $('#apiFaultyTable_paginate').show();
                     },
                });
                //$('select').css('width','80px');

                }else if (length == 0) {
                    $('#tableContainer').hide();
                    $('div#apiFaultyTable_wrapper.dataTables_wrapper.no-footer').remove();
                    $('#noData').append($('

'+i18n.t("No Data Available")+'

'));
                }

            } else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");
}

var drawAPIResponseFaultCountChart = function(from,to){
    var fromDate = from;
    var toDate = to;
    jagg.post("/site/blocks/stats/faulty-invocations/ajax/stats.jag", { action:"getAPIResponseFaultCount",currentLocation:currentLocation,fromDate:fromDate,toDate:toDate,apiFilter:apiFilter },
        function (json) {
            $('#spinner').hide();
            if (!json.error) {
                var length = json.usage.length,s1 = [];
                $('#chartContainer').empty();
                $('#noData').empty();

                if (length > 0) {
                    var faultData = [];
                    var data=[];

                    //chart data
                    for (var i = 0; i < length; i++) {
                        faultData.push({x:i, y:parseFloat(json.usage[i].count), label: json.usage[i].apiName +" v"+json.usage[i].version});
                        data.push({x:i, y:parseFloat(json.usage[i].totalRequestCount)-parseFloat(json.usage[i].count), label: json.usage[i].apiName});
                    }

                    var dataStructure = [
                        {
                            "key": "Success",
                            "values": data
                        },{
                            "key": "Fault",
                            "values": faultData
                        }];

                    (function (data) {
                    var colorRangeArray=["#4aa3df","#e74c3c"];
                        var colors = d3.scale.ordinal()
                           .range(colorRangeArray);
                        keyColor = function (d, i) {
                            return colors(d.key)
                        };

                        var chart;
                        nv.addGraph(function () {
                            chart = nv.models.stackedAreaChart().margin({left:80,right:50})
                                .x(function (d) {
                                return d.x
                            })
                                .y(function (d) {
                                return d.y
                            })
                                .color(keyColor)
                                .useInteractiveGuideline(true);

                            if (dataStructure[0].values.length > 4) chart.margin({bottom: 160});

                            var labels = [];
                            for(var i =0;i<dataStructure[0].values.length;i++){
                                labels.push(dataStructure[0].values[i].label)
                            }

                            chart.xAxis
                                .axisLabel('APIs')
                                .tickFormat(function (i) {
                                return labels[i];
                            });
                            chart.xAxis.tickValues(dataStructure[0].values.map( function(d){return d.x;}));
                            if (dataStructure[0].values.length > 4) chart.xAxis.rotateLabels(-45);

                            chart.yAxis.axisLabel('Total Hits');
                            chart.yAxis.tickFormat(d3.format(',d'));

                            d3.select('#faultyCountChart svg')
                              .datum(data)
                              .transition().duration(0)
                              .call(chart);

                            nv.utils.windowResize(chart.update);
                            return chart;
                      });
                    })(dataStructure);
                    $('#chartContainer').append($('
<svg style="height:500px;"></svg>
'));
                    $('#chartContainer').show();
                    $('#faultyCountChart svg').show();

                    drawAPIResponseFaultCountTable(fromDate,toDate);

                } else {
                    $('#tableContainer').hide();
                    $('#chartContainer').hide();
                    $('#noData').html('');
                    $('#noData').append($('

'+i18n.t("No Data Available")+'

'));
                }

            } else {
                if (json.message == "AuthenticateError") {
                    jagg.showLogin();
                } else {
                    jagg.message({content:json.message,type:"error"});
                }
            }
        }, "json");
}

function getDateTime(currentDay,fromDay){
    to = convertTimeString(currentDay);
    from = convertTimeString(fromDay);
    var toDate = to.split(" ");
    var fromDate = from.split(" ");
    var dateStr= fromDate[0]+" "+fromDate[1]+" to "+toDate[0]+" "+toDate[1]+"";
    $("#date-range span").html(dateStr);
    $('#date-range').data('daterangepicker').setStartDate(from);
    $('#date-range').data('daterangepicker').setEndDate(to);
    drawAPIResponseFaultCountChart(from,to);
}
<|endoftext|>


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

function getStyles(props) {
  return {
    label: {
      paddingLeft: 0,
      top: props.floatingLabelText ? 6 : -4,
    },
    icon: {
      right: 0,
      top: props.floatingLabelText ? 8 : 0,
    },
    hideDropDownUnderline: {
      borderTop: 'none',
    },
    dropDownMenu: {
      display: 'block',
    },
  };
}

class SelectField extends Component {
  static propTypes = {
    /**
     * If true, the width will automatically be set according to the
     * items inside the menu.
     * To control the width in CSS instead, leave this prop set to `false`.
     */
    autoWidth: PropTypes.bool,
    /**
     * The `MenuItem` elements to populate the select field with.
     * If the menu items have a `label` prop, that value will
     * represent the selected menu item in the rendered select field.
     */
    children: PropTypes.node,
    /**
     * If true, the select field will be disabled.
     */
    disabled: PropTypes.bool,
    /**
     * Object that can handle and override any property of component DropDownMenu.
     */
    dropDownMenuProps: PropTypes.object,
    /**
     * Override the inline-styles of the error element.
     */
    errorStyle: PropTypes.object,
    /**
     * The error content to display.
     */
    errorText: PropTypes.node,
    /**
     * If true, the floating label will float even when no value is selected.
     */
    floatingLabelFixed: PropTypes.bool,
    /**
     * Override the inline-styles of the floating label.
     */
    floatingLabelStyle: PropTypes.object,
    /**
     * The content of the floating label.
     */
    floatingLabelText: PropTypes.node,
    /**
     * If true, the select field will take up the full width of its container.
     */
    fullWidth: PropTypes.bool,
    /**
     * Override the inline-styles of the hint element.
     */
    hintStyle: PropTypes.object,
    /**
     * The hint content to display.
     */
    hintText: PropTypes.node,
    /**
     * Override the inline-styles of the icon element.
     */
    iconStyle: PropTypes.object,
    /**
     * The id prop for the text field.
     */
    id: PropTypes.string,
    /**
     * Override the label style when the select field is inactive.
     */
    labelStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underlying `List` element.
     */
    listStyle: PropTypes.object,
    /**
     * Override the default max-height of the underlying `DropDownMenu` element.
     */
    maxHeight: PropTypes.number,
    /**
     * Override the inline-styles of menu items.
     */
    menuItemStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underlying `DropDownMenu` element.
     */
    menuStyle: PropTypes.object,
    /**
     * If true, `value` must be an array and the menu will support
     * multiple selections.
     */
    multiple: PropTypes.bool,
    /** @ignore */
    onBlur: PropTypes.func,
    /**
     * Callback function fired when a menu item is selected.
     *
     * @param {object} event TouchTap event targeting the menu item
     * that was selected.
     * @param {number} key The index of the selected menu item, or undefined
     * if `multiple` is true.
     * @param {any} payload If `multiple` is true, the menu's `value`
     * array with either the menu item's `value` added (if
     * it wasn't already selected) or omitted (if it was already selected).
     * Otherwise, the `value` of the menu item.
     */
    onChange: PropTypes.func,
    /** @ignore */
    onFocus: PropTypes.func,
    /**
     * Override the inline-styles of selected menu items.
     */
    selectedMenuItemStyle: PropTypes.object,
    /**
     * Customize the rendering of the selected item.
     *
     * @param {any} value If `multiple` is true, the menu's `value`
     * array with either the menu item's `value` added (if
     * it wasn't already selected) or omitted (if it was already selected).
     * Otherwise, the `value` of the menu item.
     * @param {any} menuItem The selected `MenuItem`.
     * If `multiple` is true, this will be an array with the `MenuItem`s matching the `value`s parameter.
     */
    selectionRenderer: PropTypes.func,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * Override the inline-styles of the underline element when the select
     * field is disabled.
     */
    underlineDisabledStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underline element when the select field
     * is focused.
     */
    underlineFocusStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underline element.
     */
    underlineStyle: PropTypes.object,
    /**
     * If `multiple` is true, an array of the `value`s of the selected
     * menu items. Otherwise, the `value` of the selected menu item.
     * If provided, the menu will be a controlled component.
     */
    value: PropTypes.any,
  };

  static defaultProps = {
    autoWidth: false,
    disabled: false,
    fullWidth: false,
    multiple: false,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  render() {
    const {
      autoWidth,
      multiple,
      children,
      style,
      labelStyle,
      iconStyle,
      id,
      underlineDisabledStyle,
      underlineFocusStyle,
      menuItemStyle,
      selectedMenuItemStyle,
      underlineStyle,
      dropDownMenuProps,
      errorStyle,
      disabled,
      floatingLabelFixed,
      floatingLabelText,
      floatingLabelStyle,
      hintStyle,
      hintText,
      fullWidth,
      errorText,
      listStyle,
      maxHeight,
      menuStyle,
      onFocus,
      onBlur,
      onChange,
      selectionRenderer,
      value,
      ...other
    } = this.props;

    const styles = getStyles(this.props, this.context);

    return (
      <TextField
        {...other}
        style={style}
        disabled={disabled}
        floatingLabelFixed={floatingLabelFixed}
        floatingLabelText={floatingLabelText}
        floatingLabelStyle={floatingLabelStyle}
        hintStyle={hintStyle}
        hintText={(!hintText && !floatingLabelText) ? ' ' : hintText}
        fullWidth={fullWidth}
        errorText={errorText}
        underlineStyle={underlineStyle}
        errorStyle={errorStyle}
        onFocus={onFocus}
        onBlur={onBlur}
        id={id}
        role="menu"
        aria-label={floatingLabelText || hintText}
        underlineDisabledStyle={underlineDisabledStyle}
        underlineFocusStyle={underlineFocusStyle}
      >
        <DropDownMenu
          disabled={disabled}
          style={Object.assign(styles.dropDownMenu, menuStyle)}
          labelStyle={Object.assign(styles.label, labelStyle)}
          iconStyle={Object.assign(styles.icon, iconStyle)}
          menuItemStyle={menuItemStyle}
          selectedMenuItemStyle={selectedMenuItemStyle}
          underlineStyle={styles.hideDropDownUnderline}
          listStyle={listStyle}
          autoWidth={autoWidth}
          value={value}
          onChange={onChange}
          maxHeight={maxHeight}
          multiple={multiple}
          selectionRenderer={selectionRenderer}
          {...dropDownMenuProps}
        >
          {children}
        </DropDownMenu>
      </TextField>
    );
  }
}

export default SelectField;
<commit_msg>SelectField - updated the role to correct from menu to menubar for issue #122<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import TextField from '../TextField';
import DropDownMenu from '../DropDownMenu';

function getStyles(props) {
  return {
    label: {
      paddingLeft: 0,
      top: props.floatingLabelText ? 6 : -4,
    },
    icon: {
      right: 0,
      top: props.floatingLabelText ? 8 : 0,
    },
    hideDropDownUnderline: {
      borderTop: 'none',
    },
    dropDownMenu: {
      display: 'block',
    },
  };
}

class SelectField extends Component {
  static propTypes = {
    /**
     * If true, the width will automatically be set according to the
     * items inside the menu.
     * To control the width in CSS instead, leave this prop set to `false`.
     */
    autoWidth: PropTypes.bool,
    /**
     * The `MenuItem` elements to populate the select field with.
     * If the menu items have a `label` prop, that value will
     * represent the selected menu item in the rendered select field.
     */
    children: PropTypes.node,
    /**
     * If true, the select field will be disabled.
     */
    disabled: PropTypes.bool,
    /**
     * Object that can handle and override any property of component DropDownMenu.
     */
    dropDownMenuProps: PropTypes.object,
    /**
     * Override the inline-styles of the error element.
     */
    errorStyle: PropTypes.object,
    /**
     * The error content to display.
     */
    errorText: PropTypes.node,
    /**
     * If true, the floating label will float even when no value is selected.
     */
    floatingLabelFixed: PropTypes.bool,
    /**
     * Override the inline-styles of the floating label.
     */
    floatingLabelStyle: PropTypes.object,
    /**
     * The content of the floating label.
     */
    floatingLabelText: PropTypes.node,
    /**
     * If true, the select field will take up the full width of its container.
     */
    fullWidth: PropTypes.bool,
    /**
     * Override the inline-styles of the hint element.
     */
    hintStyle: PropTypes.object,
    /**
     * The hint content to display.
     */
    hintText: PropTypes.node,
    /**
     * Override the inline-styles of the icon element.
     */
    iconStyle: PropTypes.object,
    /**
     * The id prop for the text field.
     */
    id: PropTypes.string,
    /**
     * Override the label style when the select field is inactive.
     */
    labelStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underlying `List` element.
     */
    listStyle: PropTypes.object,
    /**
     * Override the default max-height of the underlying `DropDownMenu` element.
     */
    maxHeight: PropTypes.number,
    /**
     * Override the inline-styles of menu items.
     */
    menuItemStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underlying `DropDownMenu` element.
     */
    menuStyle: PropTypes.object,
    /**
     * If true, `value` must be an array and the menu will support
     * multiple selections.
     */
    multiple: PropTypes.bool,
    /** @ignore */
    onBlur: PropTypes.func,
    /**
     * Callback function fired when a menu item is selected.
     *
     * @param {object} event TouchTap event targeting the menu item
     * that was selected.
     * @param {number} key The index of the selected menu item, or undefined
     * if `multiple` is true.
     * @param {any} payload If `multiple` is true, the menu's `value`
     * array with either the menu item's `value` added (if
     * it wasn't already selected) or omitted (if it was already selected).
     * Otherwise, the `value` of the menu item.
     */
    onChange: PropTypes.func,
    /** @ignore */
    onFocus: PropTypes.func,
    /**
     * Override the inline-styles of selected menu items.
     */
    selectedMenuItemStyle: PropTypes.object,
    /**
     * Customize the rendering of the selected item.
     *
     * @param {any} value If `multiple` is true, the menu's `value`
     * array with either the menu item's `value` added (if
     * it wasn't already selected) or omitted (if it was already selected).
     * Otherwise, the `value` of the menu item.
     * @param {any} menuItem The selected `MenuItem`.
     * If `multiple` is true, this will be an array with the `MenuItem`s matching the `value`s parameter.
     */
    selectionRenderer: PropTypes.func,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * Override the inline-styles of the underline element when the select
     * field is disabled.
     */
    underlineDisabledStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underline element when the select field
     * is focused.
     */
    underlineFocusStyle: PropTypes.object,
    /**
     * Override the inline-styles of the underline element.
     */
    underlineStyle: PropTypes.object,
    /**
     * If `multiple` is true, an array of the `value`s of the selected
     * menu items. Otherwise, the `value` of the selected menu item.
     * If provided, the menu will be a controlled component.
     */
    value: PropTypes.any,
  };

  static defaultProps = {
    autoWidth: false,
    disabled: false,
    fullWidth: false,
    multiple: false,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  render() {
    const {
      autoWidth,
      multiple,
      children,
      style,
      labelStyle,
      iconStyle,
      id,
      underlineDisabledStyle,
      underlineFocusStyle,
      menuItemStyle,
      selectedMenuItemStyle,
      underlineStyle,
      dropDownMenuProps,
      errorStyle,
      disabled,
      floatingLabelFixed,
      floatingLabelText,
      floatingLabelStyle,
      hintStyle,
      hintText,
      fullWidth,
      errorText,
      listStyle,
      maxHeight,
      menuStyle,
      onFocus,
      onBlur,
      onChange,
      selectionRenderer,
      value,
      ...other
    } = this.props;

    const styles = getStyles(this.props, this.context);

    return (
      <TextField
        {...other}
        style={style}
        disabled={disabled}
        floatingLabelFixed={floatingLabelFixed}
        floatingLabelText={floatingLabelText}
        floatingLabelStyle={floatingLabelStyle}
        hintStyle={hintStyle}
        hintText={(!hintText && !floatingLabelText) ? ' ' : hintText}
        fullWidth={fullWidth}
        errorText={errorText}
        underlineStyle={underlineStyle}
        errorStyle={errorStyle}
        onFocus={onFocus}
        onBlur={onBlur}
        id={id}
        role="menubar"
        aria-label={floatingLabelText || hintText}
        underlineDisabledStyle={underlineDisabledStyle}
        underlineFocusStyle={underlineFocusStyle}
      >
        <DropDownMenu
          disabled={disabled}
          style={Object.assign(styles.dropDownMenu, menuStyle)}
          labelStyle={Object.assign(styles.label, labelStyle)}
          iconStyle={Object.assign(styles.icon, iconStyle)}
          menuItemStyle={menuItemStyle}
          selectedMenuItemStyle={selectedMenuItemStyle}
          underlineStyle={styles.hideDropDownUnderline}
          listStyle={listStyle}
          autoWidth={autoWidth}
          value={value}
          onChange={onChange}
          maxHeight={maxHeight}
          multiple={multiple}
          selectionRenderer={selectionRenderer}
          {...dropDownMenuProps}
        >
          {children}
        </DropDownMenu>
      </TextField>
    );
  }
}

export default SelectField;
<|endoftext|>


<commit_before>var BEM = require('bem'),
    Q = BEM.require('q'),
    PATH = require('path'),
    FS = require('fs'),
    shmakowiki = require('shmakowiki'),
    MD = require('marked'),
    HL = require('highlight.js'),
    mkdirp = require('mkdirp');

process.env.YENV = 'production';
process.env.BEM_I18N_LANGS = 'en ru';
process.env.SHMAKOWIKI_HL = 'server';

function processMarkdown(src) {

    var langs = {};

    return MD(src, {
            gfm: true,
            pedantic: false,
            sanitize: false,
            highlight: function(code, lang) {
                if (!lang) return code;
                var res = HL.highlight(translateAlias(lang), code);
                langs[lang] = res.language;
                return res.value;
            }
        })
        .replace(/
([\s\S]+?)<\/code><\/pre>/gm, function(m, lang, code) {

            return '
' +
                code +
                '
';

        });

}

function translateAlias(alias) {

    var lang = alias;

    switch (alias) {

        case 'js':
            lang = 'javascript';
            break;

        case 'patch':
            lang = 'diff';
            break;

        case 'md':
            lang = 'markdown';
            break;

    }

    return lang;

}

/** @name MAKE */

MAKE.decl('BundleNode', {

    getTechs: function() {

        var techs = [
                'bemjson.js',
                'bemdecl.js',
                'deps.js'
            ];

        if (PATH.basename(this.level.dir) === 'bundles-desktop') {
            return techs.concat([
                'css',
                'ie.css',
                'js'
            ]);
        }

        return techs.concat([
            'bemhtml',
            'html'
        ]);

    }

});

MAKE.decl('Arch', {
    getLibraries: function() {

        return {
            'bem-bl': {
                type: 'git',
                url: 'git://github.com/bem/bem-bl.git',
                treeish: '0.3'
            },

            'content/bem-method': {
                type: 'git',
                url: 'git://github.com/bem/bem-method.git',
                npmPackages: false
            },

            'content/bem-tools': {
                type: 'git',
                url: 'git://github.com/bem/bem-tools.git',
                treeish: 'dev',
                npmPackages: false
            },

            'content/csso': {
                type: 'git',
                url: 'git://github.com/css/csso.git',
                npmPackages: false
            },
            'content/articles/bem-articles': {
                type: 'git',
                url: 'git://github.com/bem/bem-articles.git',
                npmPackages: false
            },
            'content/articles/firm-card-story': {
                type: 'git',
                url: 'git://github.com/AndreyGeonya/firmCardStory.git',
                npmPackages: false
            }
        };
    },
    createCustomNodes: function(common, libs, blocks, bundles) {

        var node = new (MAKE.getNodeClass('PagesGeneratorNode'))({
                id: 'pages-generator',
                root: this.root,
                sources: ['bem-method', 'tools', 'bem-tools/docs', 'csso/docs', 'articles/bem-articles', 'articles/firm-card-story/docs', 'blog']
            });

        this.arch.setNode(node, bundles, libs);

        return node.getId();

    }

});

MAKE.decl('PagesGeneratorNode', 'Node', {

    __constructor: function(o) {
        this.root = o.root;
        this.sources = o.sources;
        this.__base(o);
    },

    make: function() {

        // skip rebuild if this was already done in the same process
        // TODO: this will not with `bem server`
        if (this.done) return;

        var bundlesLevel = BEM.createLevel(PATH.resolve(this.root, 'pages-desktop')),
            _this = this,
            ctx = this.ctx,
            promises;

        promises = this.sources.reduce(function(res, source) {

            var level = BEM.createLevel(PATH.resolve(_this.root, 'content', source));

            return res.concat(level.getItemsByIntrospection()
                .filter(function(item) {
                    return BEM.util.bemType(item) === 'block' && ~['md', 'wiki'].indexOf(item.tech);
                })
                //.reduce(BEM.util.uniq(BEM.util.bemKey), [])
                .map(function(item) {

                    var suffix = item.suffix.substr(1),
                        lang = suffix.split('.').shift(),
                        page = { block: source.split('/').shift() + '-' + item.block + '-' + lang },
                        srcPath = PATH.join(level.getPathByObj(item, suffix)),
                        outPath = PATH.join(bundlesLevel.getPathByObj(page, 'bemjson.js'));

                    return BEM.util.isFileValid(outPath, srcPath)
                        .then(function(valid) {

                            if (valid && !ctx.force) return;

                            return BEM.util.readFile(srcPath)
                                .then(function(src) {

                                    var pageContent = _this.getTemplateBemJson(item.block, source, lang),
                                        content = item.tech === 'wiki'?
                                            shmakowiki.shmakowikiToBemjson(src) :
                                            {
                                                block: 'b-text',
                                                mods: { 'type': 'global' },
                                                content: processMarkdown(src)
                                            };

                                    pageContent.content[1].content.push(content);

                                    mkdirp.sync('pages-desktop/' + page.block);

                                    var outContent = '(' + JSON.stringify(pageContent, null, 1) + ')';
                                    return BEM.util.writeFile(outPath, outContent);

                                });

                        });

                }, _this));

        }, []);

        return Q.all(promises)
            .then(function() {
                _this.done = true;
            });

    },
    pagesConfig: function() {
        return JSON.parse(FS.readFileSync(PATH.resolve(this.root, 'content/pages-config.json'), 'utf8'));
    },
    _navLevelIdx: 0,
    structureConfig: function() {
        return JSON.parse(FS.readFileSync(PATH.resolve(this.root, 'content/site-structure-config.json'), 'utf8'));
    },
    getPageUrl: function(sourceDir, cfg) {
        cfg = cfg || this.structureConfig();

        var children;

        for (var dir in cfg) {
            if (sourceDir == dir) return cfg[dir].url;

            children = (cfg[dir].children && this.getPageUrl(sourceDir, cfg[dir].children));
            if (children) return children;
        }
    },
    getCurrentPageInfo: function(sourceDir, lang) {
        lang = lang || 'en';
        return this.pagesConfig()[lang][sourceDir] || {
            title: 'BEM: block, element, modificator',
            description: 'BEM is abbreviation for Block-Element-Modifier. It\'s a way to write code which is easy to support and develop.',
            keywords: 'bem, block, element, modifier, bemjson, bemhtml, i-bem, i-bem.js, borschik, bem tools, csso',
            menu: sourceDir.split('/').pop()
        };
    },

    getNavBemJson: function(cfg, sourceDir, lang) {
        var _this = this,
            navBemJson = [],
            currentDir,
            sub,
            level = ['first', 'second', 'third', 'fourth'],
            getMenuBemJson = function(mods) {
                _this._navLevelIdx++;

                return {
                    block: 'b-menu-horiz',
                    mods: { layout: 'normal' },
                    mix: [{ block: 'nav' , mods: mods }],
                    js: false,
                    content: []
                };
            },

            currentNavLevelResult = getMenuBemJson({ level: level[_this._navLevelIdx] }),

            checkParent = function(dir, currentStructureLevel) {
                if (dir == sourceDir) return true;

                var children = currentStructureLevel[dir].children;
                if (!children) return false;

                for (var child in children) {
                    if (child == sourceDir || checkParent(child, children)) return true;
                }

                return false;
            };

        for (var dir in cfg) {
            var isParent = checkParent(dir, cfg),
                isCurrent = dir == sourceDir,
                title = this.getCurrentPageInfo(dir, lang).menu;

            isParent && (currentDir = dir);

            currentNavLevelResult.content.push({
                elem: 'item',
                elemMods: isCurrent ? { state: 'current' } : isParent ? { state: 'parent' } : undefined,
                content: isCurrent ? title : {
                    block: 'b-link',
                    url: '/' + cfg[dir].url + '/',
                    content: title
                }
            });
        }

        navBemJson.push(currentNavLevelResult);

        sub = cfg[currentDir] ? cfg[currentDir].children : null;
        sub && navBemJson.push(this.getNavBemJson(sub, sourceDir, lang));

        _this._navLevelIdx = 0;
        return navBemJson;
    },

    getTemplateBemJson: function(pagename, source, lang) {
        /*
        * upyachka:
        * this.getNavBemJson returns array with two elements:
        * first element is first level menu
        * second element consists of second and third level menues
        */
        var sourceDir = source + '/' + pagename,
            pageInfo = this.getCurrentPageInfo(sourceDir, lang),
            resourceFileName = '_' + source.split('/').shift() + '-' + pagename + '-' + lang,
            nav = this.getNavBemJson(this.structureConfig(), sourceDir, lang),
            mainNav = [],
            subNav = nav[1][1],
            langSwitcherContent = lang == 'ru' ? [{
                                    block: 'b-link',
                                    url: '//bem.info/' + this.getPageUrl(sourceDir) + '/',
                                    content: 'English'
                                },
                                ' | Русский' ] : [
                                    'English | ',
                                    {
                                        block: 'b-link',
                                        url: '//ru.bem.info/' + this.getPageUrl(sourceDir) + '/',
                                        content: 'Русский'
                                    }
                                ];

        mainNav.push(nav[0], nav[1][0]);

        return {
            block: 'b-page',
            title: pageInfo.title,
            favicon: '/favicon.ico',
            head: [
                { elem: 'css', url: '/bundles-desktop/inner/_inner.css' },
                // { elem: 'css', url: '/bundles-desktop/inner/_inner.css', ie: false },
                // { elem: 'css', url: '/bundles-desktop/inner/_inner', ie: true },
                // { block: 'i-jquery', elem: 'core' },
                // { elem: 'js', url: '/bundles-desktop/inner/_inner.js' },
                { elem: 'meta', attrs: { name: 'description', content: pageInfo.description }},
                { elem: 'meta', attrs: { name: 'keywords', content: pageInfo.keywords }}
            ],
            content: [
                {
                    block: 'gh-ribbon'
                },
                {
                    block: 'header',
                    content: [
                        {
                            block: 'b-link',
                            mix: [{ block: 'header', elem: 'logo' }],
                            url: '/'
                        },
                        {
                            block: 'lang-switcher',
                            content: langSwitcherContent
                        },
                        mainNav
                    ]
                },
                {
                    block: 'content',
                    content: [subNav]
                },
                {
                    block: 'footer'
                },
                {
                    block: 'metrika'
                }
            ]
        };
    }
}, {

    createId: function(o) {
        return o.id;
    }

});
<commit_msg>inner: don't add gh-ribbon for inner pages<commit_after>var BEM = require('bem'),
    Q = BEM.require('q'),
    PATH = require('path'),
    FS = require('fs'),
    shmakowiki = require('shmakowiki'),
    MD = require('marked'),
    HL = require('highlight.js'),
    mkdirp = require('mkdirp');

process.env.YENV = 'production';
process.env.BEM_I18N_LANGS = 'en ru';
process.env.SHMAKOWIKI_HL = 'server';

function processMarkdown(src) {

    var langs = {};

    return MD(src, {
            gfm: true,
            pedantic: false,
            sanitize: false,
            highlight: function(code, lang) {
                if (!lang) return code;
                var res = HL.highlight(translateAlias(lang), code);
                langs[lang] = res.language;
                return res.value;
            }
        })
        .replace(/
([\s\S]+?)<\/code><\/pre>/gm, function(m, lang, code) {

            return '
' +
                code +
                '
';

        });

}

function translateAlias(alias) {

    var lang = alias;

    switch (alias) {

        case 'js':
            lang = 'javascript';
            break;

        case 'patch':
            lang = 'diff';
            break;

        case 'md':
            lang = 'markdown';
            break;

    }

    return lang;

}

/** @name MAKE */

MAKE.decl('BundleNode', {

    getTechs: function() {

        var techs = [
                'bemjson.js',
                'bemdecl.js',
                'deps.js'
            ];

        if (PATH.basename(this.level.dir) === 'bundles-desktop') {
            return techs.concat([
                'css',
                'ie.css',
                'js'
            ]);
        }

        return techs.concat([
            'bemhtml',
            'html'
        ]);

    }

});

MAKE.decl('Arch', {
    getLibraries: function() {

        return {
            'bem-bl': {
                type: 'git',
                url: 'git://github.com/bem/bem-bl.git',
                treeish: '0.3'
            },

            'content/bem-method': {
                type: 'git',
                url: 'git://github.com/bem/bem-method.git',
                npmPackages: false
            },

            'content/bem-tools': {
                type: 'git',
                url: 'git://github.com/bem/bem-tools.git',
                treeish: 'dev',
                npmPackages: false
            },

            'content/csso': {
                type: 'git',
                url: 'git://github.com/css/csso.git',
                npmPackages: false
            },
            'content/articles/bem-articles': {
                type: 'git',
                url: 'git://github.com/bem/bem-articles.git',
                npmPackages: false
            },
            'content/articles/firm-card-story': {
                type: 'git',
                url: 'git://github.com/AndreyGeonya/firmCardStory.git',
                npmPackages: false
            }
        };
    },
    createCustomNodes: function(common, libs, blocks, bundles) {

        var node = new (MAKE.getNodeClass('PagesGeneratorNode'))({
                id: 'pages-generator',
                root: this.root,
                sources: ['bem-method', 'tools', 'bem-tools/docs', 'csso/docs', 'articles/bem-articles', 'articles/firm-card-story/docs', 'blog']
            });

        this.arch.setNode(node, bundles, libs);

        return node.getId();

    }

});

MAKE.decl('PagesGeneratorNode', 'Node', {

    __constructor: function(o) {
        this.root = o.root;
        this.sources = o.sources;
        this.__base(o);
    },

    make: function() {

        // skip rebuild if this was already done in the same process
        // TODO: this will not with `bem server`
        if (this.done) return;

        var bundlesLevel = BEM.createLevel(PATH.resolve(this.root, 'pages-desktop')),
            _this = this,
            ctx = this.ctx,
            promises;

        promises = this.sources.reduce(function(res, source) {

            var level = BEM.createLevel(PATH.resolve(_this.root, 'content', source));

            return res.concat(level.getItemsByIntrospection()
                .filter(function(item) {
                    return BEM.util.bemType(item) === 'block' && ~['md', 'wiki'].indexOf(item.tech);
                })
                //.reduce(BEM.util.uniq(BEM.util.bemKey), [])
                .map(function(item) {

                    var suffix = item.suffix.substr(1),
                        lang = suffix.split('.').shift(),
                        page = { block: source.split('/').shift() + '-' + item.block + '-' + lang },
                        srcPath = PATH.join(level.getPathByObj(item, suffix)),
                        outPath = PATH.join(bundlesLevel.getPathByObj(page, 'bemjson.js'));

                    return BEM.util.isFileValid(outPath, srcPath)
                        .then(function(valid) {

                            if (valid && !ctx.force) return;

                            return BEM.util.readFile(srcPath)
                                .then(function(src) {

                                    var pageContent = _this.getTemplateBemJson(item.block, source, lang),
                                        content = item.tech === 'wiki'?
                                            shmakowiki.shmakowikiToBemjson(src) :
                                            {
                                                block: 'b-text',
                                                mods: { 'type': 'global' },
                                                content: processMarkdown(src)
                                            };

                                    pageContent.content[1].content.push(content);

                                    mkdirp.sync('pages-desktop/' + page.block);

                                    var outContent = '(' + JSON.stringify(pageContent, null, 1) + ')';
                                    return BEM.util.writeFile(outPath, outContent);

                                });

                        });

                }, _this));

        }, []);

        return Q.all(promises)
            .then(function() {
                _this.done = true;
            });

    },
    pagesConfig: function() {
        return JSON.parse(FS.readFileSync(PATH.resolve(this.root, 'content/pages-config.json'), 'utf8'));
    },
    _navLevelIdx: 0,
    structureConfig: function() {
        return JSON.parse(FS.readFileSync(PATH.resolve(this.root, 'content/site-structure-config.json'), 'utf8'));
    },
    getPageUrl: function(sourceDir, cfg) {
        cfg = cfg || this.structureConfig();

        var children;

        for (var dir in cfg) {
            if (sourceDir == dir) return cfg[dir].url;

            children = (cfg[dir].children && this.getPageUrl(sourceDir, cfg[dir].children));
            if (children) return children;
        }
    },
    getCurrentPageInfo: function(sourceDir, lang) {
        lang = lang || 'en';
        return this.pagesConfig()[lang][sourceDir] || {
            title: 'BEM: block, element, modificator',
            description: 'BEM is abbreviation for Block-Element-Modifier. It\'s a way to write code which is easy to support and develop.',
            keywords: 'bem, block, element, modifier, bemjson, bemhtml, i-bem, i-bem.js, borschik, bem tools, csso',
            menu: sourceDir.split('/').pop()
        };
    },

    getNavBemJson: function(cfg, sourceDir, lang) {
        var _this = this,
            navBemJson = [],
            currentDir,
            sub,
            level = ['first', 'second', 'third', 'fourth'],
            getMenuBemJson = function(mods) {
                _this._navLevelIdx++;

                return {
                    block: 'b-menu-horiz',
                    mods: { layout: 'normal' },
                    mix: [{ block: 'nav' , mods: mods }],
                    js: false,
                    content: []
                };
            },

            currentNavLevelResult = getMenuBemJson({ level: level[_this._navLevelIdx] }),

            checkParent = function(dir, currentStructureLevel) {
                if (dir == sourceDir) return true;

                var children = currentStructureLevel[dir].children;
                if (!children) return false;

                for (var child in children) {
                    if (child == sourceDir || checkParent(child, children)) return true;
                }

                return false;
            };

        for (var dir in cfg) {
            var isParent = checkParent(dir, cfg),
                isCurrent = dir == sourceDir,
                title = this.getCurrentPageInfo(dir, lang).menu;

            isParent && (currentDir = dir);

            currentNavLevelResult.content.push({
                elem: 'item',
                elemMods: isCurrent ? { state: 'current' } : isParent ? { state: 'parent' } : undefined,
                content: isCurrent ? title : {
                    block: 'b-link',
                    url: '/' + cfg[dir].url + '/',
                    content: title
                }
            });
        }

        navBemJson.push(currentNavLevelResult);

        sub = cfg[currentDir] ? cfg[currentDir].children : null;
        sub && navBemJson.push(this.getNavBemJson(sub, sourceDir, lang));

        _this._navLevelIdx = 0;
        return navBemJson;
    },

    getTemplateBemJson: function(pagename, source, lang) {
        /*
        * upyachka:
        * this.getNavBemJson returns array with two elements:
        * first element is first level menu
        * second element consists of second and third level menues
        */
        var sourceDir = source + '/' + pagename,
            pageInfo = this.getCurrentPageInfo(sourceDir, lang),
            resourceFileName = '_' + source.split('/').shift() + '-' + pagename + '-' + lang,
            nav = this.getNavBemJson(this.structureConfig(), sourceDir, lang),
            mainNav = [],
            subNav = nav[1][1],
            langSwitcherContent = lang == 'ru' ? [{
                                    block: 'b-link',
                                    url: '//bem.info/' + this.getPageUrl(sourceDir) + '/',
                                    content: 'English'
                                },
                                ' | Русский' ] : [
                                    'English | ',
                                    {
                                        block: 'b-link',
                                        url: '//ru.bem.info/' + this.getPageUrl(sourceDir) + '/',
                                        content: 'Русский'
                                    }
                                ];

        mainNav.push(nav[0], nav[1][0]);

        return {
            block: 'b-page',
            title: pageInfo.title,
            favicon: '/favicon.ico',
            head: [
                { elem: 'css', url: '/bundles-desktop/inner/_inner.css' },
                // { elem: 'css', url: '/bundles-desktop/inner/_inner.css', ie: false },
                // { elem: 'css', url: '/bundles-desktop/inner/_inner', ie: true },
                // { block: 'i-jquery', elem: 'core' },
                // { elem: 'js', url: '/bundles-desktop/inner/_inner.js' },
                { elem: 'meta', attrs: { name: 'description', content: pageInfo.description }},
                { elem: 'meta', attrs: { name: 'keywords', content: pageInfo.keywords }}
            ],
            content: [
               {
                    block: 'header',
                    content: [
                        {
                            block: 'b-link',
                            mix: [{ block: 'header', elem: 'logo' }],
                            url: '/'
                        },
                        {
                            block: 'lang-switcher',
                            content: langSwitcherContent
                        },
                        mainNav
                    ]
                },
                {
                    block: 'content',
                    content: [subNav]
                },
                {
                    block: 'footer'
                },
                {
                    block: 'metrika'
                }
            ]
        };
    }
}, {

    createId: function(o) {
        return o.id;
    }

});
<|endoftext|>


<commit_before>/*
    TODO:

    dialog => refresh page na submit ( zelfde tree state (open folders)? )

    - http://localhost:8000/categories/create-symbolic/
        - target with search filter

    - keep state on refresh

    - sub menu in contextmenu

 */

( function ( $ ) {

    'use strict'

    function tree( element ) {
        this.element = $( '[data-tree]' );
        this.url = {};
        this.url.data = this.element.data( 'tree' );
        this.url.post = '/categories/navigation-move-node/';
        this.tree = this.element.find( '[data-tree-container]' );
        this.search = this.element.find( '[data-tree-search]' );

        this.plugins = [];

        var self = this;
        self.init();

        window.foo = this;
    }

    tree.prototype.init = function ( ) {
        var self = this;

        // jstree config
        self.config();

        // creates jstree
        self.build();

        // iniate search if plugin is enabled
        if ( $.inArray('search', self.plugins ) ) {
            this.search.submit( function( event ) {
                self.searchInTree( event );
            });
        }

        // handle dragged item
        self.tree.on("move_node.jstree", function ( event, data ) {
            self.isDragged( event, data )
        } );

        // interaction with tree
        // self.tree.on("changed.jstree", function ( event, data ) {
        //     console.log( data )
        //     console.log( data.changed.selected );
        //     console.log( data.changed.deselected );
        // })
    }

    // build tree config, return it and place it within self.plugins
    tree.prototype.config = function ( ) {
        var self = this;

        self.setDnd();
        self.setTypes();
        self.setContextmenu();

        // active changed
        self.plugins.push( 'changed' );

        // activate search when <data-tree-search /> is set
        if ( self.search.length ) {
            self.plugins.push( 'search' );
        }
    }

    // drag and drop
    tree.prototype.setDnd = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'dnd' );

        // callbacks
        self.dnd_callback = {
            drop_check: function ( data ) {
                console.log( data, 'checked')
            }
        }
    }

    // types and add icons
    tree.prototype.setTypes = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'types' );

        // set types
        self.types = {};
        self.types.symbolic = {
            "icon": "symbolic"
        };
    }

    // context menu
    tree.prototype.setContextmenu = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'contextmenu' );

        var links = function ( node ) {

            var items = {
                "Create": {
                    "label": "Create new",
                    "action": function ( obj ) {
                        self.createCategory( node );
                    }
                },
                "Symbolic": {
                    "label": "Create symbolic",
                    "action": function ( obj ) {
                        self.createSymbolic( node );
                    }
                }
            }

            return items;
        }

        // handlers
        self.contextmenu = {
            "items": function ( node ) {
                return links( node )
            }
        }
    }

    // builds tree
    tree.prototype.build = function ( ) {
        var self = this;

        self.tree.jstree({
             'core' : {
                'check_callback' : function (operation, node, node_parent, node_position, more) {

                    // it's a drag event
                    if ( more && more.dnd && ( operation === 'move_node' )) {

                        // disable dragging on root level
                        if ( node.parent === '#' ) {
                            return false;
                        }

                        // limit dragging to same parent level
                        if ( node.parent !== node_parent.id ) {
                            return false;
                        }

                    }

                    return true;
                },
                'data' : {
                    "url" : self.url.data,
                    "data" : function ( node ) {
                        console.log( node );

                        if ( node.id == '#' ) {
                            return { "level" : 0 };
                        } else {
                            return { "id" : node.id };
                        }
                    }
                }
            },
            "plugins": self.plugins,
            "types" : self.types,
            "contextmenu": self.contextmenu,
            "dnd": self.dnd
        })
    }

    // posts new location of dragged node
    tree.prototype.isDragged = function ( event, data ) {
        var self = this;

        // TODO POSITION CHECK!
        // show a loader..

        var postdata = {}
        postdata.parent = data.parent;
        postdata.move = data.node.id;
        postdata.position = ( data.position );

        var post = $.ajax({
            type: "POST",
            url: self.url.post,
            data: postdata,
            dataType: 'json'
        });

        post.success( function() {
            // remove loader...
        });

        post.fail( function() {
            alert( 'Error when sending drag change');
            throw new Error( 'Error when sending drag change' );
        });
    }

    // search within tree
    tree.prototype.searchInTree = function ( event ) {
        event.preventDefault();

        var self = this;
        var searchValue = self.search.find( 'input[type=text]' ).val();

        $( '[data-tree-container]' ).jstree( true ).search( searchValue );
    }

    // open dialog with create category
    tree.prototype.createCategory = function ( node ) {
        var self = this;

        var url = self.element.data( 'create-category' );
        var dialog = $( '[data-reveal]' );

        if ( dialog && url && node.id ) {
            url = url + "&pk_category=" + node.id;

            // open dialog
            arctic.utils.revealIframe.open( dialog, url );
        }
    }

    // open dialog with create symbolic
    tree.prototype.createSymbolic = function ( node ) {
        var self = this;

        var url = self.element.data( 'create-symbolic' );
        var dialog = $( '[data-reveal]' );

        if ( dialog && url && node.id ) {
            url = url + "&pk_category=" + node.id;

            // open dialog
            arctic.utils.revealIframe.open( dialog, url );
        }
    }

    // initiate
    $( function () {
        new tree();
    });

})( jQuery );<commit_msg>open create dialog<commit_after>/*
    TODO:

    dialog => refresh page na submit ( zelfde tree state (open folders)? )

    - http://localhost:8000/categories/create-symbolic/
        - target with search filter

    - keep state on refresh

    - sub menu in contextmenu

 */

( function ( $ ) {

    'use strict'

    function tree( element ) {
        this.element = $( '[data-tree]' );
        this.url = {};
        this.url.data = this.element.data( 'tree' );
        this.url.post = '/categories/navigation-move-node/';
        this.tree = this.element.find( '[data-tree-container]' );
        this.search = this.element.find( '[data-tree-search]' );

        this.plugins = [];

        var self = this;
        self.init();

        window.foo = this;
    }

    tree.prototype.init = function ( ) {
        var self = this;

        // jstree config
        self.config();

        // creates jstree
        self.build();

        // iniate search if plugin is enabled
        if ( $.inArray('search', self.plugins ) ) {
            this.search.submit( function( event ) {
                self.searchInTree( event );
            });
        }

        // handle dragged item
        self.tree.on("move_node.jstree", function ( event, data ) {
            self.isDragged( event, data )
        } );
    }

    // build tree config, return it and place it within self.plugins
    tree.prototype.config = function ( ) {
        var self = this;

        self.setDnd();
        self.setTypes();
        self.setContextmenu();

        // active changed
        self.plugins.push( 'changed' );

        // activate search when <data-tree-search /> is set
        if ( self.search.length ) {
            self.plugins.push( 'search' );
        }
    }

    // drag and drop
    tree.prototype.setDnd = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'dnd' );

        // callbacks
        self.dnd_callback = {
            drop_check: function ( data ) {
                console.log( data, 'checked')
            }
        }
    }

    // types and add icons
    tree.prototype.setTypes = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'types' );

        // set types
        self.types = {};
        self.types.symbolic = {
            "icon": "symbolic"
        };
    }

    // context menu
    tree.prototype.setContextmenu = function ( ) {
        var self = this;

        // activate plugin
        self.plugins.push( 'contextmenu' );

        var links = function ( node ) {

            var items = {
                "Create": {
                    "label": "Create new",
                    "action": function ( obj ) {
                        self.createCategory( node );
                    }
                },
                "Symbolic": {
                    "label": "Create symbolic",
                    "action": function ( obj ) {
                        self.createSymbolic( node );
                    }
                }
            }

            return items;
        }

        // handlers
        self.contextmenu = {
            "items": function ( node ) {
                return links( node )
            }
        }
    }

    // builds tree
    tree.prototype.build = function ( ) {
        var self = this;

        self.tree.jstree({
             'core' : {
                'check_callback' : function (operation, node, node_parent, node_position, more) {

                    // it's a drag event
                    if ( more && more.dnd && ( operation === 'move_node' )) {

                        // disable dragging on root level
                        if ( node.parent === '#' ) {
                            return false;
                        }

                        // limit dragging to same parent level
                        if ( node.parent !== node_parent.id ) {
                            return false;
                        }

                    }

                    return true;
                },
                'data' : {
                    "url" : self.url.data,
                    "data" : function ( node ) {
                        console.log( node );

                        if ( node.id == '#' ) {
                            return { "level" : 0 };
                        } else {
                            return { "id" : node.id };
                        }
                    }
                }
            },
            "plugins": self.plugins,
            "types" : self.types,
            "contextmenu": self.contextmenu,
            "dnd": self.dnd
        })
    }

    // posts new location of dragged node
    tree.prototype.isDragged = function ( event, data ) {
        var self = this;

        // TODO POSITION CHECK!
        // show a loader..

        var postdata = {}
        postdata.parent = data.parent;
        postdata.move = data.node.id;
        postdata.position = ( data.position );

        var post = $.ajax({
            type: "POST",
            url: self.url.post,
            data: postdata,
            dataType: 'json'
        });

        post.success( function() {
            // remove loader...
        });

        post.fail( function() {
            alert( 'Error when sending drag change');
            throw new Error( 'Error when sending drag change' );
        });
    }

    // search within tree
    tree.prototype.searchInTree = function ( event ) {
        event.preventDefault();

        var self = this;
        var searchValue = self.search.find( 'input[type=text]' ).val();

        $( '[data-tree-container]' ).jstree( true ).search( searchValue );
    }

    // open dialog with create category
    tree.prototype.createCategory = function ( node ) {
        var self = this;

        var url = self.element.data( 'create-category' );
        var dialog = $( '[data-reveal]' );

        if ( dialog && url && node.parent ) {
            url = url + "&parent_id=" + node.parent;

            // open dialog
            arctic.utils.revealIframe.open( dialog, url );
        }
    }

    // open dialog with create symbolic
    tree.prototype.createSymbolic = function ( node ) {
        var self = this;

        var url = self.element.data( 'create-symbolic' );
        var dialog = $( '[data-reveal]' );

        if ( dialog && url && node.id ) {
            url = url + "&pk_category=" + node.id;

            // open dialog
            arctic.utils.revealIframe.open( dialog, url );
        }
    }

    // initiate
    $( function () {
        new tree();
    });

})( jQuery );<|endoftext|>