<commit_before>import {LightningElement, api, track} from 'lwc';
import getDataImportModel
    from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.getDataImportModel';
import getDataImportRows
    from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.getDataImportRows';
import GeFormService from 'c/geFormService';
import STATUS_FIELD from '@salesforce/schema/DataImport__c.Status__c';
import FAILURE_INFORMATION_FIELD
    from '@salesforce/schema/DataImport__c.FailureInformation__c';
import DONATION_AMOUNT from '@salesforce/schema/DataImport__c.Donation_Amount__c';
import {deleteRecord} from 'lightning/uiRecordApi';
import {handleError} from 'c/utilTemplateBuilder';
import runBatchDryRun from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.runBatchDryRun';
import geDonorColumnLabel from '@salesforce/label/c.geDonorColumnLabel';
import geDonationColumnLabel from '@salesforce/label/c.geDonationColumnLabel';
import bgeActionDelete from '@salesforce/label/c.bgeActionDelete';
import geBatchGiftsCount from '@salesforce/label/c.geBatchGiftsCount';
import geBatchGiftsTotal from '@salesforce/label/c.geBatchGiftsTotal';
import commonOpen from '@salesforce/label/c.commonOpen';
import { isNotEmpty } from 'c/utilCommon';

export default class GeBatchGiftEntryTable extends LightningElement {
    @api batchId;
    @track ready = false;

    _batchLoaded = false;
    @track data = [];
    @track hasData;

    _columnsLoaded = false;
    @track columns = [];
    _columns = [
        {label: 'Status', fieldName: STATUS_FIELD.fieldApiName, type: 'text'},
        {label: 'Errors', fieldName: FAILURE_INFORMATION_FIELD.fieldApiName, type: 'text'},
        {
            label: geDonorColumnLabel, fieldName: 'donorLink', type: 'url',
            typeAttributes: {label: {fieldName: 'donorName'}}
        },
        {
            label: geDonationColumnLabel, fieldName: 'matchedRecordUrl', type: 'url',
            typeAttributes: {label: {fieldName: 'matchedRecordLabel'}}
        }
    ];
    _actionsColumn = {
        type: 'action',
        typeAttributes: {
            rowActions: [
                {label: commonOpen, name: 'open'},
                {label: bgeActionDelete, name: 'delete'}
            ],
            menuAlignment: 'auto'
        }
    };

    @api title;
    @api total;
    @api expectedTotal;
    @api count;
    @api expectedCount;
    @track isLoaded = true;

    connectedCallback() {
        if (this.batchId) {
            this.loadBatch();
        }
    }

    setReady() {
        this.ready = this._columnsLoaded && this._batchLoaded;
    }

    loadBatch() {
        getDataImportModel({batchId: this.batchId})
            .then(
                response => {
                    const dataImportModel = JSON.parse(response);
                    this._count = dataImportModel.totalCountOfRows;
                    this._total = dataImportModel.totalRowAmount;
                    dataImportModel.dataImportRows.forEach(row => {
                            this.data.push(
                                Object.assign(row, row.record));
                        }
                    );
                    this.data = [...this.data];
                    this.hasData = this.data.length > 0 ? true : false;
                    this.batchLoaded();
                }
            )
            .catch(
                error => {
                    handleError(error);
                }
            );
    }

    batchLoaded() {
        this._batchLoaded = true;
        this.setReady();
    }

    @api
    handleSectionsRetrieved(sections) {
        this.initColumns(this.buildColumns(sections));
    }

    initColumns(userDefinedColumns) {
        this.columns = [
            ...this._columns,
            ...userDefinedColumns,
            this._actionsColumn];
        this.columnsLoaded();
    }

    buildColumns(sections) {
        const columns = [];
        sections.forEach(
            section => {
                section.elements
                    .filter(e => e.elementType === 'field')
                    .forEach(
                    element => {
                        const fieldWrapper = GeFormService.getFieldMappingWrapper(element.dataImportFieldMappingDevNames[0]);
                        if (isNotEmpty(fieldWrapper)) {
                            const column = {
                                label: element.customLabel,
                                fieldName: fieldWrapper.Source_Field_API_Name,
                                type: GeFormService.getInputTypeFromDataType(
                                    element.dataType
                                ) === 'date' ? 'date-local' :
                                    GeFormService.getInputTypeFromDataType(element.dataType)
                            };
                            columns.push(column);
                        }
                    }
                );
            }
        );
        return columns;
    }

    columnsLoaded() {
        this._columnsLoaded = true;
        this.setReady();
    }

    @api
    upsertData(dataRow, idProperty) {
        const existingRowIndex = this.data.findIndex(row =>
            row[idProperty] === dataRow[idProperty]
        );

        if (existingRowIndex !== -1) {
            this.data.splice(existingRowIndex, 1, dataRow);
            this.data = [...this.data];
        } else {
            this.data = [dataRow, ...this.data];
            if (this.hasData == false) {
                this.hasData = true;
            }
        }
    }

    handleRowActions(event) {
        switch (event.detail.action.name) {
            case 'open':
                this.loadRow(event.detail.row);
                break;
            case 'delete':
                deleteRecord(event.detail.row.Id).then(() => {
                    this.deleteDIRow(event.detail.row);
                }).catch(error => {
                        handleError(error);
                    }
                );
                break;
        }
    }

    deleteDIRow(rowToDelete) {
        const isRowToDelete = row => row.Id == rowToDelete.Id;
        const index = this.data.findIndex(isRowToDelete);
        this.data.splice(index, 1);
        this.data = [...this.data];
        this.dispatchEvent(new CustomEvent('delete', {
            detail: {
                amount: rowToDelete[DONATION_AMOUNT.fieldApiName]
            }
        }));
    }

    loadMoreData(event) {
        event.target.isLoading = true;
        const disableInfiniteLoading = function () {
            this.enableInfiniteLoading = false;
        }.bind(event.target);

        const disableIsLoading = function () {
            this.isLoading = false;
        }.bind(event.target);

        getDataImportRows({batchId: this.batchId, offset: this.data.length})
            .then(rows => {
                rows.forEach(row => {
                        this.data.push(
                            Object.assign(row, row.record)
                        );
                    }
                );
                this.data = [...this.data];
                if (this.data.length >= this.count) {
                    disableInfiniteLoading();
                }
                disableIsLoading();
            })
            .catch(error => {
                handleError(error);
            });
    }

    @api
    runBatchDryRun(callback) {
        runBatchDryRun({
            batchId: this.batchId,
            numberOfRowsToReturn: this.data.length
        })
            .then(result => {
                const dataImportModel = JSON.parse(result);
                this._count = dataImportModel.totalCountOfRows;
                this._total = dataImportModel.totalRowAmount;
                dataImportModel.dataImportRows.forEach((row, idx) => {
                    this.upsertData(
                        Object.assign(row, row.record), 'Id');
                });
            })
            .catch(error => {
                handleError(error);
            })
            .finally(() => {
                callback();
            });
    }

    get geBatchGiftsCountLabel() {
        return geBatchGiftsCount;
    }

    get geBatchGiftsTotalLabel() {
        return geBatchGiftsTotal;
    }

    loadRow(row) {
        this.dispatchEvent(new CustomEvent('loaddata', {
            detail: row
        }));
    }

    /**
     * @description Internal setters used to communicate the current count and total
     *              up to the App, which needs them to keep track of whether the batch's
     *              expected totals match.
     */
    set _count(count) {
        this.dispatchEvent(new CustomEvent('countchanged', {
            detail: {
                value: count
            }
        }));
    }

    set _total(total) {
        this.dispatchEvent(new CustomEvent('totalchanged', {
            detail: {
                value: total
            }
        }));
    }

}<commit_msg>update bge table to display column headers based on field in data import batch record<commit_after>import {LightningElement, api, track} from 'lwc';
import getDataImportModel
    from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.getDataImportModel';
import getDataImportRows
    from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.getDataImportRows';
import GeFormService from 'c/geFormService';
import STATUS_FIELD from '@salesforce/schema/DataImport__c.Status__c';
import FAILURE_INFORMATION_FIELD
    from '@salesforce/schema/DataImport__c.FailureInformation__c';
import DONATION_AMOUNT from '@salesforce/schema/DataImport__c.Donation_Amount__c';
import {deleteRecord} from 'lightning/uiRecordApi';
import {handleError} from 'c/utilTemplateBuilder';
import runBatchDryRun from '@salesforce/apex/BGE_DataImportBatchEntry_CTRL.runBatchDryRun';
import geDonorColumnLabel from '@salesforce/label/c.geDonorColumnLabel';
import geDonationColumnLabel from '@salesforce/label/c.geDonationColumnLabel';
import bgeActionDelete from '@salesforce/label/c.bgeActionDelete';
import geBatchGiftsCount from '@salesforce/label/c.geBatchGiftsCount';
import geBatchGiftsTotal from '@salesforce/label/c.geBatchGiftsTotal';
import commonOpen from '@salesforce/label/c.commonOpen';
import { isNotEmpty } from 'c/utilCommon';

export default class GeBatchGiftEntryTable extends LightningElement {
    @api batchId;
    @track ready = false;

    _batchLoaded = false;
    @track data = [];
    @track hasData;

    _columnsLoaded = false;
    @track columns = [];
    _columns = [
        {label: 'Status', fieldName: STATUS_FIELD.fieldApiName, type: 'text'},
        {label: 'Errors', fieldName: FAILURE_INFORMATION_FIELD.fieldApiName, type: 'text'},
        {
            label: geDonorColumnLabel, fieldName: 'donorLink', type: 'url',
            typeAttributes: {label: {fieldName: 'donorName'}}
        },
        {
            label: geDonationColumnLabel, fieldName: 'matchedRecordUrl', type: 'url',
            typeAttributes: {label: {fieldName: 'matchedRecordLabel'}}
        }
    ];
    _actionsColumn = {
        type: 'action',
        typeAttributes: {
            rowActions: [
                {label: commonOpen, name: 'open'},
                {label: bgeActionDelete, name: 'delete'}
            ],
            menuAlignment: 'auto'
        }
    };
    _userDefinedBatchTableColumnNames;
    _columnsBySourceFieldApiName = {};

    @api title;
    @api total;
    @api expectedTotal;
    @api count;
    @api expectedCount;
    @track isLoaded = true;

    connectedCallback() {
        if (this.batchId && this._columnsLoaded) {
            this.loadBatch();
        } else {
            this.needsToLoadBatch = true;
        }
    }

    renderedCallback() {
        if (this.needsToLoadBatch) {
            this.needsToLoadBatch = false;
            this.loadBatch();
        }
    }

    setReady() {
        this.ready = this._columnsLoaded && this._batchLoaded;
    }

    loadBatch() {
        getDataImportModel({batchId: this.batchId})
            .then(
                response => {
                    const dataImportModel = JSON.parse(response);
                    this._count = dataImportModel.totalCountOfRows;
                    this._total = dataImportModel.totalRowAmount;
                    dataImportModel.dataImportRows.forEach(row => {
                            this.data.push(
                                Object.assign(row, row.record));
                        }
                    );
                    this.data = [...this.data];
                    this.hasData = this.data.length > 0 ? true : false;
                    this._userDefinedBatchTableColumnNames =
                        dataImportModel.batchTableColumnSourceFieldApiNames;

                    this.batchLoaded();
                }
            )
            .catch(
                error => {
                    handleError(error);
                }
            );
    }

    batchLoaded() {
        this._batchLoaded = true;
        this.setReady();
    }

    @api
    handleSectionsRetrieved(sections) {
        this.buildColumns(sections);
        this.initColumns(this.getUserDefinedColums());
    }

    getUserDefinedColums() {
        let userDefinedColumns = [];
        this._userDefinedBatchTableColumnNames.forEach(columnName => {
            userDefinedColumns.push(this._columnsBySourceFieldApiName[columnName]);
        });
        return userDefinedColumns;
    }

    initColumns(userDefinedColumns) {
        this.columns = [
            ...userDefinedColumns,
            this._actionsColumn];
        this.columnsLoaded();
    }

    buildColumns(sections) {
        this.addSpecialCasedColumns();

        sections.forEach(
            section => {
                section.elements
                    .filter(e => e.elementType === 'field')
                    .forEach(
                    element => {
                        const fieldWrapper = GeFormService.getFieldMappingWrapper(element.dataImportFieldMappingDevNames[0]);
                        if (isNotEmpty(fieldWrapper)) {
                            const column = {
                                label: element.customLabel,
                                fieldName: fieldWrapper.Source_Field_API_Name,
                                type: GeFormService.getInputTypeFromDataType(
                                    element.dataType
                                ) === 'date' ? 'date-local' :
                                    GeFormService.getInputTypeFromDataType(element.dataType)
                            };

                            this._columnsBySourceFieldApiName[column.fieldName] = column;
                        }
                    }
                );
            }
        );

    }

    addSpecialCasedColumns() {
        this._columnsBySourceFieldApiName[this._columns[0].fieldName] = this._columns[0];
        this._columnsBySourceFieldApiName[this._columns[1].fieldName] = this._columns[1];
        this._columnsBySourceFieldApiName[this._columns[2].fieldName] = this._columns[2];
        this._columnsBySourceFieldApiName[this._columns[3].fieldName] = this._columns[3];
    }

    columnsLoaded() {
        this._columnsLoaded = true;
        this.setReady();
    }

    @api
    upsertData(dataRow, idProperty) {
        const existingRowIndex = this.data.findIndex(row =>
            row[idProperty] === dataRow[idProperty]
        );

        if (existingRowIndex !== -1) {
            this.data.splice(existingRowIndex, 1, dataRow);
            this.data = [...this.data];
        } else {
            this.data = [dataRow, ...this.data];
            if (this.hasData == false) {
                this.hasData = true;
            }
        }
    }

    handleRowActions(event) {
        switch (event.detail.action.name) {
            case 'open':
                this.loadRow(event.detail.row);
                break;
            case 'delete':
                deleteRecord(event.detail.row.Id).then(() => {
                    this.deleteDIRow(event.detail.row);
                }).catch(error => {
                        handleError(error);
                    }
                );
                break;
        }
    }

    deleteDIRow(rowToDelete) {
        const isRowToDelete = row => row.Id == rowToDelete.Id;
        const index = this.data.findIndex(isRowToDelete);
        this.data.splice(index, 1);
        this.data = [...this.data];
        this.dispatchEvent(new CustomEvent('delete', {
            detail: {
                amount: rowToDelete[DONATION_AMOUNT.fieldApiName]
            }
        }));
    }

    loadMoreData(event) {
        event.target.isLoading = true;
        const disableInfiniteLoading = function () {
            this.enableInfiniteLoading = false;
        }.bind(event.target);

        const disableIsLoading = function () {
            this.isLoading = false;
        }.bind(event.target);

        getDataImportRows({batchId: this.batchId, offset: this.data.length})
            .then(rows => {
                rows.forEach(row => {
                        this.data.push(
                            Object.assign(row, row.record)
                        );
                    }
                );
                this.data = [...this.data];
                if (this.data.length >= this.count) {
                    disableInfiniteLoading();
                }
                disableIsLoading();
            })
            .catch(error => {
                handleError(error);
            });
    }

    @api
    runBatchDryRun(callback) {
        runBatchDryRun({
            batchId: this.batchId,
            numberOfRowsToReturn: this.data.length
        })
            .then(result => {
                const dataImportModel = JSON.parse(result);
                this._count = dataImportModel.totalCountOfRows;
                this._total = dataImportModel.totalRowAmount;
                dataImportModel.dataImportRows.forEach((row, idx) => {
                    this.upsertData(
                        Object.assign(row, row.record), 'Id');
                });
            })
            .catch(error => {
                handleError(error);
            })
            .finally(() => {
                callback();
            });
    }

    get geBatchGiftsCountLabel() {
        return geBatchGiftsCount;
    }

    get geBatchGiftsTotalLabel() {
        return geBatchGiftsTotal;
    }

    loadRow(row) {
        this.dispatchEvent(new CustomEvent('loaddata', {
            detail: row
        }));
    }

    /**
     * @description Internal setters used to communicate the current count and total
     *              up to the App, which needs them to keep track of whether the batch's
     *              expected totals match.
     */
    set _count(count) {
        this.dispatchEvent(new CustomEvent('countchanged', {
            detail: {
                value: count
            }
        }));
    }

    set _total(total) {
        this.dispatchEvent(new CustomEvent('totalchanged', {
            detail: {
                value: total
            }
        }));
    }

}<|endoftext|>


<commit_before>/* objective:
Determine if characters "a" & "b" are separated by exactly 3 places
anywhere in string */

// solution:
const assert = require('assert');

const ABCheck = (str) => {
  // First, declare regex expression to match if a & b ever occur three characters apart
  // . is a "wildcard" metacharacter in regex that matches almost any character
  const ab = /[a]...b/.test(str);

  // return answer
  return ab;
};

// console.log(ABCheck('aj44ikb'));
const r1 = 'false'; // input
const t1 = ABCheck('aj44ikb'); // output
assert(r1, t1);
<commit_msg>small text edit<commit_after>// objective:
// Determine if characters "a"&"b" are separated by exactly 3 places in string

// solution:
const assert = require('assert');

const ABCheck = (str) => {
  // First, declare regex expression to match if a & b ever occur three characters apart
  // . is a "wildcard" metacharacter in regex that matches almost any character
  const ab = /[a]...b/.test(str);

  // return answer
  return ab;
};

// console.log(ABCheck('aj44ikb'));
const r1 = 'false'; // input
const t1 = ABCheck('aj44ikb'); // output
assert(r1, t1);
<|endoftext|>


<commit_before>import React, {Component} from 'react'
import { ButtonToolbar, Tooltip, OverlayTrigger, Button } from 'react-bootstrap'
import {Icon} from '@conveyal/woonerf'

export default class EntityListButtons extends Component {
  render () {
    const {
      activeComponent,
      cloneEntity,
      feedSource,
      showConfirmModal,
      deleteEntity,
      setActiveEntity,
      entities,
      newGtfsEntity,
      toIndex,
      fromIndex,
      activeEntity,
      list,
      updateIndexes
    } = this.props
    return (

        <ButtonToolbar
          className='pull-right'
        >
          {activeComponent === 'route'
            ? <OverlayTrigger placement='bottom' overlay={<Tooltip id={`merge-route`}>Merge routes</Tooltip>}>
              <Button
                bsSize='small'
                disabled={toIndex - fromIndex !== 1}
                onClick={() => {
                  // cloneEntity(feedSource.id, activeComponent, activeEntity.id)
                }}
              >
                <Icon type='compress' />
              </Button>
            </OverlayTrigger>
            : null
          }
          <OverlayTrigger placement='bottom' overlay={<Tooltip id={`duplicate-${activeComponent}`}>Duplicate {activeComponent}</Tooltip>}>
            <Button
              bsSize='small'
              disabled={!activeEntity}
              onClick={() => {
                cloneEntity(feedSource.id, activeComponent, activeEntity.id)
              }}
            >
              <Icon type='clone' />
            </Button>
          </OverlayTrigger>
          <OverlayTrigger placement='bottom' overlay={<Tooltip id={`delete-${activeComponent}`}>Delete {activeComponent}</Tooltip>}>
            <Button
              bsSize='small'
              disabled={!activeEntity && typeof fromIndex === 'undefined'}
              bsStyle='danger'
              onClick={() => {
                let fromIndex, toIndex
                if (activeEntity) {
                  showConfirmModal({
                    title: `Delete ${activeComponent}?`,
                    body: `Are you sure you want to delete this ${activeComponent}?`,
                    onConfirm: () => {
                      deleteEntity(feedSource.id, activeComponent, activeEntity.id)
                      updateIndexes(fromIndex, toIndex)
                      setActiveEntity(feedSource.id, activeComponent)
                    }
                  })
                  // deleteEntity(feedSource.id, activeComponent, activeEntity.id)
                } else {
                  showConfirmModal({
                    title: `Delete ${+toIndex - +fromIndex} ${activeComponent}s?`,
                    body: `Are you sure you want to delete these ${toIndex - fromIndex} ${activeComponent}s?`,
                    onConfirm: () => {
                      for (var i = 0; i < list.length; i++) {
                        if (list[i].isSelected) {
                          deleteEntity(feedSource.id, activeComponent, list[i].id)
                        }
                      }
                      updateIndexes(fromIndex, toIndex)
                      setActiveEntity(feedSource.id, activeComponent)
                    }
                  })
                }
              }}
            >
              <Icon type='trash' />
            </Button>
          </OverlayTrigger>
        </ButtonToolbar>
        {// Create new entity
          activeComponent === 'stop'
          ? Right-click map for new stop
          : <Button
            bsSize='small'
            disabled={entities && entities.findIndex(e => e.id === 'new') !== -1}
            onClick={() => {
              newGtfsEntity(feedSource.id, activeComponent)
            }}
          ><Icon type='plus' /> New {activeComponent === 'scheduleexception' ? 'exception' : activeComponent}
          </Button>
        }

    )
  }
}
<commit_msg>fix for too-wide icon<commit_after>import React, {Component} from 'react'
import { ButtonToolbar, Tooltip, OverlayTrigger, Button } from 'react-bootstrap'
import {Icon} from '@conveyal/woonerf'

export default class EntityListButtons extends Component {
  render () {
    const {
      activeComponent,
      cloneEntity,
      feedSource,
      showConfirmModal,
      deleteEntity,
      setActiveEntity,
      entities,
      newGtfsEntity,
      toIndex,
      fromIndex,
      activeEntity,
      list,
      updateIndexes
    } = this.props
    return (

        <ButtonToolbar
          className='pull-right'
        >
          {activeComponent === 'route'
            ? <OverlayTrigger placement='bottom' overlay={<Tooltip id={`merge-route`}>Merge routes</Tooltip>}>
              <Button
                bsSize='small'
                disabled={toIndex - fromIndex !== 1}
                onClick={() => {
                  // cloneEntity(feedSource.id, activeComponent, activeEntity.id)
                }}
              >
                <Icon type='compress' />
              </Button>
            </OverlayTrigger>
            : null
          }
          <OverlayTrigger placement='bottom' overlay={<Tooltip id={`duplicate-${activeComponent}`}>Duplicate {activeComponent}</Tooltip>}>
            <Button
              bsSize='small'
              disabled={!activeEntity}
              onClick={() => {
                cloneEntity(feedSource.id, activeComponent, activeEntity.id)
              }}
            >
              <Icon type='clone' />
            </Button>
          </OverlayTrigger>
          <OverlayTrigger placement='bottom' overlay={<Tooltip id={`delete-${activeComponent}`}>Delete {activeComponent}</Tooltip>}>
            <Button
              bsSize='small'
              disabled={!activeEntity && typeof fromIndex === 'undefined'}
              bsStyle='danger'
              onClick={() => {
                let fromIndex, toIndex
                if (activeEntity) {
                  showConfirmModal({
                    title: `Delete ${activeComponent}?`,
                    body: `Are you sure you want to delete this ${activeComponent}?`,
                    onConfirm: () => {
                      deleteEntity(feedSource.id, activeComponent, activeEntity.id)
                      updateIndexes(fromIndex, toIndex)
                      setActiveEntity(feedSource.id, activeComponent)
                    }
                  })
                  // deleteEntity(feedSource.id, activeComponent, activeEntity.id)
                } else {
                  showConfirmModal({
                    title: `Delete ${+toIndex - +fromIndex} ${activeComponent}s?`,
                    body: `Are you sure you want to delete these ${toIndex - fromIndex} ${activeComponent}s?`,
                    onConfirm: () => {
                      for (var i = 0; i < list.length; i++) {
                        if (list[i].isSelected) {
                          deleteEntity(feedSource.id, activeComponent, list[i].id)
                        }
                      }
                      updateIndexes(fromIndex, toIndex)
                      setActiveEntity(feedSource.id, activeComponent)
                    }
                  })
                }
              }}
            >
              <Icon type='trash' />
            </Button>
          </OverlayTrigger>
        </ButtonToolbar>
        {// Create new entity
          activeComponent === 'stop'
          ? Right-click map for new stop
          : <Button
            bsSize='small'
            disabled={entities && entities.findIndex(e => e.id === 'new') !== -1}
            onClick={() => {
              newGtfsEntity(feedSource.id, activeComponent)
            }}
          ><Icon style={{margin: '-5px'}} type='plus' /> New {activeComponent === 'scheduleexception' ? 'exception' : activeComponent}
          </Button>
        }

    )
  }
}
<|endoftext|>


<commit_before>var expect = require('expect.js');
var request = require('request');
var express = require('express');

var host = "http://localhost";
var dom = require('express-dom');

dom.settings.stall = 5000;
dom.settings.allow = 'all';
dom.settings.timeout = 10000;
dom.settings.console = true;

var renderPlugins = [
	dom.plugins.hide,
	dom.plugins.nomedia,
	dom.plugins.redirect,
	dom.plugins.referrer,
	dom.plugins.html
];

describe("Two-phase rendering", function suite() {
	this.timeout(3000);
	var server, port;

	before(function(done) {
		var app = express();
		app.set('views', __dirname + '/public');
		app.get(/\.(json|js|css|png|templates)$/, express.static(app.get('views')));
		app.get(/\/templates\/.+\.html$/, express.static(app.get('views')));
		app.get(/\.html$/, dom().load());

		server = app.listen(function(err) {
			if (err) console.error(err);
			port = server.address().port;
			done();
		});
	});

	after(function(done) {
		server.close();
		done();
	});

	it("should run build then setup", function(done) {
		var buildUrl = host + ':' + port + '/build.html';
		request({
			method: 'GET',
			url: buildUrl
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(buildUrl).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			});
		});
	});

	it("should run route and imports", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/route-import.html'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm setup")).to.be.greaterThan(0);
			expect(body.indexOf("your body")).to.be.greaterThan(0);
			done();
		});
	});

});

<commit_msg>Test two-phase rendering for route-import<commit_after>var expect = require('expect.js');
var request = require('request');
var express = require('express');

var host = "http://localhost";
var dom = require('express-dom');

dom.settings.stall = 5000;
dom.settings.allow = 'all';
dom.settings.timeout = 10000;
dom.settings.console = true;

var renderPlugins = [
	dom.plugins.hide,
	dom.plugins.nomedia,
	dom.plugins.redirect,
	dom.plugins.referrer,
	dom.plugins.html
];

describe("Two-phase rendering", function suite() {
	this.timeout(3000);
	var server, port;

	before(function(done) {
		var app = express();
		app.set('views', __dirname + '/public');
		app.get(/\.(json|js|css|png|templates)$/, express.static(app.get('views')));
		app.get(/\/templates\/.+\.html$/, express.static(app.get('views')));
		app.get(/\.html$/, dom().load());

		server = app.listen(function(err) {
			if (err) console.error(err);
			port = server.address().port;
			done();
		});
	});

	after(function(done) {
		server.close();
		done();
	});

	it("should run build then setup", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/build.html'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				console.error(err);
			});
		});
	});

	it("should run route and imports", function(done) {
		request({
			method: 'GET',
			url: host + ':' + port + '/route-import.html'
		}, function(err, res, body) {
			expect(res.statusCode).to.be(200);
			expect(body.indexOf("I'm built0")).to.be.greaterThan(0);
			expect(body.indexOf("your body0")).to.be.greaterThan(0);
			dom(body).load({
				plugins: renderPlugins
			})(res.request.uri.href).then(function(state) {
				expect(state.body.indexOf("I'm setup")).to.be.greaterThan(0);
				done();
			}).catch(function(err) {
				console.error(err);
			});
		});
	});

});

<|endoftext|>


<commit_before>/* global module: true */
module.exports = function (grunt) {
  "use strict";

  var hintFiles = [
    "Gruntfile.js",
    "package.json",
    ".jshintrc",
    ".jsbeautifyrc",
    "src/**/*.js",
    "test/**/*.js",
    "test/.jshintrc",
    "karma/*",
  ];

  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),
    watch: {
      files: hintFiles,
      tasks: ["test"]
    },
    jshint: {
      files: hintFiles,
      options: {
        extensions: ".js, .jshintrc, .jsbeautifyrc",
        jshintrc: true
      }
    },
    jsbeautifier: {
      "write": {
        src: hintFiles,
        options: {
          config: ".jsbeautifyrc"
        }
      },
      "verify": {
        src: hintFiles,
        options: {
          config: ".jsbeautifyrc",
          mode: "VERIFY_ONLY"
        }
      }
    },
    jasmine: {
      default: {
        src: ["src/gurps.js", "src/**/*.js"],
        options: {
          keepRunner: true,
          specs: "test/**/*.js"
        }
      }
    },
    autowrap: {
      nodefy: {
        options: {
          wrapType: "exports"
        },
        files: {
          "lib/main.js": ["src/gurps.js", "src/*.js"],
        },
      }
    },
    clean: {
      build: ["lib"]
    },
    karma: {
      options: {
        /*preprocessors: {
          //all but polyfill
          "src/!(polyfill).js": ["coverage"]
        },
        coverageReporter: {
          reporters: [{
            type: "lcovonly",
            dir: 'coverage/'
          }, {
            //type: "text-summary"
            type: "text"
          }],
        },*/
        basePath: "..", //default is *.conf.js path
        files: ["src/gurps.js", "src/*.js", "test/*.js"],
        frameworks: ["jasmine"]
      },
      browserstack: {
        configFile: "karma/browserstack.conf.js",
        singleRun: true
      },
      unit: {
        configFile: "karma/local.conf.js"
      }
    }
  });

  /* loading plugins */

  grunt.loadNpmTasks("grunt-contrib-watch");
  grunt.loadNpmTasks("grunt-contrib-jshint");
  grunt.loadNpmTasks("grunt-contrib-jasmine");
  grunt.loadNpmTasks("grunt-contrib-clean");
  grunt.loadNpmTasks("grunt-jsbeautifier");
  grunt.loadNpmTasks("grunt-autowrap");
  grunt.loadNpmTasks("grunt-karma");

  /* tasks */

  //test
  var pullRequest = process.env.TRAVIS_PULL_REQUEST,
    travisTasks = [];
  if (pullRequest !== "false") {
    travisTasks.push("browserstack");
  }
  console.log("process.env.TRAVIS_PULL_REQUEST:");
  console.log(process.env.TRAVIS_PULL_REQUEST);
  grunt.registerTask("test", ["jasmine"]); //through phantomjs
  grunt.registerTask("browserstack", ["karma:browserstack"]);
  grunt.registerTask("travis", travisTasks)
  grunt.registerTask("browsers", ["karma:unit"]);

  //code quality
  grunt.registerTask("format", ["jshint", "jsbeautifier:write"]);
  grunt.registerTask("verify", ["jshint", "jsbeautifier:verify"]);
  grunt.registerTask("lint", ["jshint"]);

  //build
  grunt.registerTask("build", ["autowrap:nodefy"]);
  //grunt.registerTask("clean", ["clean:build"]);

  //develop
  grunt.registerTask("dev", ["default", "watch"]);
  grunt.registerTask("default", ["test", "verify"]);

};
<commit_msg>fixing travis browserstack integration<commit_after>/* global module: true */
module.exports = function (grunt) {
  "use strict";

  var hintFiles = [
    "Gruntfile.js",
    "package.json",
    ".jshintrc",
    ".jsbeautifyrc",
    "src/**/*.js",
    "test/**/*.js",
    "test/.jshintrc",
    "karma/*",
  ];

  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),
    watch: {
      files: hintFiles,
      tasks: ["test"]
    },
    jshint: {
      files: hintFiles,
      options: {
        extensions: ".js, .jshintrc, .jsbeautifyrc",
        jshintrc: true
      }
    },
    jsbeautifier: {
      "write": {
        src: hintFiles,
        options: {
          config: ".jsbeautifyrc"
        }
      },
      "verify": {
        src: hintFiles,
        options: {
          config: ".jsbeautifyrc",
          mode: "VERIFY_ONLY"
        }
      }
    },
    jasmine: {
      default: {
        src: ["src/gurps.js", "src/**/*.js"],
        options: {
          keepRunner: true,
          specs: "test/**/*.js"
        }
      }
    },
    autowrap: {
      nodefy: {
        options: {
          wrapType: "exports"
        },
        files: {
          "lib/main.js": ["src/gurps.js", "src/*.js"],
        },
      }
    },
    clean: {
      build: ["lib"]
    },
    karma: {
      options: {
        /*preprocessors: {
          //all but polyfill
          "src/!(polyfill).js": ["coverage"]
        },
        coverageReporter: {
          reporters: [{
            type: "lcovonly",
            dir: 'coverage/'
          }, {
            //type: "text-summary"
            type: "text"
          }],
        },*/
        basePath: "..", //default is *.conf.js path
        files: ["src/gurps.js", "src/*.js", "test/*.js"],
        frameworks: ["jasmine"]
      },
      browserstack: {
        configFile: "karma/browserstack.conf.js",
        singleRun: true
      },
      unit: {
        configFile: "karma/local.conf.js"
      }
    }
  });

  /* loading plugins */

  grunt.loadNpmTasks("grunt-contrib-watch");
  grunt.loadNpmTasks("grunt-contrib-jshint");
  grunt.loadNpmTasks("grunt-contrib-jasmine");
  grunt.loadNpmTasks("grunt-contrib-clean");
  grunt.loadNpmTasks("grunt-jsbeautifier");
  grunt.loadNpmTasks("grunt-autowrap");
  grunt.loadNpmTasks("grunt-karma");

  /* tasks */

  //test
  var pullRequest = process.env.TRAVIS_PULL_REQUEST,
    travisTasks = [];
  if (pullRequest === "false") {
    travisTasks.push("browserstack");
  }
  grunt.registerTask("test", ["jasmine"]); //through phantomjs
  grunt.registerTask("browserstack", ["karma:browserstack"]);
  grunt.registerTask("travis", travisTasks)
  grunt.registerTask("browsers", ["karma:unit"]);

  //code quality
  grunt.registerTask("format", ["jshint", "jsbeautifier:write"]);
  grunt.registerTask("verify", ["jshint", "jsbeautifier:verify"]);
  grunt.registerTask("lint", ["jshint"]);

  //build
  grunt.registerTask("build", ["autowrap:nodefy"]);
  //grunt.registerTask("clean", ["clean:build"]);

  //develop
  grunt.registerTask("dev", ["default", "watch"]);
  grunt.registerTask("default", ["test", "verify"]);

};
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    "use strict";

    main.consumes = [
        "Plugin", "tabManager", "settings", "preferences", "auth"
    ];
    main.provides = ["closeconfirmation"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var tabs = imports.tabManager;
        var settings = imports.settings;
        var prefs = imports.preferences;
        var auth = imports.auth;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit = plugin.getEmitter();

        var defaultValue = options.defaultValue;

        var loaded = false;
        function load(callback) {
            if (loaded) return false;
            loaded = true;

            // when unloading the window
            window.onbeforeunload = onBeforeUnloadHandler;

            settings.on("read", function(){
                settings.setDefaults("user/general", [
                    ["confirmexit", defaultValue]
                ]);
            }, plugin);

            prefs.add({
                "General" : {
                    "General" : {
                        "Warn Before Exiting" : {
                            type: "checkbox",
                            position: 8000,
                            path: "user/general/@confirmexit"
                        }
                    }
                }
            }, plugin);
        }

        function unload() {
            if (window.onbeforeunload === onBeforeUnloadHandler)
                window.onbeforeunload = null;
        }

        /***** Methods *****/

        function onBeforeUnloadHandler() {
            var changed = tabs.getTabs().some(function(tab) {
                return tab.document.value && tab.document.changed;
            });

            emit("exit", { changed: changed });

            // see what's in the settings
            var confirmExit = settings.getBool("user/general/@confirmexit") && auth.loggedIn;
            if (confirmExit) {
                if (changed)
                    return "You have unsaved changes. Your changes will be lost if you don't save them";
                else
                    return "You're about to leave Cloud9.";
            }
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            unload();
            loaded = false;
        });

        /***** Register and define API *****/
        /**
         * Shows a 'close confirmation' popup when closing the IDE
         * @singleton
         */
        plugin.freezePublicAPI({
        });

        register(null, {
            closeconfirmation: plugin
        });
    }
});
<commit_msg>Revert "Merge pull request +4132 from c9/fix/desktop"<commit_after>define(function(require, exports, module) {
    "use strict";

    main.consumes = [
        "Plugin", "tabManager", "settings", "preferences", "auth"
    ];
    main.provides = ["closeconfirmation"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var tabs = imports.tabManager;
        var settings = imports.settings;
        var prefs = imports.preferences;
        var auth = imports.auth;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit = plugin.getEmitter();

        var defaultValue = options.defaultValue;
        var loggingIn = false;

        var loaded = false;
        function load(callback) {
            if (loaded) return false;
            loaded = true;

            // when unloading the window
            window.onbeforeunload = onBeforeUnloadHandler;

            settings.on("read", function(){
                settings.setDefaults("user/general", [
                    ["confirmexit", defaultValue]
                ]);
            }, plugin);

            auth.on("loggingin", function() {
                loggingIn = true;
            });

            auth.on("login", function() {
                loggingIn = false;
            });

            prefs.add({
                "General" : {
                    "General" : {
                        "Warn Before Exiting" : {
                            type: "checkbox",
                            position: 8000,
                            path: "user/general/@confirmexit"
                        }
                    }
                }
            }, plugin);
        }

        function unload() {
            if (window.onbeforeunload === onBeforeUnloadHandler)
                window.onbeforeunload = null;
        }

        /***** Methods *****/

        function onBeforeUnloadHandler() {
            var changed = tabs.getTabs().some(function(tab) {
                return tab.document.value && tab.document.changed;
            });

            emit("exit", { changed: changed });

            // see what's in the settings
            var confirmExit = settings.getBool("user/general/@confirmexit") && !loggingIn;
            if (confirmExit) {
                if (changed)
                    return "You have unsaved changes. Your changes will be lost if you don't save them";
                else
                    return "You're about to leave Cloud9.";
            }
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            unload();
            loaded = false;
        });

        /***** Register and define API *****/
        /**
         * Shows a 'close confirmation' popup when closing the IDE
         * @singleton
         */
        plugin.freezePublicAPI({
        });

        register(null, {
            closeconfirmation: plugin
        });
    }
});
<|endoftext|>


<commit_before>'use strict';
const build = require('./build');
const fs = require('fs');
const path = require('path');
const config = require('./build/config');
module.exports = grunt => {
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-webpack');
  grunt.initConfig({
    pkg: grunt.file.readJSON('./package.json'),
    uglify: {
      build: {
        files: {
          '<%=grunt.option("path")%>.min.js': '<%=grunt.option("path")%>.js',
        },
        options: {
          mangle: {
            keep_fnames: true,
          },
          compress: {
            keep_fnames: true,
            pure_getters: true,
          },
          output: {
            max_line_len: 32000,
          },
          ie8: true,
          sourceMap: true,
          banner: config.banner,
        },
      },
    },
    clean: ['./library'],
    copy: {
      lib: {
        files: [
          {
            expand: true,
            cwd: './',
            src: ['es/**', 'stage/**', 'web/**', 'core/**', 'fn/**', 'index.js'],
            dest: './library/',
          }, {
            expand: true,
            cwd: './',
            src: ['modules/*'],
            dest: './library/',
            filter: 'isFile',
          }, {
            expand: true,
            cwd: './modules/library/',
            src: '*',
            dest: './library/modules/',
          },
        ],
      },
    },
    karma: {
      options: {
        frameworks: ['qunit'],
        basePath: './',
        browsers: ['PhantomJS'],
        singleRun: true,
      },
      default: {
        files: [
          'client/core.js',
          'tests/bundles/qunit-helpers.js',
          'tests/bundles/tests.js',
        ].map(it => ({ src: it })),
      },
      library: {
        files: [
          'client/library.js',
          'tests/bundles/qunit-helpers.js',
          'tests/bundles/library.js',
        ].map(it => ({ src: it })),
      },
    },
    webpack: {
      options: {
        module: {
          loaders: [{
            test: /\.js$/,
            loader: 'babel-loader',
            options: {
              // use transforms which does not use es5+ builtins
              plugins: [
                ['transform-es3-member-expression-literals'],
                ['transform-es3-property-literals'],
                // use it instead of webpack es modules for support engines without descriptors
                ['transform-es2015-modules-commonjs', { loose: true }],
                ['transform-es2015-arrow-functions'],
                ['transform-es2015-block-scoped-functions'],
                ['transform-es2015-block-scoping'],
                ['transform-es2015-classes', { loose: true }],
                ['transform-es2015-computed-properties', { loose: true }],
                ['transform-es2015-destructuring', { loose: true }],
                ['transform-es2015-literals'],
                ['transform-es2015-parameters'],
                ['transform-es2015-shorthand-properties'],
                ['transform-es2015-spread', { loose: true }],
                ['transform-es2015-template-literals', { loose: true, spec: true }],
                ['transform-exponentiation-operator'],
                ['transform-for-of-as-array'],
                ['check-es2015-constants'],
              ],
            },
          }],
        },
        node: {
          global: false,
          process: false,
          setImmediate: false,
        },
        stats: false,
        output: {
          path: path.resolve(__dirname, 'tests/bundles'),
        },
      },
      helpers: {
        entry: './tests/helpers/qunit-helpers.js',
        output: { filename: 'qunit-helpers.js' },
      },
      library: {
        entry: './tests/library/index.js',
        output: { filename: 'library.js' },
      },
      tests: {
        entry: './tests/tests/index.js',
        output: { filename: 'tests.js' },
      },
      'promises-aplus-tests': {
        entry: 'promises-aplus-tests/lib/testFiles.js',
        output: { filename: 'promises-aplus.js' },
      },
    },
  });
  grunt.registerTask('build', function (options) {
    const done = this.async();
    return build({
      modules: (options || 'es,esnext,web,core').split(','),
      blacklist: (grunt.option('blacklist') || '').split(','),
      library: !!~['yes', 'on', 'true'].indexOf(grunt.option('library')),
      umd: !~['no', 'off', 'false'].indexOf(grunt.option('umd')),
    }).then(it => {
      grunt.option('path') || grunt.option('path', './custom');
      fs.writeFile(grunt.option('path') + '.js', it, done);
    }).catch(it => {
      // eslint-disable-next-line no-console
      console.error(it);
      process.exit(1);
    });
  });
  grunt.registerTask('client', () => {
    grunt.option('library', '');
    grunt.option('path', './client/core');
    return grunt.task.run(['build:es,esnext,web', 'uglify']);
  });
  grunt.registerTask('library', () => {
    grunt.option('library', 'true');
    grunt.option('path', './client/library');
    return grunt.task.run(['build:es,esnext,web,core', 'uglify']);
  });
  return grunt.registerTask('default', ['clean', 'copy', 'client', 'library']);
};
<commit_msg>remove not exists folder from the `grunt copy` task<commit_after>'use strict';
const build = require('./build');
const fs = require('fs');
const path = require('path');
const config = require('./build/config');
module.exports = grunt => {
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-webpack');
  grunt.initConfig({
    pkg: grunt.file.readJSON('./package.json'),
    uglify: {
      build: {
        files: {
          '<%=grunt.option("path")%>.min.js': '<%=grunt.option("path")%>.js',
        },
        options: {
          mangle: {
            keep_fnames: true,
          },
          compress: {
            keep_fnames: true,
            pure_getters: true,
          },
          output: {
            max_line_len: 32000,
          },
          ie8: true,
          sourceMap: true,
          banner: config.banner,
        },
      },
    },
    clean: ['./library'],
    copy: {
      lib: {
        files: [
          {
            expand: true,
            cwd: './',
            src: ['es/**', 'stage/**', 'web/**', 'fn/**', 'index.js'],
            dest: './library/',
          }, {
            expand: true,
            cwd: './',
            src: ['modules/*'],
            dest: './library/',
            filter: 'isFile',
          }, {
            expand: true,
            cwd: './modules/library/',
            src: '*',
            dest: './library/modules/',
          },
        ],
      },
    },
    karma: {
      options: {
        frameworks: ['qunit'],
        basePath: './',
        browsers: ['PhantomJS'],
        singleRun: true,
      },
      default: {
        files: [
          'client/core.js',
          'tests/bundles/qunit-helpers.js',
          'tests/bundles/tests.js',
        ].map(it => ({ src: it })),
      },
      library: {
        files: [
          'client/library.js',
          'tests/bundles/qunit-helpers.js',
          'tests/bundles/library.js',
        ].map(it => ({ src: it })),
      },
    },
    webpack: {
      options: {
        module: {
          loaders: [{
            test: /\.js$/,
            loader: 'babel-loader',
            options: {
              // use transforms which does not use es5+ builtins
              plugins: [
                ['transform-es3-member-expression-literals'],
                ['transform-es3-property-literals'],
                // use it instead of webpack es modules for support engines without descriptors
                ['transform-es2015-modules-commonjs', { loose: true }],
                ['transform-es2015-arrow-functions'],
                ['transform-es2015-block-scoped-functions'],
                ['transform-es2015-block-scoping'],
                ['transform-es2015-classes', { loose: true }],
                ['transform-es2015-computed-properties', { loose: true }],
                ['transform-es2015-destructuring', { loose: true }],
                ['transform-es2015-literals'],
                ['transform-es2015-parameters'],
                ['transform-es2015-shorthand-properties'],
                ['transform-es2015-spread', { loose: true }],
                ['transform-es2015-template-literals', { loose: true, spec: true }],
                ['transform-exponentiation-operator'],
                ['transform-for-of-as-array'],
                ['check-es2015-constants'],
              ],
            },
          }],
        },
        node: {
          global: false,
          process: false,
          setImmediate: false,
        },
        stats: false,
        output: {
          path: path.resolve(__dirname, 'tests/bundles'),
        },
      },
      helpers: {
        entry: './tests/helpers/qunit-helpers.js',
        output: { filename: 'qunit-helpers.js' },
      },
      library: {
        entry: './tests/library/index.js',
        output: { filename: 'library.js' },
      },
      tests: {
        entry: './tests/tests/index.js',
        output: { filename: 'tests.js' },
      },
      'promises-aplus-tests': {
        entry: 'promises-aplus-tests/lib/testFiles.js',
        output: { filename: 'promises-aplus.js' },
      },
    },
  });
  grunt.registerTask('build', function (options) {
    const done = this.async();
    return build({
      modules: (options || 'es,esnext,web,core').split(','),
      blacklist: (grunt.option('blacklist') || '').split(','),
      library: !!~['yes', 'on', 'true'].indexOf(grunt.option('library')),
      umd: !~['no', 'off', 'false'].indexOf(grunt.option('umd')),
    }).then(it => {
      grunt.option('path') || grunt.option('path', './custom');
      fs.writeFile(grunt.option('path') + '.js', it, done);
    }).catch(it => {
      // eslint-disable-next-line no-console
      console.error(it);
      process.exit(1);
    });
  });
  grunt.registerTask('client', () => {
    grunt.option('library', '');
    grunt.option('path', './client/core');
    return grunt.task.run(['build:es,esnext,web', 'uglify']);
  });
  grunt.registerTask('library', () => {
    grunt.option('library', 'true');
    grunt.option('path', './client/library');
    return grunt.task.run(['build:es,esnext,web,core', 'uglify']);
  });
  return grunt.registerTask('default', ['clean', 'copy', 'client', 'library']);
};
<|endoftext|>


<commit_before>// NOTE: this is one of the places where I'm using internal state rather than redux global state
// reason for doing so is because this intended to be used multiple times in a giant listview
// it's therefore easier to keep the state attached to the component rather than build a giant array in redux

import React, {Component} from 'react';
import {
    View,
    Text,
    StyleSheet,
    TouchableOpacity,
    TouchableHighlight,
    TextInput,
    Keyboard,
    Platform,
    Alert,
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import Pill from 'app/shared_features/pill/Pill';
import * as Analytics from 'app/services/Analytics';

class SetForm extends Component {

    constructor(props) {
        super(props);

        this.state = {
            tags: this.props.tags,
            weight: this.props.weight,
            didChangeWeight: false,
            metric: this.props.metric,
            rpe: this.props.rpe,
            didChangeRPE: false,
            removed: this.props.removed,
        };
    }

    // this uses didChange flags to prevent overwriting of values while you're still typing while still allowing sync to update it
    componentWillReceiveProps(nextProps) {
        this.setState({
            tags: nextProps.tags,
            weight: this.state.didChangeWeight ? this.state.weight : nextProps.weight,
            didChangeWeight: false,
            metric: nextProps.metric,
            rpe: this.state.didChangeRPE ? this.state.rpe : nextProps.rpe,
            didChangeRPE: false,
            removed: nextProps.removed
        });
    }

    componentWillUpdate(nextProps, nextState) {
        // meant to be update only for analytics purposes
        // do NOT read the weight values from this
        if (this.props.hasOwnProperty('updateWeight') && this.state.weight !== nextState.weight) {
            this.props.updateWeight(nextState.weight);
        }

        if (this.props.hasOwnProperty('updateRPE') && this.state.rpe !== nextState.rpe) {
            this.props.updateRPE(nextState.rpe);
        }
    }

    // KEYBOARD

    componentWillMount() {
        this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => { this._keyboardDidHide() });
    }

    componentWillUnmount() {
        this._save();
        this.keyboardDidHideListener.remove();
    }

    _keyboardDidHide() {
        this._save();
    }

    _onChangeWeight(weight) {
        this.setState({
            weight: weight,
            didChangeWeight: true
        });
    }

    _onChangeRPE(rpe) {
        this.setState({
            rpe: rpe,
            didChangeRPE: true
        });
    }

    _tapDisabledRPE() {
        // TODO: move this to actions, it doesn't belong here
        // doing it here right now for raw speed as no time
        Analytics.logEvent('old_rpe_alert', {});
        Alert.alert(
            '',
            "It has been too long since this set to log RPE.",
            [
                {text: 'Close', style: 'cancel'},
            ]
        );
    }

    _onEndEditWeight() {
        this._save();
        this.props.dismissWeight(this.props.setID);
    }

    _onEndEditRPE() {
        this._save();
        this.props.dismissRPE(this.props.setID);
    }

    // SAVING

    componentDidUpdate(nextProps, nextState) {
        if (nextState.metric !== this.state.metric) {
            this._save();
        }
    }

    _save() {
        if (this.props.weight !== this.state.weight
            || this.props.metric !== this.state.metric
            || this.props.rpe !== this.state.rpe) {
            this.props.saveSet(this.props.setID, this.state.weight, this.state.metric, this.state.rpe);
        }
    }

    _toggleMetric() {
        if (this.state.metric === 'kgs') {
            this.setState({metric: 'lbs'});
            this.props.toggleMetric(this.props.setID);
        } else if (this.state.metric === 'lbs') {
            this.setState({metric: 'kgs'});
            this.props.toggleMetric(this.props.setID);
        }
    }

    // RENDER

    _displayTags() {
        if (this.state.tags === undefined || this.state.tags === null || this.state.tags.length === 0) {
            return (<Text style={[styles.tagText, styles.placeholderText]}>Tags</Text>);
        }

        var pills = [];
        let position = 0;
        this.state.tags.map((tag) => {
            let key = position;
            pills.push(
                <Pill key={key} text={tag} style={{paddingRight: 5, paddingBottom: 3, paddingTop: 3}} />
            );
            position++;
        });

        return (<View style={styles.tagField}>{pills}</View>);
    }

    _displayMetric() {
        if (this.state.metric === 'kgs') {
            return "KGs";
        } else if (this.state.metric === 'lbs') {
            return "LBs";
        }
    }

    _renderWeight() {
        return (
            <View style={[styles.field, {flex: 3, marginRight: 5}]}>
                <TextInput
                    style={styles.fieldText}
                    keyboardType={'numeric'}
                    underlineColorAndroid={'transparent'}
                    editable = {true}
                    placeholder="Weight"
                    placeholderTextColor={'rgba(189, 189, 189, 1)'}
                    value={this.state.weight}

                    onEndEditing={() => this._onEndEditWeight() }
                    onFocus={() => this.props.tapWeight(this.props.setID) }
                    onChangeText={(weight) => this._onChangeWeight(weight) }
                />
                <View style={styles.fieldDetails}>
                    <TouchableOpacity onPress={() => this._toggleMetric()}>
                        <View style={{flexDirection: 'row', alignItems: 'center', }}>
                            <Text style={styles.detailText}>{this._displayMetric()} </Text>
                            <Icon name="refresh" size={10} color="gray" />
                        </View>
                    </TouchableOpacity>
                </View>
            </View>
        );
    }

    _renderRPE() {
        if (this.props.rpeDisabled) {
            return (
                <View style={[styles.field, {flex: 2}]}>
                    <TouchableOpacity onPress={() => this._tapDisabledRPE()}>
                        <TextInput
                            style={styles.fieldText}
                            keyboardType={'numeric'}
                            underlineColorAndroid={'transparent'}
                            editable = {false}
                            placeholder="RPE"
                            placeholderTextColor={'rgba(189, 189, 189, 1)'}
                            value = {this.state.rpe}
                            pointerEvents='none'
                        />
                        <View style={styles.fieldDetails} pointerEvents='none'>
                            <Text style={styles.detailText}>RPE</Text>
                        </View>
                    </TouchableOpacity>
                </View>
            );
        } else {
            return (
                <View style={[styles.field, {flex: 2}]}>
                    <TextInput
                        style={styles.fieldText}
                        keyboardType={'numeric'}
                        underlineColorAndroid={'transparent'}
                        editable = {true}
                        placeholder="RPE"
                        onEndEditing={() => this._onEndEditRPE() }
                        placeholderTextColor={'rgba(189, 189, 189, 1)'}
                        value = {this.state.rpe}
                        onFocus={() => this.props.tapRPE(this.props.setID) }
                        onChangeText={(rpe) => this._onChangeRPE(rpe) }
                    />
                    <View style={styles.fieldDetails} pointerEvents='none'>
                        <Text style={styles.detailText}>RPE</Text>
                    </View>
                </View>
            );
        }
    }

    _renderTags() {
        return (
            <View style={[styles.field, {flex: 1}]}>
                <TouchableHighlight onPress={() => this.props.tapTags(this.props.setID, this.state.tags)} underlayColor='#e0e0e0'>
                    {this._displayTags()}
                </TouchableHighlight>
            </View>
        );
    }

    render() {
        return (
            <View style={[{flex: 1, flexDirection: 'column'}, styles.border]}>
                <View style={[{flex: 1, flexDirection: 'column', paddingLeft: 12, paddingRight: 12, paddingTop: 0, paddingBottom: 7}]}>
                    <View style={{flex: 1, flexDirection: 'row', justifyContent: 'space-between'}}>
                        <View style={{flex: 1}}>
                            <View style={{flex: 1, flexDirection: 'row'}}>
                                { this._renderWeight() }
                                { this._renderRPE() }
                            </View>
                            <View>{ this._renderTags() }</View>
                        </View>

                        <View>{ this.props.renderDetailComponent() }</View>
                    </View>
                </View>
            </View>
        );
    }

}

const styles = StyleSheet.create({
    field: {
        backgroundColor: 'rgba(239, 239, 239, 1)',
        borderColor: 'rgba(239, 239, 239, 1)',
        borderWidth: 3,
        borderRadius: 3,
        marginBottom: 5,
        zIndex: 2,
        minHeight: 35,
    },
    fieldDetails: {
        position: 'absolute',
        right: 5,
        top: -1,
        bottom: 0,
        justifyContent: 'center',
    },
    fieldText: {
        height: 29,
        fontSize: 13,
        paddingLeft: 4,
        paddingTop: 4,
        paddingBottom: 5,
        paddingRight: 30,
        color: 'rgba(77, 77, 77, 1)',
    },
    tagText: {
        height: 29,
        paddingTop: 6,
        paddingLeft: 4,
        fontSize: 13,
        paddingRight: 30,
        color: 'rgba(77, 77, 77, 1)',
    },
    tagField: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        minHeight: 29,
        paddingLeft: 2,
        paddingRight: 0,
    },
    placeholderText: {
        color: 'rgba(189, 189, 189, 1)'
    },
    detailText: {
        fontSize: 13,
        color: 'gray',
        backgroundColor: 'rgba(0, 0, 0, 0)'
    },
    disabledText: {
        fontSize: 13,
        color: 'rgba(189, 189, 189, 1)',
        backgroundColor: 'rgba(0, 0, 0, 0)'
    },
    border: {
        borderColor: '#e0e0e0',
        borderLeftWidth: 1,
        borderRightWidth: 1,
        borderBottomWidth: 1,
    },
});

export default SetForm;
<commit_msg>now editing rpe or weight in 1rm edit set wont lose the value when you tap on exercise or tags<commit_after>// NOTE: this is one of the places where I'm using internal state rather than redux global state
// reason for doing so is because this intended to be used multiple times in a giant listview
// it's therefore easier to keep the state attached to the component rather than build a giant array in redux

import React, {Component} from 'react';
import {
    View,
    Text,
    StyleSheet,
    TouchableOpacity,
    TouchableHighlight,
    TextInput,
    Keyboard,
    Platform,
    Alert,
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import Pill from 'app/shared_features/pill/Pill';
import * as Analytics from 'app/services/Analytics';

class SetForm extends Component {

    constructor(props) {
        super(props);

        this.state = {
            tags: this.props.tags,
            weight: this.props.weight,
            didChangeWeight: false,
            metric: this.props.metric,
            rpe: this.props.rpe,
            didChangeRPE: false,
            removed: this.props.removed,
        };
    }

    // this uses didChange flags to prevent overwriting of values while you're still typing while still allowing sync to update it
    componentWillReceiveProps(nextProps) {
        this.setState({
            tags: nextProps.tags,
            weight: this.state.didChangeWeight ? this.state.weight : nextProps.weight,
            didChangeWeight: false,
            metric: nextProps.metric,
            rpe: this.state.didChangeRPE ? this.state.rpe : nextProps.rpe,
            didChangeRPE: false,
            removed: nextProps.removed
        });
    }

    // KEYBOARD

    componentWillMount() {
        this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => { this._keyboardDidHide() });
    }

    componentWillUnmount() {
        this._save();
        this.keyboardDidHideListener.remove();
    }

    _keyboardDidHide() {
        this._save();
    }

    _onChangeWeight(weight) {
        this.setState({
            weight: weight,
            didChangeWeight: true,
        }, () => {
            // hack to guarantee that the weight won't be overriden by updateWeight
            if (this.props.hasOwnProperty('updateWeight')) {
                this.setState({
                    weight: weight,
                    didChangeWeight: true,
                });
            }
        });

        if (this.props.hasOwnProperty('updateWeight')) {
            this.props.updateWeight(weight);
        }
    }

    _onChangeRPE(rpe) {
        this.setState({
            rpe: rpe,
            didChangeRPE: true,
        }, () => {
            // hack to guarantee that the rpe won't be overriden by updateRPE
            if (this.props.hasOwnProperty('updateRPE')) {
                this.setState({
                    rpe: rpe,
                    didChangeRPE: true,
                });
            }
        });

        if (this.props.hasOwnProperty('updateRPE')) {
            this.props.updateRPE(rpe);
        }
    }

    _tapDisabledRPE() {
        // TODO: move this to actions, it doesn't belong here
        // doing it here right now for raw speed as no time
        Analytics.logEvent('old_rpe_alert', {});
        Alert.alert(
            '',
            "It has been too long since this set to log RPE.",
            [
                {text: 'Close', style: 'cancel'},
            ]
        );
    }

    _onEndEditWeight() {
        this._save();
        this.props.dismissWeight(this.props.setID);
    }

    _onEndEditRPE() {
        this._save();
        this.props.dismissRPE(this.props.setID);
    }

    // SAVING

    componentDidUpdate(nextProps, nextState) {
        if (nextState.metric !== this.state.metric) {
            this._save();
        }
    }

    _save() {
        if (this.props.weight !== this.state.weight
            || this.props.metric !== this.state.metric
            || this.props.rpe !== this.state.rpe) {
            this.props.saveSet(this.props.setID, this.state.weight, this.state.metric, this.state.rpe);
        }
    }

    _toggleMetric() {
        if (this.state.metric === 'kgs') {
            this.setState({metric: 'lbs'});
            this.props.toggleMetric(this.props.setID);
        } else if (this.state.metric === 'lbs') {
            this.setState({metric: 'kgs'});
            this.props.toggleMetric(this.props.setID);
        }
    }

    // RENDER

    _displayTags() {
        if (this.state.tags === undefined || this.state.tags === null || this.state.tags.length === 0) {
            return (<Text style={[styles.tagText, styles.placeholderText]}>Tags</Text>);
        }

        var pills = [];
        let position = 0;
        this.state.tags.map((tag) => {
            let key = position;
            pills.push(
                <Pill key={key} text={tag} style={{paddingRight: 5, paddingBottom: 3, paddingTop: 3}} />
            );
            position++;
        });

        return (<View style={styles.tagField}>{pills}</View>);
    }

    _displayMetric() {
        if (this.state.metric === 'kgs') {
            return "KGs";
        } else if (this.state.metric === 'lbs') {
            return "LBs";
        }
    }

    _renderWeight() {
        return (
            <View style={[styles.field, {flex: 3, marginRight: 5}]}>
                <TextInput
                    style={styles.fieldText}
                    keyboardType={'numeric'}
                    underlineColorAndroid={'transparent'}
                    editable = {true}
                    placeholder="Weight"
                    placeholderTextColor={'rgba(189, 189, 189, 1)'}
                    value={this.state.weight}

                    onEndEditing={() => this._onEndEditWeight() }
                    onFocus={() => this.props.tapWeight(this.props.setID) }
                    onChangeText={(weight) => this._onChangeWeight(weight) }
                />
                <View style={styles.fieldDetails}>
                    <TouchableOpacity onPress={() => this._toggleMetric()}>
                        <View style={{flexDirection: 'row', alignItems: 'center', }}>
                            <Text style={styles.detailText}>{this._displayMetric()} </Text>
                            <Icon name="refresh" size={10} color="gray" />
                        </View>
                    </TouchableOpacity>
                </View>
            </View>
        );
    }

    _renderRPE() {
        if (this.props.rpeDisabled) {
            return (
                <View style={[styles.field, {flex: 2}]}>
                    <TouchableOpacity onPress={() => this._tapDisabledRPE()}>
                        <TextInput
                            style={styles.fieldText}
                            keyboardType={'numeric'}
                            underlineColorAndroid={'transparent'}
                            editable = {false}
                            placeholder="RPE"
                            placeholderTextColor={'rgba(189, 189, 189, 1)'}
                            value = {this.state.rpe}
                            pointerEvents='none'
                        />
                        <View style={styles.fieldDetails} pointerEvents='none'>
                            <Text style={styles.detailText}>RPE</Text>
                        </View>
                    </TouchableOpacity>
                </View>
            );
        } else {
            return (
                <View style={[styles.field, {flex: 2}]}>
                    <TextInput
                        style={styles.fieldText}
                        keyboardType={'numeric'}
                        underlineColorAndroid={'transparent'}
                        editable = {true}
                        placeholder="RPE"
                        onEndEditing={() => this._onEndEditRPE() }
                        placeholderTextColor={'rgba(189, 189, 189, 1)'}
                        value = {this.state.rpe}
                        onFocus={() => this.props.tapRPE(this.props.setID) }
                        onChangeText={(rpe) => this._onChangeRPE(rpe) }
                    />
                    <View style={styles.fieldDetails} pointerEvents='none'>
                        <Text style={styles.detailText}>RPE</Text>
                    </View>
                </View>
            );
        }
    }

    _renderTags() {
        return (
            <View style={[styles.field, {flex: 1}]}>
                <TouchableHighlight onPress={() => this.props.tapTags(this.props.setID, this.state.tags)} underlayColor='#e0e0e0'>
                    {this._displayTags()}
                </TouchableHighlight>
            </View>
        );
    }

    render() {
        return (
            <View style={[{flex: 1, flexDirection: 'column'}, styles.border]}>
                <View style={[{flex: 1, flexDirection: 'column', paddingLeft: 12, paddingRight: 12, paddingTop: 0, paddingBottom: 7}]}>
                    <View style={{flex: 1, flexDirection: 'row', justifyContent: 'space-between'}}>
                        <View style={{flex: 1}}>
                            <View style={{flex: 1, flexDirection: 'row'}}>
                                { this._renderWeight() }
                                { this._renderRPE() }
                            </View>
                            <View>{ this._renderTags() }</View>
                        </View>

                        <View>{ this.props.renderDetailComponent() }</View>
                    </View>
                </View>
            </View>
        );
    }

}

const styles = StyleSheet.create({
    field: {
        backgroundColor: 'rgba(239, 239, 239, 1)',
        borderColor: 'rgba(239, 239, 239, 1)',
        borderWidth: 3,
        borderRadius: 3,
        marginBottom: 5,
        zIndex: 2,
        minHeight: 35,
    },
    fieldDetails: {
        position: 'absolute',
        right: 5,
        top: -1,
        bottom: 0,
        justifyContent: 'center',
    },
    fieldText: {
        height: 29,
        fontSize: 13,
        paddingLeft: 4,
        paddingTop: 4,
        paddingBottom: 5,
        paddingRight: 30,
        color: 'rgba(77, 77, 77, 1)',
    },
    tagText: {
        height: 29,
        paddingTop: 6,
        paddingLeft: 4,
        fontSize: 13,
        paddingRight: 30,
        color: 'rgba(77, 77, 77, 1)',
    },
    tagField: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        minHeight: 29,
        paddingLeft: 2,
        paddingRight: 0,
    },
    placeholderText: {
        color: 'rgba(189, 189, 189, 1)'
    },
    detailText: {
        fontSize: 13,
        color: 'gray',
        backgroundColor: 'rgba(0, 0, 0, 0)'
    },
    disabledText: {
        fontSize: 13,
        color: 'rgba(189, 189, 189, 1)',
        backgroundColor: 'rgba(0, 0, 0, 0)'
    },
    border: {
        borderColor: '#e0e0e0',
        borderLeftWidth: 1,
        borderRightWidth: 1,
        borderBottomWidth: 1,
    },
});

export default SetForm;
<|endoftext|>


<commit_before>/**
 * Created by jopitz on 12/15/2014.
 */

var gulp   = require( 'gulp' ),
	rimraf = require( 'gulp-rimraf' ),
	exec   = require( 'gulp-exec' ),
	insert = require( 'gulp-insert' ),
	seq    = require( 'run-sequence' ),
	rename = require( 'gulp-rename' ),
	argv   = require( 'yargs' ).argv,

	_comma = 'commafix: tired of the hassle of remembering to add/remove a comma for the last var'

///////////////////////
//	TASKS
///////////////////////

var ver = argv.ver ? '#' + argv.ver : '';
var vs = ver || 'latest';
var src = argv.src;

console.log( 'version: ', vs )

gulp.task( 'init', function()
{
	return gulp.src( [ './dist' ], { read: false } )
		.pipe( rimraf( { force: true } ) );
} )

gulp.task( 'build-bootstrap', function()
{
	return gulp.src( '' )
		.pipe( exec( 'napa angular-ui/bootstrap' + ver + ':_tmp && ' +  //use napa to pull from git and store into our app, we could bypass napa and just go git
					 'cd ./node_modules/_tmp && ' +
					 'npm install && ' + //install deps to build the distros
					 'grunt --force' ) ) //force the build in case they don't have an env var for CHROME_BIN
} )

gulp.task( 'curl', function()
{
	src = src || './tmp'

	var v = argv.ver ||
			(function() {throw new Error( 'manually building requires a valid version number e.g. 0.13.0' )})()

	var norm = 'ui-bootstrap-tpls-' + v + '.js';
	var mini = 'ui-bootstrap-tpls-' + v + '.min.js';

	return gulp.src( '' )
		.pipe( exec( 'mkdir ./tmp && ' +
					 'curl -o ./tmp/' + norm + ' http://angular-ui.github.io/bootstrap/' + norm + ' && ' +
					 'curl -o ./tmp/' + mini + ' http://angular-ui.github.io/bootstrap/' + mini ) )

} )

gulp.task( 'package', function()
{
	src = src || './node_modules/_tmp/dist'

	return gulp.src( [ src + '/ui-bootstrap-tpls-*.js' ] )
		.pipe( insert.append( 'if(typeof module!==\'undefined\')module.exports=\'ui.bootstrap\';' ) ) //just making this compatible with common-js packages for use w/ browserify
		.pipe( gulp.dest( './tmp' ) )
} )

gulp.task( 'rename', function()
{
	gulp.src( './tmp/*.min.js' )
		.pipe( rename( 'angular-bootstrap.min.js' ) )
		.pipe( gulp.dest( './dist' ) )

	return gulp.src( [ './tmp/*.js', '!./tmp/*.min.js' ] )
		.pipe( rename( 'angular-bootstrap.js' ) )
		.pipe( gulp.dest( './dist' ) )
} )

gulp.task( 'clean', function()
{
	return gulp.src( [ './tmp', './node_modules/_tmp' ], { read: false } )
		.pipe( rimraf( { force: true } ) );
} )

///////////////////////
//	DEFAULT
///////////////////////

gulp.task( 'default', function() { seq( 'init', 'build-bootstrap', 'package', 'rename', 'clean' ); } )

gulp.task( 'manual', function() { seq( 'init', 'curl', 'package', 'rename', 'clean' );} )<commit_msg>removed build process, defaulting to curl'ing from git<commit_after>/**
 * Created by jopitz on 12/15/2014.
 */

var gulp   = require( 'gulp' ),
	rimraf = require( 'gulp-rimraf' ),
	exec   = require( 'gulp-exec' ),
	insert = require( 'gulp-insert' ),
	seq    = require( 'run-sequence' ),
	rename = require( 'gulp-rename' ),
	argv   = require( 'yargs' ).argv,

	_comma = 'commafix: tired of the hassle of remembering to add/remove a comma for the last var'

///////////////////////
//	TASKS
///////////////////////

var ver = argv.ver ? '#' + argv.ver : '';
var vs = ver || 'latest';
var src = argv.src;

console.log( 'version: ', vs )

gulp.task( 'init', function()
{
	return gulp.src( [ './dist' ], { read: false } )
		.pipe( rimraf( { force: true } ) );
} )

gulp.task( 'curl', function()
{
	src = src || './tmp'

	var v = argv.ver ||
			(function() {throw new Error( 'manually building requires a valid version number e.g. 0.13.0' )})()

	var norm = 'ui-bootstrap-tpls-' + v + '.js';
	var mini = 'ui-bootstrap-tpls-' + v + '.min.js';

	return gulp.src( '' )
		.pipe( exec( 'mkdir ./tmp && ' +
					 'curl -o ./tmp/' + norm + ' http://angular-ui.github.io/bootstrap/' + norm + ' && ' +
					 'curl -o ./tmp/' + mini + ' http://angular-ui.github.io/bootstrap/' + mini ) )

} )

gulp.task( 'package', function()
{
	src = src || './node_modules/_tmp/dist'

	return gulp.src( [ src + '/ui-bootstrap-tpls-*.js' ] )
		.pipe( insert.append( 'if(typeof module!==\'undefined\')module.exports=\'ui.bootstrap\';' ) ) //just making this compatible with common-js packages for use w/ browserify
		.pipe( gulp.dest( './tmp' ) )
} )

gulp.task( 'rename', function()
{
	gulp.src( './tmp/*.min.js' )
		.pipe( rename( 'angular-bootstrap.min.js' ) )
		.pipe( gulp.dest( './dist' ) )

	return gulp.src( [ './tmp/*.js', '!./tmp/*.min.js' ] )
		.pipe( rename( 'angular-bootstrap.js' ) )
		.pipe( gulp.dest( './dist' ) )
} )

gulp.task( 'clean', function()
{
	return gulp.src( [ './tmp', './node_modules/_tmp' ], { read: false } )
		.pipe( rimraf( { force: true } ) );
} )

///////////////////////
//	DEFAULT
///////////////////////

gulp.task( 'default', function() { seq( 'init', 'curl', 'package', 'rename', 'clean' );} )<|endoftext|>


<commit_before>var events = require("events"),
    util = require("util");

// Control Arduino Input/Output through Johnny-Five
var five = require("johnny-five");

var pincatalog = {
    UNO: {
      analog: ["A0","A1","A2","A3","A4","A5"],
      digital: [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
    },
    MEGA: {
      analog: ["A0","A1","A2","A3","A4","A5","A6","A7","A8", "A9"]
    } ,
    LEONARDO: {
      analog: ["A0","A1","A2","A3","A4","A5"]
    }
};

var Webduino = function(server) {

  if ( !(this instanceof Webduino) ) {
    return new Webduino( server );
  }

  var self = this;
  events.EventEmitter.call(this);

  this.pins = {};
  this.sensors = {};
  this.leds = {};
  this.board = null;
  this.five = five;;
  this.type;
  this.server = server;
  this.io = require('socket.io').listen(server,  { log: false });

  this.board = new five.Board();

  this.board.on("ready",function() {
    self.start(five, this.board)
    self.io.sockets.on('connection',function() {});
  });

}

// Inherit event api
util.inherits( Webduino, events.EventEmitter );

/**
 * start  Initialize the variables associated to pins
 * @return {Webduino}
 */
Webduino.prototype.start = function(_five, _board) {
    this.five = _five;
    this.board = _board;
    this.type = board.type;
    this.numPins = 0;

    // References to analog pins
    for (var i = 0 ; i < pincatalog[this.type].analog.length; i++) {
      var pinid = pincatalog[this.type].analog[i]
      this.pins[pinid] = new this.five.Pin(pinid);

      // CHECK HOW TO DO THIS IN J5
      this.pins[pinid].id = pinid
    }

    // References to digital pins
    for (var i = 0 ; i < pincatalog[this.type].digital.length; i++) {
      var pinid = pincatalog[this.type].digital[i]
      this.pins[pinid] = new this.five.Pin(pinid)

      // CHECK HOW TO DO THIS IN J5
      this.pins[pinid].id = pinid
    }

    this.numPins = pincatalog[this.type].analog.length + pincatalog[this.type].digital.length;

    this.emit( "ready", null );

    return this;
};

/**
 * getPinState  Get the state of a given pin id through callback function
 * @return {Webduino}
 */
Webduino.prototype.getPinState = function(id, callback) {
    var pin = this.pins[id];

    // pin.query does not work well with analog pins // this is a patch to get their state
    if (pin.type == "analog") {
      console.log(pin);
      var pinstate = pin.firmata.pins[pin.firmata.analogPins[pin.addr]];
      pinstate.id = id;
      callback(pinstate);
    } else  {
      pin.query(function(state) {
        state.id = id;
        callback(state)
      });
    }

    return this;
};

/**
 * getPin
 *
 * @return {Webduino}
 */
Webduino.prototype.getPin = function(req, res) {
    var id = req.params.id;
    var pin = this.pins[id];

    this.getPinState(id, function(state) {
      res.send(state)
    })
    return this;
};

/**
 * getPins  Get an array with current state of each pin
 * @return {Webduino}
 */
Webduino.prototype.getPins = function(req, res) {
  var out = [];
  var self = this;

  for (var id in this.pins){
    this.getPinState(id, function(state) {
      out.push(state);

      // Once received data from all pins - send reply
      if (out.length >= self.numPins) {
        res.send(out);
      }

    })

  }
  return this;
};

/**
 * putPin  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.putPin = function(req, res) {
  var id = req.params.id;
  var value = req.body.value;

  var self = this;
  var pin = this.pins[id];
  pin.write(value);

  this.getPinState(id, function(state) {
    self.socketBroadcastPinState(state);
    res.send(state);
  });
}

/**
* getSensor
*/
Webduino.prototype.getSensor = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";

  var state = this.getSensorState(id)

  res.send(state);
}

/**
 * getSensors
 */
Webduino.prototype.getSensors = function(req, res) {
  var self = this;
  var out = [];

  for (id in this.sensors) {
    var state = this.getSensorState(id)
    out.push(state);
  }

  res.send(out);
}

 /**
 * putSensor  Add a new sensor on the given pin id
 * @return {Webduino}
 */
Webduino.prototype.putSensor = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "A0";
  var freq = req.body.freq ? req.body.freq : 25;

  if (!this.sensors[id]) {
    this.sensors[id] = {};
    this.sensors[id].j5sensor = new five.Sensor({'pin':id, 'freq':freq});
  }

  var sensor = this.sensors[id];
  sensor.freq = freq;

  // Broadcast through sockets.io when each sample is received
  sensor.j5sensor.on("data", function() {
    var state = {};
    state.id = id;
    state.value = this.value;
    state.mode = this.mode;

    self.socketBroadcastSensorState(state);
  })

  var state = this.getSensorState(id)
  res.send(state);
}

 /**
 * postLed  Create a new Led object on the given pin id
 */
Webduino.prototype.putLed = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";
  var state = req.body.state ? req.body.state : "off";
  var strobe = req.body.strobe ? req.body.strobe : false;
  var strobetime = req.body.strobetime ? req.body.strobetime : 500;

  if (!this.leds[id]) {
    this.leds[id] = {};
    this.leds[id].j5led = new five.Led(id);
  }

  var led = this.leds[id];

  if (state == "on") {led.j5led.on();} else {led.j5led.off();}
  led.state = state;

  if (strobe) {
    led.j5led.strobe(strobetime);
  } else {
    led.j5led.stop();
  }

  led.strobe = strobe;
  led.strobetime = strobetime;

  var state = this.getLedState(id);

  self.socketBroadcastLedState(state);

  res.send(state);
}

 /**
 * postLed
 */
Webduino.prototype.getLed = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";

  var state = this.getLedState(id)

  res.send(state);
}

/**
 * getLeds
 */
Webduino.prototype.getLeds = function(req, res) {
  var self = this;
  var out = [];

  for (id in this.leds) {
    var state = this.getLedState(id)
    out.push(state);
  }

  res.send(out);
}

/**
* getLedState
*/
Webduino.prototype.getLedState = function(id) {
  var state = {}
  if (this.leds[id]) {
    var led = this.leds[id];
    state.id = id;
    state.state = led.state;
    state.strobe = led.strobe;
    state.strobetime = led.strobetime;
  }
  return state;
}

/**
* getSensorState
*/
Webduino.prototype.getSensorState = function(id) {
  var state = {}
  if (this.sensors[id]) {
    var sensor = this.sensors[id];
    state.id = id;
    state.freq = sensor.freq;
  }
  return state;
}

/**
 * socketBroadcastPinState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastPinState = function(state) {
  this.io.sockets.emit("pin", state)
}

/**
 * socketBroadcastSensorState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastSensorState = function(state) {
  this.io.sockets.emit("sensor", state)
}

/**
 * socketBroadcastLedState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastLedState = function(state) {
  this.io.sockets.emit("led", state)
}

module.exports = Webduino;
<commit_msg>change firmata to io<commit_after>var events = require("events"),
    util = require("util");

// Control Arduino Input/Output through Johnny-Five
var five = require("johnny-five");

var pincatalog = {
    UNO: {
      analog: ["A0","A1","A2","A3","A4","A5"],
      digital: [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
    },
    MEGA: {
      analog: ["A0","A1","A2","A3","A4","A5","A6","A7","A8", "A9"]
    } ,
    LEONARDO: {
      analog: ["A0","A1","A2","A3","A4","A5"]
    }
};

var Webduino = function(server) {

  if ( !(this instanceof Webduino) ) {
    return new Webduino( server );
  }

  var self = this;
  events.EventEmitter.call(this);

  this.pins = {};
  this.sensors = {};
  this.leds = {};
  this.board = null;
  this.five = five;;
  this.type;
  this.server = server;
  this.io = require('socket.io').listen(server,  { log: false });

  this.board = new five.Board();

  this.board.on("ready",function() {
    self.start(five, this.board)
    self.io.sockets.on('connection',function() {});
  });

}

// Inherit event api
util.inherits( Webduino, events.EventEmitter );

/**
 * start  Initialize the variables associated to pins
 * @return {Webduino}
 */
Webduino.prototype.start = function(_five, _board) {
    this.five = _five;
    this.board = _board;
    this.type = board.type;
    this.numPins = 0;

    // References to analog pins
    for (var i = 0 ; i < pincatalog[this.type].analog.length; i++) {
      var pinid = pincatalog[this.type].analog[i]
      this.pins[pinid] = new this.five.Pin(pinid);

      // CHECK HOW TO DO THIS IN J5
      this.pins[pinid].id = pinid
    }

    // References to digital pins
    for (var i = 0 ; i < pincatalog[this.type].digital.length; i++) {
      var pinid = pincatalog[this.type].digital[i]
      this.pins[pinid] = new this.five.Pin(pinid)

      // CHECK HOW TO DO THIS IN J5
      this.pins[pinid].id = pinid
    }

    this.numPins = pincatalog[this.type].analog.length + pincatalog[this.type].digital.length;

    this.emit( "ready", null );

    return this;
};

/**
 * getPinState  Get the state of a given pin id through callback function
 * @return {Webduino}
 */
Webduino.prototype.getPinState = function(id, callback) {
    var pin = this.pins[id];

    // pin.query does not work well with analog pins // this is a patch to get their state
    if (pin.type == "analog") {
      console.log(pin);
      var pinstate = pin.io.pins[pin.io.analogPins[pin.addr]];
      pinstate.id = id;
      callback(pinstate);
    } else  {
      pin.query(function(state) {
        state.id = id;
        callback(state)
      });
    }

    return this;
};

/**
 * getPin
 *
 * @return {Webduino}
 */
Webduino.prototype.getPin = function(req, res) {
    var id = req.params.id;
    var pin = this.pins[id];

    this.getPinState(id, function(state) {
      res.send(state)
    })
    return this;
};

/**
 * getPins  Get an array with current state of each pin
 * @return {Webduino}
 */
Webduino.prototype.getPins = function(req, res) {
  var out = [];
  var self = this;

  for (var id in this.pins){
    this.getPinState(id, function(state) {
      out.push(state);

      // Once received data from all pins - send reply
      if (out.length >= self.numPins) {
        res.send(out);
      }

    })

  }
  return this;
};

/**
 * putPin  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.putPin = function(req, res) {
  var id = req.params.id;
  var value = req.body.value;

  var self = this;
  var pin = this.pins[id];
  pin.write(value);

  this.getPinState(id, function(state) {
    self.socketBroadcastPinState(state);
    res.send(state);
  });
}

/**
* getSensor
*/
Webduino.prototype.getSensor = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";

  var state = this.getSensorState(id)

  res.send(state);
}

/**
 * getSensors
 */
Webduino.prototype.getSensors = function(req, res) {
  var self = this;
  var out = [];

  for (id in this.sensors) {
    var state = this.getSensorState(id)
    out.push(state);
  }

  res.send(out);
}

 /**
 * putSensor  Add a new sensor on the given pin id
 * @return {Webduino}
 */
Webduino.prototype.putSensor = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "A0";
  var freq = req.body.freq ? req.body.freq : 25;

  if (!this.sensors[id]) {
    this.sensors[id] = {};
    this.sensors[id].j5sensor = new five.Sensor({'pin':id, 'freq':freq});
  }

  var sensor = this.sensors[id];
  sensor.freq = freq;

  // Broadcast through sockets.io when each sample is received
  sensor.j5sensor.on("data", function() {
    var state = {};
    state.id = id;
    state.value = this.value;
    state.mode = this.mode;

    self.socketBroadcastSensorState(state);
  })

  var state = this.getSensorState(id)
  res.send(state);
}

 /**
 * postLed  Create a new Led object on the given pin id
 */
Webduino.prototype.putLed = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";
  var state = req.body.state ? req.body.state : "off";
  var strobe = req.body.strobe ? req.body.strobe : false;
  var strobetime = req.body.strobetime ? req.body.strobetime : 500;

  if (!this.leds[id]) {
    this.leds[id] = {};
    this.leds[id].j5led = new five.Led(id);
  }

  var led = this.leds[id];

  if (state == "on") {led.j5led.on();} else {led.j5led.off();}
  led.state = state;

  if (strobe) {
    led.j5led.strobe(strobetime);
  } else {
    led.j5led.stop();
  }

  led.strobe = strobe;
  led.strobetime = strobetime;

  var state = this.getLedState(id);

  self.socketBroadcastLedState(state);

  res.send(state);
}

 /**
 * postLed
 */
Webduino.prototype.getLed = function(req, res) {
  var self = this;

  var id = req.params.id ? req.params.id : "13";

  var state = this.getLedState(id)

  res.send(state);
}

/**
 * getLeds
 */
Webduino.prototype.getLeds = function(req, res) {
  var self = this;
  var out = [];

  for (id in this.leds) {
    var state = this.getLedState(id)
    out.push(state);
  }

  res.send(out);
}

/**
* getLedState
*/
Webduino.prototype.getLedState = function(id) {
  var state = {}
  if (this.leds[id]) {
    var led = this.leds[id];
    state.id = id;
    state.state = led.state;
    state.strobe = led.strobe;
    state.strobetime = led.strobetime;
  }
  return state;
}

/**
* getSensorState
*/
Webduino.prototype.getSensorState = function(id) {
  var state = {}
  if (this.sensors[id]) {
    var sensor = this.sensors[id];
    state.id = id;
    state.freq = sensor.freq;
  }
  return state;
}

/**
 * socketBroadcastPinState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastPinState = function(state) {
  this.io.sockets.emit("pin", state)
}

/**
 * socketBroadcastSensorState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastSensorState = function(state) {
  this.io.sockets.emit("sensor", state)
}

/**
 * socketBroadcastLedState  Set the value of a PIN
 * @return {Webduino}
 */
Webduino.prototype.socketBroadcastLedState = function(state) {
  this.io.sockets.emit("led", state)
}

module.exports = Webduino;
<|endoftext|>