<commit_before>/**
 * @fileOverview read a csv file with updated field details and update all the docs in mongo.
 * @author Dong Liu
 */

var csv = require('csv');
var fs = require('fs');
var path = require('path');
var mongoose = require('mongoose');
var Request = require('../model/request.js').Request;
var Cable = require('../model/request.js').Cable;
var Change = require('../model/request.js').Change;

var inputPath;
var realPath;
var db;
var line = 0;
var specLine = 0;
var spec = {};
var parser;
var cablesProcessed = 0;
var cablesToUpdate = 0;
var cablesUpdated = 0;
var cablesChecked = 0;
var requestsProcessed = 0;
var requestsToUpdate = 0;
var requestsUpdated = 0;
var requestsChecked = 0;

var dryrun = true;

if (process.argv.length === 3) {
  inputPath = process.argv[2];
} else {
  console.warn('needs exact one argument for the input csv file path');
  process.exit(1);
}

realPath = path.resolve(process.cwd(), inputPath);

if (!fs.existsSync(realPath)) {
  console.warn(realPath + ' does not exist.');
  console.warn('Please input a valid csv file path.');
  process.exit(1);
}

mongoose.connect('mongodb://localhost/cable_frib');

db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));

db.once('open', function () {
  console.log('db connected');
});

function requestsDone() {
  console.log(requestsChecked + ' requests were checked, ' + requestsToUpdate + ' requests need update, and ' + requestsUpdated + ' were updated.');
  if (dryrun) {
    console.log('Please note that this is a dryrun.');
  }
  console.log('Bye.');
  mongoose.connection.close();
  process.exit();
}

function itemsAllChecked(total, processed, cb) {
  if (total === processed) {
    console.log(total + ' items are processed.');
    cb();
  }
}

function checkRequests() {
  Request.where('status').equals(1).exec(function (err, docs) {
    var current = 0;
    if (err) {
      console.error(err);
      requestsDone();
    } else {
      console.log('find ' + docs.length + ' requests in db.');
      docs.forEach(function (doc) {
        console.log('checking ' + (++current) + ' request with id ' + doc._id);
        var modified = 0;
        var update = {};
        if (!!doc.from.rack && spec.hasOwnProperty(doc.from.rack.trim())) {
          update['from.rack'] = spec[doc.from.rack.trim()];
          console.log('need to update request ' + doc._id + ' at from.rack');
          modified += 1;
        }
        if (!!doc.to.rack && spec.hasOwnProperty(doc.to.rack.trim())) {
          update['to.rack'] = spec[doc.to.rack.trim()];
          console.log('need to update request ' + doc._id + ' at to.rack');
          modified += 1;
        }
        requestsChecked += 1;
        if (modified > 0) {
          requestsToUpdate += 1;
        }
        if (dryrun) {
          requestsProcessed += 1;
          itemsAllChecked(docs.length, requestsProcessed, requestsDone);
        } else {
          if (modified > 0) {
            update.updatedOn = Date.now();
            update.updatedBy = 'system';
            doc.update(update, {
              new: true
            }, function (err, cable) {
              if (err) {
                console.error(err);
              } else {
                requestsUpdated += 1;
              }
              requestsProcessed += 1;
              itemsAllChecked(docs.length, requestsProcessed, requestsDone);
            });
          } else {
            requestsProcessed += 1;
            itemsAllChecked(docs.length, requestsProcessed, requestsDone);
          }
        }
      });
    }
  });
}

function cablesDone() {
  console.log(cablesChecked + ' cables were checked, ' + cablesToUpdate + ' cables need update, and ' + cablesUpdated + ' were updated.');
  console.log('Starting processing requests ...');
  checkRequests();
}

function checkCables() {
  Cable.where('status').gte(100).lte(199).exec(function (err, docs) {
    var current = 0;
    if (err) {
      console.error(err);
      cablesDone();
    } else {
      console.log('find ' + docs.length + ' cables in db.');
      docs.forEach(function (doc) {
        console.log('checking ' + (++current) + ' cable with id ' + doc._id);
        var update = {};
        var changes = [];
        var change;
        if (!!doc.from.rack && spec.hasOwnProperty(doc.from.rack.trim())) {
          update['from.rack'] = spec[doc.from.rack.trim()];
          change = {
            cableName: doc._id,
            property: 'from.rack',
            oldValue: doc.from.rack,
            newValue: spec[doc.from.rack.trim()],
            updatedBy: 'system',
            updatedOn: Date.now()
          };
          changes.push(change);
          console.log('need to update cable ' + doc._id + ' at from.rack');
        }
        if (!!doc.to.rack && spec.hasOwnProperty(doc.to.rack.trim())) {
          update['to.rack'] = spec[doc.to.rack.trim()];
          change = {
            cableName: doc._id,
            property: 'to.rack',
            oldValue: doc.to.rack,
            newValue: spec[doc.to.rack.trim()],
            updatedBy: 'system',
            updatedOn: Date.now()
          };
          changes.push(change);
          console.log('need to update cable ' + doc._id + ' at to.rack');
          // modified += 1;
        }
        cablesChecked += 1;
        if (changes.length > 0) {
          cablesToUpdate += 1;
        }
        if (dryrun) {
          cablesProcessed += 1;
          itemsAllChecked(docs.length, cablesChecked, cablesDone);
        } else {
          if (changes.length > 0) {
            update.updatedOn = Date.now();
            update.updatedBy = 'system';
            update.$inc = {
              __v: 1
            };
            Change.create(changes, function (err, cs) {
              if (err) {
                console.error(err);
                cablesProcessed += 1;
                itemsAllChecked(docs.length, cablesProcessed, cablesDone);
              } else {
                var ids = cs.map(function (e) {
                  return e._id;
                });
                update.$push = {
                  changeHistory: {
                    $each: ids
                  }
                };
                doc.update(update, {
                  new: true
                }, function (err, cable) {
                  if (err) {
                    console.error(err);
                  } else {
                    cablesUpdated += 1;
                  }
                  cablesProcessed += 1;
                  itemsAllChecked(docs.length, cablesProcessed, cablesDone);
                });
              }
            });
          } else {
            cablesProcessed += 1;
            itemsAllChecked(docs.length, cablesProcessed, cablesDone);
          }
        }
      });
    }
  });
}

function specParsed() {
  console.log(specLine + ' spec lines are parsed.');
  console.log('Starting processing cables ...');
  checkCables();
}

parser = csv.parse();

parser.on('readable', function () {
  var record;
  do {
    record = parser.read();
    if (!!record) {
      line += 1;
      // console.log('read ' + line + ' line of the spec ...');
      if (record[0].indexOf('C') === 0) {
        spec[record[0]] = record[1];
        specLine += 1;
      }
    }
  } while (!!record);
});

parser.on('error', function (err) {
  console.log(err.message);
});

parser.on('finish', function () {
  specParsed();
});

fs.createReadStream(realPath).pipe(parser);
<commit_msg>check processed cables when finishing<commit_after>/**
 * @fileOverview read a csv file with updated field details and update all the docs in mongo.
 * @author Dong Liu
 */

var csv = require('csv');
var fs = require('fs');
var path = require('path');
var mongoose = require('mongoose');
var Request = require('../model/request.js').Request;
var Cable = require('../model/request.js').Cable;
var Change = require('../model/request.js').Change;

var inputPath;
var realPath;
var db;
var line = 0;
var specLine = 0;
var spec = {};
var parser;
var cablesProcessed = 0;
var cablesToUpdate = 0;
var cablesUpdated = 0;
var cablesChecked = 0;
var requestsProcessed = 0;
var requestsToUpdate = 0;
var requestsUpdated = 0;
var requestsChecked = 0;

var dryrun = true;

if (process.argv.length === 3) {
  inputPath = process.argv[2];
} else {
  console.warn('needs exact one argument for the input csv file path');
  process.exit(1);
}

realPath = path.resolve(process.cwd(), inputPath);

if (!fs.existsSync(realPath)) {
  console.warn(realPath + ' does not exist.');
  console.warn('Please input a valid csv file path.');
  process.exit(1);
}

mongoose.connect('mongodb://localhost/cable_frib');

db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));

db.once('open', function () {
  console.log('db connected');
});

function requestsDone() {
  console.log(requestsChecked + ' requests were checked, ' + requestsToUpdate + ' requests need update, and ' + requestsUpdated + ' were updated.');
  if (dryrun) {
    console.log('Please note that this is a dryrun.');
  }
  console.log('Bye.');
  mongoose.connection.close();
  process.exit();
}

function itemsAllChecked(total, processed, cb) {
  if (total === processed) {
    console.log(total + ' items are processed.');
    cb();
  }
}

function checkRequests() {
  Request.where('status').equals(1).exec(function (err, docs) {
    var current = 0;
    if (err) {
      console.error(err);
      requestsDone();
    } else {
      console.log('find ' + docs.length + ' requests in db.');
      docs.forEach(function (doc) {
        console.log('checking ' + (++current) + ' request with id ' + doc._id);
        var modified = 0;
        var update = {};
        if (!!doc.from.rack && spec.hasOwnProperty(doc.from.rack.trim())) {
          update['from.rack'] = spec[doc.from.rack.trim()];
          console.log('need to update request ' + doc._id + ' at from.rack');
          modified += 1;
        }
        if (!!doc.to.rack && spec.hasOwnProperty(doc.to.rack.trim())) {
          update['to.rack'] = spec[doc.to.rack.trim()];
          console.log('need to update request ' + doc._id + ' at to.rack');
          modified += 1;
        }
        requestsChecked += 1;
        if (modified > 0) {
          requestsToUpdate += 1;
        }
        if (dryrun) {
          requestsProcessed += 1;
          itemsAllChecked(docs.length, requestsProcessed, requestsDone);
        } else {
          if (modified > 0) {
            update.updatedOn = Date.now();
            update.updatedBy = 'system';
            doc.update(update, {
              new: true
            }, function (err, cable) {
              if (err) {
                console.error(err);
              } else {
                requestsUpdated += 1;
              }
              requestsProcessed += 1;
              itemsAllChecked(docs.length, requestsProcessed, requestsDone);
            });
          } else {
            requestsProcessed += 1;
            itemsAllChecked(docs.length, requestsProcessed, requestsDone);
          }
        }
      });
    }
  });
}

function cablesDone() {
  console.log(cablesChecked + ' cables were checked, ' + cablesToUpdate + ' cables need update, and ' + cablesUpdated + ' were updated.');
  console.log('Starting processing requests ...');
  checkRequests();
}

function checkCables() {
  Cable.where('status').gte(100).lte(199).exec(function (err, docs) {
    var current = 0;
    if (err) {
      console.error(err);
      cablesDone();
    } else {
      console.log('find ' + docs.length + ' cables in db.');
      docs.forEach(function (doc) {
        console.log('checking ' + (++current) + ' cable with id ' + doc._id);
        var update = {};
        var changes = [];
        var change;
        if (!!doc.from.rack && spec.hasOwnProperty(doc.from.rack.trim())) {
          update['from.rack'] = spec[doc.from.rack.trim()];
          change = {
            cableName: doc._id,
            property: 'from.rack',
            oldValue: doc.from.rack,
            newValue: spec[doc.from.rack.trim()],
            updatedBy: 'system',
            updatedOn: Date.now()
          };
          changes.push(change);
          console.log('need to update cable ' + doc._id + ' at from.rack');
        }
        if (!!doc.to.rack && spec.hasOwnProperty(doc.to.rack.trim())) {
          update['to.rack'] = spec[doc.to.rack.trim()];
          change = {
            cableName: doc._id,
            property: 'to.rack',
            oldValue: doc.to.rack,
            newValue: spec[doc.to.rack.trim()],
            updatedBy: 'system',
            updatedOn: Date.now()
          };
          changes.push(change);
          console.log('need to update cable ' + doc._id + ' at to.rack');
          // modified += 1;
        }
        cablesChecked += 1;
        if (changes.length > 0) {
          cablesToUpdate += 1;
        }
        if (dryrun) {
          cablesProcessed += 1;
          itemsAllChecked(docs.length, cablesProcessed, cablesDone);
        } else {
          if (changes.length > 0) {
            update.updatedOn = Date.now();
            update.updatedBy = 'system';
            update.$inc = {
              __v: 1
            };
            Change.create(changes, function (err, cs) {
              if (err) {
                console.error(err);
                cablesProcessed += 1;
                itemsAllChecked(docs.length, cablesProcessed, cablesDone);
              } else {
                var ids = cs.map(function (e) {
                  return e._id;
                });
                update.$push = {
                  changeHistory: {
                    $each: ids
                  }
                };
                doc.update(update, {
                  new: true
                }, function (err, cable) {
                  if (err) {
                    console.error(err);
                  } else {
                    cablesUpdated += 1;
                  }
                  cablesProcessed += 1;
                  itemsAllChecked(docs.length, cablesProcessed, cablesDone);
                });
              }
            });
          } else {
            cablesProcessed += 1;
            itemsAllChecked(docs.length, cablesProcessed, cablesDone);
          }
        }
      });
    }
  });
}

function specParsed() {
  console.log(specLine + ' spec lines are parsed.');
  console.log('Starting processing cables ...');
  checkCables();
}

parser = csv.parse();

parser.on('readable', function () {
  var record;
  do {
    record = parser.read();
    if (!!record) {
      line += 1;
      // console.log('read ' + line + ' line of the spec ...');
      if (record[0].indexOf('C') === 0) {
        spec[record[0]] = record[1];
        specLine += 1;
      }
    }
  } while (!!record);
});

parser.on('error', function (err) {
  console.log(err.message);
});

parser.on('finish', function () {
  specParsed();
});

fs.createReadStream(realPath).pipe(parser);
<|endoftext|>


<commit_before>// @flow

import type {
  NavigationScreenProp,
  NavigationLeafRoute,
  NavigationScene,
  NavigationTransitionProps,
} from 'react-navigation';
import {
  type VerticalBounds,
  verticalBoundsPropType,
  type LayoutCoordinates,
  layoutCoordinatesPropType,
} from '../types/lightbox-types';
import type { AppState } from '../redux/redux-setup';
import { type Dimensions, dimensionsPropType } from 'lib/types/media-types';

import * as React from 'react';
import Animated, { Easing } from 'react-native-reanimated';
import { View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';

import { connect } from 'lib/utils/redux-utils';

import {
  contentBottomOffset,
  dimensionsSelector,
} from '../selectors/dimension-selectors';

const {
  Value,
} = Animated;

type TooltipEntry<CustomProps> = {|
  text: string,
  onPress: (props: CustomProps) => mixed,
|};
type TooltipSpec<CustomProps> = $ReadOnlyArray<TooltipEntry<CustomProps>>;

type NavProp<CustomProps> = NavigationScreenProp<{|
  ...NavigationLeafRoute,
  params: {
    ...CustomProps,
    initialCoordinates: LayoutCoordinates,
    verticalBounds: VerticalBounds,
  },
|}>;

type ButtonProps<Navigation> = {
  navigation: Navigation,
};

type TooltipProps<Navigation> = {
  navigation: Navigation,
  scene: NavigationScene,
  transitionProps: NavigationTransitionProps,
  position: Value,
  screenDimensions: Dimensions,
};
function createTooltip<
  CustomProps: {},
  Navigation: NavProp<CustomProps>,
  TooltipPropsType: TooltipProps<Navigation>,
  ButtonComponentType: React.ComponentType<ButtonProps<Navigation>>,
  TooltipComponent: React.ComponentType<TooltipPropsType>,
>(
  ButtonComponent: ButtonComponentType,
  tooltipSpec: TooltipSpec<CustomProps>,
): TooltipComponent {
  class Tooltip extends React.PureComponent<TooltipPropsType> {

    static propTypes = {
      navigation: PropTypes.shape({
        state: PropTypes.shape({
          params: PropTypes.shape({
            initialCoordinates: layoutCoordinatesPropType.isRequired,
            verticalBounds: verticalBoundsPropType.isRequired,
          }).isRequired,
        }).isRequired,
        goBack: PropTypes.func.isRequired,
      }).isRequired,
      transitionProps: PropTypes.object.isRequired,
      scene: PropTypes.object.isRequired,
      position: PropTypes.instanceOf(Value).isRequired,
      screenDimensions: dimensionsPropType.isRequired,
    };

    get contentContainerStyle() {
      const { verticalBounds } = this.props.navigation.state.params;
      const fullScreenHeight = this.props.screenDimensions.height
        + contentBottomOffset;
      const top = verticalBounds.y;
      const bottom = fullScreenHeight
        - verticalBounds.y - verticalBounds.height;
      const verticalStyle = { marginTop: top, marginBottom: bottom };
      return [ styles.contentContainer, verticalStyle ];
    }

    get buttonStyle() {
      const { params } = this.props.navigation.state;
      const { initialCoordinates, verticalBounds } = params;
      const { x, y, width, height } = initialCoordinates;
      return {
        width,
        height,
        marginTop: y - verticalBounds.y,
        marginLeft: x,
      };
    }

    render() {
      const { navigation } = this.props;
      return (
        <TouchableWithoutFeedback onPress={this.onPressBackdrop}>
          <View style={styles.backdrop}>
            <View style={this.contentContainerStyle}>
              <View style={this.buttonStyle}>
                <ButtonComponent navigation={navigation} />
              </View>
            </View>
          </View>
        </TouchableWithoutFeedback>
      );
    }

    onPressBackdrop = () => {
      this.props.navigation.goBack();
    }

  }
  return connect(
    (state: AppState) => ({
      screenDimensions: dimensionsSelector(state),
    }),
  )(Tooltip);
}

const styles = StyleSheet.create({
  backdrop: {
    flex: 1,
    opacity: 0.7,
    backgroundColor: 'black',
  },
  contentContainer: {
    flex: 1,
    overflow: "hidden",
  },
});

export {
  createTooltip,
};
<commit_msg>[native] Animate Tooltip opacity<commit_after>// @flow

import type {
  NavigationScreenProp,
  NavigationLeafRoute,
  NavigationScene,
  NavigationTransitionProps,
} from 'react-navigation';
import {
  type VerticalBounds,
  verticalBoundsPropType,
  type LayoutCoordinates,
  layoutCoordinatesPropType,
} from '../types/lightbox-types';
import type { AppState } from '../redux/redux-setup';
import { type Dimensions, dimensionsPropType } from 'lib/types/media-types';

import * as React from 'react';
import Animated, { Easing } from 'react-native-reanimated';
import { View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';

import { connect } from 'lib/utils/redux-utils';

import {
  contentBottomOffset,
  dimensionsSelector,
} from '../selectors/dimension-selectors';

const {
  Value,
  Extrapolate,
  interpolate,
} = Animated;

type TooltipEntry<CustomProps> = {|
  text: string,
  onPress: (props: CustomProps) => mixed,
|};
type TooltipSpec<CustomProps> = $ReadOnlyArray<TooltipEntry<CustomProps>>;

type NavProp<CustomProps> = NavigationScreenProp<{|
  ...NavigationLeafRoute,
  params: {
    ...CustomProps,
    initialCoordinates: LayoutCoordinates,
    verticalBounds: VerticalBounds,
  },
|}>;

type ButtonProps<Navigation> = {
  navigation: Navigation,
};

type TooltipProps<Navigation> = {
  navigation: Navigation,
  scene: NavigationScene,
  transitionProps: NavigationTransitionProps,
  position: Value,
  screenDimensions: Dimensions,
};
function createTooltip<
  CustomProps: {},
  Navigation: NavProp<CustomProps>,
  TooltipPropsType: TooltipProps<Navigation>,
  ButtonComponentType: React.ComponentType<ButtonProps<Navigation>>,
  TooltipComponent: React.ComponentType<TooltipPropsType>,
>(
  ButtonComponent: ButtonComponentType,
  tooltipSpec: TooltipSpec<CustomProps>,
): TooltipComponent {
  class Tooltip extends React.PureComponent<TooltipPropsType> {

    static propTypes = {
      navigation: PropTypes.shape({
        state: PropTypes.shape({
          params: PropTypes.shape({
            initialCoordinates: layoutCoordinatesPropType.isRequired,
            verticalBounds: verticalBoundsPropType.isRequired,
          }).isRequired,
        }).isRequired,
        goBack: PropTypes.func.isRequired,
      }).isRequired,
      transitionProps: PropTypes.object.isRequired,
      scene: PropTypes.object.isRequired,
      position: PropTypes.instanceOf(Value).isRequired,
      screenDimensions: dimensionsPropType.isRequired,
    };
    tooltipOpacity: Value;

    constructor(props: TooltipPropsType) {
      super(props);

      const { position } = props;
      const { index } = props.scene;
      this.tooltipOpacity = interpolate(
        position,
        {
          inputRange: [ index - 1, index ],
          outputRange: [ 0, 1 ],
          extrapolate: Extrapolate.CLAMP,
        },
      );
    }

    get opacityStyle() {
      return {
        flex: 1,
        opacity: this.tooltipOpacity,
      };
    }

    get contentContainerStyle() {
      const { verticalBounds } = this.props.navigation.state.params;
      const fullScreenHeight = this.props.screenDimensions.height
        + contentBottomOffset;
      const top = verticalBounds.y;
      const bottom = fullScreenHeight
        - verticalBounds.y - verticalBounds.height;
      const verticalStyle = { marginTop: top, marginBottom: bottom };
      return [ styles.contentContainer, verticalStyle ];
    }

    get buttonStyle() {
      const { params } = this.props.navigation.state;
      const { initialCoordinates, verticalBounds } = params;
      const { x, y, width, height } = initialCoordinates;
      return {
        width,
        height,
        marginTop: y - verticalBounds.y,
        marginLeft: x,
      };
    }

    render() {
      const { navigation } = this.props;
      return (
        <TouchableWithoutFeedback onPress={this.onPressBackdrop}>
          <Animated.View style={this.opacityStyle}>
            <View style={styles.backdrop}>
              <View style={this.contentContainerStyle}>
                <View style={this.buttonStyle}>
                  <ButtonComponent navigation={navigation} />
                </View>
              </View>
            </View>
          </Animated.View>
        </TouchableWithoutFeedback>
      );
    }

    onPressBackdrop = () => {
      this.props.navigation.goBack();
    }

  }
  return connect(
    (state: AppState) => ({
      screenDimensions: dimensionsSelector(state),
    }),
  )(Tooltip);
}

const styles = StyleSheet.create({
  backdrop: {
    flex: 1,
    opacity: 0.7,
    backgroundColor: 'black',
  },
  contentContainer: {
    flex: 1,
    overflow: "hidden",
  },
});

export {
  createTooltip,
};
<|endoftext|>


<commit_before>require('./check-versions')()

var config = require('../config')
if (!process.env.NODE_ENV) {
  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}

var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
//console.log(JSON.stringify(webpackConfig, null, 2));

// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable

var app = express()
var compiler = webpack(webpackConfig)

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  quiet: true
})

var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = { target: options }
  }
  app.use(proxyMiddleware(options.filter || context, options))
})

// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)

// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))

var uri = 'http://localhost:' + port

var _resolve
var readyPromise = new Promise(resolve => {
  _resolve = resolve
})

console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
  console.log('> Listening at ' + uri + '\n')
  // when env is testing, don't need open it
  //if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
  //  opn(uri, {app: 'google chrome'});
  //}
  _resolve()
})

var server = app.listen(port)

module.exports = {
  ready: readyPromise,
  close: () => {
    server.close()
  }
}
<commit_msg>去除 dev-server 中 config 依赖<commit_after>require('./check-versions')()

var config = require('../config')
if (!process.env.NODE_ENV) {
  process.env.NODE_ENV = JSON.parse('"development"')
}

var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
//console.log(JSON.stringify(webpackConfig, null, 2));

// default port where dev server listens for incoming traffic
var port = process.env.PORT || 8011
// automatically open browser, if not set will be false
var autoOpenBrowser = false
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = {}

var app = express()
var compiler = webpack(webpackConfig)

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  quiet: true
})

var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = { target: options }
  }
  app.use(proxyMiddleware(options.filter || context, options))
})

// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)

// serve pure static assets
var staticPath = path.posix.join('/', 'static')
app.use(staticPath, express.static('./static'))

var uri = 'http://localhost:' + port

var _resolve
var readyPromise = new Promise(resolve => {
  _resolve = resolve
})

console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
  console.log('> Listening at ' + uri + '\n')
  // when env is testing, don't need open it
  //if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
  //  opn(uri, {app: 'google chrome'});
  //}
  _resolve()
})

var server = app.listen(port)

module.exports = {
  ready: readyPromise,
  close: () => {
    server.close()
  }
}
<|endoftext|>


<commit_before>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Utilities for adding, removing and setting classes.  Prefer
 * {@link goog.dom.classlist} over these utilities since goog.dom.classlist
 * conforms closer to the semantics of Element.classList, is faster (uses
 * native methods rather than parsing strings on every call) and compiles
 * to smaller code as a result.
 *
 * Note: these utilities are meant to operate on HTMLElements and
 * will not work on elements with differing interfaces (such as SVGElements).
 *
 */

goog.provide('goog.dom.classes');

goog.require('goog.array');

/**
 * Sets the entire class name of an element.
 * @param {Node} element DOM node to set class of.
 * @param {string} className Class name(s) to apply to element.
 */
goog.dom.classes.set = function(element, className) {
  element.className = className;
};

/**
 * Gets an array of class names on an element
 * @param {Node} element DOM node to get class of.
 * @return {!Array} Class names on {@code element}. Some browsers add extra
 *     properties to the array. Do not depend on any of these!
 */
goog.dom.classes.get = function(element) {
  var className = element.className;
  // Some types of elements don't have a className in IE (e.g. iframes).
  // Furthermore, in Firefox, className is not a string when the element is
  // an SVG element.
  return goog.isString(className) && className.match(/\S+/g) || [];
};

/**
 * Adds a class or classes to an element. Does not add multiples of class names.
 * @param {Node} element DOM node to add class to.
 * @param {...string} var_args Class names to add.
 * @return {boolean} Whether class was added (or all classes were added).
 */
goog.dom.classes.add = function(element, var_args) {
  var classes = goog.dom.classes.get(element);
  var args = goog.array.slice(arguments, 1);
  var expectedCount = classes.length + args.length;
  goog.dom.classes.add_(classes, args);
  element.className = classes.join(' ');
  return classes.length == expectedCount;
};

/**
 * Removes a class or classes from an element.
 * @param {Node} element DOM node to remove class from.
 * @param {...string} var_args Class name(s) to remove.
 * @return {boolean} Whether all classes in {@code var_args} were found and
 *     removed.
 */
goog.dom.classes.remove = function(element, var_args) {
  var classes = goog.dom.classes.get(element);
  var args = goog.array.slice(arguments, 1);
  var newClasses = goog.dom.classes.getDifference_(classes, args);
  element.className = newClasses.join(' ');
  return newClasses.length == classes.length - args.length;
};

/**
 * Helper method for {@link goog.dom.classes.add} and
 * {@link goog.dom.classes.addRemove}. Adds one or more classes to the supplied
 * classes array.
 * @param {Array.<string>} classes All class names for the element, will be
 *     updated to have the classes supplied in {@code args} added.
 * @param {Array.<string>} args Class names to add.
 * @private
 */
goog.dom.classes.add_ = function(classes, args) {
  for (var i = 0; i < args.length; i++) {
    if (!goog.array.contains(classes, args[i])) {
      classes.push(args[i]);
    }
  }
};

/**
 * Helper method for {@link goog.dom.classes.remove} and
 * {@link goog.dom.classes.addRemove}. Calculates the difference of two arrays.
 * @param {!Array.<string>} arr1 First array.
 * @param {!Array.<string>} arr2 Second array.
 * @return {!Array.<string>} The first array without the elements of the second
 *     array.
 * @private
 */
goog.dom.classes.getDifference_ = function(arr1, arr2) {
  return goog.array.filter(arr1, function(item) {
    return !goog.array.contains(arr2, item);
  });
};

/**
 * Switches a class on an element from one to another without disturbing other
 * classes. If the fromClass isn't removed, the toClass won't be added.
 * @param {Node} element DOM node to swap classes on.
 * @param {string} fromClass Class to remove.
 * @param {string} toClass Class to add.
 * @return {boolean} Whether classes were switched.
 */
goog.dom.classes.swap = function(element, fromClass, toClass) {
  var classes = goog.dom.classes.get(element);

  var removed = false;
  for (var i = 0; i < classes.length; i++) {
    if (classes[i] == fromClass) {
      goog.array.splice(classes, i--, 1);
      removed = true;
    }
  }

  if (removed) {
    classes.push(toClass);
    element.className = classes.join(' ');
  }

  return removed;
};

/**
 * Adds zero or more classes to an element and removes zero or more as a single
 * operation. Unlike calling {@link goog.dom.classes.add} and
 * {@link goog.dom.classes.remove} separately, this is more efficient as it only
 * parses the class property once.
 *
 * If a class is in both the remove and add lists, it will be added. Thus,
 * you can use this instead of {@link goog.dom.classes.swap} when you have
 * more than two class names that you want to swap.
 *
 * @param {Node} element DOM node to swap classes on.
 * @param {?(string|Array.<string>)} classesToRemove Class or classes to
 *     remove, if null no classes are removed.
 * @param {?(string|Array.<string>)} classesToAdd Class or classes to add, if
 *     null no classes are added.
 */
goog.dom.classes.addRemove = function(element, classesToRemove, classesToAdd) {
  var classes = goog.dom.classes.get(element);
  if (goog.isString(classesToRemove)) {
    goog.array.remove(classes, classesToRemove);
  } else if (goog.isArray(classesToRemove)) {
    classes = goog.dom.classes.getDifference_(classes, classesToRemove);
  }

  if (goog.isString(classesToAdd) &&
      !goog.array.contains(classes, classesToAdd)) {
    classes.push(classesToAdd);
  } else if (goog.isArray(classesToAdd)) {
    goog.dom.classes.add_(classes, classesToAdd);
  }

  element.className = classes.join(' ');
};

/**
 * Returns true if an element has a class.
 * @param {Node} element DOM node to test.
 * @param {string} className Class name to test for.
 * @return {boolean} Whether element has the class.
 */
goog.dom.classes.has = function(element, className) {
  return goog.array.contains(goog.dom.classes.get(element), className);
};

/**
 * Adds or removes a class depending on the enabled argument.
 * @param {Node} element DOM node to add or remove the class on.
 * @param {string} className Class name to add or remove.
 * @param {boolean} enabled Whether to add or remove the class (true adds,
 *     false removes).
 */
goog.dom.classes.enable = function(element, className, enabled) {
  if (enabled) {
    goog.dom.classes.add(element, className);
  } else {
    goog.dom.classes.remove(element, className);
  }
};

/**
 * Removes a class if an element has it, and adds it the element doesn't have
 * it.  Won't affect other classes on the node.
 * @param {Node} element DOM node to toggle class on.
 * @param {string} className Class to toggle.
 * @return {boolean} True if class was added, false if it was removed
 *     (in other words, whether element has the class after this function has
 *     been called).
 */
goog.dom.classes.toggle = function(element, className) {
  var add = !goog.dom.classes.has(element, className);
  goog.dom.classes.enable(element, className, add);
  return add;
};
<commit_msg><commit_after>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Utilities for adding, removing and setting classes.  Prefer
 * {@link goog.dom.classlist} over these utilities since goog.dom.classlist
 * conforms closer to the semantics of Element.classList, is faster (uses
 * native methods rather than parsing strings on every call) and compiles
 * to smaller code as a result.
 *
 * Note: these utilities are meant to operate on HTMLElements and
 * will not work on elements with differing interfaces (such as SVGElements).
 *
 */

goog.provide('goog.dom.classes');

goog.require('goog.array');

/**
 * Sets the entire class name of an element.
 * @param {Node} element DOM node to set class of.
 * @param {string} className Class name(s) to apply to element.
 */
goog.dom.classes.set = function(element, className) {
  element.className = className;
};

/**
 * Gets an array of class names on an element
 * @param {Node} element DOM node to get class of.
 * @return {!Array} Class names on {@code element}. Some browsers add extra
 *     properties to the array. Do not depend on any of these!
 */
goog.dom.classes.get = function(element) {
  var className = element.className;
  // Some types of elements don't have a className in IE (e.g. iframes).
  // Furthermore, in Firefox, className is not a string when the element is
  // an SVG element.
  return goog.isString(className) && className.match(/\S+/g) || [];
};

/**
 * Adds a class or classes to an element. Does not add multiples of class names.
 * @param {Node} element DOM node to add class to.
 * @param {...string} var_args Class names to add.
 * @return {boolean} Whether class was added (or all classes were added).
 */
goog.dom.classes.add = function(element, var_args) {
  var classes = goog.dom.classes.get(element);
  var args = goog.array.slice(arguments, 1);
  var expectedCount = classes.length + args.length;
  goog.dom.classes.add_(classes, args);
  goog.dom.classes.set(element, classes.join(' '));
  return classes.length == expectedCount;
};

/**
 * Removes a class or classes from an element.
 * @param {Node} element DOM node to remove class from.
 * @param {...string} var_args Class name(s) to remove.
 * @return {boolean} Whether all classes in {@code var_args} were found and
 *     removed.
 */
goog.dom.classes.remove = function(element, var_args) {
  var classes = goog.dom.classes.get(element);
  var args = goog.array.slice(arguments, 1);
  var newClasses = goog.dom.classes.getDifference_(classes, args);
  goog.dom.classes.set(element, newClasses.join(' '));
  return newClasses.length == classes.length - args.length;
};

/**
 * Helper method for {@link goog.dom.classes.add} and
 * {@link goog.dom.classes.addRemove}. Adds one or more classes to the supplied
 * classes array.
 * @param {Array.<string>} classes All class names for the element, will be
 *     updated to have the classes supplied in {@code args} added.
 * @param {Array.<string>} args Class names to add.
 * @private
 */
goog.dom.classes.add_ = function(classes, args) {
  for (var i = 0; i < args.length; i++) {
    if (!goog.array.contains(classes, args[i])) {
      classes.push(args[i]);
    }
  }
};

/**
 * Helper method for {@link goog.dom.classes.remove} and
 * {@link goog.dom.classes.addRemove}. Calculates the difference of two arrays.
 * @param {!Array.<string>} arr1 First array.
 * @param {!Array.<string>} arr2 Second array.
 * @return {!Array.<string>} The first array without the elements of the second
 *     array.
 * @private
 */
goog.dom.classes.getDifference_ = function(arr1, arr2) {
  return goog.array.filter(arr1, function(item) {
    return !goog.array.contains(arr2, item);
  });
};

/**
 * Switches a class on an element from one to another without disturbing other
 * classes. If the fromClass isn't removed, the toClass won't be added.
 * @param {Node} element DOM node to swap classes on.
 * @param {string} fromClass Class to remove.
 * @param {string} toClass Class to add.
 * @return {boolean} Whether classes were switched.
 */
goog.dom.classes.swap = function(element, fromClass, toClass) {
  var classes = goog.dom.classes.get(element);

  var removed = false;
  for (var i = 0; i < classes.length; i++) {
    if (classes[i] == fromClass) {
      goog.array.splice(classes, i--, 1);
      removed = true;
    }
  }

  if (removed) {
    classes.push(toClass);
    goog.dom.classes.set(element, classes.join(' '));
  }

  return removed;
};

/**
 * Adds zero or more classes to an element and removes zero or more as a single
 * operation. Unlike calling {@link goog.dom.classes.add} and
 * {@link goog.dom.classes.remove} separately, this is more efficient as it only
 * parses the class property once.
 *
 * If a class is in both the remove and add lists, it will be added. Thus,
 * you can use this instead of {@link goog.dom.classes.swap} when you have
 * more than two class names that you want to swap.
 *
 * @param {Node} element DOM node to swap classes on.
 * @param {?(string|Array.<string>)} classesToRemove Class or classes to
 *     remove, if null no classes are removed.
 * @param {?(string|Array.<string>)} classesToAdd Class or classes to add, if
 *     null no classes are added.
 */
goog.dom.classes.addRemove = function(element, classesToRemove, classesToAdd) {
  var classes = goog.dom.classes.get(element);
  if (goog.isString(classesToRemove)) {
    goog.array.remove(classes, classesToRemove);
  } else if (goog.isArray(classesToRemove)) {
    classes = goog.dom.classes.getDifference_(classes, classesToRemove);
  }

  if (goog.isString(classesToAdd) &&
      !goog.array.contains(classes, classesToAdd)) {
    classes.push(classesToAdd);
  } else if (goog.isArray(classesToAdd)) {
    goog.dom.classes.add_(classes, classesToAdd);
  }

  goog.dom.classes.set(element, classes.join(' '));
};

/**
 * Returns true if an element has a class.
 * @param {Node} element DOM node to test.
 * @param {string} className Class name to test for.
 * @return {boolean} Whether element has the class.
 */
goog.dom.classes.has = function(element, className) {
  return goog.array.contains(goog.dom.classes.get(element), className);
};

/**
 * Adds or removes a class depending on the enabled argument.
 * @param {Node} element DOM node to add or remove the class on.
 * @param {string} className Class name to add or remove.
 * @param {boolean} enabled Whether to add or remove the class (true adds,
 *     false removes).
 */
goog.dom.classes.enable = function(element, className, enabled) {
  if (enabled) {
    goog.dom.classes.add(element, className);
  } else {
    goog.dom.classes.remove(element, className);
  }
};

/**
 * Removes a class if an element has it, and adds it the element doesn't have
 * it.  Won't affect other classes on the node.
 * @param {Node} element DOM node to toggle class on.
 * @param {string} className Class to toggle.
 * @return {boolean} True if class was added, false if it was removed
 *     (in other words, whether element has the class after this function has
 *     been called).
 */
goog.dom.classes.toggle = function(element, className) {
  var add = !goog.dom.classes.has(element, className);
  goog.dom.classes.enable(element, className, add);
  return add;
};
<|endoftext|>


<commit_before>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Datastructure: Set.
 *
 *
 * This class implements a set data structure. Adding and removing is O(1). It
 * supports both object and primitive values. Be careful because you can add
 * both 1 and new Number(1), because these are not the same. You can even add
 * multiple new Number(1) because these are not equal.
 */

goog.provide('goog.structs.Set');

goog.require('goog.structs');
goog.require('goog.structs.Map');

/**
 * A set that can contain both primitives and objects.  Adding and removing
 * elements is O(1).  Primitives are treated as identical if they have the same
 * type and convert to the same string.  Objects are treated as identical only
 * if they are references to the same object.  WARNING: A goog.structs.Set can
 * contain both 1 and (new Number(1)), because they are not the same.  WARNING:
 * Adding (new Number(1)) twice will yield two distinct elements, because they
 * are two different objects.  WARNING: Any object that is added to a
 * goog.structs.Set will be modified!  Because goog.getUid() is used to
 * identify objects, every object in the set will be mutated.
 * @param {Array|Object=} opt_values Initial values to start with.
 * @constructor
 */
goog.structs.Set = function(opt_values) {
  this.map_ = new goog.structs.Map;
  if (opt_values) {
    this.addAll(opt_values);
  }
};

/**
 * Obtains a unique key for an element of the set.  Primitives will yield the
 * same key if they have the same type and convert to the same string.  Object
 * references will yield the same key only if they refer to the same object.
 * @param {*} val Object or primitive value to get a key for.
 * @return {string} A unique key for this value/object.
 * @private
 */
goog.structs.Set.getKey_ = function(val) {
  var type = typeof val;
  if (type == 'object' && val || type == 'function') {
    return 'o' + goog.getUid(/** @type {Object} */ (val));
  } else {
    return type.substr(0, 1) + val;
  }
};

/**
 * @return {number} The number of elements in the set.
 */
goog.structs.Set.prototype.getCount = function() {
  return this.map_.getCount();
};

/**
 * Add a primitive or an object to the set.
 * @param {*} element The primitive or object to add.
 */
goog.structs.Set.prototype.add = function(element) {
  this.map_.set(goog.structs.Set.getKey_(element), element);
};

/**
 * Adds all the values in the given collection to this set.
 * @param {Array|Object} col A collection containing the elements to add.
 */
goog.structs.Set.prototype.addAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0; i < l; i++) {
    this.add(values[i]);
  }
};

/**
 * Removes all values in the given collection from this set.
 * @param {Array|Object} col A collection containing the elements to remove.
 */
goog.structs.Set.prototype.removeAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0; i < l; i++) {
    this.remove(values[i]);
  }
};

/**
 * Removes the given element from this set.
 * @param {*} element The primitive or object to remove.
 * @return {boolean} Whether the element was found and removed.
 */
goog.structs.Set.prototype.remove = function(element) {
  return this.map_.remove(goog.structs.Set.getKey_(element));
};

/**
 * Removes all elements from this set.
 */
goog.structs.Set.prototype.clear = function() {
  this.map_.clear();
};

/**
 * Tests whether this set is empty.
 * @return {boolean} True if there are no elements in this set.
 */
goog.structs.Set.prototype.isEmpty = function() {
  return this.map_.isEmpty();
};

/**
 * Tests whether this set contains the given element.
 * @param {*} element The primitive or object to test for.
 * @return {boolean} True if this set contains the given element.
 */
goog.structs.Set.prototype.contains = function(element) {
  return this.map_.containsKey(goog.structs.Set.getKey_(element));
};

/**
 * Tests whether this set contains all the values in a given collection.
 * Repeated elements in the collection are ignored, e.g.  (new
 * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
 * @param {Object} col A collection-like object.
 * @return {boolean} True if the set contains all elements.
 */
goog.structs.Set.prototype.containsAll = function(col) {
  return goog.structs.every(col, this.contains, this);
};

/**
 * Finds all values that are present in both this set and the given collection.
 * @param {Array|Object} col A collection.
 * @return {goog.structs.Set} A new set containing all the values (primitives
 *     or objects) present in both this set and the given collection.
 */
goog.structs.Set.prototype.intersection = function(col) {
  var result = new goog.structs.Set();

  var values = goog.structs.getValues(col);
  for (var i = 0; i < values.length; i++) {
    var value = values[i];
    if (this.contains(value)) {
      result.add(value);
    }
  }

  return result;
};

/**
 * Returns an array containing all the elements in this set.
 * @return {Array} An array containing all the elements in this set.
 */
goog.structs.Set.prototype.getValues = function() {
  return this.map_.getValues();
};

/**
 * Creates a shallow clone of this set.
 * @return {goog.structs.Set} A new set containing all the same elements as
 *     this set.
 */
goog.structs.Set.prototype.clone = function() {
  return new goog.structs.Set(this);
};

/**
 * Tests whether the given collection consists of the same elements as this set,
 * regardless of order, without repetition.  Primitives are treated as equal if
 * they have the same type and convert to the same string; objects are treated
 * as equal if they are references to the same object.  This operation is O(n).
 * @param {Object} col A collection.
 * @return {boolean} True if the given collection consists of the same elements
 *     as this set, regardless of order, without repetition.
 */
goog.structs.Set.prototype.equals = function(col) {
  return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
};

/**
 * Tests whether the given collection contains all the elements in this set.
 * Primitives are treated as equal if they have the same type and convert to the
 * same string; objects are treated as equal if they are references to the same
 * object.  This operation is O(n).
 * @param {Object} col A collection.
 * @return {boolean} True if this set is a subset of the given collection.
 */
goog.structs.Set.prototype.isSubsetOf = function(col) {
  var colCount = goog.structs.getCount(col);
  if (this.getCount() > colCount) {
    return false;
  }
  // TODO(user) Find the minimal collection size where the conversion makes
  // the contains() method faster.
  if (!(col instanceof goog.structs.Set) && colCount > 5) {
    // Convert to a goog.structs.Set so that goog.structs.contains runs in
    // O(1) time instead of O(n) time.
    col = new goog.structs.Set(col);
  }
  return goog.structs.every(this, function(value) {
    return goog.structs.contains(col, value);
  });
};

/**
 * Returns an iterator that iterates over the elements in this set.
 * @param {boolean=} opt_keys This argument is ignored.
 * @return {goog.iter.Iterator} An iterator over the elements in this set.
 */
goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
  return this.map_.__iterator__(false);
};
<commit_msg><commit_after>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Datastructure: Set.
 *
 *
 * This class implements a set data structure. Adding and removing is O(1). It
 * supports both object and primitive values. Be careful because you can add
 * both 1 and new Number(1), because these are not the same. You can even add
 * multiple new Number(1) because these are not equal.
 */

goog.provide('goog.structs.Set');

goog.require('goog.structs');
goog.require('goog.structs.Map');

/**
 * A set that can contain both primitives and objects.  Adding and removing
 * elements is O(1).  Primitives are treated as identical if they have the same
 * type and convert to the same string.  Objects are treated as identical only
 * if they are references to the same object.  WARNING: A goog.structs.Set can
 * contain both 1 and (new Number(1)), because they are not the same.  WARNING:
 * Adding (new Number(1)) twice will yield two distinct elements, because they
 * are two different objects.  WARNING: Any object that is added to a
 * goog.structs.Set will be modified!  Because goog.getUid() is used to
 * identify objects, every object in the set will be mutated.
 * @param {Array|Object=} opt_values Initial values to start with.
 * @constructor
 */
goog.structs.Set = function(opt_values) {
  this.map_ = new goog.structs.Map;
  if (opt_values) {
    this.addAll(opt_values);
  }
};

/**
 * Obtains a unique key for an element of the set.  Primitives will yield the
 * same key if they have the same type and convert to the same string.  Object
 * references will yield the same key only if they refer to the same object.
 * @param {*} val Object or primitive value to get a key for.
 * @return {string} A unique key for this value/object.
 * @private
 */
goog.structs.Set.getKey_ = function(val) {
  var type = typeof val;
  if (type == 'object' && val || type == 'function') {
    return 'o' + goog.getUid(/** @type {Object} */ (val));
  } else {
    return type.substr(0, 1) + val;
  }
};

/**
 * @return {number} The number of elements in the set.
 */
goog.structs.Set.prototype.getCount = function() {
  return this.map_.getCount();
};

/**
 * Add a primitive or an object to the set.
 * @param {*} element The primitive or object to add.
 */
goog.structs.Set.prototype.add = function(element) {
  this.map_.set(goog.structs.Set.getKey_(element), element);
};

/**
 * Adds all the values in the given collection to this set.
 * @param {Array|Object} col A collection containing the elements to add.
 */
goog.structs.Set.prototype.addAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0; i < l; i++) {
    this.add(values[i]);
  }
};

/**
 * Removes all values in the given collection from this set.
 * @param {Array|Object} col A collection containing the elements to remove.
 */
goog.structs.Set.prototype.removeAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0; i < l; i++) {
    this.remove(values[i]);
  }
};

/**
 * Removes the given element from this set.
 * @param {*} element The primitive or object to remove.
 * @return {boolean} Whether the element was found and removed.
 */
goog.structs.Set.prototype.remove = function(element) {
  return this.map_.remove(goog.structs.Set.getKey_(element));
};

/**
 * Removes all elements from this set.
 */
goog.structs.Set.prototype.clear = function() {
  this.map_.clear();
};

/**
 * Tests whether this set is empty.
 * @return {boolean} True if there are no elements in this set.
 */
goog.structs.Set.prototype.isEmpty = function() {
  return this.map_.isEmpty();
};

/**
 * Tests whether this set contains the given element.
 * @param {*} element The primitive or object to test for.
 * @return {boolean} True if this set contains the given element.
 */
goog.structs.Set.prototype.contains = function(element) {
  return this.map_.containsKey(goog.structs.Set.getKey_(element));
};

/**
 * Tests whether this set contains all the values in a given collection.
 * Repeated elements in the collection are ignored, e.g.  (new
 * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
 * @param {Object} col A collection-like object.
 * @return {boolean} True if the set contains all elements.
 */
goog.structs.Set.prototype.containsAll = function(col) {
  return goog.structs.every(col, this.contains, this);
};

/**
 * Finds all values that are present in both this set and the given collection.
 * @param {Array|Object} col A collection.
 * @return {goog.structs.Set} A new set containing all the values (primitives
 *     or objects) present in both this set and the given collection.
 */
goog.structs.Set.prototype.intersection = function(col) {
  var result = new goog.structs.Set();

  var values = goog.structs.getValues(col);
  for (var i = 0; i < values.length; i++) {
    var value = values[i];
    if (this.contains(value)) {
      result.add(value);
    }
  }

  return result;
};

/**
 * Returns an array containing all the elements in this set.
 * @return {!Array} An array containing all the elements in this set.
 */
goog.structs.Set.prototype.getValues = function() {
  return this.map_.getValues();
};

/**
 * Creates a shallow clone of this set.
 * @return {goog.structs.Set} A new set containing all the same elements as
 *     this set.
 */
goog.structs.Set.prototype.clone = function() {
  return new goog.structs.Set(this);
};

/**
 * Tests whether the given collection consists of the same elements as this set,
 * regardless of order, without repetition.  Primitives are treated as equal if
 * they have the same type and convert to the same string; objects are treated
 * as equal if they are references to the same object.  This operation is O(n).
 * @param {Object} col A collection.
 * @return {boolean} True if the given collection consists of the same elements
 *     as this set, regardless of order, without repetition.
 */
goog.structs.Set.prototype.equals = function(col) {
  return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
};

/**
 * Tests whether the given collection contains all the elements in this set.
 * Primitives are treated as equal if they have the same type and convert to the
 * same string; objects are treated as equal if they are references to the same
 * object.  This operation is O(n).
 * @param {Object} col A collection.
 * @return {boolean} True if this set is a subset of the given collection.
 */
goog.structs.Set.prototype.isSubsetOf = function(col) {
  var colCount = goog.structs.getCount(col);
  if (this.getCount() > colCount) {
    return false;
  }
  // TODO(user) Find the minimal collection size where the conversion makes
  // the contains() method faster.
  if (!(col instanceof goog.structs.Set) && colCount > 5) {
    // Convert to a goog.structs.Set so that goog.structs.contains runs in
    // O(1) time instead of O(n) time.
    col = new goog.structs.Set(col);
  }
  return goog.structs.every(this, function(value) {
    return goog.structs.contains(col, value);
  });
};

/**
 * Returns an iterator that iterates over the elements in this set.
 * @param {boolean=} opt_keys This argument is ignored.
 * @return {goog.iter.Iterator} An iterator over the elements in this set.
 */
goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
  return this.map_.__iterator__(false);
};
<|endoftext|>


<commit_before>var map = function() {
    emit(
        {t: this.value.t, l: this.value.l},
        {o: this.value.o}
    );
}

var reduce = function(key, values) {

    var allLinks = values.reduce(function(memo, value) {

        return memo.concat(value.o);

    }, []);

    return {
        o: allLinks
    };
}

db.mr_dedup.drop();
db.mr_tags.mapReduce(map, reduce, {out: {replace: "mr_dedup", sharded: true}});

// dedup the links by flattening everything
var map = function() {

    var t = this._id.t;
    var l = this._id.l;

    this.value.o.forEach(function(link) {

        emit({
            t: t,
            l: l,
            oid: link.oid,
            ot: link.ot
        }, null);

    });
}

var reduce = function(key, values) {
    return values[0];
}

db.mr_flattened.drop();
db.mr_dedup.mapReduce(map, reduce, {out: {replace: "mr_flattened", sharded: true}});
<commit_msg>dedup tags and links in one m/r<commit_after>var map = function() {

    var t = this._id.t;
    var l = this._id.l;

    this.value.o.forEach(function(o) {
        emit({
            t: t,
            l: l,
            oid: o.oid,
            ot: o.ot
        }, null);
    });
}

var reduce = function(key, values) {
    return values[0];
}

db.mr_dedup.drop();
db.mr_tags.mapReduce(map, reduce, {out: {replace: "mr_dedup", sharded: false}});
<|endoftext|>


<commit_before>
/**
 * Panel to browse FileMeta.
 */
Ext.define('devilry.extjshelpers.assignmentgroup.FileMetaBrowserPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.filemetabrowserpanel',
    cls: 'widget-filemetabrowserpanel',

    config: {
        /**
         * @cfg
         * FileMeta ``Ext.data.Store``. (Required).
         * _Note_ that ``filemetastore.proxy.extraParams`` is changed by this
         * class.
         */
        filemetastore: undefined,

        /**
         * @cfg
         * Id of the delivery in which the filemetas belong.
         */
        deliveryid: undefined,
    },

    initComponent: function() {
        this.filemetastore.proxy.extraParams.filters = Ext.JSON.encode([
            {field: 'delivery', comp:'exact', value: this.deliveryid}
        ]);

        this.on('render', function() {
            Ext.defer(function() {
                if(this.filemetastore.loading) {
                    this.setLoading(true);
                }
            }, 100, this);
        });
        this.filemetastore.load({
            scope: this,
            callback: function() {
                this.setLoading(false);
            }
        });

        Ext.apply(this, {
            items: [{
                xtype: 'grid',
                sortableColumns: false,
                store: this.filemetastore,
                cls: 'selectable-grid',
                columns: [{
                    header: gettext('File name'),
                    menuDisabled: true,
                    flex:1,
                    dataIndex: 'filename'
                }, {
                    header: gettext('Size'),
                    menuDisabled: true,
                    dataIndex: 'size',
                    renderer: function(value) {
                        var units = ['Bytes', 'KBytes', 'MBytes', 'GBytes'];
                        var i = 0;
                        while(value >= 1024) {
                            value /= 1024;
                            ++i;
                        }
                        if(i < units.length) {
                            return value.toFixed() + ' ' + units[i];
                        } else {
                            return value + ' ' + units[0];
                        }

                    }
                }],
                listeners: {
                    scope: this,
                    itemclick: function(self, record) {
                        var url = DevilrySettings.DEVILRY_URLPATH_PREFIX + "/student/show-delivery/filedownload/" + record.get('id');
                        window.open(url, 'download');
                    }
                }

            }],

            bbar: [{
                xtype: 'button',
                scale: 'large',
                text: gettext('Download all files (.zip)'),
                listeners: {
                    scope: this,
                    click: function(view, record, item) {
                        var url = Ext.String.format(
                            '{0}/student/show-delivery/compressedfiledownload/{1}',
                            DevilrySettings.DEVILRY_URLPATH_PREFIX, this.deliveryid
                        );
                        window.open(url, 'download');
                    }
                }
            }]
            // , {
                // xtype: 'button',
                // text: 'Download all files (tar.gz)',
                // listeners: {
                    // click: function() {
                        // console.log('Downloading tar.gz some time in the future');
                    // }
                // }
            // }]
        });
        this.callParent(arguments);
    }
});
<commit_msg>examiner...FileMetaBrowserPanel: Use link for download.<commit_after>
/**
 * Panel to browse FileMeta.
 */
Ext.define('devilry.extjshelpers.assignmentgroup.FileMetaBrowserPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.filemetabrowserpanel',
    cls: 'widget-filemetabrowserpanel',

    /**
     * @cfg
     * FileMeta ``Ext.data.Store``. (Required).
     * _Note_ that ``filemetastore.proxy.extraParams`` is changed by this
     * class.
     */
    filemetastore: undefined,

    /**
     * @cfg
     * Id of the delivery in which the filemetas belong.
     */
    deliveryid: undefined,

    fileTpl: [
        '{data.filename} ({size})'
    ],

    initComponent: function() {
        this.filemetastore.proxy.extraParams.filters = Ext.JSON.encode([
            {field: 'delivery', comp:'exact', value: this.deliveryid}
        ]);

        this.on('render', function() {
            Ext.defer(function() {
                if(this.filemetastore.loading) {
                    this.setLoading(true);
                }
            }, 100, this);
        });
        this.filemetastore.load({
            scope: this,
            callback: function() {
                this.setLoading(false);
            }
        });

        var renderTpl = Ext.create('Ext.XTemplate', this.fileTpl);
        var me = this;
        Ext.apply(this, {
            items: [{
                xtype: 'grid',
                sortableColumns: false,
                store: this.filemetastore,
                hideHeaders: true,
                disableSelection: true,
                cls: 'bootstrap',
                columns: [{
                    flex:1,
                    menuDisabled: true,
                    dataIndex: 'size',
                    renderer: function(size, unused, record) {
                        var units = ['Bytes', 'KBytes', 'MBytes', 'GBytes'];
                        var i = 0;
                        while(size >= 1024) {
                            size /= 1024;
                            ++i;
                        }
                        var sizeWithUnit;
                        if(i < units.length) {
                            sizeWithUnit = size.toFixed() + ' ' + units[i];
                        } else {
                            sizeWithUnit = size + ' ' + units[0];
                        }

                        var url = Ext.String.format("{0}/student/show-delivery/filedownload/{1}",
                            DevilrySettings.DEVILRY_URLPATH_PREFIX, record.get('id'));
                        return renderTpl.apply({
                            data: record.data,
                            size: sizeWithUnit,
                            downloadurl: url
                        });
                    }
                }]
//                listeners: {
//                    scope: this,
//                    itemclick: function(self, record) {
//                        var url = DevilrySettings.DEVILRY_URLPATH_PREFIX + "/student/show-delivery/filedownload/" + record.get('id');
//                        window.open(url, 'download');
//                    }
//                }

            }],

            bbar: [{
                xtype: 'button',
                scale: 'large',
                text: gettext('Download all files (.zip)'),
                listeners: {
                    scope: this,
                    click: function(view, record, item) {
                        var url = Ext.String.format(
                            '{0}/student/show-delivery/compressedfiledownload/{1}',
                            DevilrySettings.DEVILRY_URLPATH_PREFIX, this.deliveryid
                        );
                        window.open(url, 'download');
                    }
                }
            }]
        });
        this.callParent(arguments);
    }
});
<|endoftext|>


<commit_before>"use strict";

const request = require("request-promise-native");

module.exports = exports = {
    addWorklog,
    getAssignedIssues,
    getRecentIssues
};

// adds a new worklog under a particular issue key
function addWorklog(jiraOptions, issueKey, worklog, callback) {
    let urlStub = `issue/${issueKey}/worklog`;
    let options = _getRequestOptions(jiraOptions, urlStub, worklog);

    return request.post(options).then((response) => {
        let newWorklogId = response.id;

        return newWorklogId;
    }).catch(_handleFailure);
}

// gets the issues that are assigned to a particular user
function getAssignedIssues(jiraOptions) {
    let urlStub = `search?jql=assignee=${jiraOptions.username}&fields=summary`;
    let options = _getRequestOptions(jiraOptions, urlStub);

    return request.get(options).then((response) => {
        let issues = _summarizeIssues(JSON.parse(response));

        return issues;
    }).catch(_handleFailure);
}

// gets the issues that a particular user has recently logged time under
function getRecentIssues(jiraOptions, days, callback) {
    let urlStub = `search?jql=worklogAuthor=${jiraOptions.username}
     AND worklogDate >= -${days}d&fields=summary`;
    let options = _getRequestOptions(jiraOptions, urlStub);

    return request.get(options).then((response) => {
        let issues = _summarizeIssues(JSON.parse(response));

        return issues;
    }).catch(_handleFailure);
}

// generates the options object for HTTP requests
function _getRequestOptions(jiraOptions, urlStub, payload) {
    let url = `${jiraOptions.url}/rest/api/latest/${urlStub}`;
    let { username, password } = jiraOptions;

    return {
        url,
        headers: {
            "Content-Type": "application/json"
        },
        auth: {
            username,
            password
        },
        json: payload
    };
}

// flattens the list of issues to a key-summary list
function _summarizeIssues(data) {
    return data.issues.map((issue) => {
        let { key, fields: { summary } } = issue;

        return {
            key,
            summary
        };
    });
}

// handles failure of HTTP requests
function _handleFailure(error) {
    let { statusCode } = error, message;

    if (!statusCode) {
        message = error.message;
    }
    else {
        message = `Failed with ${statusCode}`;
    }

    return Promise.reject(message);
}<commit_msg>add console.logs.<commit_after>"use strict";

const request = require("request-promise-native");

module.exports = exports = {
    addWorklog,
    getAssignedIssues,
    getRecentIssues
};

// adds a new worklog under a particular issue key
function addWorklog(jiraOptions, issueKey, worklog, callback) {
    let urlStub = `issue/${issueKey}/worklog`;
    let options = _getRequestOptions(jiraOptions, urlStub, worklog);

    console.log('Add worklog: ', JSON.stringify(options));

    return request.post(options).then((response) => {
        let newWorklogId = response.id;

        return newWorklogId;
    }).catch(_handleFailure);
}

// gets the issues that are assigned to a particular user
function getAssignedIssues(jiraOptions) {
    let urlStub = `search?jql=assignee=${jiraOptions.username}&fields=summary`;
    let options = _getRequestOptions(jiraOptions, urlStub);

    return request.get(options).then((response) => {
        let issues = _summarizeIssues(JSON.parse(response));

        return issues;
    }).catch(_handleFailure);
}

// gets the issues that a particular user has recently logged time under
function getRecentIssues(jiraOptions, days, callback) {
    let urlStub = `search?jql=worklogAuthor=${jiraOptions.username}
     AND worklogDate >= -${days}d&fields=summary`;
    let options = _getRequestOptions(jiraOptions, urlStub);

    return request.get(options).then((response) => {
        let issues = _summarizeIssues(JSON.parse(response));

        return issues;
    }).catch(_handleFailure);
}

// generates the options object for HTTP requests
function _getRequestOptions(jiraOptions, urlStub, payload) {
    let url = `${jiraOptions.url}/rest/api/latest/${urlStub}`;
    let {
        username,
        password
    } = jiraOptions;

    return {
        url,
        headers: {
            "Content-Type": "application/json"
        },
        auth: {
            username,
            password
        },
        json: payload
    };
}

// flattens the list of issues to a key-summary list
function _summarizeIssues(data) {
    return data.issues.map((issue) => {
        let {
            key,
            fields: {
                summary
            }
        } = issue;

        return {
            key,
            summary
        };
    });
}

// handles failure of HTTP requests
function _handleFailure(error) {
    let {
        statusCode
    } = error, message;

    if (!statusCode) {
        message = error.message;
    } else {
        message = `Failed with ${statusCode}`;
    }

    return Promise.reject(message);
}<|endoftext|>


<commit_before>/*jshint expr:true*/
describe('hello', function () {
  it('should haz a henry', function () {
    'henry'.should.exist;
  });
});<commit_msg>remove null test<commit_after><|endoftext|>


<commit_before>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual(FILL_ME_IN);
    expect(odd.length).toBe(FILL_ME_IN);
    expect(numbers.length).toBe(FILL_ME_IN);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual(FILL_ME_IN);
    expect(_.range(1, 4)).toEqual(FILL_ME_IN);
    expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(FILL_ME_IN);
  });

});

<commit_msg>fixed higherOrderFunctions "filter array items that meet criteria"<commit_after>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1,3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual(FILL_ME_IN);
    expect(_.range(1, 4)).toEqual(FILL_ME_IN);
    expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(FILL_ME_IN);
  });

});

<|endoftext|>


<commit_before>(function($) {

zeit.cms.declare_namespace('zeit.content.article');

zeit.content.article.PreviewTabs = gocept.Class.extend({

    SESSION_KEY: 'zeit.content.article.preview.selected',

    construct: function(id) {
        var self = this;
        self.initialize_tabs(id);
        self.restore_selection();
    },

    initialize_tabs: function(id) {
        var self = this;
        self.tabs = $(id).tabs();
        $(id)[0].preview_tab = self;
        self.tabs.tabs('add', '#preview-tablet', 'iPad');
        self.tabs.tabs('add', '#preview-full', 'Desktop');

        self.tabs.bind('tabsselect', function(event, ui) {
            var id = $(ui.tab).attr('href');
            self.save_selection(id);
            self.reload_frame(id);
        });

        $('#edit-form-article-content').bind('fold',function(e,folded){
            if (!folded){
                var id = window.sessionStorage.getItem(self.SESSION_KEY);
                if ($(id).css('height')=="500px"){
                    $(id).data('reloaded',false);
                    self.reload_frame(id);
                }
            }
        });
    },

    reload_frame: function(id) {
        if (!$(id).data('reloaded')){
            $(id).data('reloaded',true);
            $(id).attr("src", $(id).attr("src"));
        }
    },

    save_selection: function(id) {
        var self = this;
        window.sessionStorage.setItem(self.SESSION_KEY, id);
    },

    restore_selection: function() {
        var self = this;
        var id = window.sessionStorage.getItem(self.SESSION_KEY);
        $(id).data('reloaded',true);
        self.tabs.tabs('select', id);
    }

});

MochiKit.Signal.connect(window, 'cp-editor-loaded', function() {
    if ($('#preview-tabs').length) {

        var preview_tabs = new zeit.content.article.PreviewTabs('#preview-tabs');

        window.addEventListener("message", function(e){
            var id =  e.data.tablet ? "#preview-tablet" : "#preview-full";
            var height = e.data.height_obj.offsetHeight;
            if (height >= 500){
               $(id).css('height',(height+20)+"px");
            }
        }, false);
    }
});

})(jQuery);
<commit_msg>whitespace<commit_after>(function($) {

zeit.cms.declare_namespace('zeit.content.article');

zeit.content.article.PreviewTabs = gocept.Class.extend({

    SESSION_KEY: 'zeit.content.article.preview.selected',

    construct: function(id) {
        var self = this;
        self.initialize_tabs(id);
        self.restore_selection();
    },

    initialize_tabs: function(id) {
        var self = this;
        self.tabs = $(id).tabs();
        $(id)[0].preview_tab = self;
        self.tabs.tabs('add', '#preview-tablet', 'iPad');
        self.tabs.tabs('add', '#preview-full', 'Desktop');

        self.tabs.bind('tabsselect', function(event, ui) {
            var id = $(ui.tab).attr('href');
            self.save_selection(id);
            self.reload_frame(id);
        });

        $('#edit-form-article-content').bind('fold',function(e,folded){
            if (!folded){
                var id = window.sessionStorage.getItem(self.SESSION_KEY);
                if ($(id).css('height')=="500px"){
                    $(id).data('reloaded',false);
                    self.reload_frame(id);
                }
            }
        });
    },

    reload_frame: function(id) {
        if (!$(id).data('reloaded')){
            $(id).data('reloaded',true);
            $(id).attr("src", $(id).attr("src"));
        }
    },

    save_selection: function(id) {
        var self = this;
        window.sessionStorage.setItem(self.SESSION_KEY, id);
    },

    restore_selection: function() {
        var self = this;
        var id = window.sessionStorage.getItem(self.SESSION_KEY);
        $(id).data('reloaded',true);
        self.tabs.tabs('select', id);
    }

});

MochiKit.Signal.connect(window, 'cp-editor-loaded', function() {
    if ($('#preview-tabs').length) {

        var preview_tabs = new zeit.content.article.PreviewTabs('#preview-tabs');

        window.addEventListener("message", function(e){
            var id =  e.data.tablet ? "#preview-tablet" : "#preview-full";
            var height = e.data.height_obj.offsetHeight;
            if (height >= 500){
               $(id).css('height',(height+20)+"px");
            }
        }, false);
    }
});

})(jQuery);
<|endoftext|>


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

/* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying
 * LICENSE file.
 */

/**
 *
 * Author : paul menager
 * Requirements : intended to be run on synology disks (NAS)
 * Installation : npm install public-ip aws-sdk
 * Run : node updateRoute53.js
 * Date : 20150814
 */

/**
 * Configuration
 */
var AWS_ACCESS_KEY = "EDIT_ME";
var AWS_SECRET_KEY = "EDIT_ME";
var AWS_REGION = "us-west-1";//EDIT_ME
var previousIpFileLocation = "ip.txt";
var fileEncoding = "utf8";
var ROUTE53_HOSTED_ZONE_ID = "/hostedzone/EDIT_ME";
var ROUTE53_DOMAIN = "EDIT_ME";
/**
 * Global variables
 */
var currentIP = null;
var previousIP = null;

/**
 * Dependencies
 */
/*
 Package for getting public IP
 */
var publicIp = require('public-ip');
/*
 Package for file system
 */
var fs = require('fs');
/*
 var AWS = require('aws-sdk');
 */
var AWS = require('aws-sdk');
AWS.config.update({
    accessKeyId: AWS_ACCESS_KEY,
    secretAccessKey: AWS_SECRET_KEY
});
AWS.config.update({region: AWS_REGION});
/*
 Package used for calling synology DSM CLI tool
 */
var exec = require('child_process').exec;

var publicIpCallback = function (err, ip) {
    if (err) {
        console.log("Unable to get public IP");
        return console.log(err);
    } else {
        currentIP = ip;
        console.log("Current public IP is " + currentIP);
        if (previousIP) {
            compareIP();
        }
    }
};

var getPublicIP = function () {
    publicIp(publicIpCallback);
};

var getPreviousIP = function () {
    fs.stat(previousIpFileLocation, function (err, stat) {
        if (err && err.code == 'ENOENT') {
            fs.writeFile(previousIpFileLocation, '');
        } else if (err) {
            console.log('Error creating previous IP file : ', err.code);
            notifySynologyDSM("Error creating previous IP file : " + err.code);
        }
    });

    fs.readFile(previousIpFileLocation, fileEncoding, function (err, data) {
        if (err) {
            console.log("Error reading file : " + err.code);
            notifySynologyDSM("Error reading previous IP file : " + err.code);
        } else if (!data || data === '') {
            writeCurrentIPInFile();
        } else {
            previousIP = data;
            console.log("Previous public IP was " + previousIP);
            if (currentIP) {
                compareIP();
            }
        }
    });
};

var writeCurrentIPInFile = function () {
    if (currentIP) {
        fs.writeFile(previousIpFileLocation, currentIP, function (err) {
            if (err) {
                console.log("Error writing previous IP file : " + err.code);
                notifySynologyDSM("Error writing previous IP file : " + err.code);
            }
            console.log("The previous IP file was updated with the new IP : " + currentIP);
        });
    }
};

var compareIP = function () {
    if (hasIPChanged()) {
        updateRoute53WithNewIP();
    } else {
        console.log("Nothing to do ...");
    }
};

var hasIPChanged = function () {
    if (currentIP && previousIP) {
        return currentIP !== previousIP
    }
};

var updateRoute53WithNewIP = function () {
    var route53 = new AWS.Route53();
    var params = {
        "HostedZoneId": ROUTE53_HOSTED_ZONE_ID,
        "ChangeBatch": {
            "Changes": [
                {
                    "Action": 'UPSERT',
                    "ResourceRecordSet": {
                        "Name": ROUTE53_DOMAIN,
                        "Type": 'A',
                        "TTL": 300,
                        "ResourceRecords": [
                            {
                                "Value": currentIP
                            }
                        ]
                    }
                }
            ]
        }
    };
    route53.changeResourceRecordSets(params, function (err, data) {
        if (err) {
            console.log("Unable to update Route 53 !");
            notifySynologyDSM("Error updating route 53 : " + err.code + " / " + err.statusCode);
            console.log(err, err.stack);
        }
        else {
            console.log("Successfully updated Route 53");
            notifySynologyDSM("New IP(" + currentIP + ") has successfully been submitted to route 53.");
            writeCurrentIPInFile();
        }
    });

};

var notifySynologyDSM = function (body) {
    var title = "Script DNS route 53 updater.";
    exec("synodsmnotify @administrators '" + title + "' '" + body + "'", function (error, stdout, stderr) {
        // command output is in stdout
    });
};

var startPoint = function () {
    getPublicIP();
    getPreviousIP();
};

startPoint();
<commit_msg>Update synoDNSUpdater.js<commit_after>#!/usr/bin/env node

/* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying
 * LICENSE file.
 */

/**
 *
 * Author : paul menager (w/ update from shawn mcnaughton)
 * Requirements : intended to be run on synology disks (NAS)
 * Installation : npm install
 * Run : node synoDNSUpdater.js
 * Date : 20170618
 */

/**************************************
 * Start Configuration
 **************************************/
// AWS_ACCESS_KEY
// AWS Access Key for a user with route53:ChangeResourceRecordSets and route53:ListResourceRecordSets on the domain you want to modify
// Example: ABCABCABCABCABCABC1A
var AWS_ACCESS_KEY = "EDIT_ME";

// AWS_SECRET_KEY
// AWS Secret Key for a user with route53:ChangeResourceRecordSets and route53:ListResourceRecordSets on the domain you want to modify
// Example: ABCD+v+Abc123Abc123Abc123Abc123Abc123Abc
var AWS_SECRET_KEY = "EDIT_ME";

// AWS_REGION
// AWS Region to act in - won't matter for most records, except R53 'latency optimized'
// Example: us-west-1
var AWS_REGION = "EDIT_ME";

// ROUTE53_HOSTED_ZONE_ID
// The Hosted Zone ID in Route 53 for the domain
// Example: /hostedzone/ABC123ABC123AB
var ROUTE53_HOSTED_ZONE_ID = "/hostedzone/EDIT_ME";

// ROUTE53_DOMAIN
// The actual name of the domain name to modify, including an ending period
// Examples: mysite.com. OR me.myshareddomain.com.
var ROUTE53_DOMAIN = "EDIT_ME";

/**************************************
 * End Configuration
 **************************************/

/**
 * Global variables
 */
var currentIP = null;
var previousIP = null;

/**
 * Dependencies
 */
var Promise = require('bluebird');
var publicIp = require('public-ip');
var AWS = require('aws-sdk');
var exec = require('child_process').exec;

AWS.config.update({
    accessKeyId: AWS_ACCESS_KEY,
    secretAccessKey: AWS_SECRET_KEY
});
AWS.config.update({region: AWS_REGION});
var route53 = new AWS.Route53();
var route53Async = Promise.promisifyAll(route53);

var getPublicIP = function () {
    return publicIp.v4()
	    .then(function(ip) {
	        currentIP = ip;
	        console.log("Current public IP is " + currentIP);
    	}).catch(function(err) {
	        console.log("Unable to get public IP");
	        console.log(err);
	        throw err;
    	});
};

var getLatestRegisteredIPFromRoute53 = function() {
    var params = {
        "HostedZoneId": ROUTE53_HOSTED_ZONE_ID,
        "StartRecordName": ROUTE53_DOMAIN,
        "StartRecordType": 'A',
        "MaxItems": '1'
    };
    return route53Async.listResourceRecordSetsAsync(params)
    	.then(function(listResults) {
    		previousIP = listResults.ResourceRecordSets[0].ResourceRecords[0].Value;
            console.log("Successfully polled Route 53 and retrieved Registered IP of " + currentIP);
            notifySynologyDSM("Successfully polled Route 53 and retrieved Registered IP of (" + currentIP + ")");
            return previousIP;
    	})
    	.catch(function(err) {
            console.log("Unable to poll from Route 53!");
            notifySynologyDSM("Error polling route 53 : " + err.code + " / " + err.statusCode);
            console.log(err, err.stack);
            throw err;
    	});
};

var updateRoute53WithNewIP = function() {
    var params = {
        "HostedZoneId": ROUTE53_HOSTED_ZONE_ID,
        "ChangeBatch": {
            "Changes": [
                {
                    "Action": 'UPSERT',
                    "ResourceRecordSet": {
                        "Name": ROUTE53_DOMAIN,
                        "Type": 'A',
                        "TTL": 300,
                        "ResourceRecords": [
                            {
                                "Value": currentIP
                            }
                        ]
                    }
                }
            ]
        }
    };
    return route53Async.changeResourceRecordSetsAsync(params)
    	.then(function() {
            console.log("Successfully updated Route 53");
            notifySynologyDSM("New IP(" + currentIP + ") has successfully been submitted to route 53.");
            return true;
    	})
    	.catch(function(err) {
            console.log("Unable to update Route 53 !");
            notifySynologyDSM("Error updating route 53 : " + err.code + " / " + err.statusCode);
            console.log(err, err.stack);
            throw err;
    	});
};

var notifySynologyDSM = function (body) {
    var title = "Script DNS route 53 updater.";
    exec("synodsmnotify @administrators '" + title + "' '" + body + "'", function (error, stdout, stderr) {
        // command output is in stdout
    });
};

var startPoint = function () {
    Promise.all([getPublicIP(), getLatestRegisteredIPFromRoute53()])
    	.then(function() {
		    if (currentIP !== previousIP) {
		        console.log("Current IP " + currentIP + " differs from Registered IP " + previousIP + "; updating...");
		        return updateRoute53WithNewIP();
		    } else {
		        console.log("Current and Registered IP are both " + currentIP + "; exiting...");
		        return true;
		    }
		});
};

startPoint();
<|endoftext|>


<commit_before>module.exports = (client, command) => `${client.config.prefix}${command.conf.aliases.length === 0 ? command.help.name : `(${command.help.name}|${command.conf.aliases.join("|")})`}${command.help.usage !== "" ? ` ${command.help.usage.split(" ").join(command.help.usageDelim)}` : ""}`;
<commit_msg>Delete fullUsage.js<commit_after><|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var config = require('../config'),
  chalk = require('chalk'),
  path = require('path'),
  mongoose = require('mongoose');

// Load the mongoose models
module.exports.loadModels = function (callback) {
  // Globbing model files
  config.files.server.models.forEach(function (modelPath) {
    require(path.resolve(modelPath));
  });

  if (callback) callback();
};

// Initialize Mongoose
module.exports.connect = function (cb) {
  var _this = this;

  var db = mongoose.connect(config.db.uri, config.db.options, function (err) {
    // Log Error
    if (err) {
      console.error(chalk.red('Could not connect to MongoDB!'));
      console.log(err);
    } else {

      mongoose.Promise = config.db.promise;

      // Enabling mongoose debug mode if required
      mongoose.set('debug', config.db.debug);

      // Call callback FN
      if (cb) cb(db);
    }
  });
};

module.exports.disconnect = function (cb) {
  mongoose.disconnect(function (err) {
    console.info(chalk.yellow('Disconnected from MongoDB.'));
    cb(err);
  });
};
<commit_msg>fix(mongoose): fixing mongoose deprecation notice for promises lib (#1691)<commit_after>'use strict';

/**
 * Module dependencies.
 */
var config = require('../config'),
  chalk = require('chalk'),
  path = require('path'),
  mongoose = require('mongoose');

// Load the mongoose models
module.exports.loadModels = function (callback) {
  // Globbing model files
  config.files.server.models.forEach(function (modelPath) {
    require(path.resolve(modelPath));
  });

  if (callback) callback();
};

// Initialize Mongoose
module.exports.connect = function (cb) {
  var _this = this;

  mongoose.Promise = config.db.promise;

  var db = mongoose.connect(config.db.uri, config.db.options, function (err) {
    // Log Error
    if (err) {
      console.error(chalk.red('Could not connect to MongoDB!'));
      console.log(err);
    } else {

      // Enabling mongoose debug mode if required
      mongoose.set('debug', config.db.debug);

      // Call callback FN
      if (cb) cb(db);
    }
  });
};

module.exports.disconnect = function (cb) {
  mongoose.disconnect(function (err) {
    console.info(chalk.yellow('Disconnected from MongoDB.'));
    cb(err);
  });
};
<|endoftext|>