<commit_before>{
  trackMouseOver: true,
  loadMask: true,
  autoScroll: true,

  componentLoadMask: {msg: "Loading..."},
  deleteMaskMsg: "Deleting...",
  multiSelect: true,

  initComponent: function(){
    var metaColumn;
    var fields = []; // field configs for the underlying data model

    this.plugins = this.plugins || [];
    this.features = this.features || [];

    // Enable filters feature
    this.features.push({
      encode: true,
      ftype: 'filters'
    });

    // Run through columns and set up different configuration for each
    Ext.each(this.columns, function(c, i){

      this.normalizeRenderer(c);

      // Build the field configuration for this column
      var fieldConfig = {name: c.name, defaultValue: c.defaultValue};

      if (c.name !== '_meta') fieldConfig.type = this.fieldTypeForAttrType(c.attrType); // field type (grid editors need this to function well)

      if (c.attrType == 'datetime') {
        fieldConfig.dateFormat = 'Y-m-d g:i:s'; // in this format we receive dates from the server

        if (!c.renderer) {
          c.renderer = Ext.util.Format.dateRenderer(c.format || fieldConfig.dateFormat); // format in which the data will be rendered
        }
      };

      if (c.attrType == 'date') {
        fieldConfig.dateFormat = 'Y-m-d'; // in this format we receive dates from the server

        if (!c.renderer) {
          c.renderer = Ext.util.Format.dateRenderer(c.format || fieldConfig.dateFormat); // format in which the data will be rendered
        }
      };

      fields.push(fieldConfig);

      // We will not use meta columns as actual columns (not even hidden) - only to create the records
      if (c.meta) {
        metaColumn = c;
        return;
      }

      // if comboboxOptions are provided, we render a combobox instead of textfield
      // if (c.comboboxOptions && c.editor.xtype === "textfield") {
      //   c.editor = {xtype: "combobox", options: c.comboboxOptions.split('\\n')}
      // }

      // Set rendeder for association columns (the one displaying associations by the specified method instead of id)
      if (c.assoc) {
        // Editor for association column
        c.editor = Ext.apply({
          parentId: this.id,
          name: c.name,
          selectOnFocus: true // ?
        }, c.editor);

        // Renderer for association column
        this.normalizeAssociationRenderer(c);
      }

      if (c.editor) {
        Ext.applyIf(c.editor, {selectOnFocus: true});
      }

      // Setting the default filter type
      if (c.filterable && !c.filter) {
        c.filter = {type: this.fieldTypeForAttrType(c.attrType)};
      }

      // setting dataIndex
      c.dataIndex = c.name;

      // HACK: somehow this is not set by Ext (while it should be)
      // if (c.xtype == 'datecolumn') c.format = c.format || Ext.util.Format.dateFormat;

    }, this);

    /* ... and done with the columns */

    // Define the model
    Ext.define(this.id, {
      extend: 'Ext.data.Model',
      idProperty: this.pri, // Primary key
      fields: fields
    });

    // After we created the record (model), we can get rid of the meta column
    Ext.Array.remove(this.columns, metaColumn);

    // Prepare column model config with columns in the correct order; columns out of order go to the end.
    var colModelConfig = [];
    var columns = this.columns;

    Ext.each(this.columnsOrder, function(c) {
      var mainColConfig;
      Ext.each(this.columns, function(oc) {
        if (c.name === oc.name) {
          mainColConfig = Ext.apply({}, oc);
          return false;
        }
      });

      colModelConfig.push(Ext.apply(mainColConfig, c));
    }, this);

    // We don't need original columns any longer
    delete this.columns;

    // ... instead, define own column model
    this.columns = colModelConfig;

    var reader = Ext.create('Ext.data.reader.Array', {root: 'data', totalProperty: 'total'});

    // DirectProxy that uses our Ext.direct provider
    var proxy = Ext.create('Ext.data.proxy.Direct', {
      directFn: Netzke.providers[this.id].getData,
      reader: reader,
      listeners: {
        exception: {
          fn: this.loadExceptionHandler,
          scope: this
        },
        load: { // Netzke-introduced event; this will also be fired when an exception occurs.
          fn: function(proxy, response, operation) {
            // besides getting data into the store, we may also get commands to execute
            response = response.result;
            if (response) { // or did we have an exception?
              Ext.each(['data', 'total', 'success'], function(property){delete response[property];});
              this.bulkExecute(response);
            }
          },
          scope: this
        }
      }
    });

    this.store = Ext.create('Ext.data.Store', {
      model: this.id,
      proxy: proxy,
      pruneModifiedRecords: true,
      remoteSort: true,
      pageSize: this.rowsPerPage
    });

    if (this.inlineData) this.store.loadRawData(this.inlineData);

    // Drag'n'Drop
    if (this.enableRowsReordering){
      this.ddPlugin = new Ext.ux.dd.GridDragDropRowOrder({
        scrollable: true // enable scrolling support (default is false)
      });
      this.plugins.push(this.ddPlugin);
    }

    // Cell editing
    if (!this.prohibitUpdate) {
      this.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {pluginId: 'celleditor'}));
    }

    // Toolbar
    this.dockedItems = this.dockedItems || [];
    if (this.enablePagination) {
      this.dockedItems.push({
        xtype: 'pagingtoolbar',
        dock: 'bottom',
        store: this.store,
        items: this.bbar && ["-"].concat(this.bbar) // append the old bbar. TODO: get rid of it.
      });
    } else if (this.bbar) {
      this.dockedItems.push({
        xtype: 'toolbar',
        dock: 'bottom',
        items: this.bbar
      });
    }

    delete this.bbar;

    // Now let Ext.grid.EditorGridPanel do the rest (original initComponent)
    this.callParent();

    // Context menu
    if (this.contextMenu) {
      this.on('itemcontextmenu', this.onItemContextMenu, this);
    }

    // Disabling/enabling editInForm button according to current selection
    if (this.enableEditInForm && !this.prohibitUpdate) {
      this.getSelectionModel().on('selectionchange', function(selModel, selected){
        var disabled;
        if (selected.length === 0) { // empty?
          disabled = true;
        } else {
          // Disable "edit in form" button if new record is present in selection
          Ext.each(selected, function(r){
            if (r.isNew) { disabled = true; return false; }
          });
        };
        this.actions.editInForm.setDisabled(disabled);
      }, this);
    }

    // Process selectionchange event to enable/disable actions
    this.getSelectionModel().on('selectionchange', function(selModel){
      if (this.actions.del) this.actions.del.setDisabled(!selModel.hasSelection() || this.prohibitDelete);
      if (this.actions.edit) this.actions.edit.setDisabled(selModel.getCount() != 1 || this.prohibitUpdate);
    }, this);

    // Drag n Drop event
    if (this.enableRowsReordering){
      this.ddPlugin.on('afterrowmove', this.onAfterRowMove, this);
    }

    // WIP: GridView
    this.getView().getRowClass = this.defaultGetRowClass;

    // FIXME
    // When starting editing as assocition column, pre-load the combobox store from the meta column, so that we don't see the real value of this cell (the id of the associated record), but rather the associated record by the configured method.
    // this.on('beforeedit', function(e){
    //   console.log("e:", e);
    //   if (e.column.assoc && e.record.get('_meta')) {
    //     var data = [e.record.get(e.field), e.record.get('_meta').associationValues[e.field]],
    //         store = e.column.getEditor().store;
    //     if (store.getCount() === 0) {
    //       store.loadData([data]);
    //     }
    //   }
    // }, this);

    this.on('afterrender', function() {
      // Persistence-related events (afterrender to avoid blank event firing on render)
      if (this.persistence) {
        // Inform the server part about column operations
        this.on('columnresize', this.onColumnResize, this);
        this.on('columnmove', this.onColumnMove, this);
        this.on('columnhide', this.onColumnHide, this);
        this.on('columnshow', this.onColumnShow, this);
      }
    }, this);
  },

  fieldTypeForAttrType: function(attrType){
    var map = {
      integer   : 'int',
      decimal   : 'float',
      datetime  : 'date',
      date      : 'date',
      string    : 'string',
      text      : 'string',
      'boolean' : 'boolean'
    };
    return map[attrType] || 'string';
  },

  update: function(){
    this.store.load();
  },

  loadStoreData: function(data){
    var dataRecords = this.getStore().getProxy().getReader().read(data);
    this.getStore().loadData(dataRecords.records);
    Ext.each(['data', 'total', 'success'], function(property){delete data[property];}, this);
    this.bulkExecute(data);
  },

  // Tries editing the first editable (i.e. not hidden, not read-only) sell
  tryStartEditing: function(r){
    var editableIndex = 0;
    Ext.each(this.initialConfig.columns, function(c){
      // skip columns that cannot be edited
      if (!(c.hidden == true || c.editable == false || !c.editor || c.attrType == 'boolean')) {
        return false;
      }
      editableIndex++;
    });

    if (editableIndex < this.initialConfig.columns.length) {this.getPlugin('celleditor').startEdit(r, this.columns[editableIndex]);}
  },

  // Called by the server side to update newly created records
  updateNewRecords: function(records){
    this.updateRecords(records);
  },

  // Called by the server side to update modified records
  updateModRecords: function(records){
    this.updateRecords(records, true);
  },

  // Updates modified or newly created records, by record ID
  // Example of the records argument (updated columns):
  //   {1098 => [1, 'value1', 'value2'], 1099 => [2, 'value1', 'value2']}
  // Example of the records argument (new columns, id autogenerated by Ext):
  //   {"ext-record-200" => [1, 'value1', 'value2']}
  updateRecords: function(records, mod){
    if (!mod) {mod = false;}
    var modRecordsInGrid = [].concat(this.store.getUpdatedRecords()); // there must be a better way to clone an array...
    // replace arrays of data in the args object with Ext.data.Record objects
    for (var k in records){
      records[k] = this.getStore().getProxy().getReader().read({data:[records[k]]}).records[0];
    }
    // for each new record write the data returned by the server, and commit the record
    Ext.each(modRecordsInGrid, function(recordInGrid){
      if (mod ^ recordInGrid.isNew) {
        // if record is new, we access its id by "id", otherwise, the id is in the primary key column
        var recordId = recordInGrid.getId();
        // new data that the server sent us to update this record (identified by the id)
        var newData =  records[recordId];

        if (newData){
          for (var k in newData.data){
            recordInGrid.set(k, newData.get(k));
          }

          recordInGrid.isNew = false;
          recordInGrid.commit();
        }

      }
    }, this);

    // clear the selections
    this.getSelectionModel().clearSelections();

    // check if there are still records with errors
    var modRecords = this.store.getUpdatedRecords();
    if (modRecords.length == 0) {
      // if all records are accepted, reload the grid (so that eventual order/filtering is correct)
      this.store.load();

      // ... and set default getRowClass function
      this.getView().getRowClass = this.defaultGetRowClass;
    } else {
      this.getView().getRowClass = function(r){
        return r.dirty ? "grid-dirty-record" : ""
      }
    }

    this.getView().refresh();
    this.getSelectionModel().fireEvent('selectionchange', this.getSelectionModel());
  },

  defaultGetRowClass: function(r){
    return r.isNew ? "grid-dirty-record" : ""
  },

  selectFirstRow: function(){
    this.getSelectionModel().suspendEvents();
    this.getSelectionModel().selectRow(0);
    this.getSelectionModel().resumeEvents();
  },

  // Normalizes the renderer for a column.
  // Renderer may be:
  // 1) a string that contains the name of the function to be used as renderer.
  // 2) an array, where the first element is the function name, and the rest - the arguments
  // that will be passed to that function along with the value to be rendered.
  // The function is searched in the following objects: 1) Ext.util.Format, 2) this.
  // If not found, it is simply evaluated. Handy, when as renderer we receive an inline JS function,
  // or reference to a function in some other scope.
  // So, these will work:
  // * "uppercase"
  // * ["ellipsis", 10]
  // * ["substr", 3, 5]
  // * "myRenderer" (if this.myRenderer is a function)
  // * ["Some.scope.Format.customRenderer", 10, 20, 30] (if Some.scope.Format.customRenderer is a function)
  // * "function(v){ return 'Value: ' + v; }"
  normalizeRenderer: function(c) {
    if (!c.renderer) return;

    var name, args = [];

    if ('string' === typeof c.renderer) {
      name = c.renderer.camelize(true);
    } else {
      name = c.renderer[0];
      args = c.renderer.slice(1);
    }

    // First check whether Ext.util.Format has it
    if (Ext.isFunction(Ext.util.Format[name])) {
       c.renderer = Ext.Function.bind(Ext.util.Format[name], this, args, 1);
    } else if (Ext.isFunction(this[name])) {
      // ... then if our own class has it
      c.renderer = Ext.Function.bind(this[name], this, args, 1);
    } else {
      // ... and, as last resort, evaluate it (allows passing inline javascript function as renderer)
      eval("c.renderer = " + c.renderer + ";");
    }
  },

  /*
  Set a renderer that displayes association values instead of association record ID.
  The association values are passed in the meta-column under associationValues hash.
  */
  normalizeAssociationRenderer: function(c) {
    c.scope = this;
    var passedRenderer = c.renderer; // renderer we got from normalizeRenderer
    c.renderer = function(value, a, r, ri, ci){
      var column = this.headerCt.items.getAt(ci),
          editor = column.getEditor && column.getEditor(),
          // HACK: using private property 'store'
          recordFromStore = editor && editor.isXType('combobox') && editor.store.findRecord('field1', value),
          renderedValue;

      if (recordFromStore) {
        renderedValue = recordFromStore.get('field2');
      } else if (c.assoc && r.get('_meta')) {
        renderedValue = r.get('_meta').associationValues[c.name] || value;
      } else {
        renderedValue = value;
      }

      return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
    };
  }
}
<commit_msg>Cleaner handling of dates and datetimes<commit_after>{
  trackMouseOver: true,
  loadMask: true,
  autoScroll: true,

  componentLoadMask: {msg: "Loading..."},
  deleteMaskMsg: "Deleting...",
  multiSelect: true,

  initComponent: function(){
    var metaColumn;
    var fields = []; // field configs for the underlying data model

    this.plugins = this.plugins || [];
    this.features = this.features || [];

    // Enable filters feature
    this.features.push({
      encode: true,
      ftype: 'filters'
    });

    // Run through columns and set up different configuration for each
    Ext.each(this.columns, function(c, i){

      this.normalizeRenderer(c);

      // Build the field configuration for this column
      var fieldConfig = {name: c.name, defaultValue: c.defaultValue};

      if (c.name !== '_meta') fieldConfig.type = this.fieldTypeForAttrType(c.attrType); // field type (grid editors need this to function well)

      if (c.attrType == 'datetime') {
        fieldConfig.dateFormat = 'Y-m-d H:i:s'; // set the format in which we receive datetime from the server (so that the model can parse it)

        // While for 'date' columns the renderer is set up automatically (through using column's xtype), there's no appropriate xtype for our custom datetime column.
        // Thus, we need to set the renderer manually.
        // NOTE: for Ext there's no distinction b/w date and datetime; date fields can include time.
        if (!c.renderer) {
          // format in which the data will be rendered; if c.format is nil, Ext.Date.defaultFormat extended with time will be used
          c.renderer = Ext.util.Format.dateRenderer(c.format || Ext.Date.defaultFormat + " H:i:s");
        }
      };

      fields.push(fieldConfig);

      // We will not use meta columns as actual columns (not even hidden) - only to create the records
      if (c.meta) {
        metaColumn = c;
        return;
      }

      // if comboboxOptions are provided, we render a combobox instead of textfield
      // if (c.comboboxOptions && c.editor.xtype === "textfield") {
      //   c.editor = {xtype: "combobox", options: c.comboboxOptions.split('\\n')}
      // }

      // Set rendeder for association columns (the one displaying associations by the specified method instead of id)
      if (c.assoc) {
        // Editor for association column
        c.editor = Ext.apply({
          parentId: this.id,
          name: c.name,
          selectOnFocus: true // ?
        }, c.editor);

        // Renderer for association column
        this.normalizeAssociationRenderer(c);
      }

      if (c.editor) {
        Ext.applyIf(c.editor, {selectOnFocus: true});
      }

      // Setting the default filter type
      if (c.filterable && !c.filter) {
        c.filter = {type: this.fieldTypeForAttrType(c.attrType)};
      }

      // setting dataIndex
      c.dataIndex = c.name;

    }, this);

    /* ... and done with the columns */

    // Define the model
    Ext.define(this.id, {
      extend: 'Ext.data.Model',
      idProperty: this.pri, // Primary key
      fields: fields
    });

    // After we created the record (model), we can get rid of the meta column
    Ext.Array.remove(this.columns, metaColumn);

    // Prepare column model config with columns in the correct order; columns out of order go to the end.
    var colModelConfig = [];
    var columns = this.columns;

    Ext.each(this.columnsOrder, function(c) {
      var mainColConfig;
      Ext.each(this.columns, function(oc) {
        if (c.name === oc.name) {
          mainColConfig = Ext.apply({}, oc);
          return false;
        }
      });

      colModelConfig.push(Ext.apply(mainColConfig, c));
    }, this);

    // We don't need original columns any longer
    delete this.columns;

    // ... instead, define own column model
    this.columns = colModelConfig;

    var reader = Ext.create('Ext.data.reader.Array', {root: 'data', totalProperty: 'total'});

    // DirectProxy that uses our Ext.direct provider
    var proxy = Ext.create('Ext.data.proxy.Direct', {
      directFn: Netzke.providers[this.id].getData,
      reader: reader,
      listeners: {
        exception: {
          fn: this.loadExceptionHandler,
          scope: this
        },
        load: { // Netzke-introduced event; this will also be fired when an exception occurs.
          fn: function(proxy, response, operation) {
            // besides getting data into the store, we may also get commands to execute
            response = response.result;
            if (response) { // or did we have an exception?
              Ext.each(['data', 'total', 'success'], function(property){delete response[property];});
              this.bulkExecute(response);
            }
          },
          scope: this
        }
      }
    });

    this.store = Ext.create('Ext.data.Store', {
      model: this.id,
      proxy: proxy,
      pruneModifiedRecords: true,
      remoteSort: true,
      pageSize: this.rowsPerPage
    });

    if (this.inlineData) this.store.loadRawData(this.inlineData);

    // Drag'n'Drop
    if (this.enableRowsReordering){
      this.ddPlugin = new Ext.ux.dd.GridDragDropRowOrder({
        scrollable: true // enable scrolling support (default is false)
      });
      this.plugins.push(this.ddPlugin);
    }

    // Cell editing
    if (!this.prohibitUpdate) {
      this.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {pluginId: 'celleditor'}));
    }

    // Toolbar
    this.dockedItems = this.dockedItems || [];
    if (this.enablePagination) {
      this.dockedItems.push({
        xtype: 'pagingtoolbar',
        dock: 'bottom',
        store: this.store,
        items: this.bbar && ["-"].concat(this.bbar) // append the old bbar. TODO: get rid of it.
      });
    } else if (this.bbar) {
      this.dockedItems.push({
        xtype: 'toolbar',
        dock: 'bottom',
        items: this.bbar
      });
    }

    delete this.bbar;

    // Now let Ext.grid.EditorGridPanel do the rest (original initComponent)
    this.callParent();

    // Context menu
    if (this.contextMenu) {
      this.on('itemcontextmenu', this.onItemContextMenu, this);
    }

    // Disabling/enabling editInForm button according to current selection
    if (this.enableEditInForm && !this.prohibitUpdate) {
      this.getSelectionModel().on('selectionchange', function(selModel, selected){
        var disabled;
        if (selected.length === 0) { // empty?
          disabled = true;
        } else {
          // Disable "edit in form" button if new record is present in selection
          Ext.each(selected, function(r){
            if (r.isNew) { disabled = true; return false; }
          });
        };
        this.actions.editInForm.setDisabled(disabled);
      }, this);
    }

    // Process selectionchange event to enable/disable actions
    this.getSelectionModel().on('selectionchange', function(selModel){
      if (this.actions.del) this.actions.del.setDisabled(!selModel.hasSelection() || this.prohibitDelete);
      if (this.actions.edit) this.actions.edit.setDisabled(selModel.getCount() != 1 || this.prohibitUpdate);
    }, this);

    // Drag n Drop event
    if (this.enableRowsReordering){
      this.ddPlugin.on('afterrowmove', this.onAfterRowMove, this);
    }

    // WIP: GridView
    this.getView().getRowClass = this.defaultGetRowClass;

    // FIXME
    // When starting editing as assocition column, pre-load the combobox store from the meta column, so that we don't see the real value of this cell (the id of the associated record), but rather the associated record by the configured method.
    // this.on('beforeedit', function(e){
    //   console.log("e:", e);
    //   if (e.column.assoc && e.record.get('_meta')) {
    //     var data = [e.record.get(e.field), e.record.get('_meta').associationValues[e.field]],
    //         store = e.column.getEditor().store;
    //     if (store.getCount() === 0) {
    //       store.loadData([data]);
    //     }
    //   }
    // }, this);

    this.on('afterrender', function() {
      // Persistence-related events (afterrender to avoid blank event firing on render)
      if (this.persistence) {
        // Inform the server part about column operations
        this.on('columnresize', this.onColumnResize, this);
        this.on('columnmove', this.onColumnMove, this);
        this.on('columnhide', this.onColumnHide, this);
        this.on('columnshow', this.onColumnShow, this);
      }
    }, this);
  },

  fieldTypeForAttrType: function(attrType){
    var map = {
      integer   : 'int',
      decimal   : 'float',
      datetime  : 'date',
      date      : 'date',
      string    : 'string',
      text      : 'string',
      'boolean' : 'boolean'
    };
    return map[attrType] || 'string';
  },

  update: function(){
    this.store.load();
  },

  loadStoreData: function(data){
    var dataRecords = this.getStore().getProxy().getReader().read(data);
    this.getStore().loadData(dataRecords.records);
    Ext.each(['data', 'total', 'success'], function(property){delete data[property];}, this);
    this.bulkExecute(data);
  },

  // Tries editing the first editable (i.e. not hidden, not read-only) sell
  tryStartEditing: function(r){
    var editableIndex = 0;
    Ext.each(this.initialConfig.columns, function(c){
      // skip columns that cannot be edited
      if (!(c.hidden == true || c.editable == false || !c.editor || c.attrType == 'boolean')) {
        return false;
      }
      editableIndex++;
    });

    if (editableIndex < this.initialConfig.columns.length) {this.getPlugin('celleditor').startEdit(r, this.columns[editableIndex]);}
  },

  // Called by the server side to update newly created records
  updateNewRecords: function(records){
    this.updateRecords(records);
  },

  // Called by the server side to update modified records
  updateModRecords: function(records){
    this.updateRecords(records, true);
  },

  // Updates modified or newly created records, by record ID
  // Example of the records argument (updated columns):
  //   {1098 => [1, 'value1', 'value2'], 1099 => [2, 'value1', 'value2']}
  // Example of the records argument (new columns, id autogenerated by Ext):
  //   {"ext-record-200" => [1, 'value1', 'value2']}
  updateRecords: function(records, mod){
    if (!mod) {mod = false;}
    var modRecordsInGrid = [].concat(this.store.getUpdatedRecords()); // there must be a better way to clone an array...
    // replace arrays of data in the args object with Ext.data.Record objects
    for (var k in records){
      records[k] = this.getStore().getProxy().getReader().read({data:[records[k]]}).records[0];
    }
    // for each new record write the data returned by the server, and commit the record
    Ext.each(modRecordsInGrid, function(recordInGrid){
      if (mod ^ recordInGrid.isNew) {
        // if record is new, we access its id by "id", otherwise, the id is in the primary key column
        var recordId = recordInGrid.getId();
        // new data that the server sent us to update this record (identified by the id)
        var newData =  records[recordId];

        if (newData){
          for (var k in newData.data){
            recordInGrid.set(k, newData.get(k));
          }

          recordInGrid.isNew = false;
          recordInGrid.commit();
        }

      }
    }, this);

    // clear the selections
    this.getSelectionModel().clearSelections();

    // check if there are still records with errors
    var modRecords = this.store.getUpdatedRecords();
    if (modRecords.length == 0) {
      // if all records are accepted, reload the grid (so that eventual order/filtering is correct)
      this.store.load();

      // ... and set default getRowClass function
      this.getView().getRowClass = this.defaultGetRowClass;
    } else {
      this.getView().getRowClass = function(r){
        return r.dirty ? "grid-dirty-record" : ""
      }
    }

    this.getView().refresh();
    this.getSelectionModel().fireEvent('selectionchange', this.getSelectionModel());
  },

  defaultGetRowClass: function(r){
    return r.isNew ? "grid-dirty-record" : ""
  },

  selectFirstRow: function(){
    this.getSelectionModel().suspendEvents();
    this.getSelectionModel().selectRow(0);
    this.getSelectionModel().resumeEvents();
  },

  // Normalizes the renderer for a column.
  // Renderer may be:
  // 1) a string that contains the name of the function to be used as renderer.
  // 2) an array, where the first element is the function name, and the rest - the arguments
  // that will be passed to that function along with the value to be rendered.
  // The function is searched in the following objects: 1) Ext.util.Format, 2) this.
  // If not found, it is simply evaluated. Handy, when as renderer we receive an inline JS function,
  // or reference to a function in some other scope.
  // So, these will work:
  // * "uppercase"
  // * ["ellipsis", 10]
  // * ["substr", 3, 5]
  // * "myRenderer" (if this.myRenderer is a function)
  // * ["Some.scope.Format.customRenderer", 10, 20, 30] (if Some.scope.Format.customRenderer is a function)
  // * "function(v){ return 'Value: ' + v; }"
  normalizeRenderer: function(c) {
    if (!c.renderer) return;

    var name, args = [];

    if ('string' === typeof c.renderer) {
      name = c.renderer.camelize(true);
    } else {
      name = c.renderer[0];
      args = c.renderer.slice(1);
    }

    // First check whether Ext.util.Format has it
    if (Ext.isFunction(Ext.util.Format[name])) {
       c.renderer = Ext.Function.bind(Ext.util.Format[name], this, args, 1);
    } else if (Ext.isFunction(this[name])) {
      // ... then if our own class has it
      c.renderer = Ext.Function.bind(this[name], this, args, 1);
    } else {
      // ... and, as last resort, evaluate it (allows passing inline javascript function as renderer)
      eval("c.renderer = " + c.renderer + ";");
    }
  },

  /*
  Set a renderer that displayes association values instead of association record ID.
  The association values are passed in the meta-column under associationValues hash.
  */
  normalizeAssociationRenderer: function(c) {
    c.scope = this;
    var passedRenderer = c.renderer; // renderer we got from normalizeRenderer
    c.renderer = function(value, a, r, ri, ci){
      var column = this.headerCt.items.getAt(ci),
          editor = column.getEditor && column.getEditor(),
          // HACK: using private property 'store'
          recordFromStore = editor && editor.isXType('combobox') && editor.store.findRecord('field1', value),
          renderedValue;

      if (recordFromStore) {
        renderedValue = recordFromStore.get('field2');
      } else if (c.assoc && r.get('_meta')) {
        renderedValue = r.get('_meta').associationValues[c.name] || value;
      } else {
        renderedValue = value;
      }

      return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
    };
  }
}
<|endoftext|>


<commit_before>var strings = require("../../libs/helpers/strings"),
    createRepository = require("../../libs/repositories").createRepository;

var Projects = createRepository("projects", {
    init: function() {
        // initializing a reactive method
        var that = this;
        this.sockets.createReactiveMethod('getProject', function(parameters, callback) {
            if (parameters.code) {
                that.getByCode(parameters.code, function(project) {
                    callback(project);
                });
            }
        });
    },

    // gets a list of project, sorted by date_created
    getAllByDate: function(callback) {
        this.find().sort({ date_created: 1 }).toArray(function(err, projects) {
            if (err) console.log(err);
            return callback(projects ? projects : null);
        });
    },

    // gets one project by its code
    getByCode: function(code, callback) {
        this.baseFindOne({ code: code }, function(project) {
            return callback(project ? project : null);
        });
    },

    // saves a project
    save: function(project, callback) {
        // converts the project's code to a slug
        project.code = strings.slugify(project.name);

        this.baseSave(project, function(savedProject, errors) {
            return callback(savedProject, errors);
        });
    },

    // deletes a project by its ObjectID
    delete: function(objectId, callback) {
        this.baseDelete({ _id: this.ObjectId(objectId) }, function(success, project) {
            return callback(success, project);
        });
    }
});

module.exports = Projects;<commit_msg>restructured repositories<commit_after>var ThinAir = require('../../libs/thinair');

module.exports = ThinAir.createRepository("projects", {
    // gets a list of project, sorted by date_created
    getAllByDate: function(callback) {
        this.find().sort({ date_created: 1 }).toArray(function(err, projects) {
            if (err) console.log(err);
            return callback(projects ? projects : null);
        });
    },
});<|endoftext|>


<commit_before>'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name bind2vind
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/bind2vind}
*/
setReadOnly( ns, 'bind2vind', require( '@stdlib/types/ndarray/base/bind2vind' ) );

/**
* @name ind2sub
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/ind2sub}
*/
setReadOnly( ns, 'ind2sub', require( '@stdlib/types/ndarray/base/ind2sub' ) );

/**
* @name numel
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/numel}
*/
setReadOnly( ns, 'numel', require( '@stdlib/types/ndarray/base/numel' ) );

/**
* @name shape2strides
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/shape2strides}
*/
setReadOnly( ns, 'shape2strides', require( '@stdlib/types/ndarray/base/shape2strides' ) );

/**
* @name strides2offset
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/strides2offset}
*/
setReadOnly( ns, 'strides2offset', require( '@stdlib/types/ndarray/base/strides2offset' ) );

/**
* @name sub2ind
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/sub2ind}
*/
setReadOnly( ns, 'sub2ind', require( '@stdlib/types/ndarray/base/sub2ind' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name bind2vind
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/bind2vind}
*/
setReadOnly( ns, 'bind2vind', require( '@stdlib/types/ndarray/base/bind2vind' ) );

/**
* @name ind2sub
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/ind2sub}
*/
setReadOnly( ns, 'ind2sub', require( '@stdlib/types/ndarray/base/ind2sub' ) );

/**
* @name numel
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/numel}
*/
setReadOnly( ns, 'numel', require( '@stdlib/types/ndarray/base/numel' ) );

/**
* @name shape2strides
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/shape2strides}
*/
setReadOnly( ns, 'shape2strides', require( '@stdlib/types/ndarray/base/shape2strides' ) );

/**
* @name strides2offset
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/strides2offset}
*/
setReadOnly( ns, 'strides2offset', require( '@stdlib/types/ndarray/base/strides2offset' ) );

/**
* @name sub2ind
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/sub2ind}
*/
setReadOnly( ns, 'sub2ind', require( '@stdlib/types/ndarray/base/sub2ind' ) );

/**
* @name vind2bind
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/types/ndarray/base/vind2bind}
*/
setReadOnly( ns, 'vind2bind', require( '@stdlib/types/ndarray/base/vind2bind' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>var hmac = require('crypto-browserify/create-hmac')
var config = require('./bricoleurConfig.json')
var Buffer = require('buffer/').Buffer
var through = require('through')

var interface = function (db, cvs, user) {
  self = this

  console.log(config)

  var s = through(function Write (d) { // multiple ways to call api
    console.log(d)
  })

  cvs._.brico = {s : s}

  cvs._.render = require(config.canvasRender)

  var login = search(config.library.root, config.auth)

  if (sessionStorage[user])
    self.auth({value: {name: user, session: sessionStorage[user]}})

  if (!sessionStorage[user] && user !== 'default')
    cvs.draw({key:'pipe:'+genUID(), value: config.auth + '>brico'})

  cvs.draw([login,'login>brico'])

  db.liveStream({reverse : true})
    .on('data', sync)

  function sync (d) { // sync up with db / push updates
    var path = d.key.split(':')
    if (path[0] === 'library') { // install library in this function!

    }
  }

  this.auth = function (d) {
    var img = new Buffer(config.uImg).toString()

    var auth = { name: d.value.name }
    if (!d.value.session)
      auth.pass = hmac('sha256', img).update(d.value.pass).digest('hex')

    if (d.value.session) auth.session = d.value.session

    db.auth(auth, function (e, res) {
      if (e) {
        if (!search(cvs._, config.auth)) {
          cvs.draw({
            key: 'module:'+genUID(),
            value: search(config.library.root, config.auth)
          })
          cvs.draw({key:'pipe:'+genUID(), value: config.auth + '>brico'})
        } else console.error(e) // draw login interface!
        return false
      }
      sessionStorage[res.name] = res.token
      if (config.users[user].canvas) api.canvas.put(config.users[user].canvas)
      if (d.value.origin) cvs._[d.value.origin].s.write(res)
    })
  }

  this.deauth = function (d) {
    db.deauth(function () {
      delete sessionStorage[user]
      var path = (!getPath()) ? home : home + getPath()
      window.location = path
    })
  }

  this.canvas = function (d) {
    var objects = []
    if (d.modules) {
      d.modules.map(function (currentValue, index, array) {
        var pkg = search(config.library.root, currentValue)
        objects.push({key:'module:'+genUID(), value: pkg})
      })
      objects.forEach(cvs.draw)
    }
    if (d.pipes) {
      objects = []
      d.pipes.forEach(function (p) {
        objects.push({key:'pipe:'+genUID(), value:p})
      })
      objects.forEach(cvs.draw)
    }
  }

  this.data = function (d) {

  }

  return s
}

var Canvas = function (interface) {
  var self = this

  this._ = { brico : { s : interface } }

  this.draw = function (d) {
    if (typeof d === 'string') {
      if (d.split('>').length > 0) {
        drawPipe(d.split('>'))
      } else drawModule(d)
    }
    if (typeof d === 'object' && d.nimoy) drawModule(d)
    if (d instanceof Array) { // sync draw
      d.forEach(function (str) {
        if (typeof str === 'string' && str.split('>').length > 0) {
          drawPipe(str.split('>'))
        } else drawModule(str)
      })
    }

    function drawPipe (conn) {
      var a = search(self._, conn[0]).s
      var b = search(self._, conn[1]).s
      var key = 'pipe:' + conn + ':' + genUID()
      a.pipe(b)
      self._[key] = [a , b]
    }

    function drawModule (nameOrPkg) {
      var pkg = (typeof nameOrPkg !== 'object')
        ? search(config.library.master, nameOrPkg)
        : nameOrPkg

      console.log(pkg)

      var key = 'module:' + pkg.name + ':' + genUID()
      self._[key] = self._.render({key:key, value:pkg})
    }
  }

  this.erase = function (d) {
    if (typeof d === 'string') {
      if (d.split('>').length > 0) {
        erasePipe(d.split('>'))
      } else eraseModule(d)
    }
    if (typeof d === 'object' && d.nimoy) eraseModule(d)
    if (d instanceof Array) { // sync draw
      d.forEach(function (str) {
        if (typeof str === 'string' && str.split('>').length > 0) {
          erasePipe(str.split('>'))
        } else eraseModule(d)
      })
    }

    function erasePipe (pipeID) {
      var a = self._[pipeID][0]
      var b = self._[pipeID][1]
      a.unpipe(b)
      delete self._[pipeID]
    }

    function eraseModule (moduleID) { // check for pipes first then delete
      delete self._[mod]

      var key = 'module:' + pkg.name + ':' + genUID()
      self._[key] = self._.render(pkg)
    }
  }
}

module.exports = function Bricoleur (multiLevel, usr, cb) {
  var cvs = new Canvas()
  var api = new interface(multiLevel, cvs, usr)

  window.cvs = cvs._

  return api
}

// UTILS
function genUID () { return Math.random().toString().slice(2) }

function search (haystack, needle) {
  for (hay in haystack) {
    if (hay.match(needle)) return haystack[hay]
  }
}

function getPath () {
  if (!window.location.hash) return false
  if (window.location.hash) return window.location.hash.slice(1)
}
<commit_msg>properly hash/id modules, fix auth bugs<commit_after>var hmac = require('crypto-browserify/create-hmac')
var hash = require('crypto-browserify/create-hash')
var config = require('./bricoleurConfig.json')
var Buffer = require('buffer/').Buffer
var through = require('through')

var interface = function (db, cvs, user) {
  self = this

  var s = through(function Write (d) {
    if (d.key) {
      var path = d.key.split(':')
      if (self[path]) self[path](d)
    }
  })

  cvs._.brico = {s : s}

  cvs._.render = require(config.canvasRender)

  this.auth = function (d) {
    if (!d.value.session) {
      var img = new Buffer(config.uImg).toString()
      var pass = hmac('sha256', img).update(d.value.pass).digest('hex')
      db.auth({name: d.value.name, pass: pass}, handleAuth)
    } else if (d.value.session) {
      db.auth({name: d.value.name, session: d.value.session}, handleAuth)
    }

    function handleAuth (e, res) {
      if (e) { cvs.draw([config.auth, config.auth+'>brico']) }
      if (!e) {
        sessionStorage[res.name] = res.token
        var login = search(cvs._, config.auth)
        if (typeof login ==='object') cvs.erase(login.html.id)
        if (config.users[user].canvas) { // !
          cvs.draw(config.users[user].canvas.modules)
          cvs.draw(config.users[user].canvas.pipes)
        }
        return false
      }
    }
  }

  this.deauth = function (d) {
    db.deauth(function () {
      delete sessionStorage[user]
      var path = (!getPath()) ? home : home + getPath()
      window.location = path
    })
  }

  this.data = function (d) {
    console.log(d)
  }

  if (sessionStorage[user])
    this.auth({value: {name: user, session: sessionStorage[user]}})

  if (!sessionStorage[user] && user !== 'default')
    cvs.draw([config.auth, config.auth+'>brico'])

  db.liveStream({reverse : true})
    .on('data', sync)

  function sync (d) {
    console.log(d)
    var path = d.key.split(':')
    if (path[0] === 'library') {

    }
  }

  return s
}

var Canvas = function (interface) {
  var self = this

  this._ = { brico : { s : interface } }

  this.draw = function (d) {
    if (typeof d === 'string') {
      if (d.split('>').length > 1) {
        drawPipe(d.split('>'))
      } else drawModule(d)
    }
    if (typeof d === 'object' && d.nimoy) drawModule(d)
    if (d instanceof Array) {
      d.forEach(function (str) {
        if (typeof str === 'string' && str.split('>').length > 1) {
          drawPipe(str.split('>'))
        } else drawModule(str)
      })
    }

    function drawPipe (conn) {
      var a = search(self._, conn[0]).s
      var b = search(self._, conn[1]).s
      var key = 'pipe:' + genUID(conn) + ':' + conn[0] + '|' + conn[1]
      a.pipe(b)
      self._[key] = [a , b]
    }

    function drawModule (nameOrPkg) {
      var pkg = (typeof nameOrPkg !== 'object')
        ? search(config.library.master, nameOrPkg)
        : nameOrPkg
      var key = 'module:' + genUID() + ':' + pkg.name
      self._[key] = self._.render({key:key, value:pkg})
    }
  }

  this.erase = function (d) {
    if (typeof d === 'string') {
      if (d.split('>').length > 1) {
        erasePipe(d.split('>'))
      } else eraseModule(d)
    }
    if (typeof d === 'object' && d.nimoy) eraseModule(d)
    if (d instanceof Array) {
      d.forEach(function (str) {
        if (typeof str === 'string' && str.split('>').length > 1) {
          erasePipe(str.split('>'))
        } else eraseModule(d)
      })
    }

    function erasePipe (pipeID) {
      var a = self._[pipeID][0]
      var b = self._[pipeID][1]
      a.unpipe(b)
      delete self._[pipeID]
    }

    function eraseModule (moduleID) {
      var mod = search(self._, moduleID)
      if (mod) {
        mod.s.end()
        mod.erase()
        delete mod
      }
    }
  }
}

module.exports = function Bricoleur (multiLevel, usr, cb) {
  var cvs = new Canvas()
  var api = new interface(multiLevel, cvs, usr)

  window.cvs = cvs._

  return api
}

// UTILS

function genUID (name) {
  var r = Math.random().toString().slice(2)
  return hash('sha1').update(name+r).digest('hex')
}

function search (haystack, needle) {
  for (hay in haystack) {
    if (hay.match(needle)) return haystack[hay]
  }
}

function getPath () {
  if (!window.location.hash) return false
  if (window.location.hash) return window.location.hash.slice(1)
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Link } from 'react-router'

import SocialAccountItem from '../components/SocialAccountItem'
import {
  getName, getVerifiedAccounts, getAvatarUrl,
  getAddress, getBirthDate, getConnections
} from '../utils/profile-utils.js'
import { IdentityActions } from '../store/identities'
import { SearchActions } from '../store/search'
import Image from '../components/Image'

function mapStateToProps(state) {
  return {
    currentIdentity: state.identities.current,
    localIdentities: state.identities.local,
    nameLookupUrl: state.settings.api.nameLookupUrl,
    bookmarks: state.settings.bookmarks
  }
}

function mapDispatchToProps(dispatch) {
  let actions = Object.assign(IdentityActions, SearchActions)
  return bindActionCreators(actions, dispatch)
}

class ViewProfilePage extends Component {
  static propTypes = {
    fetchCurrentIdentity: PropTypes.func.isRequired,
    updateCurrentIdentity: PropTypes.func.isRequired,
    updateQuery: PropTypes.func.isRequired,
    currentIdentity: PropTypes.object.isRequired,
    localIdentities: PropTypes.array.isRequired,
    nameLookupUrl: PropTypes.string.isRequired
  }

  constructor(props) {
    super(props)

    this.state = {
      currentIdentity: {
        id: null,
        profile: null,
        verifications: [],
        blockNumber: null,
        transactionNumber: null
      }
    }
  }

  componentHasNewRouteParams(routeParams) {
    if (routeParams.index) {
      const profile = this.props.localIdentities[routeParams.index].profile,
            name = this.props.localIdentities[routeParams.index].id,
            verifications = []
      this.props.updateCurrentIdentity(name, profile, verifications)
    } else if (routeParams.name) {
      this.props.fetchCurrentIdentity(routeParams.name, this.props.nameLookupUrl)
    }
  }

  componentWillMount() {
    this.componentHasNewRouteParams(this.props.routeParams)
  }

  componentWillUnmount() {
    this.props.updateCurrentIdentity('', {}, [])
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.routeParams !== this.props.routeParams) {
      this.componentHasNewRouteParams(nextProps.routeParams)
    }
    this.setState({
      currentIdentity: nextProps.currentIdentity
    })
  }

  render() {
    let identity = this.state.currentIdentity,
      blockchainId = identity.id

    if (blockchainId === 'naval.id') {
      identity = this.props.bookmarks[0]
    }

    let profile = identity.profile,
        verifications = identity.verifications,
        blockNumber = identity.blockNumber,
        transactionIndex = identity.transactionIndex,
        connections = getConnections(profile),
        address = getAddress(profile),
        birthDate = getBirthDate(profile)

    return (

        { profile !== null && profile !== undefined ?

                  <Link to={this.props.location.pathname + "/edit"}
                    className="btn btn-primary btn-lg btn-pro-edit">
                    Edit
                  </Link>

                  { (blockNumber && transactionIndex) ?

                    Registered in block #{blockNumber},

                    transaction #{transactionIndex}

                  : null }

{getName(profile)}

                    {profile.description}

                  { address ?

                    {address}

                  : null }
                  { birthDate ?

                    {birthDate}

                  : null }

              {connections.length ?

Connections

              : null }
              {connections.map((connection, index) => {
                if (connection.id) {
                  return (
                    <Link to={`/profile/blockchain/${connection.id}`}
                      key={index} className="connections">
                      <Image src={getAvatarUrl(connection)}
                        fallbackSrc="https://s3.amazonaws.com/65m/avatar-placeholder.png"
                        style={{ width: '40px', height: '40px' }} />
                    </Link>
                  )
                }
              })}

                {getVerifiedAccounts(profile, verifications).map(function(account) {
                  return (
                    <SocialAccountItem
                      key={account.service + '-' + account.identifier}
                      service={account.service}
                      identifier={account.identifier}
                      proofUrl={account.proofUrl} />
                  )
                })}

        :

        }

    )
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ViewProfilePage)
<commit_msg>show the edit button for local profiles and the connect button for remote profiles<commit_after>import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Link } from 'react-router'

import SocialAccountItem from '../components/SocialAccountItem'
import {
  getName, getVerifiedAccounts, getAvatarUrl,
  getAddress, getBirthDate, getConnections
} from '../utils/profile-utils.js'
import { IdentityActions } from '../store/identities'
import { SearchActions } from '../store/search'
import Image from '../components/Image'

function mapStateToProps(state) {
  return {
    currentIdentity: state.identities.current,
    localIdentities: state.identities.local,
    nameLookupUrl: state.settings.api.nameLookupUrl,
    bookmarks: state.settings.bookmarks
  }
}

function mapDispatchToProps(dispatch) {
  let actions = Object.assign(IdentityActions, SearchActions)
  return bindActionCreators(actions, dispatch)
}

class ViewProfilePage extends Component {
  static propTypes = {
    fetchCurrentIdentity: PropTypes.func.isRequired,
    updateCurrentIdentity: PropTypes.func.isRequired,
    updateQuery: PropTypes.func.isRequired,
    currentIdentity: PropTypes.object.isRequired,
    localIdentities: PropTypes.array.isRequired,
    nameLookupUrl: PropTypes.string.isRequired
  }

  constructor(props) {
    super(props)

    this.state = {
      currentIdentity: {
        id: null,
        profile: null,
        verifications: [],
        blockNumber: null,
        transactionNumber: null
      }
    }
  }

  componentHasNewRouteParams(routeParams) {
    if (routeParams.index) {
      const profile = this.props.localIdentities[routeParams.index].profile,
            name = this.props.localIdentities[routeParams.index].id,
            verifications = []
      this.props.updateCurrentIdentity(name, profile, verifications)
    } else if (routeParams.name) {
      this.props.fetchCurrentIdentity(routeParams.name, this.props.nameLookupUrl)
    }
  }

  componentWillMount() {
    this.componentHasNewRouteParams(this.props.routeParams)
  }

  componentWillUnmount() {
    this.props.updateCurrentIdentity('', {}, [])
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.routeParams !== this.props.routeParams) {
      this.componentHasNewRouteParams(nextProps.routeParams)
    }
    this.setState({
      currentIdentity: nextProps.currentIdentity
    })
  }

  render() {
    let identity = this.state.currentIdentity,
      blockchainId = identity.id

    if (blockchainId === 'naval.id') {
      identity = this.props.bookmarks[0]
    }

    let profile = identity.profile,
        verifications = identity.verifications,
        blockNumber = identity.blockNumber,
        transactionIndex = identity.transactionIndex,
        connections = getConnections(profile),
        address = getAddress(profile),
        birthDate = getBirthDate(profile)

    let isLocal = false
    if (this.props.routeParams.hasOwnProperty('index')) {
      isLocal = true
    }

    return (

        { profile !== null && profile !== undefined ?

                { isLocal ?

                  <Link to={this.props.location.pathname + "/edit"}
                    className="btn btn-primary btn-lg btn-pro-edit">
                    Edit
                  </Link>

                :

                  <button className="btn btn-primary btn-lg btn-pro-edit">
                    Connect
                  </button>

                }

                  { (blockNumber && transactionIndex) ?

                    Registered in block #{blockNumber},

                    transaction #{transactionIndex}

                  : null }

{getName(profile)}

                    {profile.description}

                  { address ?

                    {address}

                  : null }
                  { birthDate ?

                    {birthDate}

                  : null }

              {connections.length ?

Connections

              : null }
              {connections.map((connection, index) => {
                if (connection.id) {
                  return (
                    <Link to={`/profile/blockchain/${connection.id}`}
                      key={index} className="connections">
                      <Image src={getAvatarUrl(connection)}
                        fallbackSrc="https://s3.amazonaws.com/65m/avatar-placeholder.png"
                        style={{ width: '40px', height: '40px' }} />
                    </Link>
                  )
                }
              })}

                {getVerifiedAccounts(profile, verifications).map(function(account) {
                  return (
                    <SocialAccountItem
                      key={account.service + '-' + account.identifier}
                      service={account.service}
                      identifier={account.identifier}
                      proofUrl={account.proofUrl} />
                  )
                })}

        :

        }

    )
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ViewProfilePage)
<|endoftext|>


<commit_before>define([
  'Class',
  'uri',
  'underscore',
  'backbone'
], function(Class, UriTemplate, _, Backbone) {
  'use strict';

  var AtlasService = Class.extend({

    products: [
      {
        name: 'Tomatoes',
        id: '0702'
      },
      {
        name: 'Onions',
        id: '0703'
      },
      {
        name: 'Cabbages',
        id: '0704'
      },
      {
        name: 'Lettuce',
        id: '0705'
      },
      {
        name: 'Root Vegetables',
        id: '0706'
      },
      {
        name: 'Cucumbers',
        id: '0707'
      },
      {
        name: 'Legumes',
        id: '0708'
      },
      {
        name: 'Other Vegetables',
        id: '0709'
      },
      {
        name: 'Cassava',
        id: '0714'
      },
      {
        name: 'Coconuts, Brazil Nuts, and Cashews',
        id: '0801'
      },
      {
        name: 'Other Nuts',
        id: '0802'
      },
      {
        name: 'Bananas',
        id: '0803'
      },
      {
        name: 'Tropical Fruits',
        id: '0804'
      },
      {
        name: 'Citrus',
        id: '0805'
      },
      {
        name: 'Grapes',
        id: '0806'
      },
      {
        name: 'Melons',
        id: '0807'
      },
      {
        name: 'Apples and Pears',
        id: '0808'
      },
      {
        name: 'Other Fruits',
        id: '0810'
      },
      {
        name: 'Coffee',
        id: '0901'
      },
      {
        name: 'Tea',
        id: '0902'
      },
      {
        name: 'MatŽ',
        id: '0903'
      },
      {
        name: 'Wheat',
        id: '1001'
      },
      {
        name: 'Rye',
        id: '1002'
      },
      {
        name: 'Barley',
        id: '1003'
      },
      {
        name: 'Oats',
        id: '1004'
      },
      {
        name: 'Corn',
        id: '1005'
      },
      {
        name: 'Rice',
        id: '1006'
      },
      {
        name: 'Buckwheat',
        id: '1008'
      },
      {
        name: 'Malt',
        id: '1107'
      },
      {
        name: 'Soybeans',
        id: '1201'
      },
      {
        name: 'Ground Nuts',
        id: '1202'
      },
      {
        name: 'Hops',
        id: '1210'
      },
      {
        name: 'Locust Beans',
        id: '1212'
      }
    ],

    defaults: {
      classification: 'hs',
      tradeFlow: 'export',
      year: 2012,
      origin: 'esp',
      destination: 'show',
      product: 'all'
    },

    urlTemplate: 'http://atlas.media.mit.edu/{classification}/{tradeFlow}/' +
      '{year}/{origin}/{destination}/{product}/',

    get: function(params, callback) {
      var url = this._getUrl(params);

      $.getJSON(url, function(d) {
        Backbone.Events.trigger('AtlasService/change', d.data);
        callback && callback(d.data);
      });
    },

    getProductsList: function() {
      return this.products;
    },

    _getUrl: function(params) {
      params = _.extend({}, this.defaults, params || {});
      var url = new UriTemplate(this.urlTemplate).fillFromObject(params);
      return decodeURIComponent(url);
    },

  });

  return new AtlasService();
});<commit_msg>trigger events<commit_after>define([
  'Class',
  'uri',
  'underscore',
  'backbone'
], function(Class, UriTemplate, _, Backbone) {
  'use strict';

  var AtlasService = Class.extend({

    products: [
      {
        name: 'Tomatoes',
        id: '0702',
        production: 4007000
      },
      {
        name: 'Onions',
        id: '0703',
        production: 1464700
      },
      {
        name: 'Cabbages',
        id: '0704',
        production: 325500
      },
      {
        name: 'Lettuce',
        id: '0705',
        production: 870200
      },
      {
        name: 'Root Vegetables',
        id: '0706',
        production: 907400
      },
      {
        name: 'Cucumbers',
        id: '0707',
        production: 713200
      },
      {
        name: 'Legumes',
        id: '0708',
        production: 293100
      },
      {
        name: 'Other Vegetables',
        id: '0709',
        production: 4828300
      },
      {
        name: 'Cassava',
        id: '0714',
        production: 28000
      },
      {
        name: 'Coconuts, Brazil Nuts, and Cashews',
        id: '0801',
        production:
      },
      {
        name: 'Other Nuts',
        id: '0802',
        production: 257100
      },
      {
        name: 'Bananas',
        id: '0803',
        production: 364600
      },
      {
        name: 'Tropical Fruits',
        id: '0804',
        production: 175700
      },
      {
        name: 'Citrus',
        id: '0805',
        production: 5501500
      },
      {
        name: 'Grapes',
        id: '0806',
        production:
      },
      {
        name: 'Melons',
        id: '0807',
        production: 1724500
      },
      {
        name: 'Apples and Pears',
        id: '0808',
        production: 973500
      },
      {
        name: 'Other Fruits',
        id: '0810',
        production: 529747
      },
      {
        name: 'Coffee',
        id: '0901',
        production: 0
      },
      {
        name: 'Tea',
        id: '0902',
        production:
      },
      {
        name: 'MatŽ',
        id: '0903',
        production:
      },
      {
        name: 'Wheat',
        id: '1001',
        production: 4650300
      },
      {
        name: 'Rye',
        id: '1002',
        production: 296700
       },
      {
        name: 'Barley',
        id: '1003',
        production: 5976900
      },
      {
        name: 'Oats',
        id: '1004',
        production: 683500
      },
      {
        name: 'Corn',
        id: '1005',
        production: 4234600
      },
      {
        name: 'Rice',
        id: '1006',
        production:
      },
      {
        name: 'Buckwheat',
        id: '1008',
        production:
      },
      {
        name: 'Malt',
        id: '1107',
        production:
      },
      {
        name: 'Soybeans',
        id: '1201',
        production:
      },
      {
        name: 'Ground Nuts',
        id: '1202'
      },
      {
        name: 'Hops',
        id: '1210',
        production:
      },
      {
        name: 'Locust Beans',
        id: '1212',
        production:
      }
    ],

    defaults: {
      classification: 'hs',
      tradeFlow: 'export',
      year: 2012,
      origin: 'esp',
      destination: 'show',
      product: 'all'
    },

    urlTemplate: 'http://atlas.media.mit.edu/{classification}/{tradeFlow}/' +
      '{year}/{origin}/{destination}/{product}/',

    get: function(params, callback) {
      var url = this._getUrl(params);

      $.getJSON(url, function(d) {
        Backbone.Events.trigger('AtlasService/change', d.data);
        callback && callback(d.data);
      });
    },

    getProductsList: function() {
      return this.products;
    },

    _getUrl: function(params) {
      params = _.extend({}, this.defaults, params || {});
      var url = new UriTemplate(this.urlTemplate).fillFromObject(params);
      return decodeURIComponent(url);
    },

  });

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


<commit_before>'use strict';

document.onscroll = function() {
    var fileContainers = document.getElementsByClassName('file');
    var maxBerofeZero = -1000000;
    var maxBerofeZeroIndex = -1;
    for(var i=0; i<fileContainers.length; i++) {
      var currentTop = fileContainers[i].getBoundingClientRect().top;
      if (currentTop > maxBerofeZero && currentTop < 0) {
        maxBerofeZero = currentTop;
        maxBerofeZeroIndex = i;
      }
    }
    if (maxBerofeZeroIndex === -1) {
      document.getElementsByClassName('file-header')[0].style.top = '0px';
      return;
    }
    var currentfileContent = fileContainers[maxBerofeZeroIndex];
    var currentFileHeader = currentfileContent.getElementsByClassName('file-header')[0];
    var headerHeight = currentFileHeader.getBoundingClientRect().height;
    currentfileContent.style.paddingTop = headerHeight + 'px';
    var newHeaderTop = (currentfileContent.getBoundingClientRect().top * -1 - 1);
    if (newHeaderTop < 0) {
      // We reached the top of the file scrolling up
      return;
    }
    if (newHeaderTop + headerHeight > currentfileContent.getBoundingClientRect().height) {
      // We reached the bottom of the file scrolling down
      currentFileHeader.style.top = currentfileContent.getBoundingClientRect().height - headerHeight + 'px';
      return;
    }
    currentFileHeader.style.top = newHeaderTop + 'px';
    currentFileHeader.style.position = 'absolute';
    currentFileHeader.style.width = '100%';
    currentFileHeader.style.zIndex = 2;

    var fileHeaders = document.getElementsByClassName('file-header');
    for (i = maxBerofeZeroIndex + 1; i < fileHeaders.length; i++) {
      fileHeaders[i].style.top = '0px';
    }
  };
<commit_msg>Fix script indentation<commit_after>'use strict';

document.onscroll = function() {
  var fileContainers = document.getElementsByClassName('file');
  var maxBerofeZero = -1000000;
  var maxBerofeZeroIndex = -1;
  for(var i=0; i<fileContainers.length; i++) {
    var currentTop = fileContainers[i].getBoundingClientRect().top;
    if (currentTop > maxBerofeZero && currentTop < 0) {
      maxBerofeZero = currentTop;
      maxBerofeZeroIndex = i;
    }
  }
  if (maxBerofeZeroIndex === -1) {
    document.getElementsByClassName('file-header')[0].style.top = '0px';
    return;
  }
  var currentfileContent = fileContainers[maxBerofeZeroIndex];
  var currentFileHeader = currentfileContent.getElementsByClassName('file-header')[0];
  var headerHeight = currentFileHeader.getBoundingClientRect().height;
  currentfileContent.style.paddingTop = headerHeight + 'px';
  var newHeaderTop = (currentfileContent.getBoundingClientRect().top * -1 - 1);
  if (newHeaderTop < 0) {
    // We reached the top of the file scrolling up
    return;
  }
  if (newHeaderTop + headerHeight > currentfileContent.getBoundingClientRect().height) {
    // We reached the bottom of the file scrolling down
    currentFileHeader.style.top = currentfileContent.getBoundingClientRect().height - headerHeight + 'px';
    return;
  }
  currentFileHeader.style.top = newHeaderTop + 'px';
  currentFileHeader.style.position = 'absolute';
  currentFileHeader.style.width = '100%';
  currentFileHeader.style.zIndex = 2;

  var fileHeaders = document.getElementsByClassName('file-header');
  for (i = maxBerofeZeroIndex + 1; i < fileHeaders.length; i++) {
    fileHeaders[i].style.top = '0px';
  }
};
<|endoftext|>


<commit_before>'use strict';

chrome.storage.sync.get({
	useTransliterator: true
}, function(items) {
	if (items.useTransliterator) {
		console.log("TODO find text that was in latin letters and transliterate it");
		console.log(Translitit);
	} else {
		console.log("Transliteration is off");
	}
});
<commit_msg>transliterating every terminal text node<commit_after>'use strict';

chrome.storage.sync.get({
	useTransliterator: true
}, function(items) {
	if (items.useTransliterator) {
		window.setInterval(function(){
			var walkTheDOM = function walk(node, func) {
				func(node);
				node = node.firstChild;
				while (node) {
					walk(node, func);
					node = node.nextSibling;
				}
			};
			walkTheDOM(document.body, function(node) {
				if (node.nodeType === 1) {
					// alert(node.id); // alert if we have a type 1 node
					if (node.childElementCount === 0) {
						var previousText = node.textContent ? node.textContent.trim() : "";
						if (previousText) {
							// console.log(previousText);
							var changedText = Translitit(previousText);
							node.innerHTML = changedText;
							node.title = previousText;
						}
					}
				}
			});
		}, 2000);
	} else {
		console.log('Transliteration is off');
	}
});
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name memekit.saveSvgAsPng
 * @description
 * # saveSvgAsPng
 * Service in the memekit.
*/

(function(){
var app = angular.module('memekit')
  .service('util', function ($window) {
    // http://stackoverflow.com/questions/1119289/how-to-show-the-are-you-sure-you-want-to-navigate-away-from-this-page-when-ch

    var confirmOnPageExit = function (e) {
      // If we haven't been passed the event get the window.event
      e = e || window.event;

      var message = 'Warning: If you leave or reload this page, your changes will be lost.';

      // For IE6-8 and Firefox prior to version 4
      if (e)
      {
          e.returnValue = message;
      }

      // For Chrome, Safari, IE8+ and Opera 12+
      return message;
    };

    // Turn it on - assign the function that returns the string
    window.onbeforeunload = confirmOnPageExit;

    // Turn it off - remove the function entirely
    // window.onbeforeunload = null;

  });
})();
<commit_msg>onbeforeunload verbiage update<commit_after>'use strict';

/**
 * @ngdoc service
 * @name memekit.saveSvgAsPng
 * @description
 * # saveSvgAsPng
 * Service in the memekit.
*/

(function(){
var app = angular.module('memekit')
  .service('util', function ($window) {
    // http://stackoverflow.com/questions/1119289/how-to-show-the-are-you-sure-you-want-to-navigate-away-from-this-page-when-ch

    var confirmOnPageExit = function (e) {
      // If we haven't been passed the event get the window.event
      e = e || window.event;

      var message = 'Unsaved changes will be lost if you leave or reload the page.';

      // For IE6-8 and Firefox prior to version 4
      if (e)
      {
          e.returnValue = message;
      }

      // For Chrome, Safari, IE8+ and Opera 12+
      return message;
    };

    // Turn it on - assign the function that returns the string
    window.onbeforeunload = confirmOnPageExit;

    // Turn it off - remove the function entirely
    // window.onbeforeunload = null;

  });
})();
<|endoftext|>


<commit_before>/*global define*/
define([
    'jquery',
    'underscore',
    'backbone',
    'templates',
    'models/report',
    'models/user'
], function ($, _, Backbone, JST, ReportModel, UserModel) {

    'use strict';

    var View = {};

    View.ReportsLayout = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/reports.ejs'],
        render: function() {
            console.log('render reports');
            this.$el.html(this.template({'reports': this.collection.toJSON()}));
            return this;
        }
    });

    View.SingleReport = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/report.ejs'],
        render: function() {
            this.$el.html(this.template({'report': this.model.toJSON()}));
            return this;
        }
    });

    View.ReportCreate = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/createReport.ejs'],
        events: {
            'click button': 'save'
        },
        initialize: function() {
            if (navigator.geolocation)
            {
                navigator.geolocation.getCurrentPosition(this.showPosition);
            }
        },
        showPosition: function(position) {
            $('#lat').val(position.coords.latitude);
            $('#lng').val(position.coords.longitude);
        },
        render: function() {
            this.$el.html(this.template({'types': this.collection.toJSON()}));
            return this;
        },
        save: function() {
            console.log('Saving data');
            var newReport = new ReportModel();
            newReport.url = 'http://localhost:8001/api/reports';
            newReport.set({
                'description': $('#description').val(),
                'types_id': $('#types_id').val(),
                'lat': $('#lat').val(),
                'lng': $('#lng').val(),
                'fb_id': UserModel.get('fb_id')
            });

            newReport.save();
        }
    });

    return View;
});
<commit_msg>Simple login check<commit_after>/*global define*/
define([
    'jquery',
    'underscore',
    'backbone',
    'templates',
    'models/report',
    'models/user'
], function ($, _, Backbone, JST, ReportModel, UserModel) {

    'use strict';

    var View = {};

    View.ReportsLayout = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/reports.ejs'],
        render: function() {
            console.log('render reports');
            this.$el.html(this.template({'reports': this.collection.toJSON()}));
            return this;
        }
    });

    View.SingleReport = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/report.ejs'],
        render: function() {
            this.$el.html(this.template({'report': this.model.toJSON()}));
            return this;
        }
    });

    View.ReportCreate = Backbone.View.extend({
        el: '#main',
        template: JST['app/scripts/templates/createReport.ejs'],
        events: {
            'click button': 'save'
        },
        initialize: function() {
            if (navigator.geolocation)
            {
                navigator.geolocation.getCurrentPosition(this.showPosition);
            }
        },
        showPosition: function(position) {
            $('#lat').val(position.coords.latitude);
            $('#lng').val(position.coords.longitude);
        },
        render: function() {
            if(UserModel.authorized) {
                this.$el.html(this.template({'types': this.collection.toJSON()}));
            }

            return this;
        },
        save: function() {
            console.log('Saving data');
            var newReport = new ReportModel();
            newReport.url = 'http://localhost:8001/api/reports';
            newReport.set({
                'description': $('#description').val(),
                'types_id': $('#types_id').val(),
                'lat': $('#lat').val(),
                'lng': $('#lng').val(),
                'fb_id': UserModel.get('fb_id')
            });

            newReport.save();
        }
    });

    return View;
});
<|endoftext|>


<commit_before>/**
 *
 * Rate Limit Module
 * @module lib/rate_limit
 * @author CJ Barker
 */
var common = require('../lib/common');
var lcd_msg = require('../lib/lcd_msg');
var lcd = require('../lib/lcd');
var _ = require('../lib/_');

var rateLimit = {
  /**
   * Check configuration setting of when user is allowed to drink
   * within allocated timeframe.
   * @return True if attempting to pour drink given during blocked time frame
   */
  isTimeRateLimited: function() {
    console.log('rate_limit.isTimeRateLimited');
    var date = new Date();
    var hour = date.getHours();
    var configs = common.db.configs;

    var start_hour = configs.find({
      name: 'start_hour_allowed'
    }).value;

    var stop_hour = configs.find({
      name: 'stop_hour_allowed'
    }).value;

    if (hour >= stop_hour && hour < start_hour) {
      console.log("Rate limiting based on hour: " + hour);
      return true;
    } else {
      return false;
    }
  },

  isAccountExpired: function(user) {
    if (user === null) {
      return false;
    }

    // card expired as UTC timestamp
    var expiration = (new Date(user.expires)).getTime();
    var now = (new Date()).getTime();
    var diff = expiration - now;

    //console.log("Exp " + expiration);
    //console.log("Now " + now);
    //console.log("Diff is " + diff);

    return (diff < 0);
  },

  /**
   * Determines remaining liquid volume remaining for given
   * user.
   * @return mL remaining within
   */
  getVolumeRemaining: function(user) {
    if (user == null) {
      return 0;
    }

    // drink up admins :)
    if (_.contains(user.roles, 'admin')) {
      return 355;
    }

    if (rateLimit.isTimeRateLimited()) {
      lcd_msg.showDeniedMsg('off_hours');
      return 0;
    }

    if (rateLimit.isAccountExpired(user)) {
      lcd_msg.showDeniedMsg('expired');
      return 0;
    }

    var today = (new Date()).toLocaleDateString();
    var logQuery = {
      user: user.id,
      date: today
    };

    var usageLogs = common.db.usage.where(logQuery);
    var useToday = 0;

    if (usageLogs.length > 1) {
      useToday = _.reduce(usageLogs, function(sum, log) {
        if (!_.isNumber(sum)) {
          sum = 0;
        }
        return sum + log.amount;
      });
    } else if (usageLogs.length == 1) {
      useToday = usageLogs[0].amount;
    } else {
      useToday = 0;
    }

    useToday = isNaN(useToday) ? 0 : useToday;

    console.log('useToday', useToday);
    var dailyLimit = common.db.configs.find({
      name: 'ml_per_day'
    }).value;
    console.log('dailyLimit', dailyLimit);

    var amountRemaining = dailyLimit - useToday;
    amountRemaining = amountRemaining.toFixed(2)

    console.log('amountRemaining', amountRemaining);
    if (amountRemaining < 1) {
      lcd_msg.showDeniedMsg('rate_limited');
      return 0;
    }

    lcd_msg.getInfoMsg('remaining_today', {
      'REMAINING': amountRemaining
    }, function(lcdMsg) {
      console.log(lcdMsg);
      lcd.clear();
      lcd.print(lcdMsg, null);
    });

    return amountRemaining;
  }
};
module.exports = rateLimit;
<commit_msg>fix bugs in rate_limit<commit_after>/**
 *
 * Rate Limit Module
 * @module lib/rate_limit
 * @author CJ Barker
 */
var common = require('../lib/common');
var lcd_msg = require('../lib/lcd_msg');
var lcd = require('../lib/lcd');
var _ = require('../lib/_');

var rateLimit = {
  /**
   * Check configuration setting of when user is allowed to drink
   * within allocated timeframe.
   * @return True if attempting to pour drink given during blocked time frame
   */
  isTimeRateLimited: function() {
    console.log('rate_limit.isTimeRateLimited');
    var date = new Date();
    var hour = date.getHours();
    var configs = common.db.configs;

    var start_hour = configs.find({
      name: 'start_hour_allowed'
    }).value;

    var stop_hour = configs.find({
      name: 'stop_hour_allowed'
    }).value;

    if (hour >= stop_hour && hour < start_hour) {
      console.log("Rate limiting based on hour: " + hour);
      return true;
    } else {
      return false;
    }
  },

  isAccountExpired: function(user) {
    if (user === null) {
      return false;
    }

    // card expired as UTC timestamp
    var expiration = (new Date(user.expires)).getTime();
    var now = (new Date()).getTime();
    var diff = expiration - now;

    //console.log("Exp " + expiration);
    //console.log("Now " + now);
    //console.log("Diff is " + diff);

    return (diff < 0);
  },

  /**
   * Determines remaining liquid volume remaining for given
   * user.
   * @return mL remaining within
   */
  getVolumeRemaining: function(user) {
    if (user == null) {
      return 0;
    }

    // drink up admins :)
    if (user.roles.indexOf('admin')!==-1) {
      return 355;
    }

    if (rateLimit.isTimeRateLimited()) {
      lcd_msg.showDeniedMsg('off_hours');
      return 0;
    }

    if (rateLimit.isAccountExpired(user)) {
      lcd_msg.showDeniedMsg('expired');
      return 0;
    }

    var today = (new Date()).toLocaleDateString();
    var logQuery = {
      user: user.id,
      date: today
    };

    var usageLogs = common.db.usage.find(logQuery);
    var useToday = 0;

    if (usageLogs.length > 1) {
      useToday = _.reduce(usageLogs, function(sum, log) {
        if (!_.isNumber(sum)) {
          sum = 0;
        }
        return sum + log.amount;
      });
    } else if (usageLogs.length == 1) {
      useToday = usageLogs[0].amount;
    } else {
      useToday = 0;
    }

    useToday = isNaN(useToday) ? 0 : useToday;

    console.log('useToday', useToday);
    var dailyLimit = common.db.configs.find({
      name: 'ml_per_day'
    }).value;
    console.log('dailyLimit', dailyLimit);

    var amountRemaining = dailyLimit - useToday;
    amountRemaining = amountRemaining.toFixed(2);

    console.log('amountRemaining', amountRemaining);
    if (amountRemaining < 1) {
      lcd_msg.showDeniedMsg('rate_limited');
      return 0;
    }

    lcd_msg.getInfoMsg('remaining_today', {
      'REMAINING': amountRemaining
    }, function(lcdMsg) {
      console.log(lcdMsg);
      lcd.clear();
      lcd.print(lcdMsg, null);
    });

    return amountRemaining;
  }
};
module.exports = rateLimit;
<|endoftext|>


<commit_before>import { computed } from '@ember/object';
import Service from '@ember/service';
import ENV from '../config/environment';

function computedFromConfig(prop) {
  return computed(function(){
    return ENV['ember-modal-dialog'] && ENV['ember-modal-dialog'][prop];
  });
}

export default Service.extend({
  hasEmberTether: computedFromConfig('hasEmberTether'),
  hasLiquidWormhole: computedFromConfig('hasLiquidWormhole'),
  hasLiquidTether: computedFromConfig('hasLiquidTether'),
  destinationElementId: computed(function() {
    /*
      everywhere except test, this property will be overwritten
      by the initializer that appends the modal container div
      to the DOM. because initializers don't run in unit/integration
      tests, this is a nice fallback.
    */
    if (ENV.environment === 'test') {
      return 'ember-testing';
    }
  })
});
<commit_msg>Revert modules update to file in app directory<commit_after>import Ember from 'ember';
import ENV from '../config/environment';

const { computed, Service } = Ember;

function computedFromConfig(prop) {
  return computed(function(){
    return ENV['ember-modal-dialog'] && ENV['ember-modal-dialog'][prop];
  });
}

export default Service.extend({
  hasEmberTether: computedFromConfig('hasEmberTether'),
  hasLiquidWormhole: computedFromConfig('hasLiquidWormhole'),
  hasLiquidTether: computedFromConfig('hasLiquidTether'),
  destinationElementId: computed(function() {
    /*
      everywhere except test, this property will be overwritten
      by the initializer that appends the modal container div
      to the DOM. because initializers don't run in unit/integration
      tests, this is a nice fallback.
    */
    if (ENV.environment === 'test') {
      return 'ember-testing';
    }
  })
});
<|endoftext|>