<commit_before>#!/usr/bin/env node

/* eslint-disable id-length, no-console, no-process-env */
const fs = require('fs')
const ora = require('ora')
const getIt = require('get-it')
const {promise} = require('get-it/middleware')
const meow = require('meow')
const prettyMs = require('pretty-ms')
const sanityClient = require('@sanity/client')
const sanityImport = require('@sanity/import')

const red = (str) => `\u001b[31m${str}\u001b[39m`
const yellow = (str) => `\u001b[33m${str}\u001b[39m`
const printError = (str) => console.error(red(`ERROR: ${str}`))

const cli = meow(
  `
  Usage
    $ sanity-import -p <projectId> -d <dataset> -t <token> sourceFile.ndjson

  Options
    -p, --project <projectId> Project ID to import to
    -d, --dataset <dataset> Dataset to import to
    -t, --token <token> Token to authenticate with
    --asset-concurrency <concurrency> Number of parallel asset imports
    --replace Replace documents with the same IDs
    --missing Skip documents that already exist
    --allow-failing-assets Skip assets that cannot be fetched/uploaded
    --replace-assets Skip reuse of existing assets
    --help Show this help

  Rarely used options (should generally not be used)
    --allow-assets-in-different-dataset Allow asset documents to reference different project/dataset

  Examples
    # Import "./my-dataset.ndjson" into dataset "staging"
    $ sanity-import -p myPrOj -d staging -t someSecretToken my-dataset.ndjson

    # Import into dataset "test" from stdin, read token from env var
    $ cat my-dataset.ndjson | sanity-import -p myPrOj -d test -

  Environment variables (fallbacks for missing flags)
    --token = SANITY_IMPORT_TOKEN
`,
  {
    flags: {
      // Required, but validated below for better error output
      project: {
        type: 'string',
        alias: 'p',
      },

      dataset: {
        type: 'string',
        alias: 'd',
      },

      token: {
        type: 'string',
        alias: 't',
      },

      // Optional
      replace: {
        type: 'boolean',
        default: false,
      },

      missing: {
        type: 'boolean',
        default: false,
      },

      allowFailingAssets: {
        type: 'boolean',
        default: false,
      },

      allowAssetsInDifferentDataset: {
        type: 'boolean',
        default: false,
      },

      replaceAssets: {
        type: 'boolean',
        default: false,
      },

      assetConcurrency: {
        type: 'number',
        alias: 'c',
      },
    },
  }
)

const {flags, input, showHelp} = cli
const {dataset, allowFailingAssets, replaceAssets, allowAssetsInDifferentDataset} = flags
const token = flags.token || process.env.SANITY_IMPORT_TOKEN
const projectId = flags.project
const assetConcurrency = flags.assetConcurrency
const source = input[0]

if (!projectId) {
  printError('Flag `--project` is required')
  showHelp()
}

if (!dataset) {
  printError('Flag `--dataset` is required')
  showHelp()
}

if (!token) {
  printError('Flag `--token` is required (or set SANITY_IMPORT_TOKEN)')
  showHelp()
}

if (!source) {
  printError('Source file is required, use `-` to read from stdin')
  showHelp()
}

let operation = 'create'
if (flags.replace || flags.missing) {
  if (flags.replace && flags.missing) {
    printError('Cannot use both `--replace` and `--missing`')
    showHelp()
  }

  operation = flags.replace ? 'createOrReplace' : 'createIfNotExists'
}

let currentStep
let currentProgress
let stepStart
let spinInterval

const client = sanityClient({
  apiVersion: '1',
  projectId,
  dataset,
  token,
  useCdn: false,
})

getStream()
  .then((stream) =>
    sanityImport(stream, {
      client,
      operation,
      onProgress,
      allowFailingAssets,
      allowAssetsInDifferentDataset,
      assetConcurrency,
      replaceAssets,
    })
  )
  .then(({numDocs, warnings}) => {
    const timeSpent = prettyMs(Date.now() - stepStart, {secondsDecimalDigits: 2})
    currentProgress.text = `[100%] ${currentStep} (${timeSpent})`
    currentProgress.succeed()

    console.log('Done! Imported %d documents to dataset "%s"\n', numDocs, dataset)
    printWarnings(warnings)
  })
  .catch((err) => {
    if (currentProgress) {
      currentProgress.fail()
    }

    printError(err.stack)
  })

function printWarnings(warnings) {
  const assetFails = warnings.filter((warn) => warn.type === 'asset')

  if (!assetFails.length) {
    return
  }

  console.warn(
    yellow('⚠ Failed to import the following %s:'),
    assetFails.length > 1 ? 'assets' : 'asset'
  )

  warnings.forEach((warning) => {
    console.warn(`  ${warning.url}`)
  })
}

function getStream() {
  if (/^https:\/\//i.test(source)) {
    return getUriStream(source)
  }

  return Promise.resolve(source === '-' ? process.stdin : fs.createReadStream(source))
}

function getUriStream(uri) {
  const get = getIt([promise()])
  return get({url: uri, stream: true}).then(
    (res) => {
      if (res.statusCode !== 200) {
        throw new Error(`Error fetching source: HTTP ${res.statusCode}`)
      }

      return res.body
    },
    (err) => {
      throw new Error(`Error fetching source:\n${err.message}`)
    }
  )
}

function onProgress(opts) {
  const lengthComputable = opts.total
  const sameStep = opts.step == currentStep
  const percent = getPercentage(opts)

  if (lengthComputable && opts.total === opts.current) {
    clearInterval(spinInterval)
    spinInterval = null
  }

  if (sameStep && !lengthComputable) {
    return
  }

  if (sameStep) {
    const timeSpent = prettyMs(Date.now() - stepStart, {secDecimalDigits: 2})
    currentProgress.text = `${percent}${opts.step} (${timeSpent})`
    currentProgress.render()
    return
  }

  // Moved to a new step
  const prevStep = currentStep
  const prevStepStart = stepStart
  stepStart = Date.now()
  currentStep = opts.step

  if (spinInterval) {
    clearInterval(spinInterval)
    spinInterval = null
  }

  if (currentProgress && currentProgress.succeed) {
    const timeSpent = prettyMs(Date.now() - prevStepStart, {
      secDecimalDigits: 2,
    })
    currentProgress.text = `[100%] ${prevStep} (${timeSpent})`
    currentProgress.succeed()
  }

  currentProgress = ora(`[0%] ${opts.step} (0.00s)`).start()

  if (!lengthComputable) {
    spinInterval = setInterval(() => {
      const timeSpent = prettyMs(Date.now() - prevStepStart, {
        secDecimalDigits: 2,
      })
      currentProgress.text = `${percent}${opts.step} (${timeSpent})`
      currentProgress.render()
    }, 60)
  }
}

function getPercentage(opts) {
  if (!opts.total) {
    return ''
  }

  const percent = Math.floor((opts.current / opts.total) * 100)
  return `[${percent}%] `
}
<commit_msg>fix(import-cli): fix file asset urls not working with ndjson target<commit_after>#!/usr/bin/env node

/* eslint-disable id-length, no-console, no-process-env */
const fs = require('fs')
const path = require('path')
const ora = require('ora')
const getIt = require('get-it')
const {promise} = require('get-it/middleware')
const meow = require('meow')
const prettyMs = require('pretty-ms')
const sanityClient = require('@sanity/client')
const sanityImport = require('@sanity/import')

const red = (str) => `\u001b[31m${str}\u001b[39m`
const yellow = (str) => `\u001b[33m${str}\u001b[39m`
const printError = (str) => console.error(red(`ERROR: ${str}`))

const cli = meow(
  `
  Usage
    $ sanity-import -p <projectId> -d <dataset> -t <token> sourceFile.ndjson

  Options
    -p, --project <projectId> Project ID to import to
    -d, --dataset <dataset> Dataset to import to
    -t, --token <token> Token to authenticate with
    --asset-concurrency <concurrency> Number of parallel asset imports
    --replace Replace documents with the same IDs
    --missing Skip documents that already exist
    --allow-failing-assets Skip assets that cannot be fetched/uploaded
    --replace-assets Skip reuse of existing assets
    --help Show this help

  Rarely used options (should generally not be used)
    --allow-assets-in-different-dataset Allow asset documents to reference different project/dataset

  Examples
    # Import "./my-dataset.ndjson" into dataset "staging"
    $ sanity-import -p myPrOj -d staging -t someSecretToken my-dataset.ndjson

    # Import into dataset "test" from stdin, read token from env var
    $ cat my-dataset.ndjson | sanity-import -p myPrOj -d test -

  Environment variables (fallbacks for missing flags)
    --token = SANITY_IMPORT_TOKEN
`,
  {
    flags: {
      // Required, but validated below for better error output
      project: {
        type: 'string',
        alias: 'p',
      },

      dataset: {
        type: 'string',
        alias: 'd',
      },

      token: {
        type: 'string',
        alias: 't',
      },

      // Optional
      replace: {
        type: 'boolean',
        default: false,
      },

      missing: {
        type: 'boolean',
        default: false,
      },

      allowFailingAssets: {
        type: 'boolean',
        default: false,
      },

      allowAssetsInDifferentDataset: {
        type: 'boolean',
        default: false,
      },

      replaceAssets: {
        type: 'boolean',
        default: false,
      },

      assetConcurrency: {
        type: 'number',
        alias: 'c',
      },
    },
  }
)

const {flags, input, showHelp} = cli
const {dataset, allowFailingAssets, replaceAssets, allowAssetsInDifferentDataset} = flags
const token = flags.token || process.env.SANITY_IMPORT_TOKEN
const projectId = flags.project
const assetConcurrency = flags.assetConcurrency
const source = input[0]

if (!projectId) {
  printError('Flag `--project` is required')
  showHelp()
}

if (!dataset) {
  printError('Flag `--dataset` is required')
  showHelp()
}

if (!token) {
  printError('Flag `--token` is required (or set SANITY_IMPORT_TOKEN)')
  showHelp()
}

if (!source) {
  printError('Source file is required, use `-` to read from stdin')
  showHelp()
}

let operation = 'create'
if (flags.replace || flags.missing) {
  if (flags.replace && flags.missing) {
    printError('Cannot use both `--replace` and `--missing`')
    showHelp()
  }

  operation = flags.replace ? 'createOrReplace' : 'createIfNotExists'
}

let currentStep
let currentProgress
let stepStart
let spinInterval

const client = sanityClient({
  apiVersion: '1',
  projectId,
  dataset,
  token,
  useCdn: false,
})

getStream()
  .then((stream) =>
    sanityImport(stream, {
      client,
      operation,
      onProgress,
      allowFailingAssets,
      allowAssetsInDifferentDataset,
      assetConcurrency,
      replaceAssets,
      assetsBase: getAssetsBase(),
    })
  )
  .then(({numDocs, warnings}) => {
    const timeSpent = prettyMs(Date.now() - stepStart, {secondsDecimalDigits: 2})
    currentProgress.text = `[100%] ${currentStep} (${timeSpent})`
    currentProgress.succeed()

    console.log('Done! Imported %d documents to dataset "%s"\n', numDocs, dataset)
    printWarnings(warnings)
  })
  .catch((err) => {
    if (currentProgress) {
      currentProgress.fail()
    }

    printError(err.stack)
  })

function printWarnings(warnings) {
  const assetFails = warnings.filter((warn) => warn.type === 'asset')

  if (!assetFails.length) {
    return
  }

  console.warn(
    yellow('⚠ Failed to import the following %s:'),
    assetFails.length > 1 ? 'assets' : 'asset'
  )

  warnings.forEach((warning) => {
    console.warn(`  ${warning.url}`)
  })
}

function getStream() {
  if (/^https:\/\//i.test(source)) {
    return getUriStream(source)
  }

  return Promise.resolve(source === '-' ? process.stdin : fs.createReadStream(source))
}

function getAssetsBase() {
  if (/^https:\/\//i.test(source) || source === '-') {
    return undefined
  }

  try {
    const fileStats = fs.statSync(source)
    const sourceIsFolder = fileStats.isDirectory()
    return sourceIsFolder ? source : path.dirname(source)
  } catch {
    return undefined
  }
}

function getUriStream(uri) {
  const get = getIt([promise()])
  return get({url: uri, stream: true}).then(
    (res) => {
      if (res.statusCode !== 200) {
        throw new Error(`Error fetching source: HTTP ${res.statusCode}`)
      }

      return res.body
    },
    (err) => {
      throw new Error(`Error fetching source:\n${err.message}`)
    }
  )
}

function onProgress(opts) {
  const lengthComputable = opts.total
  const sameStep = opts.step == currentStep
  const percent = getPercentage(opts)

  if (lengthComputable && opts.total === opts.current) {
    clearInterval(spinInterval)
    spinInterval = null
  }

  if (sameStep && !lengthComputable) {
    return
  }

  if (sameStep) {
    const timeSpent = prettyMs(Date.now() - stepStart, {secDecimalDigits: 2})
    currentProgress.text = `${percent}${opts.step} (${timeSpent})`
    currentProgress.render()
    return
  }

  // Moved to a new step
  const prevStep = currentStep
  const prevStepStart = stepStart
  stepStart = Date.now()
  currentStep = opts.step

  if (spinInterval) {
    clearInterval(spinInterval)
    spinInterval = null
  }

  if (currentProgress && currentProgress.succeed) {
    const timeSpent = prettyMs(Date.now() - prevStepStart, {
      secDecimalDigits: 2,
    })
    currentProgress.text = `[100%] ${prevStep} (${timeSpent})`
    currentProgress.succeed()
  }

  currentProgress = ora(`[0%] ${opts.step} (0.00s)`).start()

  if (!lengthComputable) {
    spinInterval = setInterval(() => {
      const timeSpent = prettyMs(Date.now() - prevStepStart, {
        secDecimalDigits: 2,
      })
      currentProgress.text = `${percent}${opts.step} (${timeSpent})`
      currentProgress.render()
    }, 60)
  }
}

function getPercentage(opts) {
  if (!opts.total) {
    return ''
  }

  const percent = Math.floor((opts.current / opts.total) * 100)
  return `[${percent}%] `
}
<|endoftext|>


<commit_before>/*
Key mappings from input id names to corresponding reducer state
*/
// TODO: there's probably a way to do this programmatically instead of relying
//       on literals. Need to import '/reducers/defaults'
export default {
  showTabCountBadgeText: 'general.showTabCountBadgeText',
  showRecentlyClosed: 'general.showRecentlyClosed',
  searchAllWindows: 'general.searchAllWindows',
  alwaysShowRecentlyClosedAtTheBottom: 'general.alwaysShowRecentlyClosedAtTheBottom',
  recentlyClosedLimit: 'general.recentlyClosedLimit',
  enableOverlay: 'general.enableOverlay',
  useFallbackFont: 'general.useFallbackFont',
  enableFuzzySearch: 'fuzzy.enableFuzzySearch',
  shouldSort: 'fuzzy.shouldSort',
  threshold: 'fuzzy.threshold',
  showUrls: 'fuzzy.keys', // Modifies 'keys'
};

<commit_msg>Get reducer paths programmatically<commit_after>/*
Key mappings from input id names to corresponding reducer state.
This works as long as these two reducers are only a flat 1-level object
*/
import {
  initialFuzzySettings,
  initialGeneralSettings,
} from 'core/reducers/defaults';

const settingSkeleton = {
  fuzzy: Object.keys(initialFuzzySettings),
  general: Object.keys(initialGeneralSettings),
};

/*
1. Map (x -> 'fuzzy.' + x)

[
  enableFuzzySearch,
  shouldSort,
  threshold,
  maxPatternLength,
  minMatchCharLength,
  keys
]
*/

const skeleton = {
  fuzzy: Object.keys(initialFuzzySettings),
  general: Object.keys(initialGeneralSettings),
};

export default Object.keys(skeleton).reduce((acc, keyPrefix) => {
  const values = skeleton[keyPrefix];
  return Object.assign(
    {},
    acc,
    values.reduce((settingAcc, setting) => {
      // In the form showUrls is in charge of changing the 'keys' prop in reducer
      const settingKey = (setting !== 'keys')
        ? setting
        : 'showUrls';
      return Object.assign(
        {},
        settingAcc,
        { [settingKey]: `${keyPrefix}.${setting}` },
      );
    }, {}),
  );
}, {});

// export default {
//   showLastQueryOnPopup: 'general.showLastQueryOnPopup',
//   showTabCountBadgeText: 'general.showTabCountBadgeText',
//   showRecentlyClosed: 'general.showRecentlyClosed',
//   searchAllWindows: 'general.searchAllWindows',
//   alwaysShowRecentlyClosedAtTheBottom: 'general.alwaysShowRecentlyClosedAtTheBottom',
//   recentlyClosedLimit: 'general.recentlyClosedLimit',
//   enableOverlay: 'general.enableOverlay',
//   useFallbackFont: 'general.useFallbackFont',
//   enableFuzzySearch: 'fuzzy.enableFuzzySearch',
//   shouldSort: 'fuzzy.shouldSort',
//   threshold: 'fuzzy.threshold',
//   showUrls: 'fuzzy.keys', // Modifies 'keys'
// };
<|endoftext|>


<commit_before>require({
           packages: [
               { name: 'jqueryui', location: '../plugins/WebApollo/jslib/jqueryui' },
               { name: 'jquery', location: '../plugins/WebApollo/jslib/jquery', main: 'jquery' }
           ]
       },
       [],
       function() {

define.amd.jQuery = true;

define(
       [
           'dojo/_base/declare',
           'dijit/MenuItem',
           'dijit/MenuSeparator',
           'dijit/CheckedMenuItem',
           'dijit/form/DropDownButton',
           'dijit/DropDownMenu',
           'dijit/form/Button',
           'JBrowse/Plugin',
           './FeatureEdgeMatchManager',
	   './FeatureSelectionManager',
           './TrackConfigTransformer',
	   './View/Track/AnnotTrack',
           'JBrowse/View/FileDialog/TrackList/GFF3Driver'
       ],
    function( declare, dijitMenuItem, dijitMenuSeparator, dijitCheckedMenuItem, dijitDropDownButton, dijitDropDownMenu, dijitButton, JBPlugin,
              FeatureEdgeMatchManager, FeatureSelectionManager, TrackConfigTransformer, AnnotTrack, GFF3Driver ) {

return declare( JBPlugin,
{
//    colorCdsByFrame: false,
//    searchMenuInitialized: false,

    constructor: function( args ) {
        var thisB = this;
        this.colorCdsByFrame = false;
        this.searchMenuInitialized = false;
        var browser = this.browser;  // this.browser set in Plugin superclass constructor

        args.cssLoaded.then( function() {
            if (! browser.config.view) { browser.config.view = {}; }
            browser.config.view.maxPxPerBp = thisB.getSequenceCharacterSize().width;
        } );

        if (! browser.config.helpUrl)  {
	    browser.config.helpUrl = "http://genomearchitect.org/webapollo/docs/help.html";
        }

        // hand the browser object to the feature edge match manager
        FeatureEdgeMatchManager.setBrowser( browser );

	this.featSelectionManager = new FeatureSelectionManager();
	this.annotSelectionManager = new FeatureSelectionManager();
        this.trackTransformer = new TrackConfigTransformer();

	// setting up selection exclusiveOr --
	//    if selection is made in annot track, any selection in other tracks is deselected, and vice versa,
	//    regardless of multi-select mode etc.
	this.annotSelectionManager.addMutualExclusion(this.featSelectionManager);
	this.featSelectionManager.addMutualExclusion(this.annotSelectionManager);

	FeatureEdgeMatchManager.addSelectionManager(this.featSelectionManager);
	FeatureEdgeMatchManager.addSelectionManager(this.annotSelectionManager);

        // add a global menu option for setting CDS color
        var cds_frame_toggle = new dijitCheckedMenuItem(
                {
                    label: "Color by CDS frame",
                    checked: false,
                    onClick: function(event) {
                        thisB.colorCdsByFrame = cds_frame_toggle.checked;
                        browser.view.redrawTracks();
                    }
                });
        browser.addGlobalMenuItem( 'view', cds_frame_toggle );

        this.addStrandFilterOptions();

        // register the WebApollo track types with the browser, so
        // that the open-file dialog and other things will have them
        // as options
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/DraggableHTMLFeatures',
            defaultForStoreTypes: [ 'JBrowse/Store/SeqFeature/NCList',
                                    'JBrowse/Store/SeqFeature/GFF3',
                                    'WebApollo/Store/SeqFeature/ApolloGFF3'
                                  ],
            label: 'WebApollo Features'
        });
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/DraggableAlignments',
            defaultForStoreTypes: [
                                    'JBrowse/Store/SeqFeature/BAM',
                                  ],
            label: 'WebApollo Alignments'
        });
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/SequenceTrack',
            defaultForStoreTypes: [ 'JBrowse/Store/Sequence/StaticChunked' ],
            label: 'WebApollo Sequence'
        });

        // transform track configs from vanilla JBrowse to WebApollo:
        // type: "JBrowse/View/Track/HTMLFeatures" ==> "WebApollo/View/Track/DraggableHTMLFeatures"
        //
        var track_configs = browser.config.tracks;
        for (var i=0; i<track_configs.length; i++)  {
            var track_config = track_configs[i];
            this.trackTransformer.transform(track_config);
        }

        // put the WebApollo logo in the powered_by place in the main JBrowse bar
        browser.afterMilestone( 'initView', function() {
            if (browser.poweredByLink)  {
                browser.poweredByLink.innerHTML = '';
                browser.poweredByLink.href = 'http://www.gmod.org/wiki/WebApollo';
                browser.poweredByLink.target = "_blank";
            }
        });

        var customGff3Driver = dojo.declare("ApolloGFF3Driver", GFF3Driver,   {
            constructor: function( args ) {
                this.storeType = 'WebApollo/Store/SeqFeature/ApolloGFF3';
            }
        } );
        browser.registerExtraFileDriver(customGff3Driver);
    },

    plusStrandFilter: function(feature)  {
        var strand = feature.get('strand');
        if (strand == 1 || strand == '+')  { return true; }
        else  { return false; }
    },

    minusStrandFilter: function(feature)  {
        var strand = feature.get('strand');
        if (strand == -1 || strand == '-')  { return true; }
        else  { return false; }
    },
    passAllFilter: function(feature)  {  return true; },
    passNoneFilter: function(feature)  { return false; },

    addStrandFilterOptions: function()  {
        var thisB = this;
        var browser = this.browser;
        var plus_strand_toggle = new dijitCheckedMenuItem(
                {
                    label: "Show plus strand",
                    checked: true,
                    onClick: function(event) {
                        var plus = plus_strand_toggle.checked;
                        var minus = minus_strand_toggle.checked;
                        console.log("plus: ", plus, " minus: ", minus);
                        if (plus && minus)  {
                            browser.setFeatureFilter(thisB.passAllFilter);
                        }
                        else if (plus)  {
                            browser.setFeatureFilter(thisB.plusStrandFilter);
                        }
                        else if (minus)  {
                            browser.setFeatureFilter(thisB.minusStrandFilter);
                        }
                        else  {
                            browser.setFeatureFilter(thisB.passNoneFilter);
                        }
                        browser.view.redrawTracks();
                    }
                });
        browser.addGlobalMenuItem( 'view', plus_strand_toggle );
        var minus_strand_toggle = new dijitCheckedMenuItem(
                {
                    label: "Show minus strand",
                    checked: true,
                    onClick: function(event) {
                        var plus = plus_strand_toggle.checked;
                        var minus = minus_strand_toggle.checked;
                        console.log("plus: ", plus, " minus: ", minus);
                        if (plus && minus)  {
                            browser.setFeatureFilter(thisB.passAllFilter);
                        }
                        else if (plus)  {
                            browser.setFeatureFilter(thisB.plusStrandFilter);
                        }
                        else if (minus)  {
                            browser.setFeatureFilter(thisB.minusStrandFilter);
                        }
                        else  {
                            browser.setFeatureFilter(thisB.passNoneFilter);
                        }
                        browser.view.redrawTracks();
                        }
                });
        browser.addGlobalMenuItem( 'view', minus_strand_toggle );
        browser.addGlobalMenuItem( 'view', new dijitMenuSeparator());
    },

/**
 * hacking addition of a "tools" menu to standard JBrowse menubar,
 *    with a "Search Sequence" dropdown
 */
    initSearchMenu: function()  {
        if (! this.searchMenuInitialized) {
            var webapollo = this;
            this.browser.addGlobalMenuItem( 'tools',
                                            new dijitMenuItem(
                                                {
		                                    label: "Search sequence",
		                                    onClick: function() {
		                                        webapollo.getAnnotTrack().searchSequence();
		                                    }
                                                }) );
            var toolMenu = this.browser.makeGlobalMenu('tools');
            if( toolMenu ) {
                var toolButton = new dijitDropDownButton(
                    { className: 'file',
                      innerHTML: 'Tools',
                      //title: '',
                      dropDown: toolMenu
                    });
                dojo.addClass( toolButton.domNode, 'menu' );
                this.browser.menuBar.appendChild( toolButton.domNode );
            }
        }
        this.searchMenuInitialized = true;
    },

    initLoginMenu: function(username) {
    	var webapollo = this;
    	var loginButton;
    	if (username)  {   // permission only set if permission request succeeded
    		this.browser.addGlobalMenuItem( 'user',
    				new dijitMenuItem(
    						{
    							label: 'Logout',
    							onClick: function()  {
    								webapollo.getAnnotTrack().logout();
    							}
    						})
    		);
    		var userMenu = this.browser.makeGlobalMenu('user');
    		loginButton = new dijitDropDownButton(
    				{ className: 'user',
    					innerHTML: '' + username,
    					title: 'user logged in: UserName',
    					dropDown: userMenu
    				});
    		// if add 'menu' class, button will be placed on left side of menubar instead (because of 'float: left'
    		//     styling in CSS rule for 'menu' class
    		// dojo.addClass( loginButton.domNode, 'menu' );
    	}
    	else  {
    		loginButton = new dijitButton(
    				{ className: 'login',
    					innerHTML: "Login",
    					onClick: function()  {
    						webapollo.getAnnotTrack().login();
    					}
    				});
    	}
    	this.browser.menuBar.appendChild( loginButton.domNode );
    	this.loginMenuInitialized = true;
    },

    /**
     *  get the GenomeView's user annotation track
     *  WebApollo assumes there is only one AnnotTrack
     *     if there are multiple AnnotTracks, getAnnotTrack returns first one found
     *         iterating through tracks list
     */
    getAnnotTrack: function()  {
        if (this.browser && this.browser.view && this.browser.view.tracks)  {
            var tracks = this.browser.view.tracks;
            for (var i = 0; i < tracks.length; i++)  {
	        // should be doing instanceof here, but class setup is not being cooperative
                if (tracks[i].isWebApolloAnnotTrack)  {
                    console.log("annot track refseq: " + tracks[i].refSeq.name);
                    return tracks[i];
                }
            }
        }
        return null;
    },

    /**
     *  get the GenomeView's sequence track
     *  WebApollo assumes there is only one SequenceTrack
     *     if there are multiple SequenceTracks, getSequenceTrack returns first one found
     *         iterating through tracks list
     */
    getSequenceTrack: function()  {
        if (this.browser && this.browser.view && this.browser.view.tracks)  {
            var tracks = this.browser.view.tracks;
            for (var i = 0; i < tracks.length; i++)  {
	        // should be doing instanceof here, but class setup is not being cooperative
                if (tracks[i].isWebApolloSequenceTrack)  {
                    // console.log("seq track refseq: " + tracks[i].refSeq.name);
                    return tracks[i];
                }
            }
        }
        return null;
    },

    /** ported from berkeleybop/jbrowse GenomeView.js
      * returns char height/width on GenomeView
      */
    getSequenceCharacterSize: function()  {
        var container = this.browser.container;
        if (this.browser.view && this.browser.view.elem)  {
            container = this.browser.view.elem;
        }
        if (! this._charSize)  {
            //	    this._charSize = this.calculateSequenceCharacterSize(this.browser.view.elem);
	    this._charSize = this.calculateSequenceCharacterSize(container);
        }
        return this._charSize;
    },

    /**
     * ported from berkeleybop/jbrowse GenomeView.js
     * Conducts a test with DOM elements to measure sequence text width
     * and height.
     */
    calculateSequenceCharacterSize: function( containerElement ) {
        var widthTest = document.createElement("div");
        widthTest.className = "wa-sequence";
        widthTest.style.visibility = "hidden";
        var widthText = "12345678901234567890123456789012345678901234567890";
        widthTest.appendChild(document.createTextNode(widthText));
        containerElement.appendChild(widthTest);

        var result = {
            width:  widthTest.clientWidth / widthText.length,
            height: widthTest.clientHeight
        };

        containerElement.removeChild(widthTest);
        return result;
    },

    /** utility function, given an array with objects that have label props,
     *        return array with all objects that don't have label
     *   D = [ { label: A }, { label: B}, { label: C } ]
     *   E = D.removeItemWithLabel("B");
     *   E ==> [ { label: A }, { label: C } ]
     */
    removeItemWithLabel: function(inarray, label) {
        var outarray = [];
        for (var i=0; i<inarray.length; i++) {
            var obj = inarray[i];
            if (! (obj.label && (obj.label === label))) {
                outarray.push(obj);
            }
        }
        return outarray;
    }

});

});

});<commit_msg>Turning off "About JBrowse" popup when clicking on poweredByLink, conflicts with jump to WebApollo wiki.  Plan to preserve "About Jbrowse" popup in Help->"About JBrowse" ?<commit_after>require({
           packages: [
               { name: 'jqueryui', location: '../plugins/WebApollo/jslib/jqueryui' },
               { name: 'jquery', location: '../plugins/WebApollo/jslib/jquery', main: 'jquery' }
           ]
       },
       [],
       function() {

define.amd.jQuery = true;

define(
       [
           'dojo/_base/declare',
           'dijit/MenuItem',
           'dijit/MenuSeparator',
           'dijit/CheckedMenuItem',
           'dijit/form/DropDownButton',
           'dijit/DropDownMenu',
           'dijit/form/Button',
           'JBrowse/Plugin',
           './FeatureEdgeMatchManager',
	   './FeatureSelectionManager',
           './TrackConfigTransformer',
	   './View/Track/AnnotTrack',
           'JBrowse/View/FileDialog/TrackList/GFF3Driver'
       ],
    function( declare, dijitMenuItem, dijitMenuSeparator, dijitCheckedMenuItem, dijitDropDownButton, dijitDropDownMenu, dijitButton, JBPlugin,
              FeatureEdgeMatchManager, FeatureSelectionManager, TrackConfigTransformer, AnnotTrack, GFF3Driver ) {

return declare( JBPlugin,
{
//    colorCdsByFrame: false,
//    searchMenuInitialized: false,

    constructor: function( args ) {
        var thisB = this;
        this.colorCdsByFrame = false;
        this.searchMenuInitialized = false;
        var browser = this.browser;  // this.browser set in Plugin superclass constructor

        args.cssLoaded.then( function() {
            if (! browser.config.view) { browser.config.view = {}; }
            browser.config.view.maxPxPerBp = thisB.getSequenceCharacterSize().width;
        } );

        if (! browser.config.helpUrl)  {
	    browser.config.helpUrl = "http://genomearchitect.org/webapollo/docs/help.html";
        }

        // hand the browser object to the feature edge match manager
        FeatureEdgeMatchManager.setBrowser( browser );

	this.featSelectionManager = new FeatureSelectionManager();
	this.annotSelectionManager = new FeatureSelectionManager();
        this.trackTransformer = new TrackConfigTransformer();

	// setting up selection exclusiveOr --
	//    if selection is made in annot track, any selection in other tracks is deselected, and vice versa,
	//    regardless of multi-select mode etc.
	this.annotSelectionManager.addMutualExclusion(this.featSelectionManager);
	this.featSelectionManager.addMutualExclusion(this.annotSelectionManager);

	FeatureEdgeMatchManager.addSelectionManager(this.featSelectionManager);
	FeatureEdgeMatchManager.addSelectionManager(this.annotSelectionManager);

        // add a global menu option for setting CDS color
        var cds_frame_toggle = new dijitCheckedMenuItem(
                {
                    label: "Color by CDS frame",
                    checked: false,
                    onClick: function(event) {
                        thisB.colorCdsByFrame = cds_frame_toggle.checked;
                        browser.view.redrawTracks();
                    }
                });
        browser.addGlobalMenuItem( 'view', cds_frame_toggle );

        this.addStrandFilterOptions();

        // register the WebApollo track types with the browser, so
        // that the open-file dialog and other things will have them
        // as options
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/DraggableHTMLFeatures',
            defaultForStoreTypes: [ 'JBrowse/Store/SeqFeature/NCList',
                                    'JBrowse/Store/SeqFeature/GFF3',
                                    'WebApollo/Store/SeqFeature/ApolloGFF3'
                                  ],
            label: 'WebApollo Features'
        });
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/DraggableAlignments',
            defaultForStoreTypes: [
                                    'JBrowse/Store/SeqFeature/BAM',
                                  ],
            label: 'WebApollo Alignments'
        });
        browser.registerTrackType({
            type:                 'WebApollo/View/Track/SequenceTrack',
            defaultForStoreTypes: [ 'JBrowse/Store/Sequence/StaticChunked' ],
            label: 'WebApollo Sequence'
        });

        // transform track configs from vanilla JBrowse to WebApollo:
        // type: "JBrowse/View/Track/HTMLFeatures" ==> "WebApollo/View/Track/DraggableHTMLFeatures"
        //
        var track_configs = browser.config.tracks;
        for (var i=0; i<track_configs.length; i++)  {
            var track_config = track_configs[i];
            this.trackTransformer.transform(track_config);
        }

        // put the WebApollo logo in the powered_by place in the main JBrowse bar
        browser.afterMilestone( 'initView', function() {
            if (browser.poweredByLink)  {
                dojo.disconnect(browser.poweredBy_clickHandle);
                browser.poweredByLink.innerHTML = '';
                browser.poweredByLink.href = 'http://www.gmod.org/wiki/WebApollo';
                browser.poweredByLink.target = "_blank";
            }
        });

        var customGff3Driver = dojo.declare("ApolloGFF3Driver", GFF3Driver,   {
            constructor: function( args ) {
                this.storeType = 'WebApollo/Store/SeqFeature/ApolloGFF3';
            }
        } );
        browser.registerExtraFileDriver(customGff3Driver);
    },

    plusStrandFilter: function(feature)  {
        var strand = feature.get('strand');
        if (strand == 1 || strand == '+')  { return true; }
        else  { return false; }
    },

    minusStrandFilter: function(feature)  {
        var strand = feature.get('strand');
        if (strand == -1 || strand == '-')  { return true; }
        else  { return false; }
    },
    passAllFilter: function(feature)  {  return true; },
    passNoneFilter: function(feature)  { return false; },

    addStrandFilterOptions: function()  {
        var thisB = this;
        var browser = this.browser;
        var plus_strand_toggle = new dijitCheckedMenuItem(
                {
                    label: "Show plus strand",
                    checked: true,
                    onClick: function(event) {
                        var plus = plus_strand_toggle.checked;
                        var minus = minus_strand_toggle.checked;
                        console.log("plus: ", plus, " minus: ", minus);
                        if (plus && minus)  {
                            browser.setFeatureFilter(thisB.passAllFilter);
                        }
                        else if (plus)  {
                            browser.setFeatureFilter(thisB.plusStrandFilter);
                        }
                        else if (minus)  {
                            browser.setFeatureFilter(thisB.minusStrandFilter);
                        }
                        else  {
                            browser.setFeatureFilter(thisB.passNoneFilter);
                        }
                        browser.view.redrawTracks();
                    }
                });
        browser.addGlobalMenuItem( 'view', plus_strand_toggle );
        var minus_strand_toggle = new dijitCheckedMenuItem(
                {
                    label: "Show minus strand",
                    checked: true,
                    onClick: function(event) {
                        var plus = plus_strand_toggle.checked;
                        var minus = minus_strand_toggle.checked;
                        console.log("plus: ", plus, " minus: ", minus);
                        if (plus && minus)  {
                            browser.setFeatureFilter(thisB.passAllFilter);
                        }
                        else if (plus)  {
                            browser.setFeatureFilter(thisB.plusStrandFilter);
                        }
                        else if (minus)  {
                            browser.setFeatureFilter(thisB.minusStrandFilter);
                        }
                        else  {
                            browser.setFeatureFilter(thisB.passNoneFilter);
                        }
                        browser.view.redrawTracks();
                        }
                });
        browser.addGlobalMenuItem( 'view', minus_strand_toggle );
        browser.addGlobalMenuItem( 'view', new dijitMenuSeparator());
    },

/**
 * hacking addition of a "tools" menu to standard JBrowse menubar,
 *    with a "Search Sequence" dropdown
 */
    initSearchMenu: function()  {
        if (! this.searchMenuInitialized) {
            var webapollo = this;
            this.browser.addGlobalMenuItem( 'tools',
                                            new dijitMenuItem(
                                                {
		                                    label: "Search sequence",
		                                    onClick: function() {
		                                        webapollo.getAnnotTrack().searchSequence();
		                                    }
                                                }) );
            var toolMenu = this.browser.makeGlobalMenu('tools');
            if( toolMenu ) {
                var toolButton = new dijitDropDownButton(
                    { className: 'file',
                      innerHTML: 'Tools',
                      //title: '',
                      dropDown: toolMenu
                    });
                dojo.addClass( toolButton.domNode, 'menu' );
                this.browser.menuBar.appendChild( toolButton.domNode );
            }
        }
        this.searchMenuInitialized = true;
    },

    initLoginMenu: function(username) {
    	var webapollo = this;
    	var loginButton;
    	if (username)  {   // permission only set if permission request succeeded
    		this.browser.addGlobalMenuItem( 'user',
    				new dijitMenuItem(
    						{
    							label: 'Logout',
    							onClick: function()  {
    								webapollo.getAnnotTrack().logout();
    							}
    						})
    		);
    		var userMenu = this.browser.makeGlobalMenu('user');
    		loginButton = new dijitDropDownButton(
    				{ className: 'user',
    					innerHTML: '' + username,
    					title: 'user logged in: UserName',
    					dropDown: userMenu
    				});
    		// if add 'menu' class, button will be placed on left side of menubar instead (because of 'float: left'
    		//     styling in CSS rule for 'menu' class
    		// dojo.addClass( loginButton.domNode, 'menu' );
    	}
    	else  {
    		loginButton = new dijitButton(
    				{ className: 'login',
    					innerHTML: "Login",
    					onClick: function()  {
    						webapollo.getAnnotTrack().login();
    					}
    				});
    	}
    	this.browser.menuBar.appendChild( loginButton.domNode );
    	this.loginMenuInitialized = true;
    },

    /**
     *  get the GenomeView's user annotation track
     *  WebApollo assumes there is only one AnnotTrack
     *     if there are multiple AnnotTracks, getAnnotTrack returns first one found
     *         iterating through tracks list
     */
    getAnnotTrack: function()  {
        if (this.browser && this.browser.view && this.browser.view.tracks)  {
            var tracks = this.browser.view.tracks;
            for (var i = 0; i < tracks.length; i++)  {
	        // should be doing instanceof here, but class setup is not being cooperative
                if (tracks[i].isWebApolloAnnotTrack)  {
                    console.log("annot track refseq: " + tracks[i].refSeq.name);
                    return tracks[i];
                }
            }
        }
        return null;
    },

    /**
     *  get the GenomeView's sequence track
     *  WebApollo assumes there is only one SequenceTrack
     *     if there are multiple SequenceTracks, getSequenceTrack returns first one found
     *         iterating through tracks list
     */
    getSequenceTrack: function()  {
        if (this.browser && this.browser.view && this.browser.view.tracks)  {
            var tracks = this.browser.view.tracks;
            for (var i = 0; i < tracks.length; i++)  {
	        // should be doing instanceof here, but class setup is not being cooperative
                if (tracks[i].isWebApolloSequenceTrack)  {
                    // console.log("seq track refseq: " + tracks[i].refSeq.name);
                    return tracks[i];
                }
            }
        }
        return null;
    },

    /** ported from berkeleybop/jbrowse GenomeView.js
      * returns char height/width on GenomeView
      */
    getSequenceCharacterSize: function()  {
        var container = this.browser.container;
        if (this.browser.view && this.browser.view.elem)  {
            container = this.browser.view.elem;
        }
        if (! this._charSize)  {
            //	    this._charSize = this.calculateSequenceCharacterSize(this.browser.view.elem);
	    this._charSize = this.calculateSequenceCharacterSize(container);
        }
        return this._charSize;
    },

    /**
     * ported from berkeleybop/jbrowse GenomeView.js
     * Conducts a test with DOM elements to measure sequence text width
     * and height.
     */
    calculateSequenceCharacterSize: function( containerElement ) {
        var widthTest = document.createElement("div");
        widthTest.className = "wa-sequence";
        widthTest.style.visibility = "hidden";
        var widthText = "12345678901234567890123456789012345678901234567890";
        widthTest.appendChild(document.createTextNode(widthText));
        containerElement.appendChild(widthTest);

        var result = {
            width:  widthTest.clientWidth / widthText.length,
            height: widthTest.clientHeight
        };

        containerElement.removeChild(widthTest);
        return result;
    },

    /** utility function, given an array with objects that have label props,
     *        return array with all objects that don't have label
     *   D = [ { label: A }, { label: B}, { label: C } ]
     *   E = D.removeItemWithLabel("B");
     *   E ==> [ { label: A }, { label: C } ]
     */
    removeItemWithLabel: function(inarray, label) {
        var outarray = [];
        for (var i=0; i<inarray.length; i++) {
            var obj = inarray[i];
            if (! (obj.label && (obj.label === label))) {
                outarray.push(obj);
            }
        }
        return outarray;
    }

});

});

});<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile<commit_msg>Work in Progress<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile,<|endoftext|>


<commit_before>// Karma configuration
// Generated on Thu Dec 29 2016 18:10:21 GMT-0200 (Horário brasileiro de verão)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
    ],

    // list of files to exclude
    exclude: [
      'test/unit/specs/*.spec.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    //reporters: ['progress'],
    reporters: ['kjhtml'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Firefox'], //to run in travis
    //browsers: ['Chrome'], //to run in locally

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<commit_msg>implementing scrutinizer<commit_after>// Karma configuration
// Generated on Thu Dec 29 2016 18:10:21 GMT-0200 (Horário brasileiro de verão)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'test/unit/specs/*.spec.js'
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    //reporters: ['progress'],
    reporters: ['kjhtml'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Firefox'], //to run in travis
    //browsers: ['Chrome'], //to run in locally

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}
<|endoftext|>


<commit_before>'use strict';

angular.module('mean').controller('ArticlesController', ['$scope', '$stateParams', '$location', 'Global', 'Articles',
    function($scope, $stateParams, $location, Global, Articles) {
        $scope.global = Global;

        $scope.hasAuthorization = function(article) {
            if (!article || !article.user) return false;
            return $scope.global.isAdmin || article.user._id === $scope.global.user._id;
        };

				$scope.wholeNumbers = [
					{value: 0},
					{value: 1},
					{value: 2},
					{value: 3},
					{value: 4},
					{value: 5},
					{value: 6},
					{value: 7},
					{value: 8},
					{value: 9},
					{value: 10},
					{value: 11},
					{value: 12}
				];

				$scope.measurements = [
					{name: 'tablespoon(s)'},
					{name: 'teaspoon(s)'},
					{name: 'cup(s)'},
					{name: 'fluid ounce(s)'},
					{name: 'pint(s)'},
					{name: 'quart(s)'},
					{name: 'gallon(s)'},
					{name: 'ounce(s)'},
					{name: 'mililiter(s)'},
					{name: 'pound(s)'},
					{name: 'liter(s)'}
				];

				$scope.fractions = [
					{fraction: '0', value: '0'},
					{fraction: '1/16', value: '0.0625'},
				  {fraction: '1/8', value: '0.125'},
				  {fraction: '1/6', value: '0.1667'},
				  {fraction: '3/16', value: '0.1875'},
				  {fraction: '1/4', value: '0.25'},
				  {fraction: '5/16', value: '0.3125'},
				  {fraction: '1/3', value: '0.3333'},
				  {fraction: '3/8', value: '0.375'},
				  {fraction: '7/16', value: '0.4375'},
				  {fraction: '1/2', value: '0.5'},
				  {fraction: '9/16', value: '0.5625'},
				  {fraction: '5/8', value: '0.625'},
				  {fraction: '2/3', value: '0.667'},
				  {fraction: '11/16', value: '0.6875'},
				  {fraction: '3/4', value: '0.75'},
				  {fraction: '13/16', value: '0.8125'},
				  {fraction: '5/6', value: '0.833'},
				  {fraction: '7/8', value: '0.875'},
				  {fraction: '15/16', value: '0.9375'}
				];

        $scope.create = function() {
						// var theingredients = new Ingredients ({
						// 							ingredient: this.ingredient,
						//               amount: this.amount,
						//               measurement: this.measurement
						//
						// 						});

            var article = new Articles({
                title: this.title,
                ingredients: this.ingredients,
                content: this.content
            });
            article.$save(function(response) {
                $location.path('articles/' + response._id);
            });

            this.title = '';
            this.content = '';
            this.ingredient = '';
						this.amount = '';
						this.amountFraction = '';
						this.measurement = '';
        };

        $scope.remove = function(article) {
            if (article) {
                article.$remove();

                for (var i in $scope.articles) {
                    if ($scope.articles[i] === article) {
                        $scope.articles.splice(i, 1);
                    }
                }
            } else {
                $scope.article.$remove(function(response) {
                    $location.path('articles');
                });
            }
        };

        $scope.update = function() {
            var article = $scope.article;
            if (!article.updated) {
                article.updated = [];
            }
            article.updated.push(new Date().getTime());

            article.$update(function() {
                $location.path('articles/' + article._id);
            });
        };

        $scope.find = function() {
            Articles.query(function(articles) {
                $scope.articles = articles;
            });
        };

				$scope.isSelected = function (theSelected, currentItem) {
					if (theSelected === currentItem) {
						return 'selected';
					}
				};

				$scope.createForm = function() {
					$scope.ingredient = {amount : '1'};
				};

				if(typeof $scope.ingredients === 'undefined') {
				    $scope.ingredients = [
					    {ingredient:'', amount: 1, amountFraction: '0', measurement: 'tablespoon(s)'}
					  ];
				  }

				$scope.addIngredient = function () {
					if(typeof $scope.ingredients === 'undefined') {
					    $scope.ingredients = [];
					  }
			    $scope.ingredients.push({ingredient:'', amount: 1, amountFraction: '0', measurement: 'tablespoon(s)'});
			  };

        $scope.findOne = function() {
            Articles.get({
                articleId: $stateParams.articleId
            }, function(article) {
                $scope.article = article;
								$scope.ingredients = article.ingredients;
								//$scope.ingredient.amount = $scope.wholeNumbers[1];
            });
        };
    }
]);
<commit_msg>good commit<commit_after>'use strict';

angular.module('mean').controller('ArticlesController', ['$scope', '$stateParams', '$location', 'Global', 'Articles',
    function($scope, $stateParams, $location, Global, Articles) {
        $scope.global = Global;

        $scope.hasAuthorization = function(article) {
            if (!article || !article.user) return false;
            return $scope.global.isAdmin || article.user._id === $scope.global.user._id;
        };

				$scope.wholeNumbers = [
					{value: 0},
					{value: 1},
					{value: 2},
					{value: 3},
					{value: 4},
					{value: 5},
					{value: 6},
					{value: 7},
					{value: 8},
					{value: 9},
					{value: 10},
					{value: 11},
					{value: 12}
				];

				$scope.measurements = [
					{name: 'tablespoon(s)'},
					{name: 'teaspoon(s)'},
					{name: 'cup(s)'},
					{name: 'fluid ounce(s)'},
					{name: 'pint(s)'},
					{name: 'quart(s)'},
					{name: 'gallon(s)'},
					{name: 'ounce(s)'},
					{name: 'mililiter(s)'},
					{name: 'pound(s)'},
					{name: 'liter(s)'}
				];

				$scope.fractions = [
					{fraction: '0', value: 0},
					{fraction: '1/16', value: 0.0625},
				  {fraction: '1/8', value: 0.125},
				  {fraction: '1/6', value: 0.1667},
				  {fraction: '3/16', value: 0.1875},
				  {fraction: '1/4', value: 0.25},
				  {fraction: '5/16', value: 0.3125},
				  {fraction: '1/3', value: 0.3333},
				  {fraction: '3/8', value: 0.375},
				  {fraction: '7/16', value: 0.4375},
				  {fraction: '1/2', value: 0.5},
				  {fraction: '9/16', value: 0.5625},
				  {fraction: '5/8', value: 0.625},
				  {fraction: '2/3', value: 0.667},
				  {fraction: '11/16', value: 0.6875},
				  {fraction: '3/4', value: 0.75},
				  {fraction: '13/16', value: 0.8125},
				  {fraction: '5/6', value: 0.833},
				  {fraction: '7/8', value: 0.875},
				  {fraction: '15/16', value: 0.9375}
				];

        $scope.create = function() {
						// var theingredients = new Ingredients ({
						// 							ingredient: this.ingredient,
						//               amount: this.amount,
						//               measurement: this.measurement
						//
						// 						});

            var article = new Articles({
                title: this.title,
                ingredients: this.ingredients,
                content: this.content
            });
            article.$save(function(response) {
                $location.path('articles/' + response._id);
            });

            this.title = '';
            this.content = '';
            this.ingredient = '';
						this.amount = '';
						this.amountFraction = '';
						this.measurement = '';
        };

        $scope.remove = function(article) {
            if (article) {
                article.$remove();

                for (var i in $scope.articles) {
                    if ($scope.articles[i] === article) {
                        $scope.articles.splice(i, 1);
                    }
                }
            } else {
                $scope.article.$remove(function(response) {
                    $location.path('articles');
                });
            }
        };

        $scope.update = function() {
            var article = $scope.article;
            if (!article.updated) {
                article.updated = [];
            }
            article.updated.push(new Date().getTime());

            article.$update(function() {
                $location.path('articles/' + article._id);
            });
        };

        $scope.find = function() {
            Articles.query(function(articles) {
                $scope.articles = articles;
            });
        };

				$scope.isSelected = function (theSelected, currentItem) {
					if (theSelected === currentItem) {
						return 'selected';
					}
				};

				$scope.createForm = function() {
					$scope.ingredient = {amount : '1'};
				};

				if(typeof $scope.ingredients === 'undefined') {
				    $scope.ingredients = [
					    {ingredient:'', amount: 1, amountFraction: 0, measurement: 'tablespoon(s)'}
					  ];
				  }

				$scope.addIngredient = function () {
					if(typeof $scope.ingredients === 'undefined') {
					    $scope.ingredients = [];
					  }
			    $scope.ingredients.push({ingredient:'', amount: 1, amountFraction: 0, measurement: 'tablespoon(s)'});
			  };

        $scope.findOne = function() {
            Articles.get({
                articleId: $stateParams.articleId
            }, function(article) {
                $scope.article = article;
								$scope.ingredients = article.ingredients;
								//$scope.ingredient.amount = $scope.wholeNumbers[1];
            });
        };
    }
]);
<|endoftext|>


<commit_before>$(document).ready(function() {
  app.hookupMap();
  app.hookupSteps();
});

var app = app || {};
app.state = {
  channel: 'sms',
  geom: undefined,
  publisher_id: undefined,
  contact: undefined,
};

app.hookupMap = function() {
  var options = {
    zoom: 13,
    center: [47.604432, -122.336014],
    tileLayer: { detectRetina: true },
    scrollWheelZoom: false,
  };
  var mapId = $('meta[name=mapId]').attr('content');
  var map = app.map = L.mapbox.map('map', mapId, options);
};

app.hookupSteps = function() {
  $('.startButton').on('click', function() {
    app.scrollToElement($('#step1'));
  });

  $('.publisher:not(.soon)').on('click', function(event) {
    $('.publisher').removeClass('selected');

    var $publisher = $(event.currentTarget);
    app.state.publisher_id = $publisher.data('publisher-id');
    $publisher.addClass('selected');

    app.scrollToElement($('#step2'));
  });

  $('.mapButton').on('click', function() {
    app.scrollToElement($('#step3'));
  });

  $('.smsButton').on('click', function(event) {
    $(event.target).addClass('selected');
    $('.extraInfo').slideDown();
  });

  var finishSubscribe = function(e) {
    // TODO: animate the done checkmark at the same time
    e.preventDefault();
    app.state.contact = $('.phoneNumber').val();

    app.submitSubscription(function() {
      $('#confirmation').slideDown();
      app.scrollToElement($('#confirmation'));
    });
  };
  $('.subscribeButton').on('click', finishSubscribe);
  $('#subscribeForm').on('submit', finishSubscribe);

  $('.resetButton').on('click', function(event) {
    app.resetState();
    app.scrollToElement($('#step1'));

    // Hide after we've scrolled up.
    setTimeout(function() {
      $('#confirmation').hide();
    }, 800);
  });

  var geolocate = function(e) {
    e.preventDefault();
    var address = $('#geolocate').val();
    app.geocode(address, function(latlng) {
      app.map.setView(latlng, 15);
    });
  };

  $('#geolocateForm').on('submit', geolocate);
  $('.geolocateButton').on('click', geolocate);
};

app.scrollToElement = function(el) {
  $('html,body').animate({
    scrollTop: el.offset().top
  }, 800);
};

app.geocode = function(city, callback, context) {
 var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(city);

 $.getJSON(url, function(response) {
    if (response.error || response.results.length === 0) {
      console.log('Unable to geocode city. Womp Womp.', response.error);
    }

    // Get the coordinates for the center of the city
    var location = response.results[0].geometry.location;
    var latlng = [location.lat, location.lng];
    callback.call(context || this, latlng);
  });
};

app.resetState = function() {

  app.state.publisher_id = undefined;
  $('.publisher').removeClass('selected');

  app.state.geom = undefined;
  if (app.prevLayer) app.map.removeLayer(app.prevLayer);
  // Let's leave the type and phone number in place, for easy re-subscribe
};

app.submitSubscription = function(callback) {
  $.post('/subscriptions', { subscription: app.state }, callback);
};
<commit_msg>Drop a marker when you select your address.<commit_after>$(document).ready(function() {
  app.hookupMap();
  app.hookupSteps();
});

var app = app || {};
app.state = {
  channel: 'sms',
  geom: undefined,
  publisher_id: undefined,
  contact: undefined,
};

app.hookupMap = function() {
  var options = {
    zoom: 13,
    center: [47.604432, -122.336014],
    tileLayer: { detectRetina: true },
    scrollWheelZoom: false,
  };
  var mapId = $('meta[name=mapId]').attr('content');
  var map = app.map = L.mapbox.map('map', mapId, options);
};

app.hookupSteps = function() {
  $('.startButton').on('click', function() {
    app.scrollToElement($('#step1'));
  });

  $('.publisher:not(.soon)').on('click', function(event) {
    $('.publisher').removeClass('selected');

    var $publisher = $(event.currentTarget);
    app.state.publisher_id = $publisher.data('publisher-id');
    $publisher.addClass('selected');

    app.scrollToElement($('#step2'));
  });

  $('.mapButton').on('click', function() {
    app.scrollToElement($('#step3'));
  });

  $('.smsButton').on('click', function(event) {
    $(event.target).addClass('selected');
    $('.extraInfo').slideDown();
  });

  var finishSubscribe = function(e) {
    // TODO: animate the done checkmark at the same time
    e.preventDefault();
    app.state.contact = $('.phoneNumber').val();

    app.submitSubscription(function() {
      $('#confirmation').slideDown();
      app.scrollToElement($('#confirmation'));
    });
  };
  $('.subscribeButton').on('click', finishSubscribe);
  $('#subscribeForm').on('submit', finishSubscribe);

  $('.resetButton').on('click', function(event) {
    app.resetState();
    app.scrollToElement($('#step1'));

    // Hide after we've scrolled up.
    setTimeout(function() {
      $('#confirmation').hide();
    }, 800);
  });

  var prevMarker;
  var geolocate = function(e) {
    e.preventDefault();
    var address = $('#geolocate').val();
    app.geocode(address, function(latlng) {
      app.map.setView(latlng, 15);
      if (prevMarker) app.map.removeLayer(prevMarker);
      prevMarker = L.marker(latlng).addTo(app.map);
    });
  };

  $('#geolocateForm').on('submit', geolocate);
  $('.geolocateButton').on('click', geolocate);
};

app.scrollToElement = function(el) {
  $('html,body').animate({
    scrollTop: el.offset().top
  }, 800);
};

app.geocode = function(city, callback, context) {
 var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(city);

 $.getJSON(url, function(response) {
    if (response.error || response.results.length === 0) {
      console.log('Unable to geocode city. Womp Womp.', response.error);
    }

    // Get the coordinates for the center of the city
    var location = response.results[0].geometry.location;
    var latlng = [location.lat, location.lng];
    callback.call(context || this, latlng);
  });
};

app.resetState = function() {

  app.state.publisher_id = undefined;
  $('.publisher').removeClass('selected');

  app.state.geom = undefined;
  if (app.prevLayer) app.map.removeLayer(app.prevLayer);
  // Let's leave the type and phone number in place, for easy re-subscribe
};

app.submitSubscription = function(callback) {
  $.post('/subscriptions', { subscription: app.state }, callback);
};
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

//
// 'Good old Watson! You are the one fixed point in a changing age.' - Sherlock Holmes, "His Last Bow"
//
// This mini module is for containing anything done to Tidepool data to make it possible to plot timezone-naive
// data reliably and consistently across different browsers and in different timezones. It is named after the
// quotation listed above as well as the fact that Watson is one of literature's ur-examples of the loyal
// assistant.
//
// Watson is a tideline *plugin*. Try as hard as you can to keep Watson out of main library code - i.e., in
// this repository, Watson should only be a requirement within other files in the plugins/ directory, not in
// the main js/ directory.
//

if ((typeof window !== 'undefined') && (typeof window._ !== 'undefined')) {
  var _ = window._;
}
else {
  var _ = require('lodash');
}

try {
  var log = window.bows('Watson');
}
catch (ReferenceError) {
  var log = require('../../../js/lib/').bows('Watson');
}

module.exports = {
  APPEND: '.000Z',

  normalize: function(i) {
    try {
      if (i.utcTime) {
        var d = new Date(i.utcTime);
        var offsetMinutes = d.getTimezoneOffset();
        d.setMinutes(d.getMinutes() - offsetMinutes);
        i.normalTime = d.toISOString();
      }
      else if (i.type === 'basal-rate-segment') {
        i.normalTime = i.start + this.APPEND;
        if (i.end) {
          i.normalEnd = i.end + this.APPEND;
        }
        else {
          i.normalEnd = null;
        }
      }
      else {
        i.normalTime = i.deviceTime + this.APPEND;
      }
      return i;
    }
    catch(e) {
      throw new TypeError('Watson choked on an undefined.');
    }

  },

  normalizeAll: function(a) {
    log('Watson normalized the data.');
    return _.map(a, function(d) {
      return this.normalize(d);
    }, this);
  }
};<commit_msg>add TODO to Watson re: removing references to utcTime<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

//
// 'Good old Watson! You are the one fixed point in a changing age.' - Sherlock Holmes, "His Last Bow"
//
// This mini module is for containing anything done to Tidepool data to make it possible to plot timezone-naive
// data reliably and consistently across different browsers and in different timezones. It is named after the
// quotation listed above as well as the fact that Watson is one of literature's ur-examples of the loyal
// assistant.
//
// Watson is a tideline *plugin*. Try as hard as you can to keep Watson out of main library code - i.e., in
// this repository, Watson should only be a requirement within other files in the plugins/ directory, not in
// the main js/ directory.
//

if ((typeof window !== 'undefined') && (typeof window._ !== 'undefined')) {
  var _ = window._;
}
else {
  var _ = require('lodash');
}

try {
  var log = window.bows('Watson');
}
catch (ReferenceError) {
  var log = require('../../../js/lib/').bows('Watson');
}

module.exports = {
  APPEND: '.000Z',

  normalize: function(i) {
    try {
      if (i.utcTime) {
        // TODO: remove after removed from demo data, deprecated
        // messages now come to blip with a normalTime
        var d = new Date(i.utcTime);
        var offsetMinutes = d.getTimezoneOffset();
        d.setMinutes(d.getMinutes() - offsetMinutes);
        i.normalTime = d.toISOString();
      }
      else if (i.type === 'basal-rate-segment') {
        i.normalTime = i.start + this.APPEND;
        if (i.end) {
          i.normalEnd = i.end + this.APPEND;
        }
        else {
          i.normalEnd = null;
        }
      }
      else {
        i.normalTime = i.deviceTime + this.APPEND;
      }
      return i;
    }
    catch(e) {
      throw new TypeError('Watson choked on an undefined.');
    }

  },

  normalizeAll: function(a) {
    log('Watson normalized the data.');
    return _.map(a, function(d) {
      return this.normalize(d);
    }, this);
  }
};<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Re<commit_msg>Fixing an important issue with the universe.<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Rea<|endoftext|>


<commit_before><commit_msg>Initial commit<commit_after><|endoftext|>