<commit_before>/*jshint multistr:true */

this.recline = this.recline || {};
this.recline.View = this.recline.View || {};

(function($, my) {
  "use strict";
  // Add new grid Control to display a new row add menu bouton
  // It display a simple side-bar menu ,for user to add new 
  // row to grid 

  my.GridControl= Backbone.View.extend({
    className: "recline-row-add",
    // Template for row edit menu , change it if you don't love
    template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
    
    initialize: function(options){
      var self = this;
      _.bindAll(this, 'render');
      this.state = new recline.Model.ObjectState();
      this.render();
    },

    render: function() {
      var self = this;
      this.$el.html(this.template)
    },

    events : {
      "click .recline-row-add" : "addNewRow"
    },

    addNewRow : function(e){
      e.preventDefault()
      this.state.trigger("change")
   }
 }
 );
// ## SlickGrid Dataset View
//
// Provides a tabular view on a Dataset, based on SlickGrid.
//
// https://github.com/mleibman/SlickGrid
//
// Initialize it with a `recline.Model.Dataset`.
//
// Additional options to drive SlickGrid grid can be given through state.
// The following keys allow for customization:
// * gridOptions: to add options at grid level
// * columnsEditor: to add editor for editable columns
//
// For example:
//    var grid = new recline.View.SlickGrid({
//         model: dataset,
//         el: $el,
//         state: {
//          gridOptions: {
//            editable: true,
//            enableAddRows: true 
//            ...
//          },
//          columnsEditor: [
//            {column: 'date', editor: Slick.Editors.Date },
//            {column: 'title', editor: Slick.Editors.Text}
//          ]
//        }
//      });
//// NB: you need an explicit height on the element for slickgrid to work
my.SlickGrid = Backbone.View.extend({
  initialize: function(modelEtc) {
    var self = this;
    this.$el.addClass('recline-slickgrid');
	
    // Template for row delete menu , change it if you don't love 
    this.templates = {
	    "deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
    };

    _.bindAll(this, 'render', 'onRecordChanged');
    this.listenTo(this.model.records, 'add remove reset', this.render);
    this.listenTo(this.model.records, 'change', this.onRecordChanged);
    var state = _.extend({
        hiddenColumns: [],
        columnsOrder: [],
        columnsSort: {},
        columnsWidth: [],
        columnsEditor: [],
        options: {},
        fitColumns: false
      }, modelEtc.state

    );
    this.state = new recline.Model.ObjectState(state);
    this._slickHandler = new Slick.EventHandler();

    //add menu for new row , check if enableAddRow is set to true or not set
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enabledAddRow != undefined 
      && this.state.get("gridOptions").enabledAddRow == true ){
      this.editor    =  new  my.GridControl()
      this.elSidebar =  this.editor.$el
	this.listenTo(this.editor.state, 'change', function(){   
	  this.model.records.add(new recline.Model.Record())
      });
    }
  },
  onRecordChanged: function(record) {
    // Ignore if the grid is not yet drawn
    if (!this.grid) {
      return;
    }
    // Let's find the row corresponding to the index
    var row_index = this.grid.getData().getModelRow( record );
    this.grid.invalidateRow(row_index);
    this.grid.getData().updateItem(record, row_index);
    this.grid.render();
  },
   render: function() {
    var self = this;
    var options = _.extend({
      enableCellNavigation: true,
      enableColumnReorder: true,
      explicitInitialization: true,
      syncColumnCellResize: true,
      forceFitColumns: this.state.get('fitColumns')
    }, self.state.get('gridOptions'));

    // We need all columns, even the hidden ones, to show on the column picker
    var columns = []; 
    // custom formatter as default one escapes html
    // plus this way we distinguish between rendering/formatting and computed value (so e.g. sort still works ...)
    // row = row index, cell = cell index, value = value, columnDef = column definition, dataContext = full row values
    var formatter = function(row, cell, value, columnDef, dataContext) {
      if(columnDef.id == "del"){
        return self.templates.deleterow 
	}
	var field = self.model.fields.get(columnDef.id);
      if (field.renderer) {
        return  field.renderer(value, field, dataContext);
      }else {
        return  value 
      }
    };
    // we need to be sure that user is entering a valid  input , for exemple if 
    // field is date type and field.format ='YY-MM-DD', we should be sure that 
    // user enter a correct value 
    var validator = function(field){
	return function(value){
	   if(field.type == "date" && isNaN(Date.parse(value))){
	      return {
              valid: false,
              msg: "A date is required, check field field-date-format"};
	   }else {
	        return {valid: true, msg :null } 
	  }
	}
    };

    //Add row delete support, check if enableReOrderRow is set to true , by
    //default it is set to false
    // state: {
    //      gridOptions: {
    //        enableReOrderRow: true,
    //      },
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enableReOrderRow != undefined 
      && this.state.get("gridOptions").enableReOrderRow == true ){
      columns.push({
        id: 'del',
        name: '',
        field: 'del',
        sortable: true,
        width: 38,
        formatter: formatter,
        validator:validator
      })
    }
    //Add row delete support, check if enabledDelRow is set to true , by
    //default it is set to false
    // state: {
    //      gridOptions: {
    //        enabledDelRow: true,
    //      },
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enabledDelRow != undefined 
      && this.state.get("gridOptions").enabledDelRow == true ){
      columns.push({
        id: "#",
        name: "",
        width: 22,
        behavior: "selectAndMove",
        selectable: false,
        resizable: false,
        cssClass: "recline-cell-reorder"
      })
    }
    _.each(this.model.fields.toJSON(),function(field){
      var column = {
        id: field.id,
        name: field.label,
        field: field.id,
        sortable: true,
        minWidth: 80,
        formatter: formatter,
        validator:validator(field)
      };
      var widthInfo = _.find(self.state.get('columnsWidth'),function(c){return c.column === field.id;});
      if (widthInfo){
        column.width = widthInfo.width;
      }
      var editInfo = _.find(self.state.get('columnsEditor'),function(c){return c.column === field.id;});
      if (editInfo){
        column.editor = editInfo.editor;
      } else {
        // guess editor type
        var typeToEditorMap = {
          'string': Slick.Editors.LongText,
          'integer': Slick.Editors.IntegerEditor,
          'number': Slick.Editors.Text,
          // TODO: need a way to ensure we format date in the right way
          // Plus what if dates are in distant past or future ... (?)
          // 'date': Slick.Editors.DateEditor,<commit_msg>[#407 support for row reordering in sclickgrid]<commit_after>/*jshint multistr:true */

this.recline = this.recline || {};
this.recline.View = this.recline.View || {};

(function($, my) {
  "use strict";
  // Add new grid Control to display a new row add menu bouton
  // It display a simple side-bar menu ,for user to add new 
  // row to grid 

  my.GridControl= Backbone.View.extend({
    className: "recline-row-add",
    // Template for row edit menu , change it if you don't love
    template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
    
    initialize: function(options){
      var self = this;
      _.bindAll(this, 'render');
      this.state = new recline.Model.ObjectState();
      this.render();
    },

    render: function() {
      var self = this;
      this.$el.html(this.template)
    },

    events : {
      "click .recline-row-add" : "addNewRow"
    },

    addNewRow : function(e){
      e.preventDefault()
      this.state.trigger("change")
   }
 }
 );
// ## SlickGrid Dataset View
//
// Provides a tabular view on a Dataset, based on SlickGrid.
//
// https://github.com/mleibman/SlickGrid
//
// Initialize it with a `recline.Model.Dataset`.
//
// Additional options to drive SlickGrid grid can be given through state.
// The following keys allow for customization:
// * gridOptions: to add options at grid level
// * columnsEditor: to add editor for editable columns
//
// For example:
//    var grid = new recline.View.SlickGrid({
//         model: dataset,
//         el: $el,
//         state: {
//          gridOptions: {
//            editable: true,
//            enableAddRows: true 
//            ...
//          },
//          columnsEditor: [
//            {column: 'date', editor: Slick.Editors.Date },
//            {column: 'title', editor: Slick.Editors.Text}
//          ]
//        }
//      });
//// NB: you need an explicit height on the element for slickgrid to work
my.SlickGrid = Backbone.View.extend({
  initialize: function(modelEtc) {
    var self = this;
    this.$el.addClass('recline-slickgrid');
	
    // Template for row delete menu , change it if you don't love 
    this.templates = {
	    "deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
    };

    _.bindAll(this, 'render', 'onRecordChanged');
    this.listenTo(this.model.records, 'add remove reset', this.render);
    this.listenTo(this.model.records, 'change', this.onRecordChanged);
    var state = _.extend({
        hiddenColumns: [],
        columnsOrder: [],
        columnsSort: {},
        columnsWidth: [],
        columnsEditor: [],
        options: {},
        fitColumns: false
      }, modelEtc.state

    );
    this.state = new recline.Model.ObjectState(state);
    this._slickHandler = new Slick.EventHandler();

    //add menu for new row , check if enableAddRow is set to true or not set
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enabledAddRow != undefined 
      && this.state.get("gridOptions").enabledAddRow == true ){
      this.editor    =  new  my.GridControl()
      this.elSidebar =  this.editor.$el
	this.listenTo(this.editor.state, 'change', function(){   
	  this.model.records.add(new recline.Model.Record())
      });
    }
  },
  onRecordChanged: function(record) {
    // Ignore if the grid is not yet drawn
    if (!this.grid) {
      return;
    }
    // Let's find the row corresponding to the index
    var row_index = this.grid.getData().getModelRow( record );
    this.grid.invalidateRow(row_index);
    this.grid.getData().updateItem(record, row_index);
    this.grid.render();
  },
   render: function() {
    var self = this;
    var options = _.extend({
      enableCellNavigation: true,
      enableColumnReorder: true,
      explicitInitialization: true,
      syncColumnCellResize: true,
      forceFitColumns: this.state.get('fitColumns')
    }, self.state.get('gridOptions'));

    // We need all columns, even the hidden ones, to show on the column picker
    var columns = []; 
    // custom formatter as default one escapes html
    // plus this way we distinguish between rendering/formatting and computed value (so e.g. sort still works ...)
    // row = row index, cell = cell index, value = value, columnDef = column definition, dataContext = full row values
    var formatter = function(row, cell, value, columnDef, dataContext) {
      if(columnDef.id == "del"){
        return self.templates.deleterow 
	}
	var field = self.model.fields.get(columnDef.id);
      if (field.renderer) {
        return  field.renderer(value, field, dataContext);
      }else {
        return  value 
      }
    };
    // we need to be sure that user is entering a valid  input , for exemple if 
    // field is date type and field.format ='YY-MM-DD', we should be sure that 
    // user enter a correct value 
    var validator = function(field){
	return function(value){
	   if(field.type == "date" && isNaN(Date.parse(value))){
	      return {
              valid: false,
              msg: "A date is required, check field field-date-format"};
	   }else {
	        return {valid: true, msg :null } 
	  }
	}
    };
    //Add row delete support, check if enabledDelRow is set to true , by
    //default it is set to false
    // state: {
    //      gridOptions: {
    //        enabledDelRow: true,
    //      },
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enabledDelRow != undefined 
      && this.state.get("gridOptions").enabledDelRow == true ){
      columns.push({
        id: "#",
        name: "",
        width: 22,
        behavior: "selectAndMove",
        selectable: false,
        resizable: false,
        cssClass: "recline-cell-reorder"
      })
    }
    //Add row delete support, check if enableReOrderRow is set to true , by
    //default it is set to false
    // state: {
    //      gridOptions: {
    //        enableReOrderRow: true,
    //      },
    if(this.state.get("gridOptions") 
	&& this.state.get("gridOptions").enableReOrderRow != undefined 
      && this.state.get("gridOptions").enableReOrderRow == true ){
      columns.push({
        id: 'del',
        name: '',
        field: 'del',
        sortable: true,
        width: 38,
        formatter: formatter,
        validator:validator
      })
    }
    _.each(this.model.fields.toJSON(),function(field){
      var column = {
        id: field.id,
        name: field.label,
        field: field.id,
        sortable: true,
        minWidth: 80,
        formatter: formatter,
        validator:validator(field)
      };
      var widthInfo = _.find(self.state.get('columnsWidth'),function(c){return c.column === field.id;});
      if (widthInfo){
        column.width = widthInfo.width;
      }
      var editInfo = _.find(self.state.get('columnsEditor'),function(c){return c.column === field.id;});
      if (editInfo){
        column.editor = editInfo.editor;
      } else {
        // guess editor type
        var typeToEditorMap = {
          'string': Slick.Editors.LongText,
          'integer': Slick.Editors.IntegerEditor,
          'number': Slick.Editors.Text,
          // TODO: need a way to ensure we format date in the right way
          // Plus what if dates are in distant past or future ... (?)
          // 'date': Slick.Editors.DateEditor,
{'fraction_non_alphanumeric': 0.13618623758986648, 'fraction_numerical': 0.0013009243409791166, 'mean_word_length': 2.2631814119749776, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2059845', 'n_tokens_mistral': 4442, 'n_tokens_neox': 4334, 'n_words': 1181}