{"action":"created","comment":{"url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/comments/84914886","pull_request_review_id":5661364,"id":84914886,"diff_hunk":"@@ -1,400 +1,8 @@\n-/**\n- *  # Usage\n- *  -------\n- *  \n- * An abstraction of \"Spreadsheet-like\" data for use in nxus applications,\n- * along with a way to create a named collection of said spreadsheet columns for use in various visualizations on a website.\n- *\n- * Uses nxus-storage and nxus-loader as interfaces to load and store data from a _DataSet_ model, which in turn holds zero or more _DataRow_ objects.\n- * A _DataRow_ is essentially schema-less, with a structure defined by the data which is loaded in.\n- * A _DataPresentation_ is a collection of fields from _DataSets_ that have been created and have had _DataRows_ uploaded.\n- *\n- * This module provides _DataSet_ and _DataPresentation_ links on the default Admin screen for managing these data types.\n- * \n- *\n- * # API\n- * -------\n- *\n- * Applications have access via nxus-storage to the models, by refrerencing their identities:\n- *    'dataset'\n- *    'datarow'\n- *    'datapresentation'\n- *\n- * The _DataPresentation_ model has a static method\n- * extractUsingFieldIds()\n- * which can be used to take a collection of DataSets and DataRows and filter just the data which applies to a supplied DataPresentation instance.\n- * The instance method \n- * extractFieldData() on _DataPresentation_ provides the same function for the current instance.\n- */\n-\n-'use strict';\n-\n-import DataSet from './models/DataSet'\n-import DataRow from './models/DataRow'\n-import DataPresentation from './models/DataPresentation'\n-import * as mconst from './models/modelConstants'\n-\n-import morph from 'morph'\n-import nodeUUID from 'node-uuid'\n-\n-import _ from 'underscore'\n-\n-export default class DataSets {\n-\n-  constructor(app) {\n-  \n-    this.app = app\n-    this.admin = this.app.get('admin-ui')\n-    this.templater = this.app.get('templater')\n-    this.loader = this.app.get('data-loader')\n-    this.storage = this.app.get('storage')\n-\n-    this.storage.model(DataSet)\n-    this.storage.model(DataRow)\n-    this.storage.model(DataPresentation)\n-\n-    this.templater.templateDir(__dirname+\"/../views\")\n-    this.templater.replace().templateFunction(\"view-dataset-detail\", (opts) => {\n-      opts.template = 'page'\n-      return this.view(opts.req)\n-    })\n-\n-    this.loader.on('model.datarow', this._processLoaderDataRow.bind(this))\n-\n-    this.app.get('base-ui').viewModel('dataset', {display: ['name', 'source', 'description']})\n-\n-    this.admin.adminModel('dataset', {\n-      display: ['name', 'source', 'description'],\n-      iconClass: 'fa fa-list'\n-    })\n-\n-    this.admin.adminModel('datapresentation', {\n-      display: ['name', 'label', 'fieldIds'],\n-      iconClass: 'fa fa-table'\n-    })\n-\n-    this.admin.instanceAction('dataset', 'Upload Data', 'data', {iconClass: 'fa fa-upload'})\n-    this.admin.instanceAction('dataset', 'View Data', 'view', {iconClass: 'fa fa-eye'})\n-  \n-    this.admin.adminPage('Upload Data', 'datasets/:id/data', {nav: false}, this.dataUpload.bind(this))\n-    this.admin.adminPage('View Data', 'datasets/:id/view', {nav: false}, this.view.bind(this)) \n-\n-    this.admin.adminRoute('post', 'datasets/:id/data/save', this.saveDataUpload.bind(this)) //save datarows for dataset - url is different for post\n-    this.admin.adminRoute('post', 'datasets/:id/dataset/save', this.saveDataSet.bind(this)) //update dataset, from custom form (see views/admin-dataset-form)\n-    this.admin.adminRoute('post', 'datasets/dataset/save', this.saveDataSet.bind(this)) //new dataset, from custom form (see views/admin-dataset-form)\n-\n-    this.admin.replace().adminRoute('get', 'datapresentations/:id/edit', this.editDataPresentation.bind(this))\n-    this.admin.adminRoute('post', 'datapresentations/selector-save', this.saveDataPresentation.bind(this))\n-\n-    this.admin.replace().adminRoute('get', 'datasets/:id/remove',  this.removeDataRowsForSet.bind(this)) //intercept admin-ui default dataset delete \n-    \n-    this.loader.uploadPath('/admin/datasets/:id/data/save', 'csvfile')\n-  }\n-\n-  /**\n-   * Handler for data rows to clean up records; attached to loader's 'model.datarow'.\n-   * @param  object row is the row of data from CSV column-header keys\n-   */\n-  _processLoaderDataRow(row) {\n-    //catch CSV column headers that would get \n-    //over-ridden or conflict downstream.\n-    if (row.id) {\n-      row.id_orig = row.id\n-      delete row.id\n-    }\n-    if ( row.dataset) {\n-      row.dataset_orig = row.dataset\n-      delete row.dataset\n-    }\n-    return row\n-  }\n-\n-  dataUpload(req, res) {\n-    let opts = {\n-      id: req.params.id\n-    }\n-    return this.templater.render('admin-dataset-upload', opts)\n-  }\n-\n-\n-\n-  view(req) {\n-    let opts = {\n-      id: req.params.id\n-    }\n-    this.app.log.debug(\"nxus-dataset View() dataset id  \", req.params.id)\n-    return this.storage.getModel(['dataset', 'datarow']).spread((dataSetModel, dataRowModel) => {\n-      return [dataSetModel.findOne(req.params.id), dataRowModel.find({dataset: req.params.id})]\n-    }).spread((set, rows) => {\n-      opts.morph = morph\n-      opts.rows = rows\n-      opts.set = set\n-      opts.fields = (set.fields ? set.fields : [])\n-      return this.templater.render('view-dataset-data', opts)\n-    })\n-  }\n-\n-  /**\n-   * Transform the datarow after storage,\n-   * associating with the given dataset ID.\n-   * @param  {[datarow]} row       DataRow instance to put under given DataSet ID\n-   * @param  {[string]} dataSetId   Parent DataSet ID\n-   * @return the original row passed in, with modifications.\n-   */\n-  _prepareDataRowInDataSet(row, dataSetId) {\n-    _.each(row, (val,key) => {\n-      if (typeof(val) == 'string') {\n-        if (val.endsWith('%')) {\n-          let what = Number.parseFloat(val)\n-          if (_.isNumber(what) && !Number.isNaN(what)) {\n-            val = what\n-          }\n-        }\n-      } else if (typeof(val) == 'undefined') {\n-        val = null\n-      }\n-      row[key] = val\n-    })\n-    row.dataset = dataSetId\n-    //nb: must return changed row rather than new object\n-    return row\n-  }\n-\n-  /**\n-   * Based on supplied data row, build array of field info objects\n-   * which include a unique field-id for each property on the row.\n-   * @param  {[datarow]} sample [representative row of data]\n-   * @return { array of object}        [name, id, and type properties for each field]\n-   */\n-  _buildFieldInfo(sample) {\n-    let fields = new Array()\n-    _.each(_.keys(sample), (key,index) => {\n-      let type = mconst.STRING_TYPE\n-      let val = sample[key]\n-      if (typeof(val) == 'string') {\n-        if (val.endsWith('%')) {\n-          type = mconst.PERCENT_TYPE\n-        } else if (! isNaN(parseFloat(val))) {\n-          type = mconst.DECIMAL_TYPE\n-        }\n-      }\n-      if ( type != mconst.PERCENT_TYPE && \n-        ((-1 < key.toLowerCase().indexOf('percent')) || (-1 < key.indexOf('%'))) ) {\n-        type = mconst.PERCENT_TYPE\n-      }\n-      if (! _.contains([\"true\", \"id\", \"dataset\", \"createdAt\", \"updatedAt\"], key)) {\n-        let genId = this._generateUniqueId()\n-        fields.push({ name: key, id: genId, label: morph.toTitle(key), type: type, primaryKey: false, visible: true })\n-      }\n-    })\n-    return fields\n-  }\n-\n-  /**\n-   * Save datarows uploaded from CSV,\n-   * associating each datarow with the parent dataset\n-   * and gathering summary field information about the collection of rows\n-   * to store in the parent.\n-   * \n-   */\n-  saveDataUpload(req, res) {\n-    let setId = req.param('id')\n-    if(!req.file) {\n-      req.flash('error', \"Error processing rows: no file supplied for the data.\")\n-      return res.redirect('/admin/datasets/'+setId+'/data')\n-    }\n-    return this.loader.importFileToModel('datarow', req.file.path, {type: 'csv', strict: false})\n-    .then((rows) => {\n-      let currentFields = []\n-      _.each(rows, (rowElem, index) => {\n-        // this.app.log.debug(\"saveDataUpload \" + index + \" processing rowElem\", rowElem)\n-        if (Array.isArray(rowElem)) {\n-          rowElem = rowElem[0] //work-around for model handler dupe bug in data-loader 3.0.0\n-        }\n-        if (_.isEmpty(currentFields)) {\n-          currentFields = this._buildFieldInfo(rowElem)\n-        }\n-        if (setId) {\n-          let rowToUpdate = this._prepareDataRowInDataSet(rowElem, setId)\n-          rowToUpdate.save().catch((err) => {\n-            this.app.log.error(\"nxus-dataset update failed for datarow \" + rowElem.id, err)\n-          })\n-        }\n-      })\n-      return this.storage.getModel('dataset').then((DataSet) => {\n-        return DataSet.findOne(setId)\n-      }).then((set) => {\n-        //warn about limitation of current implementation if set already has rows.\n-        if ( 0 < set.rowCount ) {\n-          this.app.log.error(\"Adding additional rows to a dataset isn't supported yet\")\n-          req.flash('info', \"Uable to add data rows to set with data.\")\n-          return res.redirect('/admin/datasets')\n-        } \n-        set.rowCount = rows.length\n-        set.fields = currentFields\n-        this.app.log.debug( \"nxus-dataset saveDataUpload dataset \" + setId + \" fields:\", currentFields )\n-        return set.save().then( () => {\n-          req.flash('info', \"Successfully loaded \" + rows.length + \" data rows\")\n-          res.redirect('/admin/datasets')\n-        })\n-      })\n-    }).catch((e) => {\n-      this.app.log.error( \"nxus-dataset saveDataUpload() error loading data rows  \", e, \" at: \", e.stack);\n-      req.flash('error', \"Error processing rows\")\n-      return res.redirect('/admin/datasets/'+setId+'/data')\n-    })\n-  } \n-\n-  /**\n-   * Action when a dataset is removed -\n-   * removes the dataset and all child datarows.\n-   */\n-  removeDataRowsForSet(req, res) {\n-    let dataSetId = req.param('id');\n-    return this.storage.getModel('datarow')\n-    .then( (dataRowModel) => {\n-      return dataRowModel.destroy({dataset: dataSetId}) \n-    }).then( (rowsRemoved) => {\n-      this.app.log.debug(\"remove DataSet removed \", rowsRemoved.length, \" from dataset \", dataSetId); \n-      req.flash('info', \"Successfully removed \"+rowsRemoved.length+\" data rows\")\n-      return this.storage.getModel('dataset').then( (DataSetModel) => {\n-        return DataSetModel.destroy({id: dataSetId}).then( (dsRemoved) => {\n-          this.app.log.debug(\"removed DataSet \", dataSetId); \n-          res.redirect('/admin/datasets')\n-        })\n-      })\n-    }).catch((e) => {\n-      this.app.log.debug( \"nxus-dataset error removing data rows from dataset \" + dataSetId, e);\n-      req.flash('error', \"Error removing dataset \" + e)\n-      return res.redirect('/admin/datasets/')\n-    })\n-  }\n-\n-  /**\n-   * handle POST response for edit existing \n-   * or create new dataset\n-   */\n-  saveDataSet(req, res) {\n-    let dataSetId = req.params.id\n-    this.app.log.debug(\"saveDataSet id: \", dataSetId)\n-    if (dataSetId) {\n-      \n-      this.storage.getModel( 'dataset').then((dsmodel) => {\n-        return dsmodel.findOne(dataSetId)\n-      }).then((dataset) => {\n-        dataset.name = req.body.name\n-        dataset.source = req.body.source\n-        dataset.description = req.body.description\n-        _.each( req.body, (value,key) => {\n-          //update fields from request parameters field_<field.id>_<key>\n-          if (0 <= key.indexOf('field_')) {\n-            let pComponents = key.split('_')\n-            if ( 3 == pComponents.length) {\n-              let fieldId = pComponents[1]\n-              let fieldKey = pComponents[2]\n-              let targetField = _.findWhere(dataset.fields, {id: fieldId})\n-              if (targetField) {\n-                targetField[fieldKey] = value\n-              }\n-            } \n-          }\n-        })\n-        return dataset.save().catch( (err) => {\n-          this.app.log.error(\"nxus-dataset: dataset update failed on \" + dataSetId, err.stack)\n-          return res.redirect('/admin/datasets')\n-        }).then( () => {\n-          return res.redirect('/admin/datasets')\n-        })\n-      })\n-    } else {\n-      return this.storage.getModel('dataset')\n-      .then( (dataSetModel) => {\n-        if ( req.body.name) {\n-          return dataSetModel.create({name: req.body.name, source: req.body.source, description: req.body.description})\n-          .then( (newRecord) =>{\n-            this.app.log.debug(\"dataset created \", newRecord.id)\n-            return res.redirect('/admin/datasets')\n-          })\n-        } else {\n-          req.flash('error', \"Name is required\")\n-          return res.redirect('/admin/datasets/create')\n-        }\n-      })\n-    }\n-  }\n-\n-  /**\n-   * replace the admin handler for editing, \n-   * or creating, a DataPresentation.\n-   * Adding additional objects to make the association\n-   * with DataSet.fields easier to manage.\n-   * @param  {[type]} req [description]\n-   * @return {[type]}     [description]\n-   */\n-  editDataPresentation(req, res) {\n-    let presentId = req.params.id\n-    this.app.log.debug(\"edit datapresentation id: \", presentId)\n-    if (!presentId) {\n-      presentId = 0\n-    }\n-    this.storage.getModel(['datapresentation', 'dataset'])\n-      .spread( (dataPresentModel, dataSetModel) => {\n-        return( [dataPresentModel.findOne(presentId), dataSetModel.find({})] )\n-    }).spread ( (presentation, datasets) => {\n-      let opts = {\n-        datapresentation: presentation,\n-        datasets: datasets,\n-        template: 'page'\n-      };\n-      return this.templater.render('admin-datapresentation-form-with-selector', opts)\n-      .then((contents) => { res.send(contents) })\n-    })\n-  }\n-\n-  /**\n-   * Save changed (not new) DataPresentation.\n-   * Handles the POST from custom admin-datapresentation-form\n-   * @param  {[type]} req [description]\n-   * @param  {[type]} res [description]\n-   * @return {[type]}     [description]\n-   */\n-  saveDataPresentation(req, res) {\n-    let presentId = req.body.id\n-    this.storage.getModel('datapresentation').then( (dataPresentModel) => {\n-      return dataPresentModel.findOne(presentId)\n-    }).then( (dataPresentation) => {\n-      dataPresentation.name = req.body.name\n-      dataPresentation.label = req.body.label\n-      if (Array.isArray(req.body.fieldIds)) {\n-        //clean out any submitted empty strings\n-        let cleanFieldsArr = req.body.fieldIds.filter( (elem) => { return elem })\n-        dataPresentation.fieldIds =  cleanFieldsArr\n-      } else if ( req.body.fieldIds ) {\n-        dataPresentation.fieldIds = [req.body.fieldIds]\n-      } else {\n-        dataPresentation.fieldIds = []\n-      }\n-      return dataPresentation.save()\n-    }).then( () => {\n-      if (req.body.save == \"add\") {\n-        return res.redirect( '/admin/datapresentations/' + presentId + '/edit')\n-      } else {\n-        return res.redirect( '/admin/datapresentations')\n-      }\n-    }).catch( (err) => {\n-      req.flash('error', 'Problem saving your changes', err)\n-      this.app.log.error( \"nxus-dataset: unable to save datapresentation \", err.stack)\n-      return res.redirect( '/admin/datapresentations')\n-    })\n-    \n-  }\n-    \n-    \n- _generateUniqueId() {\n-  //maybe overkill for use in cases here,\n-  // but it's unique across launches of the app\n-    return nodeUUID.v1();\n- }\n-\n-\n-}\n\\ No newline at end of file\n+import {MVCModule} from 'nxus-web'\r","path":"src/index.js","position":402,"original_position":402,"commit_id":"e59a5a3856e023452744f4a3d953c878fd113579","original_commit_id":"e59a5a3856e023452744f4a3d953c878fd113579","user":{"login":"mjreich","id":300410,"avatar_url":"https://avatars.githubusercontent.com/u/300410?v=3","gravatar_id":"","url":"https://api.github.com/users/mjreich","html_url":"https://github.com/mjreich","followers_url":"https://api.github.com/users/mjreich/followers","following_url":"https://api.github.com/users/mjreich/following{/other_user}","gists_url":"https://api.github.com/users/mjreich/gists{/gist_id}","starred_url":"https://api.github.com/users/mjreich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mjreich/subscriptions","organizations_url":"https://api.github.com/users/mjreich/orgs","repos_url":"https://api.github.com/users/mjreich/repos","events_url":"https://api.github.com/users/mjreich/events{/privacy}","received_events_url":"https://api.github.com/users/mjreich/received_events","type":"User","site_admin":false},"body":"Did the Usage documentation move somewhere else?","created_at":"2016-10-25T14:25:23Z","updated_at":"2016-10-25T14:25:43Z","html_url":"https://github.com/seabourne/nxus-dataset/pull/3#discussion_r84914886","pull_request_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/comments/84914886"},"html":{"href":"https://github.com/seabourne/nxus-dataset/pull/3#discussion_r84914886"},"pull_request":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3","id":89659725,"html_url":"https://github.com/seabourne/nxus-dataset/pull/3","diff_url":"https://github.com/seabourne/nxus-dataset/pull/3.diff","patch_url":"https://github.com/seabourne/nxus-dataset/pull/3.patch","issue_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/3","number":3,"state":"open","locked":false,"title":"nxus-4 work in progress","user":{"login":"ScottMaxson","id":5853011,"avatar_url":"https://avatars.githubusercontent.com/u/5853011?v=3","gravatar_id":"","url":"https://api.github.com/users/ScottMaxson","html_url":"https://github.com/ScottMaxson","followers_url":"https://api.github.com/users/ScottMaxson/followers","following_url":"https://api.github.com/users/ScottMaxson/following{/other_user}","gists_url":"https://api.github.com/users/ScottMaxson/gists{/gist_id}","starred_url":"https://api.github.com/users/ScottMaxson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ScottMaxson/subscriptions","organizations_url":"https://api.github.com/users/ScottMaxson/orgs","repos_url":"https://api.github.com/users/ScottMaxson/repos","events_url":"https://api.github.com/users/ScottMaxson/events{/privacy}","received_events_url":"https://api.github.com/users/ScottMaxson/received_events","type":"User","site_admin":false},"body":"For early review - files have been pulled from \"modules\" of app-boilerplate so this isn't yet packaged as stand-alone nxus module yet.","created_at":"2016-10-17T16:41:35Z","updated_at":"2016-10-25T14:25:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2c2c320387b09579906456d2c66268d98eeebf23","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3/commits","review_comments_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3/comments","review_comment_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/comments{/number}","comments_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/3/comments","statuses_url":"https://api.github.com/repos/seabourne/nxus-dataset/statuses/e59a5a3856e023452744f4a3d953c878fd113579","head":{"label":"seabourne:nxus4","ref":"nxus4","sha":"e59a5a3856e023452744f4a3d953c878fd113579","user":{"login":"seabourne","id":2642738,"avatar_url":"https://avatars.githubusercontent.com/u/2642738?v=3","gravatar_id":"","url":"https://api.github.com/users/seabourne","html_url":"https://github.com/seabourne","followers_url":"https://api.github.com/users/seabourne/followers","following_url":"https://api.github.com/users/seabourne/following{/other_user}","gists_url":"https://api.github.com/users/seabourne/gists{/gist_id}","starred_url":"https://api.github.com/users/seabourne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seabourne/subscriptions","organizations_url":"https://api.github.com/users/seabourne/orgs","repos_url":"https://api.github.com/users/seabourne/repos","events_url":"https://api.github.com/users/seabourne/events{/privacy}","received_events_url":"https://api.github.com/users/seabourne/received_events","type":"Organization","site_admin":false},"repo":{"id":63905022,"name":"nxus-dataset","full_name":"seabourne/nxus-dataset","owner":{"login":"seabourne","id":2642738,"avatar_url":"https://avatars.githubusercontent.com/u/2642738?v=3","gravatar_id":"","url":"https://api.github.com/users/seabourne","html_url":"https://github.com/seabourne","followers_url":"https://api.github.com/users/seabourne/followers","following_url":"https://api.github.com/users/seabourne/following{/other_user}","gists_url":"https://api.github.com/users/seabourne/gists{/gist_id}","starred_url":"https://api.github.com/users/seabourne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seabourne/subscriptions","organizations_url":"https://api.github.com/users/seabourne/orgs","repos_url":"https://api.github.com/users/seabourne/repos","events_url":"https://api.github.com/users/seabourne/events{/privacy}","received_events_url":"https://api.github.com/users/seabourne/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/seabourne/nxus-dataset","description":"A Nxus module for managing data sets","fork":false,"url":"https://api.github.com/repos/seabourne/nxus-dataset","forks_url":"https://api.github.com/repos/seabourne/nxus-dataset/forks","keys_url":"https://api.github.com/repos/seabourne/nxus-dataset/keys{/key_id}","collaborators_url":"https://api.github.com/repos/seabourne/nxus-dataset/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/seabourne/nxus-dataset/teams","hooks_url":"https://api.github.com/repos/seabourne/nxus-dataset/hooks","issue_events_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/events{/number}","events_url":"https://api.github.com/repos/seabourne/nxus-dataset/events","assignees_url":"https://api.github.com/repos/seabourne/nxus-dataset/assignees{/user}","branches_url":"https://api.github.com/repos/seabourne/nxus-dataset/branches{/branch}","tags_url":"https://api.github.com/repos/seabourne/nxus-dataset/tags","blobs_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/refs{/sha}","trees_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/trees{/sha}","statuses_url":"https://api.github.com/repos/seabourne/nxus-dataset/statuses/{sha}","languages_url":"https://api.github.com/repos/seabourne/nxus-dataset/languages","stargazers_url":"https://api.github.com/repos/seabourne/nxus-dataset/stargazers","contributors_url":"https://api.github.com/repos/seabourne/nxus-dataset/contributors","subscribers_url":"https://api.github.com/repos/seabourne/nxus-dataset/subscribers","subscription_url":"https://api.github.com/repos/seabourne/nxus-dataset/subscription","commits_url":"https://api.github.com/repos/seabourne/nxus-dataset/commits{/sha}","git_commits_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/commits{/sha}","comments_url":"https://api.github.com/repos/seabourne/nxus-dataset/comments{/number}","issue_comment_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/comments{/number}","contents_url":"https://api.github.com/repos/seabourne/nxus-dataset/contents/{+path}","compare_url":"https://api.github.com/repos/seabourne/nxus-dataset/compare/{base}...{head}","merges_url":"https://api.github.com/repos/seabourne/nxus-dataset/merges","archive_url":"https://api.github.com/repos/seabourne/nxus-dataset/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/seabourne/nxus-dataset/downloads","issues_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues{/number}","pulls_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls{/number}","milestones_url":"https://api.github.com/repos/seabourne/nxus-dataset/milestones{/number}","notifications_url":"https://api.github.com/repos/seabourne/nxus-dataset/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/seabourne/nxus-dataset/labels{/name}","releases_url":"https://api.github.com/repos/seabourne/nxus-dataset/releases{/id}","deployments_url":"https://api.github.com/repos/seabourne/nxus-dataset/deployments","created_at":"2016-07-21T21:58:53Z","updated_at":"2016-07-26T05:26:45Z","pushed_at":"2016-10-24T20:50:31Z","git_url":"git://github.com/seabourne/nxus-dataset.git","ssh_url":"git@github.com:seabourne/nxus-dataset.git","clone_url":"https://github.com/seabourne/nxus-dataset.git","svn_url":"https://github.com/seabourne/nxus-dataset","homepage":null,"size":45,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"seabourne:master","ref":"master","sha":"4dab7c0bde4f28e52e2acec7bdd03918a89955bc","user":{"login":"seabourne","id":2642738,"avatar_url":"https://avatars.githubusercontent.com/u/2642738?v=3","gravatar_id":"","url":"https://api.github.com/users/seabourne","html_url":"https://github.com/seabourne","followers_url":"https://api.github.com/users/seabourne/followers","following_url":"https://api.github.com/users/seabourne/following{/other_user}","gists_url":"https://api.github.com/users/seabourne/gists{/gist_id}","starred_url":"https://api.github.com/users/seabourne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seabourne/subscriptions","organizations_url":"https://api.github.com/users/seabourne/orgs","repos_url":"https://api.github.com/users/seabourne/repos","events_url":"https://api.github.com/users/seabourne/events{/privacy}","received_events_url":"https://api.github.com/users/seabourne/received_events","type":"Organization","site_admin":false},"repo":{"id":63905022,"name":"nxus-dataset","full_name":"seabourne/nxus-dataset","owner":{"login":"seabourne","id":2642738,"avatar_url":"https://avatars.githubusercontent.com/u/2642738?v=3","gravatar_id":"","url":"https://api.github.com/users/seabourne","html_url":"https://github.com/seabourne","followers_url":"https://api.github.com/users/seabourne/followers","following_url":"https://api.github.com/users/seabourne/following{/other_user}","gists_url":"https://api.github.com/users/seabourne/gists{/gist_id}","starred_url":"https://api.github.com/users/seabourne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seabourne/subscriptions","organizations_url":"https://api.github.com/users/seabourne/orgs","repos_url":"https://api.github.com/users/seabourne/repos","events_url":"https://api.github.com/users/seabourne/events{/privacy}","received_events_url":"https://api.github.com/users/seabourne/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/seabourne/nxus-dataset","description":"A Nxus module for managing data sets","fork":false,"url":"https://api.github.com/repos/seabourne/nxus-dataset","forks_url":"https://api.github.com/repos/seabourne/nxus-dataset/forks","keys_url":"https://api.github.com/repos/seabourne/nxus-dataset/keys{/key_id}","collaborators_url":"https://api.github.com/repos/seabourne/nxus-dataset/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/seabourne/nxus-dataset/teams","hooks_url":"https://api.github.com/repos/seabourne/nxus-dataset/hooks","issue_events_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/events{/number}","events_url":"https://api.github.com/repos/seabourne/nxus-dataset/events","assignees_url":"https://api.github.com/repos/seabourne/nxus-dataset/assignees{/user}","branches_url":"https://api.github.com/repos/seabourne/nxus-dataset/branches{/branch}","tags_url":"https://api.github.com/repos/seabourne/nxus-dataset/tags","blobs_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/refs{/sha}","trees_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/trees{/sha}","statuses_url":"https://api.github.com/repos/seabourne/nxus-dataset/statuses/{sha}","languages_url":"https://api.github.com/repos/seabourne/nxus-dataset/languages","stargazers_url":"https://api.github.com/repos/seabourne/nxus-dataset/stargazers","contributors_url":"https://api.github.com/repos/seabourne/nxus-dataset/contributors","subscribers_url":"https://api.github.com/repos/seabourne/nxus-dataset/subscribers","subscription_url":"https://api.github.com/repos/seabourne/nxus-dataset/subscription","commits_url":"https://api.github.com/repos/seabourne/nxus-dataset/commits{/sha}","git_commits_url":"https://api.github.com/repos/seabourne/nxus-dataset/git/commits{/sha}","comments_url":"https://api.github.com/repos/seabourne/nxus-dataset/comments{/number}","issue_comment_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues/comments{/number}","contents_url":"https://api.github.com/repos/seabourne/nxus-dataset/contents/{+path}","compare_url":"https://api.github.com/repos/seabourne/nxus-dataset/compare/{base}...{head}","merges_url":"https://api.github.com/repos/seabourne/nxus-dataset/merges","archive_url":"https://api.github.com/repos/seabourne/nxus-dataset/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/seabourne/nxus-dataset/downloads","issues_url":"https://api.github.com/repos/seabourne/nxus-dataset/issues{/number}","pulls_url":"https://api.github.com/repos/seabourne/nxus-dataset/pulls{/number}","milestones_url":"https://api.github.com/repos/seabourne/nxus-dataset/milestones{/number}","notifications_url":"https://api.github.com/repos/seabourne/nxus-dataset/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/seabourne/nxus-dataset/labels{/name}","releases_url":"https://api.github.com/repos/seabourne/nxus-dataset/releases{/id}","deployments_url":"https://api.github.com/repos/seabourne/nxus-dataset/deployments","created_at":"2016-07-21T21:58:53Z","updated_at":"2016-07-26T05:26:45Z","pushed_at":"2016-10-24T20:50:31Z","git_url":"git://github.com/seabourne/nxus-dataset.git","ssh_url":"git@github.com:seabourne/nxus-dataset.git","clone_url":"https://github.com/seabourne/nxus-dataset.git","svn_url":"https://github.com/seabourne/nxus-dataset","homepage":null,"size":45,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3"},"html":{"href":"https://github.com/seabourne/nxus-dataset/pull/3"},"issue":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/issues/3"},"comments":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/seabourne/nxus-dataset/statuses/e59a5a3856e023452744f4a3d953c878fd113579"}}}}
{"actor":{"display_login":"mjreich"}}