<commit_before>const React = require('react');
const h = require('react-hyperscript');
const _ = require('lodash');
const Loader = require('react-loader');
//const queryString = require('query-string');

// const hideTooltips = require('../../common/cy/events/click').hideTooltips;
// const removeStyle= require('../../common/cy/manage-style').removeStyle;
const make_cytoscape = require('../../common/cy/');
const enrichmentStylesheet= require('../../common/cy/enrichment-stylesheet');
const TokenInput = require('./token-input');
const { BaseNetworkView } = require('../../common/components');
const { getLayoutConfig } = require('../../common/cy/layout');
const { ServerAPI } = require('../../services/');

//const downloadTypes = require('../../common/config').downloadTypes;

const enrichmentConfig={
  //extablish toolbar and declare features to not include
  toolbarButtons: _.differenceBy(BaseNetworkView.config.toolbarButtons,[{'id': 'expandCollapse'}, {'id': 'showInfo'}],'id'),
  menus: BaseNetworkView.config.menus,
  //allow for searching of nodes
  useSearchBar: true
};

//temporary empty network for development purposes
const emptyNetworkJSON = {
    edges: [],
    nodes: []
};

const testNetwork = {
  edges: [
    {data:{id: 'edge1', source:"node3", target: "node4", similarity: 3 }},
    {data:{id: 'edge2', source:"node1", target: "node2", similarity: .4 }},
    {data:{id: 'edge3', source:"node1", target: "node4" }},
    {data:{id: 'edge4', source:"node2", target: "node4" }}
  ],
  nodes: [
    {data: {id: "node1", description: "node1"}},
    {data: {id: "node2", description: "node2"}},
    {data: {id: "node3", description: "node3"}},
    {data: {id: "node4", description: "node4"}}
  ]
};

class Enrichment extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      cy: make_cytoscape({headless: true, stylesheet: enrichmentStylesheet, showTooltipsOnEdges:false, minZoom:0.01 }),
      componentConfig: enrichmentConfig,
      layoutConfig: getLayoutConfig(),
      networkJSON: emptyNetworkJSON,
      //networkJSON: testNetwork,

      networkMetadata: {
        name: "enrichment",
        datasource: [],
        comments: []
      },

      //temporarily set to false so loading spinner is disabled
      loaded: true,

      closeToolBar: true,
      unrecognized: [],
      inputs: "",
      timedOut: false
    };

    this.handleInputs = this.handleInputs.bind(this);
    this.handleUnrecognized = this.handleUnrecognized.bind(this);
    this.handleGenes = this.handleGenes.bind(this);
  }

  handleInputs( inputs ) {
    this.setState({ inputs });
    this.setState({loaded: true});
  }

  handleUnrecognized( unrecognized ) {
    this.setState({ unrecognized });
  }

  handleGenes( genes ) {
    const updateNetworkJSON = async () => {
      const analysisResult = await ServerAPI.enrichmentAPI({ genes: genes }, "analysis");
      if( analysisResult === undefined ) {
        this.setState({ timedOut: true });
        return;
      }
      const visualizationResult = await ServerAPI.enrichmentAPI({ pathways: analysisResult.pathwayInfo}, "visualization");
      if( visualizationResult === undefined ) {
        this.setState({ timedOut: true });
        return;
      }
      this.setState({
        closeToolBar: false,
        loaded: true,
        networkJSON: {
          edges: visualizationResult.graph.elements.edges,
          nodes: visualizationResult.graph.elements.nodes
        }
      });
    };
    updateNetworkJSON();
  }

  render() {
    let { cy, componentConfig, layoutConfig, networkJSON, networkMetadata, networkLoading, closeToolBar, loaded } = this.state;
    let retrieveTokenInput = () => h(TokenInput,{
      inputs: this.state.inputs,
      handleInputs: this.handleInputs,
      handleUnrecognized: this.handleUnrecognized,
      unrecognized: this.state.unrecognized,
      handleGenes: this.handleGenes
    });

    const baseView = !this.state.timedOut ?
    h(BaseNetworkView.component, {
      cy,
      componentConfig,
      layoutConfig,
      networkJSON,
      networkMetadata,
      networkLoading,
      closeToolBar,
      titleContainer: () => h(retrieveTokenInput)
    })
    :
    h('div.no-network',[h('strong.title','Network currently unavailable'),h('span','Try a diffrent set of genes')]);

    const loadingView = h(Loader, { loaded: loaded, options: { left: '50%', color: '#16A085' }});

     // create a view shell loading view e.g looks like the view but its not
    const content = loaded ? baseView : loadingView;
    return h('div.main', [content]);
  }
}

module.exports = Enrichment;<commit_msg>test cases if api variables undefined<commit_after>const React = require('react');
const h = require('react-hyperscript');
const _ = require('lodash');
const Loader = require('react-loader');
//const queryString = require('query-string');

// const hideTooltips = require('../../common/cy/events/click').hideTooltips;
// const removeStyle= require('../../common/cy/manage-style').removeStyle;
const make_cytoscape = require('../../common/cy/');
const enrichmentStylesheet= require('../../common/cy/enrichment-stylesheet');
const TokenInput = require('./token-input');
const { BaseNetworkView } = require('../../common/components');
const { getLayoutConfig } = require('../../common/cy/layout');
const { ServerAPI } = require('../../services/');

//const downloadTypes = require('../../common/config').downloadTypes;

const enrichmentConfig={
  //extablish toolbar and declare features to not include
  toolbarButtons: _.differenceBy(BaseNetworkView.config.toolbarButtons,[{'id': 'expandCollapse'}, {'id': 'showInfo'}],'id'),
  menus: BaseNetworkView.config.menus,
  //allow for searching of nodes
  useSearchBar: true
};

//temporary empty network for development purposes
const emptyNetworkJSON = {
    edges: [],
    nodes: []
};

const testNetwork = {
  edges: [
    {data:{id: 'edge1', source:"node3", target: "node4", similarity: 3 }},
    {data:{id: 'edge2', source:"node1", target: "node2", similarity: .4 }},
    {data:{id: 'edge3', source:"node1", target: "node4" }},
    {data:{id: 'edge4', source:"node2", target: "node4" }}
  ],
  nodes: [
    {data: {id: "node1", description: "node1"}},
    {data: {id: "node2", description: "node2"}},
    {data: {id: "node3", description: "node3"}},
    {data: {id: "node4", description: "node4"}}
  ]
};

class Enrichment extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      cy: make_cytoscape({headless: true, stylesheet: enrichmentStylesheet, showTooltipsOnEdges:false, minZoom:0.01 }),
      componentConfig: enrichmentConfig,
      layoutConfig: getLayoutConfig(),
      networkJSON: emptyNetworkJSON,
      //networkJSON: testNetwork,

      networkMetadata: {
        name: "enrichment",
        datasource: [],
        comments: []
      },

      //temporarily set to false so loading spinner is disabled
      loaded: true,

      closeToolBar: true,
      unrecognized: [],
      inputs: "",
      timedOut: false
    };

    this.handleInputs = this.handleInputs.bind(this);
    this.handleUnrecognized = this.handleUnrecognized.bind(this);
    this.handleGenes = this.handleGenes.bind(this);
  }

  handleInputs( inputs ) {
    this.setState({ inputs });
    this.setState({ loaded: true });
  }

  handleUnrecognized( unrecognized ) {
    this.setState({ unrecognized });
  }

  handleGenes( genes ) {
    const updateNetworkJSON = async () => {
      const analysisResult = await ServerAPI.enrichmentAPI({ genes: genes }, "analysis");

      if( !analysisResult || !analysisResult.pathwayInfo ) {
        this.setState({ timedOut: true });
        return;
      }

      const visualizationResult = await ServerAPI.enrichmentAPI({ pathways: analysisResult.pathwayInfo}, "visualization");
      const edges = visualizationResult.graph.elements.edges;
      const nodes = visualizationResult.graph.elements.nodes;

      if( !visualizationResult || !nodes ) {
        this.setState({ timedOut: true });
        return;
      }

      this.setState({
        closeToolBar: false,
        loaded: true,
        networkJSON: {
          edges: edges,
          nodes: nodes
        }
      });
    };
    updateNetworkJSON();
  }

  render() {
    let { cy, componentConfig, layoutConfig, networkJSON, networkMetadata, networkLoading, closeToolBar, loaded } = this.state;
    let retrieveTokenInput = () => h(TokenInput,{
      inputs: this.state.inputs,
      handleInputs: this.handleInputs,
      handleUnrecognized: this.handleUnrecognized,
      unrecognized: this.state.unrecognized,
      handleGenes: this.handleGenes
    });

    const baseView = !this.state.timedOut ?
    h(BaseNetworkView.component, {
      cy,
      componentConfig,
      layoutConfig,
      networkJSON,
      networkMetadata,
      networkLoading,
      closeToolBar,
      titleContainer: () => h(retrieveTokenInput)
    })
    :
    h('div.no-network',[h('strong.title','Network currently unavailable'),h('span','Try a diffrent set of genes')]);

    const loadingView = h(Loader, { loaded: loaded, options: { left: '50%', color: '#16A085' }});

     // create a view shell loading view e.g looks like the view but its not
    const content = loaded ? baseView : loadingView;
    return h('div.main', [content]);
  }
}

module.exports = Enrichment;<|endoftext|>


<commit_before>import {
    SETTINGS_LIST_RECEIVED,
    SETTING_DELETE_START,
    SETTING_DELETE_COMPLETE,
    SETTING_SAVE_START,
    SETTING_SAVE_COMPLETE
} from '../actions/actionTypes';

const INITIAL_STATE = {
    settings:{
        directories: []
    },
    saveInProgress: false,
    currentlySavingSettingID: -1,
    lastSavedSettingID: -1,
    deleteInProgress: false,
    currentlyDeletingSettingID: -1,
    currentlyDeletingSettingCategory: "",
    lastAPIAction: ""
}

export default function settingsReducer(state = INITIAL_STATE, action){
    switch(action.type){
        case SETTINGS_LIST_RECEIVED:
            const settings = {...state.settings};
            settings[action.category] = action.settings;
            return {
                ...state,
                settings
            }
        case SETTING_SAVE_START:
            return {
                ...state,
                saveInProgress: true,
                currentlySavingSettingID: action.settingID,
                lastAPIAction: ""
            }
        case SETTING_SAVE_COMPLETE:
            const newSettings = {...state.settings};

            const category = newSettings[action.data.category];
            if(state.currentlySavingSettingID === 0){
                category.push(action.data);
            } else {
                for(let i=0; i<category.length; i++){
                    if(category[i].id === action.data.id){
                        category[i].key = action.data.key;
                        category[i].value = action.data.value;
                    }
                }
            }
            newSettings[action.data.category] = category;
            return {
                ...state,
                settings: newSettings,
                saveInProgress: false,
                currentlySavingSettingID: -1,
                lastSavedSettingID: state.currentlySavingSettingID,
                lastAPIAction: "save"
            }
        case SETTING_DELETE_START:
            return {
                ...state,
                deleteInProgress: true,
                currentlyDeletingSettingID: action.settingID,
                currentlyDeletingSettingCategory: action.category,
                lastAPIAction: ""
            }
        case SETTING_DELETE_COMPLETE:
            const copySettings = {...state.settings};
            const copyCategory = [...copySettings[state.currentlyDeletingSettingCategory]];

            for(let i = 0; i<copyCategory.length; i++){
                if(copyCategory[i].id === state.currentlyDeletingSettingID){
                    copyCategory.splice(i, 1);
                }
            }
            copySettings[state.currentlyDeletingSettingCategory] = copyCategory;
            return {
                ...state,
                settings:copySettings,
                deleteInProgress: false,
                currentlyDeletingSettingID: -1,
                currentlyDeletingSettingCategory: "",
                lastAPIAction: "delete"
            }
        default:
            return state;
    }

}<commit_msg>Removed the settings category received reducer.<commit_after>import {
    SETTINGS_ALL_RECEIVED,
    SETTING_DELETE_START,
    SETTING_DELETE_COMPLETE,
    SETTING_SAVE_START,
    SETTING_SAVE_COMPLETE
} from '../actions/actionTypes';

const INITIAL_STATE = {
    currentlyDeletingSettingID: -1,
    currentlyDeletingSettingCategory: "",
    currentlySavingSettingID: -1,
    deleteInProgress: false,
    hasAllSettings: false,
    lastAPIAction: "",
    lastSavedSettingID: -1,
    saveInProgress: false,
    settings:{
        directories: []
    }
}

export default function settingsReducer(state = INITIAL_STATE, action){
    switch(action.type){
        case SETTINGS_ALL_RECEIVED:
            const nextSettings = {};
            action.settings.forEach((setting)=>{
                const category = setting.category;
                if(!nextSettings.hasOwnProperty(category)){
                    nextSettings[category] = [];
                }
                nextSettings[category].push(setting);
            });
            return {
                ...state,
                settings: nextSettings,
                hasAllSettings: true
            }
        case SETTING_SAVE_START:
            return {
                ...state,
                saveInProgress: true,
                currentlySavingSettingID: action.settingID,
                lastAPIAction: ""
            }
        case SETTING_SAVE_COMPLETE:
            const newSettings = {...state.settings};

            const category = newSettings[action.data.category];
            if(state.currentlySavingSettingID === 0){
                category.push(action.data);
            } else {
                for(let i=0; i<category.length; i++){
                    if(category[i].id === action.data.id){
                        category[i].key = action.data.key;
                        category[i].value = action.data.value;
                    }
                }
            }
            newSettings[action.data.category] = category;
            return {
                ...state,
                settings: newSettings,
                saveInProgress: false,
                currentlySavingSettingID: -1,
                lastSavedSettingID: state.currentlySavingSettingID,
                lastAPIAction: "save"
            }
        case SETTING_DELETE_START:
            return {
                ...state,
                deleteInProgress: true,
                currentlyDeletingSettingID: action.settingID,
                currentlyDeletingSettingCategory: action.category,
                lastAPIAction: ""
            }
        case SETTING_DELETE_COMPLETE:
            const copySettings = {...state.settings};
            const copyCategory = [...copySettings[state.currentlyDeletingSettingCategory]];

            for(let i = 0; i<copyCategory.length; i++){
                if(copyCategory[i].id === state.currentlyDeletingSettingID){
                    copyCategory.splice(i, 1);
                }
            }
            copySettings[state.currentlyDeletingSettingCategory] = copyCategory;
            return {
                ...state,
                settings:copySettings,
                deleteInProgress: false,
                currentlyDeletingSettingID: -1,
                currentlyDeletingSettingCategory: "",
                lastAPIAction: "delete"
            }
        default:
            return state;
    }

}<|endoftext|>


<commit_before>(function(){
var ponto = angular.module('ponto',['timer']);

ponto.controller('PontoController', ['$scope', 'Timer', '$log', function($scope, Timer, $log){

$scope.registrar = function(element){
	console.log("oi");
}

}])

ponto.directive('registerCard', ['$log', function($log){
	var templateHtml =
	`
\n
	 	{{label}} :\n
	 	{{hour}}\n
	 	query_builder\n

`;
	return{
		restrict:'E',
		template:templateHtml,
		scope:{
			id: '@elementId',
			label: '@label',
			hour:'=ngModel'
		},
		controller: ['$scope', function($scope) {
			$scope.registrar = function(){
				$scope.hour = new Date("HH:MM:SS");
			}
		}]
	}
}]);

})();<commit_msg>asdasd<commit_after>(function(){
var ponto = angular.module('ponto',['timer']);

ponto.controller('PontoController', ['$scope', 'Timer', '$log', function($scope, Timer, $log){

$scope.registrar = function(element){
	console.log("oi");
}

}])

ponto.directive('registerCard', ['$log', function($log){
	var templateHtml =
	`
\n
	 	{{label}} :\n
	 	{{hour}}\n
	 	query_builder\n

`;
	return{
		restrict:'E',
		template:templateHtml,
		scope:{
			id: '@elementId',
			label: '@label',
			hour:'=ngModel'
		},
		controller: ['$scope', function($scope) {
			$scope.registrar = function(){
				$scope.hour = new Date();
			}
		}]
	}
}]);

})();<|endoftext|>


<commit_before>'use strict';

// Usage accumulator service.

const _ = require('underscore');
const webapp = require('abacus-webapp');
const cluster = require('abacus-cluster');
const router = require('abacus-router');
const yieldable = require('abacus-yieldable');
const urienv = require('abacus-urienv');
const oauth = require('abacus-oauth');
const mconfigcb = require('abacus-metering-config');
const rconfigcb = require('abacus-rating-config');
const transform = require('abacus-transform');
const dataflow = require('abacus-dataflow');
const seqid = require('abacus-seqid');
const timewindow = require('abacus-timewindow');

const map = _.map;
const last = _.last;
const extend = _.extend;
const omit = _.omit;
const filter = _.filter;
const rest = _.rest;
const indexOf = _.indexOf;

const treduce = yieldable(transform.reduce);

const mconfig = yieldable(mconfigcb);
const rconfig = yieldable(rconfigcb);

/* eslint camelcase: 1 */

// Setup debug log
const debug = require('abacus-debug')('abacus-usage-accumulator');

// Secure the routes or not
const secured = () => process.env.SECURED === 'true' ? true : false;

// OAuth bearer access token with Abacus system access scopes
let systemToken;

// Resolve service URIs
const uris = urienv({
  auth_server: 9882,
  aggregator: 9300
});

// Return OAuth system scopes needed to write input docs
const iwscope = (udoc) => secured() ? {
  system: ['abacus.usage.write']
} : undefined;

// Return OAuth system scopes needed to read input and output docs
const rscope = (udoc) => secured() ? {
  system: ['abacus.usage.read']
} : undefined;

// Return the keys and times of our docs
const ikey = (udoc) =>
  [udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id].join('/');

const itime = (udoc) =>
  seqid();

const igroups = (udoc) =>
  [[udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id, udoc.metering_plan_id,
    udoc.rating_plan_id, udoc.pricing_plan_id].join('/')];

const okeys = (udoc) =>
  [[udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id, udoc.metering_plan_id,
    udoc.rating_plan_id, udoc.pricing_plan_id].join('/')];

const otimes = (udoc, itime) =>
  [map([udoc.start, udoc.end], seqid.pad16).join('/')];

// The scaling factor of each time window for creating the date string
// [Second, Minute, Hour, Day, Month, Year, Forever]
const slack = () => /^[0-9]+[MDhms]$/.test(process.env.SLACK) ? {
  scale : process.env.SLACK.charAt(process.env.SLACK.length - 1),
  width : process.env.SLACK.match(/[0-9]+/)[0]
} : {
  scale : 'm',
  width : 10
};

// Time dimension keys corresponding to their respective window positions
const dimensions = ['s', 'm', 'h', 'D', 'M'];

// Millisecond representation of the time dimensions
const msDimensions = {
  M: 2678400000,
  D: 86400000,
  h: 3600000,
  m: 60000,
  s: 1000
};

// Return the configured price for the metrics that is attached in the
// usage document
const price = (pricings, metric) =>
  filter(pricings, (m) => m.name === metric)[0].price;

// Return the accumulate function for a given metric
const accumfn = (metrics, metric) => {
  return filter(metrics, (m) => m.name === metric)[0].accumulatefn;
};

// Return the rate function for a given metric
const ratefn = (metrics, metric) => {
  return filter(metrics, (m) => m.name === metric)[0].ratefn;
};

// Calculates the max number of time windows in a given time scale based on
// the slack's configuration
const maxSlack = (w) => {
  const slackscale = {
    M: { 4: 1 },
    D: { 4: 28, 3: 1 },
    h: { 4: 672, 3: 24, 2: 1 },
    m: { 4: 40320, 3: 1440, 2: 60, 1: 1 },
    s: { 4: 2419200, 3: 86400, 2: 3600, 1: 60, 0: 1 }
  };
  if(slack().scale && slackscale[slack().scale][w])
    return map(Array(Math.ceil(1 / slackscale[slack().scale][w] * slack().width)
      + 1), () => null);
  return [null];
};

// Return the accumulated usage windows for a given metric
const accum = (au, metric) => {
  const a = filter(au, (a) => a.metric === metric);
  return a.length ? a[0].windows : [maxSlack(0),
    maxSlack(1), maxSlack(2), maxSlack(3), maxSlack(4)];
};

// Accumulate usage and return new accumulated value
const accumulate = function *(a, u) {
  const now = Date.now();
  const slackLimit = msDimensions[slack().scale] * slack().width;
  if(u.end < now - slackLimit)
    throw extend(new Error('The usage submitted is older than ' + slackLimit +
      ' milliseconds'), {
        status: 409,
        error: 'conflict',
        reason: 'The usage submitted is older than ' + slackLimit +
          ' milliseconds',
        noretry: true,
        nobreaker: true
      });

  debug(
    'Accumulating usage %o from %d and new usage %o from %d',
    a, a ? a.end : 0, u, u.end);

  // Compute the accumulated usage time and new usage time
  const processed = a ? a.processed : 0;

  // Use previous accumulated value if any
  const umerge = omit(u, 'id', 'metrics', 'metered_usage', 'measured_usage');
  const amerge = a ? extend({}, a, omit(umerge, 'start')) : extend({
    accumulated_usage: []
  }, umerge);

  // Retrieve the metering plan
  const mplan = yield mconfig(
    u.metering_plan_id, systemToken && systemToken());

  // Retrieve the rating plan
  const rplan = yield rconfig(
    u.rating_plan_id, systemToken && systemToken());

  // Calculate new accumulated usage
  const newa = extend({}, amerge, {
    accumulated_usage: map(u.metered_usage, (mu) => {
      debug('Accumulating metered usage quantity %o', mu);

      // Find the rate function for the given metric
      const rfn = ratefn(rplan.metrics, mu.metric);

      // Find the price for the metric
      const rp = price(u.prices.metrics, mu.metric);

      const aw = accum(amerge.accumulated_usage, mu.metric);

      return {
        metric: mu.metric,
        windows: map(aw, (w, i) => {
          // Get the appropriate time window index
          const twi = timewindow.timeWindowIndex(w, new Date(now),
            new Date(u.end), dimensions[i], true);

          // Expand the timewindows if necessary
          if(i >= indexOf(dimensions, slack().scale) && w.length - 1 < twi)
            map(Array(twi - w.length + 1), () => w.push(null));

          // Shift the windows if now is part of a new time window
          if(a && now > processed)
            timewindow.shiftWindow(new Date(a.processed),
              new Date(now), w, dimensions[i]);

          /* eslint complexity: [1, 6] */
          const quantities = map(w, (tw, j) => {
            const bounds = timewindow.timeWindowBounds(new Date(u.end),
              dimensions[i], -j);
            if(twi === j) {
              if(tw && tw.quantity && tw.quantity.current) {
                debug('Accumulating window %d index %d' +
                  ' new quantity %o old quantity %o', i, twi, tw, mu);

                return {
                  quantity: {
                    previous: tw.quantity.current,
                    current: accumfn(mplan.metrics, mu.metric)
                      (tw.quantity.current, mu.quantity, u.start, u.end,
                      bounds.from, bounds.to)
                  }
                };
              }
              debug('New window %d index %d new quantity %o', i, twi, tw);

              return {
                quantity: {
                  current: accumfn(mplan.metrics, mu.metric)
                    (0, mu.quantity, u.start, u.end, bounds.from, bounds.to)
                }
              };
            }
            return tw ? extend({}, tw) : null;
          });

          // Calculate cost for all accumulated quantities
          return map(quantities, (q) => q ?
            extend(q, { cost: q.quantity.current ?
              rfn(rp, q.quantity.current) : 0 }) :
            null);
        })
      };
    })
  });

  debug('New accumulated usage %o', newa);
  return newa;
};

// Process a group of usage docs and compute the corresponding
// accumulated usage
const accumulateUsage = function *(accums, udocs) {
  const ologs = yield treduce(udocs, function *(log, udoc, i, l) {
    const res = yield accumulate(last(log)[0], udoc);
    return log.concat([[res]]);
  }, [[
    accums[0]
  ]]);
  return rest(ologs);
};

// Create an accumulator service app
const accumulator = () => {
  // Configure Node cluster to use a single process as we want to serialize
  // accumulation requests per db partition and app instance
  cluster.singleton();

  // Create the Webapp
  const app = webapp();

  // Secure metering and batch routes using an OAuth bearer access token
  if (secured())
    app.use(/^\/v1\/metering|^\/batch$/,
      oauth.validator(process.env.JWTKEY, process.env.JWTALGO));

  const reducer = dataflow.reducer(accumulateUsage, {
    input: {
      type: 'metered-usage',
      post: '/v1/metering/metered/usage',
      get: '/v1/metering/metered/usage' +
        '/t/:tseq/k/:korganization_id/:kresource_instance_id' +
        '/:kconsumer_id/:kplan_id',
      dbname: 'abacus-accumulator-metered-usage',
      wscope: iwscope,
      rscope: rscope,
      key: ikey,
      time: itime,
      groups: igroups
    },
    output: {
      type: 'accumulated_usage',
      get: '/v1/metering/accumulated/usage' +
        '/k/:korganization_id/:kresource_instance_id' +
        '/:kconsumer_id/:kplan_id' +
        '/t/:tend/:tstart',
      dbname: 'abacus-accumulator-accumulated-usage',
      rscope: rscope,
      keys: okeys,
      times: otimes
    },
    sink: {
      host: uris.aggregator,
      apps: process.env.AGGREGATOR_APPS,
      post: '/v1/metering/accumulated/usage',
      authentication: systemToken
    }
  });

  app.use(reducer);
  app.use(router.batch(app));

  app.reducer = reducer;
  return app;
};

// Command line interface, create the accumulator app and listen
const runCLI = () => {
  // Cache and schedule the system token renewal
  if (secured()) {
    systemToken = oauth.cache(uris.auth_server, process.env.CLIENT_ID,
      process.env.CLIENT_SECRET, 'abacus.usage.write abacus.usage.read');

    systemToken.start();
  }

  // Create the app, replay any failed events, and listen
  const app = accumulator();
  dataflow.replay(app.reducer, 0, () => {
    app.listen();
  });
};

// Export our public functions
module.exports = accumulator;
module.exports.runCLI = runCLI;
<commit_msg>Fix window bounds to use processing instead of event time<commit_after>'use strict';

// Usage accumulator service.

const _ = require('underscore');
const webapp = require('abacus-webapp');
const cluster = require('abacus-cluster');
const router = require('abacus-router');
const yieldable = require('abacus-yieldable');
const urienv = require('abacus-urienv');
const oauth = require('abacus-oauth');
const mconfigcb = require('abacus-metering-config');
const rconfigcb = require('abacus-rating-config');
const transform = require('abacus-transform');
const dataflow = require('abacus-dataflow');
const seqid = require('abacus-seqid');
const timewindow = require('abacus-timewindow');

const map = _.map;
const last = _.last;
const extend = _.extend;
const omit = _.omit;
const filter = _.filter;
const rest = _.rest;
const indexOf = _.indexOf;

const treduce = yieldable(transform.reduce);

const mconfig = yieldable(mconfigcb);
const rconfig = yieldable(rconfigcb);

/* eslint camelcase: 1 */

// Setup debug log
const debug = require('abacus-debug')('abacus-usage-accumulator');

// Secure the routes or not
const secured = () => process.env.SECURED === 'true' ? true : false;

// OAuth bearer access token with Abacus system access scopes
let systemToken;

// Resolve service URIs
const uris = urienv({
  auth_server: 9882,
  aggregator: 9300
});

// Return OAuth system scopes needed to write input docs
const iwscope = (udoc) => secured() ? {
  system: ['abacus.usage.write']
} : undefined;

// Return OAuth system scopes needed to read input and output docs
const rscope = (udoc) => secured() ? {
  system: ['abacus.usage.read']
} : undefined;

// Return the keys and times of our docs
const ikey = (udoc) =>
  [udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id].join('/');

const itime = (udoc) =>
  seqid();

const igroups = (udoc) =>
  [[udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id, udoc.metering_plan_id,
    udoc.rating_plan_id, udoc.pricing_plan_id].join('/')];

const okeys = (udoc) =>
  [[udoc.organization_id, udoc.resource_instance_id,
    udoc.consumer_id || 'UNKNOWN', udoc.plan_id, udoc.metering_plan_id,
    udoc.rating_plan_id, udoc.pricing_plan_id].join('/')];

const otimes = (udoc, itime) =>
  [map([udoc.start, udoc.end], seqid.pad16).join('/')];

// The scaling factor of each time window for creating the date string
// [Second, Minute, Hour, Day, Month, Year, Forever]
const slack = () => /^[0-9]+[MDhms]$/.test(process.env.SLACK) ? {
  scale : process.env.SLACK.charAt(process.env.SLACK.length - 1),
  width : process.env.SLACK.match(/[0-9]+/)[0]
} : {
  scale : 'm',
  width : 10
};

// Time dimension keys corresponding to their respective window positions
const dimensions = ['s', 'm', 'h', 'D', 'M'];

// Millisecond representation of the time dimensions
const msDimensions = {
  M: 2678400000,
  D: 86400000,
  h: 3600000,
  m: 60000,
  s: 1000
};

// Return the configured price for the metrics that is attached in the
// usage document
const price = (pricings, metric) =>
  filter(pricings, (m) => m.name === metric)[0].price;

// Return the accumulate function for a given metric
const accumfn = (metrics, metric) => {
  return filter(metrics, (m) => m.name === metric)[0].accumulatefn;
};

// Return the rate function for a given metric
const ratefn = (metrics, metric) => {
  return filter(metrics, (m) => m.name === metric)[0].ratefn;
};

// Calculates the max number of time windows in a given time scale based on
// the slack's configuration
const maxSlack = (w) => {
  const slackscale = {
    M: { 4: 1 },
    D: { 4: 28, 3: 1 },
    h: { 4: 672, 3: 24, 2: 1 },
    m: { 4: 40320, 3: 1440, 2: 60, 1: 1 },
    s: { 4: 2419200, 3: 86400, 2: 3600, 1: 60, 0: 1 }
  };
  if(slack().scale && slackscale[slack().scale][w])
    return map(Array(Math.ceil(1 / slackscale[slack().scale][w] * slack().width)
      + 1), () => null);
  return [null];
};

// Return the accumulated usage windows for a given metric
const accum = (au, metric) => {
  const a = filter(au, (a) => a.metric === metric);
  return a.length ? a[0].windows : [maxSlack(0),
    maxSlack(1), maxSlack(2), maxSlack(3), maxSlack(4)];
};

// Accumulate usage and return new accumulated value
const accumulate = function *(a, u) {
  const now = Date.now();
  const slackLimit = msDimensions[slack().scale] * slack().width;
  if(u.end < now - slackLimit)
    throw extend(new Error('The usage submitted is older than ' + slackLimit +
      ' milliseconds'), {
        status: 409,
        error: 'conflict',
        reason: 'The usage submitted is older than ' + slackLimit +
          ' milliseconds',
        noretry: true,
        nobreaker: true
      });

  debug(
    'Accumulating usage %o from %d and new usage %o from %d',
    a, a ? a.end : 0, u, u.end);

  // Compute the accumulated usage time and new usage time
  const processed = a ? a.processed : 0;

  // Use previous accumulated value if any
  const umerge = omit(u, 'id', 'metrics', 'metered_usage', 'measured_usage');
  const amerge = a ? extend({}, a, omit(umerge, 'start')) : extend({
    accumulated_usage: []
  }, umerge);

  // Retrieve the metering plan
  const mplan = yield mconfig(
    u.metering_plan_id, systemToken && systemToken());

  // Retrieve the rating plan
  const rplan = yield rconfig(
    u.rating_plan_id, systemToken && systemToken());

  // Calculate new accumulated usage
  const newa = extend({}, amerge, {
    accumulated_usage: map(u.metered_usage, (mu) => {
      debug('Accumulating metered usage quantity %o', mu);

      // Find the rate function for the given metric
      const rfn = ratefn(rplan.metrics, mu.metric);

      // Find the price for the metric
      const rp = price(u.prices.metrics, mu.metric);

      const aw = accum(amerge.accumulated_usage, mu.metric);

      return {
        metric: mu.metric,
        windows: map(aw, (w, i) => {
          // Get the appropriate time window index
          const twi = timewindow.timeWindowIndex(w, new Date(now),
            new Date(u.end), dimensions[i], true);

          // Expand the timewindows if necessary
          if(i >= indexOf(dimensions, slack().scale) && w.length - 1 < twi)
            map(Array(twi - w.length + 1), () => w.push(null));

          // Shift the windows if now is part of a new time window
          if(a && now > processed)
            timewindow.shiftWindow(new Date(a.processed),
              new Date(now), w, dimensions[i]);

          /* eslint complexity: [1, 6] */
          const quantities = map(w, (tw, j) => {
            const bounds = timewindow.timeWindowBounds(new Date(now),
              dimensions[i], -j);
            if(twi === j) {
              if(tw && tw.quantity && tw.quantity.current) {
                debug('Accumulating window %d index %d' +
                  ' new quantity %o old quantity %o', i, twi, tw, mu);

                return {
                  quantity: {
                    previous: tw.quantity.current,
                    current: accumfn(mplan.metrics, mu.metric)
                      (tw.quantity.current, mu.quantity, u.start, u.end,
                      bounds.from, bounds.to)
                  }
                };
              }
              debug('New window %d index %d new quantity %o', i, twi, tw);

              return {
                quantity: {
                  current: accumfn(mplan.metrics, mu.metric)
                    (0, mu.quantity, u.start, u.end, bounds.from, bounds.to)
                }
              };
            }
            return tw ? extend({}, tw) : null;
          });

          // Calculate cost for all accumulated quantities
          return map(quantities, (q) => q ?
            extend(q, { cost: q.quantity.current ?
              rfn(rp, q.quantity.current) : 0 }) :
            null);
        })
      };
    })
  });

  debug('New accumulated usage %o', newa);
  return newa;
};

// Process a group of usage docs and compute the corresponding
// accumulated usage
const accumulateUsage = function *(accums, udocs) {
  const ologs = yield treduce(udocs, function *(log, udoc, i, l) {
    const res = yield accumulate(last(log)[0], udoc);
    return log.concat([[res]]);
  }, [[
    accums[0]
  ]]);
  return rest(ologs);
};

// Create an accumulator service app
const accumulator = () => {
  // Configure Node cluster to use a single process as we want to serialize
  // accumulation requests per db partition and app instance
  cluster.singleton();

  // Create the Webapp
  const app = webapp();

  // Secure metering and batch routes using an OAuth bearer access token
  if (secured())
    app.use(/^\/v1\/metering|^\/batch$/,
      oauth.validator(process.env.JWTKEY, process.env.JWTALGO));

  const reducer = dataflow.reducer(accumulateUsage, {
    input: {
      type: 'metered-usage',
      post: '/v1/metering/metered/usage',
      get: '/v1/metering/metered/usage' +
        '/t/:tseq/k/:korganization_id/:kresource_instance_id' +
        '/:kconsumer_id/:kplan_id',
      dbname: 'abacus-accumulator-metered-usage',
      wscope: iwscope,
      rscope: rscope,
      key: ikey,
      time: itime,
      groups: igroups
    },
    output: {
      type: 'accumulated_usage',
      get: '/v1/metering/accumulated/usage' +
        '/k/:korganization_id/:kresource_instance_id' +
        '/:kconsumer_id/:kplan_id' +
        '/t/:tend/:tstart',
      dbname: 'abacus-accumulator-accumulated-usage',
      rscope: rscope,
      keys: okeys,
      times: otimes
    },
    sink: {
      host: uris.aggregator,
      apps: process.env.AGGREGATOR_APPS,
      post: '/v1/metering/accumulated/usage',
      authentication: systemToken
    }
  });

  app.use(reducer);
  app.use(router.batch(app));

  app.reducer = reducer;
  return app;
};

// Command line interface, create the accumulator app and listen
const runCLI = () => {
  // Cache and schedule the system token renewal
  if (secured()) {
    systemToken = oauth.cache(uris.auth_server, process.env.CLIENT_ID,
      process.env.CLIENT_SECRET, 'abacus.usage.write abacus.usage.read');

    systemToken.start();
  }

  // Create the app, replay any failed events, and listen
  const app = accumulator();
  dataflow.replay(app.reducer, 0, () => {
    app.listen();
  });
};

// Export our public functions
module.exports = accumulator;
module.exports.runCLI = runCLI;
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var events = require('events');
var EventEmitter = events.EventEmitter || events;
var SerialPort = require("serialport");

var EXCEPTION_LENGTH = 5;

/**
 * Simulate a modbus-RTU port using buffered serial connection
 */
var RTUBufferedPort = function(path, options) {
    var self = this;

    // options
    if (typeof(options) == 'undefined') options = {};

    // disable auto open, as we handle the open
    options.autoOpen = false;

    // internal buffer
    this._buffer = new Buffer(0);
    this._id = 0;
    this._cmd = 0;
    this._length = 0;
    this.debug = false;

    // create the SerialPort
    this._client= new SerialPort(path, options);

    // register the port data event
    this._client.on('data', function onData(data) {
        // add data to buffer
        self._buffer = Buffer.concat([self._buffer, data]);

        // check if buffer include a complete modbus answer
        var expectedLength = self._length;
        var bufferLength = self._buffer.length ;

        // check data length
        if (expectedLength < 6 || bufferLength < EXCEPTION_LENGTH) return;

        // loop and check length-sized buffer chunks
        var maxOffset = bufferLength - EXCEPTION_LENGTH;
        for (var i = 0; i <= maxOffset; i++) {
            var unitId = self._buffer[i];
            var functionCode = self._buffer[i+1];

            if (unitId !== self._id) continue;

            if (functionCode === self._cmd && i + expectedLength <= bufferLength) {
                self._emitData(i, expectedLength);
                return;
            }
            if (functionCode === (0x80 | self._cmd) && i + EXCEPTION_LENGTH <= bufferLength) {
                self._emitData(i, EXCEPTION_LENGTH);
                return;
            }
        }
    });

    EventEmitter.call(this);
};
util.inherits(RTUBufferedPort, EventEmitter);

/**
 * Emit the received response, cut the buffer and reset the internal vars.
 * @param {number} start the start index of the response within the buffer
 * @param {number} length the length of the response
 * @private
 */
RTUBufferedPort.prototype._emitData = function(start, length) {
    var buffer = this._buffer.slice(start, start + length);

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'recive', data: buffer}); }

    this.emit('data', buffer);
    this._buffer = this._buffer.slice(start + length);
};

/**
 * Simulate successful port open
 */
RTUBufferedPort.prototype.open = function (callback) {
    this._client.open(callback);
};

/**
 * Simulate successful close port
 */
RTUBufferedPort.prototype.close = function (callback) {
    this._client.close(callback);
};

/**
 * Check if port is open
 */
RTUBufferedPort.prototype.isOpen = function() {
    return this._client.isOpen();
};

/**
 * Send data to a modbus slave
 */
RTUBufferedPort.prototype.write = function (data) {
    // check data length
    if (data.length < 6) {
        // raise an error ?
        return;
    }

    // remember current unit and command
    this._id = data[0];
    this._cmd = data[1];

    // calculate expected answer length
    switch (this._cmd) {
        case 1:
        case 2:
            var length = data.readUInt16BE(4);
            this._length = 3 + parseInt((length - 1) / 8 + 1) + 2;
            break;
        case 3:
        case 4:
            var length = data.readUInt16BE(4);
            this._length = 3 + 2 * length + 2;
            break;
        case 5:
        case 6:
        case 15:
        case 16:
            this._length = 6 + 2;
            break;
        default:
            // raise and error ?
            this._length = 0;
            break;
    }

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'send', data: data}); }

    // send buffer to slave
    this._client.write(data);
};

module.exports = RTUBufferedPort;
<commit_msg>Corrected modbus frame header detection<commit_after>'use strict';
var util = require('util');
var events = require('events');
var EventEmitter = events.EventEmitter || events;
var SerialPort = require("serialport");

var EXCEPTION_LENGTH = 5;

/**
 * Simulate a modbus-RTU port using buffered serial connection
 */
var RTUBufferedPort = function(path, options) {
    var self = this;

    // options
    if (typeof(options) == 'undefined') options = {};

    // disable auto open, as we handle the open
    options.autoOpen = false;

    // internal buffer
    this._buffer = new Buffer(0);
    this._id = 0;
    this._cmd = 0;
    this._length = 0;
    this.debug = false;

    // create the SerialPort
    this._client= new SerialPort(path, options);

    // register the port data event
    this._client.on('data', function onData(data) {
        // add data to buffer
        self._buffer = Buffer.concat([self._buffer, data]);

        // check if buffer include a complete modbus answer
        var expectedLength = self._length;
        var bufferLength = self._buffer.length ;

        // check data length
        if (expectedLength < 6 || bufferLength < EXCEPTION_LENGTH) return;

        // loop and check length-sized buffer chunks
        var maxOffset = bufferLength - EXCEPTION_LENGTH;
        for (var i = 0; i <= maxOffset; i++) {
            var unitId = self._buffer[i];
            var functionCode = self._buffer[i+1];

            if ( unitId === self._id) {
                if( functionCode === self._cmd || functionCode === (0x80 | self._cmd)) {

                    // a valid modbus frame header has been identified, check for expected buffer length
                    if (functionCode === self._cmd && i + expectedLength <= bufferLength) {
                        self._emitData(i, expectedLength);
                        return;

                    } else {
                        if (functionCode === (0x80 | self._cmd) && i + EXCEPTION_LENGTH <= bufferLength) {
                            self._emitData(i, EXCEPTION_LENGTH);
                            return;
                        }
                    }
                    // frame header matches, but still missing bytes pending ... wait for further bytes
                    break;
                }
            }
        }

        // cut off illegal RX chars, else buffer will grow and grow ...
        if( i >= 1 ) {
          self._buffer = self._buffer.slice(i,self._buffer.length);
        }

    });

    EventEmitter.call(this);
};
util.inherits(RTUBufferedPort, EventEmitter);

/**
 * Emit the received response, cut the buffer and reset the internal vars.
 * @param {number} start the start index of the response within the buffer
 * @param {number} length the length of the response
 * @private
 */
RTUBufferedPort.prototype._emitData = function(start, length) {
    var buffer = this._buffer.slice(start, start + length);

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'recive', data: buffer}); }

    this.emit('data', buffer);
    this._buffer = this._buffer.slice(start + length);
};

/**
 * Simulate successful port open
 */
RTUBufferedPort.prototype.open = function (callback) {
    this._client.open(callback);
};

/**
 * Simulate successful close port
 */
RTUBufferedPort.prototype.close = function (callback) {
    this._client.close(callback);
};

/**
 * Check if port is open
 */
RTUBufferedPort.prototype.isOpen = function() {
    return this._client.isOpen();
};

/**
 * Send data to a modbus slave
 */
RTUBufferedPort.prototype.write = function (data) {
    // check data length
    if (data.length < 6) {
        // raise an error ?
        return;
    }

    // remember current unit and command
    this._id = data[0];
    this._cmd = data[1];

    // calculate expected answer length
    switch (this._cmd) {
        case 1:
        case 2:
            var length = data.readUInt16BE(4);
            this._length = 3 + parseInt((length - 1) / 8 + 1) + 2;
            break;
        case 3:
        case 4:
            var length = data.readUInt16BE(4);
            this._length = 3 + 2 * length + 2;
            break;
        case 5:
        case 6:
        case 15:
        case 16:
            this._length = 6 + 2;
            break;
        default:
            // raise and error ?
            this._length = 0;
            break;
    }

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'send', data: data}); }

    // send buffer to slave
    this._client.write(data);
};

module.exports = RTUBufferedPort;
<|endoftext|>


<commit_before>angular.module('ccdb.utils.form.date.directive', [])

    .directive('ccdbFormDate', function () {

        function range(a, z) {
            var list = [];
            for (; a <= z; a++) {
                list.push(a);
            }
            return list;
        }

        return {
            restrict: 'E',
            templateUrl: 'utils/form/date.html',
            require: 'ngModel',
            scope: {
                label: '@'
            },

            link: function (scope, element, attrs, ngModel) {

                // also need a directive that will set a related date field when another field gets a first value
                // e.g. first admitted date. and then add a <today> button.

                ngModel.$render = function () {
                    var modelValue = ngModel.$modelValue;
                    if (modelValue) {
                        scope.date = moment(modelValue).date();
                        scope.month = moment(modelValue).month();
                        scope.year = moment(modelValue).year();

                      console.log(scope.date);
                      console.log(scope.month);
                      console.log(scope.year);

                    }
                };

                scope.modelChanged = function (value) {
                    if (value) {
                        value = moment();
                        ngModel.$setViewValue(value);
                        ngModel.$render();
                    } else {
                        ngModel.$setViewValue(moment().date(scope.date).month(scope.month).year(scope.year).format());
                    }
                };

                scope.dates = range(1, 31);

                scope.months = [
                    {key: 0, value: 'January'},
                    {key: 1, value: 'February'},
                    {key: 2, value: 'March'},
                    {key: 3, value: 'April'},
                    {key: 4, value: 'May'},
                    {key: 5, value: 'June'},
                    {key: 6, value: 'July'},
                    {key: 7, value: 'August'},
                    {key: 8, value: 'September'},
                    {key: 9, value: 'October'},
                    {key: 10, value: 'November'},
                    {key: 11, value: 'December'}
                ];

                scope.years = range(1910, 2020);
            }
        };
    })
;
<commit_msg>remove comment. we already have a 'now' button<commit_after>angular.module('ccdb.utils.form.date.directive', [])

    .directive('ccdbFormDate', function () {

        function range(a, z) {
            var list = [];
            for (; a <= z; a++) {
                list.push(a);
            }
            return list;
        }

        return {
            restrict: 'E',
            templateUrl: 'utils/form/date.html',
            require: 'ngModel',
            scope: {
                label: '@'
            },

            link: function (scope, element, attrs, ngModel) {

                // also need a directive that will set a related date field when another field gets a first value
                // e.g. first admitted date.

                ngModel.$render = function () {
                    var modelValue = ngModel.$modelValue;
                    if (modelValue) {
                        scope.date = moment(modelValue).date();
                        scope.month = moment(modelValue).month();
                        scope.year = moment(modelValue).year();

                      console.log(scope.date);
                      console.log(scope.month);
                      console.log(scope.year);

                    }
                };

                scope.modelChanged = function (value) {
                    if (value) {
                        value = moment();
                        ngModel.$setViewValue(value);
                        ngModel.$render();
                    } else {
                        ngModel.$setViewValue(moment().date(scope.date).month(scope.month).year(scope.year).format());
                    }
                };

                scope.dates = range(1, 31);

                scope.months = [
                    {key: 0, value: 'January'},
                    {key: 1, value: 'February'},
                    {key: 2, value: 'March'},
                    {key: 3, value: 'April'},
                    {key: 4, value: 'May'},
                    {key: 5, value: 'June'},
                    {key: 6, value: 'July'},
                    {key: 7, value: 'August'},
                    {key: 8, value: 'September'},
                    {key: 9, value: 'October'},
                    {key: 10, value: 'November'},
                    {key: 11, value: 'December'}
                ];

                scope.years = range(1910, 2020);
            }
        };
    })
;
<|endoftext|>


<commit_before>/**
 *
 * @author     ganxun
 * @version    1.0
 * @desc
 *
 */

sumeru.router.add({
    pattern    :   '/publishbypage',
    action  :   'App.publishByPage'
});

sumeru.router.setDefault('App.publishByPage');

App.publishByPage = sumeru.controller.create(function(env, session){

    var getUserlist = function(){

        if(!session.get('pageNum')){
            session.set('pageNum',1);
        }

        if(!session.get('pagesize')){
            session.set('pagesize',2);
        }

        var pageOptions = {
            pagesize : session.get('pagesize'), //每页显示的数目
            page : session.get('pageNum'), //当前页
            uniqueField : 'time' //排序的唯一字段
        };

        session.sduser = env.subscribeByPage('pub-sduser',pageOptions,function(sduserCollection,info){
            //manipulate synced collection and bind it to serveral view blocks.
            var page = info.page;

            session.bindByPage('sduserlist', {
                page: page,//返回的当前页数
                data: sduserCollection.find()
            });
        });
    }

    //获取数据库的大小
    var getModelCount = function(){
        env.subscribe('pub-modelCount', function(count){
            session.set('modelCount',count/session.get('pagesize'));
        });
    }

    //对于每一个loader，自动创建一个闭包。 监听其中session、collection的改变，作为reactive的source
    env.onload = function(){
        return [getUserlist,getModelCount];
    };

    env.onrender = function(doRender){
        doRender('display', ['rotate','left']);
    };

    env.onready = function(doc){
        session.event("sduserlist",function(){
            var event = "click";

            if(!!('ontouchstart' in window)){
                event = 'touchstart';
            }

            if(session.get('pageNum')==1 || session.get('pageNum')<1){
                document.getElementById('pre').disabled = true;
            }else{
                document.getElementById('pre').disabled = false;
            }

            if(session.get('pageNum')==session.get('modelCount') || session.get('pageNum')>session.get('modelCount')){
                document.getElementById('next').disabled = true;
            }else{
                document.getElementById('next').disabled = false;
            }

            //下一页
            document.getElementById('pre').addEventListener(event, function(){
                var pageNum = session.get('pageNum');
                pageNum--;

                session.set('pageNum',pageNum);
                session.commit();
            });

            //上一页
            document.getElementById('next').addEventListener(event, function(){
                var pageNum = session.get('pageNum');
                pageNum++;

                session.set('pageNum',pageNum);
                session.commit();
            });
        });

        //保存
        Library.touch.on('#sdsave', 'touchstart', function(){
            var name = document.getElementById('sdname').value;
            var age = document.getElementById('sdage').value;

            if(!name){
                name = "John";
            }

            if(!age){
                age="27";
            }
            session.sduser.add({"name":name,"age":age})
            session.sduser.save();
        });
    };
});
<commit_msg>Update publishByPageController.js<commit_after>/**
 *
 * @author     ganxun
 * @version    1.0
 * @desc
 *
 */

sumeru.router.add({
    pattern    :   '/publishbypage',
    action  :   'App.publishByPage'
});

sumeru.router.setDefault('App.publishByPage');

App.publishByPage = sumeru.controller.create(function(env, session){

    var getUserlist = function(){

        if(!session.get('pageNum')){
            session.set('pageNum',1);
        }

        if(!session.get('pagesize')){
            session.set('pagesize',2);
        }

        var pageOptions = {
            pagesize : session.get('pagesize'), //每页显示的数目
            page : session.get('pageNum'), //当前页
            uniqueField : 'time' //排序的唯一字段
        };

        session.sduser = env.subscribeByPage('pub-sduser',pageOptions,function(sduserCollection,info){
            //manipulate synced collection and bind it to serveral view blocks.
            var page = info.page;

            session.bindByPage('sduserlist', {
                page: page,//返回的当前页数
                data: sduserCollection.find()
            });
        });
    }

    //获取数据库的大小
    var getModelCount = function(){
        env.subscribe('pub-modelCount', function(count){
            session.set('modelCount',count/session.get('pagesize'));
        });
    }

    //对于每一个loader，自动创建一个闭包。 监听其中session、collection的改变，作为reactive的source
    env.onload = function(){
        return [getUserlist,getModelCount];
    };

    env.onrender = function(doRender){
        doRender('display', ['rotate','left']);
    };

    env.onready = function(doc){
        session.event("sduserlist",function(){
            var event = "click";

            if(!!('ontouchstart' in window)){
                event = 'touchstart';
            }

            if(session.get('pageNum')==1 || session.get('pageNum')<1){
                document.getElementById('pre').disabled = true;
            }else{
                document.getElementById('pre').disabled = false;
            }

            if(session.get('pageNum')==session.get('modelCount') || session.get('pageNum')>session.get('modelCount')){
                document.getElementById('next').disabled = true;
            }else{
                document.getElementById('next').disabled = false;
            }

            //上一页
            document.getElementById('pre').addEventListener(event, function(){
                var pageNum = session.get('pageNum');
                pageNum--;

                session.set('pageNum',pageNum);
                session.commit();
            });

            //下一页
            document.getElementById('next').addEventListener(event, function(){
                var pageNum = session.get('pageNum');
                pageNum++;

                session.set('pageNum',pageNum);
                session.commit();
            });
        });

        //保存
        Library.touch.on('#sdsave', 'touchstart', function(){
            var name = document.getElementById('sdname').value;
            var age = document.getElementById('sdage').value;

            if(!name){
                name = "John";
            }

            if(!age){
                age="27";
            }
            session.sduser.add({"name":name,"age":age})
            session.sduser.save();
        });
    };
});
<|endoftext|>


<commit_before>const https = require("https");

class JSONRequest {
	constructor(options) {
		this._options = options;
	}

	_requestOptions(method, path, headers, encoding) {
		if(!headers) {
			headers = {
				"Content-Type": "application/json"
			};
		}

		if(!encoding) {
			encoding = "utf8";
		}

		return {
			method, headers, encoding,
			hostname: "api.postcode.nl",
			path: "/rest" + path,
			auth: this._options.key+":"+this._options.secret
		}
	}

	_parseJsonResponse(response) {
		return new Promise((resolve, reject) => {
			const strings = [];

			response.on("data", (chunk) => {
				strings.push(chunk);
			});

			response.on("end", () => {
				try {
					const string = strings.join("");
					if(response.statusCode === 200) {
						resolve(JSON.parse(string));
					}else if(response.statusCode === 401) {
						reject(Object.assign(new Error("Invalid credentials for call"), {
							statusCode: response.statusCode,
							headers: response.headers
						}));
					}else{
						let json;
						let error = "Request returned HTTP code "+response.statusCode;
						try {
							json = JSON.parse(string);
							if(json && json.exception) {
								error = json.exception;
							}
						} catch (err) {
                            reject(err)
						}
						reject(Object.assign(new Error(error), {
							string, json,
							statusCode: response.statusCode,
							headers: response.headers
						}));
					}
				} catch (err) {
					reject(err);
				}
			});

			response.on("error", reject);
		});
	}

	get(path) {
		return new Promise((resolve, reject) => {
			const opts = this._requestOptions("GET", path);
			const request = https.request(opts, (res) => {
				resolve(this._parseJsonResponse(res));
			});
			request.on("error", reject);
			request.end();
		});
	}

	post(path, data) {
		return new Promise((resolve, reject) => {
			const postData = JSON.stringify(data);
			const opts = this._requestOptions("POST", path, {
				"Content-Type": "application/json",
				"Content-Length": postData.length
			});

			const request = https.request(opts, (res) => {
				resolve(this._parseJsonResponse(res));
			});
			request.write(postData);
			request.on("error", reject);
			request.end();
		});
	}
};

module.exports = JSONRequest;<commit_msg>Fix more whitespace issues<commit_after>const https = require("https");

class JSONRequest {
	constructor(options) {
		this._options = options;
	}

	_requestOptions(method, path, headers, encoding) {
		if(!headers) {
			headers = {
				"Content-Type": "application/json"
			};
		}

		if(!encoding) {
			encoding = "utf8";
		}

		return {
			method, headers, encoding,
			hostname: "api.postcode.nl",
			path: "/rest" + path,
			auth: this._options.key+":"+this._options.secret
		}
	}

	_parseJsonResponse(response) {
		return new Promise((resolve, reject) => {
			const strings = [];

			response.on("data", (chunk) => {
				strings.push(chunk);
			});

			response.on("end", () => {
				try {
					const string = strings.join("");
					if(response.statusCode === 200) {
						resolve(JSON.parse(string));
					}else if(response.statusCode === 401) {
						reject(Object.assign(new Error("Invalid credentials for call"), {
							statusCode: response.statusCode,
							headers: response.headers
						}));
					}else{
						let json;
						let error = "Request returned HTTP code "+response.statusCode;
						try {
							json = JSON.parse(string);
							if(json && json.exception) {
								error = json.exception;
							}
						} catch (err) {
							reject(err)
						}
						reject(Object.assign(new Error(error), {
							string, json,
							statusCode: response.statusCode,
							headers: response.headers
						}));
					}
				} catch (err) {
					reject(err);
				}
			});

			response.on("error", reject);
		});
	}

	get(path) {
		return new Promise((resolve, reject) => {
			const opts = this._requestOptions("GET", path);
			const request = https.request(opts, (res) => {
				resolve(this._parseJsonResponse(res));
			});
			request.on("error", reject);
			request.end();
		});
	}

	post(path, data) {
		return new Promise((resolve, reject) => {
			const postData = JSON.stringify(data);
			const opts = this._requestOptions("POST", path, {
				"Content-Type": "application/json",
				"Content-Length": postData.length
			});

			const request = https.request(opts, (res) => {
				resolve(this._parseJsonResponse(res));
			});
			request.write(postData);
			request.on("error", reject);
			request.end();
		});
	}
};

module.exports = JSONRequest;<|endoftext|>


<commit_before>'use strict';

const request = require('request');
const url = require('url');

let robotto = {};

robotto._getRobotsUrl = function(urlP) {
    let receivedUrl = url.parse(urlP);
    return `${receivedUrl.protocol}\/\/${receivedUrl.host}/robots.txt`;
};

robotto._request = request;

robotto.fetch = function(urlP, callback) {
    callback = typeof callback === 'function' ? callback : new Function();

    let robotsUrl = robotto._getRobotsUrl(urlP);

    robotto._request(robotsUrl, (err, res, body) => {
        if (err) {
            callback(err);
            return;
        }

        if (res.statusCode !== 200) {
            callback(new Error(`Could not fetch robots.txt from ${urlP}. Server response code: ${res.statusCode}`));
            return;
        }

        callback(null, body);
    });
};

robotto.parse = function(robotsFile) {
    let lines = robotsFile.split('\n');
    let rulesObj = {
        comments: []
    };
    let lastUserAgent;

    lines.forEach((line) => {
        let hashIndex = line.indexOf('#');

        if (hashIndex > -1) {
            if (hashIndex === 0) {
                // entire line commentary
                rulesObj.comments.push(line.substr(hashIndex + 1).trim());
                return;
            }

            // portion line comment
            let portions = line.split('#');

            rulesObj.comments.push(portions[1].trim()); // push comment
            line = portions[0].trim(); // exclude comment from line
        }

        let userAgentIndex = line.toLowerCase().indexOf('user-agent:');
        if (userAgentIndex === 0) {
            lastUserAgent = line.split(':')[1].trim();
            rulesObj[lastUserAgent] = {
                allow: [],
                disallow: []
            };
            return;
        }

        let allowIndex = line.toLowerCase().indexOf('allow:');
        if (allowIndex === 0) {
            rulesObj[lastUserAgent].allow.push(line.split(':')[1].trim());
            return;
        }

        let disallowIndex = line.toLowerCase().indexOf('disallow:');
        if (disallowIndex === 0) {
            rulesObj[lastUserAgent].disallow.push(line.split(':')[1].trim());
            return;
        }
    });

    return rulesObj;
};

robotto.check = function(userAgent, urlParam, rulesObj) {
    let userAgents = Object.keys(rulesObj);
    let desiredRoute = (url.parse(urlParam).pathname + '/').split('/')[1];
    let allowed = true;

    // Searches for every user agent until it gets a match
    userAgents.forEach((agent) => {
        if (agent.indexOf(userAgent) === 0) {
            // Check if route is disallowed
            let disallowedRoutes = rulesObj[agent].disallow;
            disallowedRoutes.forEach((route) => {
                if (desiredRoute === route.split('/')[1]) {
                    allowed = false;
                } else if (route === '/') {
                    allowed = false;
                }
            });
        }
    });

    // Checks the general rules
    if (userAgents.indexOf('*') !== -1) {
        let allDisallowedRoutes = rulesObj['*'].disallow;
        allDisallowedRoutes.forEach((route) => {
            if (desiredRoute === route.split('/')[1]) {
                allowed = false;
            } else if (route === '/') {
                allowed = false;
            }
        });
    }

    return allowed;
};

module.exports = robotto;
<commit_msg>Deleting unuseful comments key before checking routes<commit_after>'use strict';

const request = require('request');
const url = require('url');

let robotto = {};

robotto._getRobotsUrl = function(urlP) {
    let receivedUrl = url.parse(urlP);
    return `${receivedUrl.protocol}\/\/${receivedUrl.host}/robots.txt`;
};

robotto._request = request;

robotto.fetch = function(urlP, callback) {
    callback = typeof callback === 'function' ? callback : new Function();

    let robotsUrl = robotto._getRobotsUrl(urlP);

    robotto._request(robotsUrl, (err, res, body) => {
        if (err) {
            callback(err);
            return;
        }

        if (res.statusCode !== 200) {
            callback(new Error(`Could not fetch robots.txt from ${urlP}. Server response code: ${res.statusCode}`));
            return;
        }

        callback(null, body);
    });
};

robotto.parse = function(robotsFile) {
    let lines = robotsFile.split('\n');
    let rulesObj = {
        comments: []
    };
    let lastUserAgent;

    lines.forEach((line) => {
        let hashIndex = line.indexOf('#');

        if (hashIndex > -1) {
            if (hashIndex === 0) {
                // entire line commentary
                rulesObj.comments.push(line.substr(hashIndex + 1).trim());
                return;
            }

            // portion line comment
            let portions = line.split('#');

            rulesObj.comments.push(portions[1].trim()); // push comment
            line = portions[0].trim(); // exclude comment from line
        }

        let userAgentIndex = line.toLowerCase().indexOf('user-agent:');
        if (userAgentIndex === 0) {
            lastUserAgent = line.split(':')[1].trim();
            rulesObj[lastUserAgent] = {
                allow: [],
                disallow: []
            };
            return;
        }

        let allowIndex = line.toLowerCase().indexOf('allow:');
        if (allowIndex === 0) {
            rulesObj[lastUserAgent].allow.push(line.split(':')[1].trim());
            return;
        }

        let disallowIndex = line.toLowerCase().indexOf('disallow:');
        if (disallowIndex === 0) {
            rulesObj[lastUserAgent].disallow.push(line.split(':')[1].trim());
            return;
        }
    });

    return rulesObj;
};

robotto.check = function(userAgent, urlParam, rulesObj) {
    delete rulesObj.comments;
    let userAgents = Object.keys(rulesObj);
    let desiredRoute = (url.parse(urlParam).pathname + '/').split('/')[1];
    let allowed = true;

    // Searches for every user agent until it gets a match
    userAgents.forEach((agent) => {
        if (agent.indexOf(userAgent) === 0) {
            // Check if route is disallowed
            let disallowedRoutes = rulesObj[agent].disallow;
            disallowedRoutes.forEach((route) => {
                if (desiredRoute === route.split('/')[1]) {
                    allowed = false;
                } else if (route === '/') {
                    allowed = false;
                }
            });
        }
    });

    // Checks the general rules
    if (userAgents.indexOf('*') !== -1) {
        let allDisallowedRoutes = rulesObj['*'].disallow;
        allDisallowedRoutes.forEach((route) => {
            if (desiredRoute === route.split('/')[1]) {
                allowed = false;
            } else if (route === '/') {
                allowed = false;
            }
        });
    }

    return allowed;
};

module.exports = robotto;
<|endoftext|>


<commit_before>"use strict";

var WWW_BUILT = 'www-built',
    WWW = 'www',
    INDEX = 'index.html',
    MANIFEST = 'manifest.json',
    GFX = 'gfx',
    DATA = 'data',
    SFX = 'sfx',
    MIN_JS = 'min.js',
    MIN_CSS = 'min.css';

var UglifyJS = require("uglify-js"),
    UglifyCSS = require('uglifycss'),
    cheerio = require('cheerio'),
    fs = require('fs'),
    minifyJSON = require("node-json-minify"),
    Minimize = require('minimize'),
    minimize = new Minimize();

buildTheProject();

function buildTheProject() {
    loadIndexFile(function (error, data) {
        if (error) {
            return console.log('error reading index file: ' + error);
        }

        mkdir(WWW_BUILT, function () {

            var $ = loadDocumentDOM(data);

            var minifiedJS = minifyJS($);
            writeJsFile(minifiedJS);

            var minifiedCSS = minifyCSS($);
            writeCssFile(minifiedCSS);

            var newIndex = updateSources($);
            minifyHtml(newIndex,
                writeIndexFile);

            cpdir(WWW + '/' + GFX, WWW_BUILT + '/' + GFX);
            cpdir(WWW + '/' + DATA, WWW_BUILT + '/' + DATA);
            cpdir(WWW + '/' + SFX, WWW_BUILT + '/' + SFX);

            minifyJSONFile(WWW, MANIFEST,
                writeFile.bind(null, WWW_BUILT, MANIFEST)
            );
        });
    });
}

function loadDocumentDOM(data) {
    console.log('parsing DOM');
    return cheerio.load(data);
}

function loadIndexFile(callback) {
    console.log('loading index file');
    fs.readFile(WWW + '/' + INDEX, 'utf8', callback);
}

function getExtension(fileName) {
    return fileName.split('.').pop();
}

function cp(srcPath, file, destPath) {
    console.log('copy ' + srcPath + '/' + file + " to " + destPath);
    fs.createReadStream(srcPath + '/' + file).pipe(fs.createWriteStream(destPath + '/' + file));
}
function isJSON(file) {
    return getExtension(file) == 'json';
}

function minifyJSONFile(srcPath, fileName, callback) {
    console.log('start task: minify ' + fileName);

    fs.readFile(srcPath + '/' + fileName, 'utf8', function (error, data) {
        var minified = minifyJSON(data);

        console.log('success task: minify ' + fileName);

        callback(minified);
    });
}

function writeFile(destPath, fileName, data) {
    console.log('start task: write ' + fileName);

    fs.writeFile(destPath + '/' + fileName, data, 'utf8', function (err) {
        if (err) {
            return console.log("error writing file: " + err);
        }
        console.log('success task: write ' + fileName);
    });
}

function cpDirFiles(srcPath, destPath) {
    fs.readdir(srcPath, function (error, files) {
        (files || []).forEach(function (file) {
            if (file == 'raw' || file == 'Thumbs.db')
                return;

            if (isJSON(file)) {
                minifyJSONFile(srcPath, file,
                    writeFile.bind(null, destPath, file)
                );
            } else {
                cp(srcPath, file, destPath);
            }
        });
    });
}
function cpdir(srcPath, destPath) {
    mkdir(destPath, function () {
        cpDirFiles(srcPath, destPath);
    });
}

function mkdir(name, callback) {
    fs.rmdir(name, function () {
        fs.mkdir(name, function () {
            callback();
        });
    });
}

function writeJsFile(data) {
    writeFile(WWW_BUILT, MIN_JS, data);
}

function writeCssFile(data) {
    writeFile(WWW_BUILT, MIN_CSS, data);
}

function minifyHtml(data, callback) {
    console.log("starting task: minify HTML");
    minimize.parse(data, function (error, data) {

        console.log("success task: minify HTML");
        callback(data);
    });
}

function writeIndexFile(data) {
    writeFile(WWW_BUILT, INDEX, data);
}

function getAllJsFileNames($) {
    var allScripts = [];
    $('script').each(function () {
        allScripts.push(WWW + '/' + $(this).attr('src'));
    });
    return allScripts;
}

function getAllCssFileNames($) {
    var allCSS = [];
    $('link').each(function () {
        if ($(this).attr('rel') == 'stylesheet')
            allCSS.push(WWW + '/' + $(this).attr('href'));
    });
    return allCSS;
}

function minifyJS($) {
    console.log("starting task: minify JS");

    var allScripts = getAllJsFileNames($);
    var minified = UglifyJS.minify(allScripts).code;

    console.log('success task: minify JS');
    return  minified;
}

function minifyCSS($) {
    console.log("starting task: minify CSS");

    var allCSS = getAllCssFileNames($);
    var minified = UglifyCSS.processFiles(allCSS, {uglyComments: true});

    console.log('success task: minify CSS');
    return  minified;
}

function updateSources($) {
    console.log("starting task: update html sources");

    $('script').remove();
    $('body').append('<script src="' + MIN_JS + '"></script>');

    $('link').each(function () {
        if ($(this).attr('rel') == 'stylesheet')
            $(this).remove();
    });

    $('head').append('<link rel="stylesheet" href="' + MIN_CSS + '">');

    var html = $.html();

    console.log("success task: update html sources");
    return  html;
}<commit_msg>adapt build script to new file / folder structure #core<commit_after>"use strict";

var WWW_BUILT = '../../target', WWW = '../www',
    INDEX = 'index.html',
    MANIFEST = 'manifest.json',
    GFX = 'gfx',
    DATA = 'data',
    SFX = 'sfx',
    MIN_JS = 'min.js',
    MIN_CSS = 'min.css';

var UglifyJS = require("uglify-js"),
    UglifyCSS = require('uglifycss'),
    cheerio = require('cheerio'),
    fs = require('fs'),
    minifyJSON = require("node-json-minify"),
    Minimize = require('minimize'),
    minimize = new Minimize();

buildTheProject();

function buildTheProject() {
    loadIndexFile(function (error, data) {
        if (error) {
            return console.log('error reading index file: ' + error);
        }

        mkdir(WWW_BUILT, function () {

            var $ = loadDocumentDOM(data);

            var minifiedJS = minifyJS($);
            writeJsFile(minifiedJS);

            var minifiedCSS = minifyCSS($);
            writeCssFile(minifiedCSS);

            var newIndex = updateSources($);
            minifyHtml(newIndex,
                writeIndexFile);

            cpdir(WWW + '/' + GFX, WWW_BUILT + '/' + GFX);
            cpdir(WWW + '/' + DATA, WWW_BUILT + '/' + DATA);
            cpdir(WWW + '/' + SFX, WWW_BUILT + '/' + SFX);

            minifyJSONFile(WWW, MANIFEST,
                writeFile.bind(null, WWW_BUILT, MANIFEST)
            );
        });
    });
}

function loadDocumentDOM(data) {
    console.log('parsing DOM');
    return cheerio.load(data);
}

function loadIndexFile(callback) {
    console.log('loading index file');
    fs.readFile(WWW + '/' + INDEX, 'utf8', callback);
}

function getExtension(fileName) {
    return fileName.split('.').pop();
}

function cp(srcPath, file, destPath) {
    console.log('copy ' + srcPath + '/' + file + " to " + destPath);
    fs.createReadStream(srcPath + '/' + file).pipe(fs.createWriteStream(destPath + '/' + file));
}
function isJSON(file) {
    return getExtension(file) == 'json';
}

function minifyJSONFile(srcPath, fileName, callback) {
    console.log('start task: minify ' + fileName);

    fs.readFile(srcPath + '/' + fileName, 'utf8', function (error, data) {
        var minified = minifyJSON(data);

        console.log('success task: minify ' + fileName);

        callback(minified);
    });
}

function writeFile(destPath, fileName, data) {
    console.log('start task: write ' + fileName);

    fs.writeFile(destPath + '/' + fileName, data, 'utf8', function (err) {
        if (err) {
            return console.log("error writing file: " + err);
        }
        console.log('success task: write ' + fileName);
    });
}

function cpDirFiles(srcPath, destPath) {
    fs.readdir(srcPath, function (error, files) {
        (files || []).forEach(function (file) {
            if (file == 'raw' || file == 'Thumbs.db')
                return;

            if (isJSON(file)) {
                minifyJSONFile(srcPath, file,
                    writeFile.bind(null, destPath, file)
                );
            } else {
                cp(srcPath, file, destPath);
            }
        });
    });
}
function cpdir(srcPath, destPath) {
    mkdir(destPath, function () {
        cpDirFiles(srcPath, destPath);
    });
}

function mkdir(name, callback) {
    fs.rmdir(name, function () {
        fs.mkdir(name, function () {
            callback();
        });
    });
}

function writeJsFile(data) {
    writeFile(WWW_BUILT, MIN_JS, data);
}

function writeCssFile(data) {
    writeFile(WWW_BUILT, MIN_CSS, data);
}

function minifyHtml(data, callback) {
    console.log("starting task: minify HTML");
    minimize.parse(data, function (error, data) {

        console.log("success task: minify HTML");
        callback(data);
    });
}

function writeIndexFile(data) {
    writeFile(WWW_BUILT, INDEX, data);
}

function getAllJsFileNames($) {
    var allScripts = [];
    $('script').each(function () {
        allScripts.push(WWW + '/' + $(this).attr('src'));
    });
    return allScripts;
}

function getAllCssFileNames($) {
    var allCSS = [];
    $('link').each(function () {
        if ($(this).attr('rel') == 'stylesheet')
            allCSS.push(WWW + '/' + $(this).attr('href'));
    });
    return allCSS;
}

function minifyJS($) {
    console.log("starting task: minify JS");

    var allScripts = getAllJsFileNames($);
    var minified = UglifyJS.minify(allScripts).code;

    console.log('success task: minify JS');
    return  minified;
}

function minifyCSS($) {
    console.log("starting task: minify CSS");

    var allCSS = getAllCssFileNames($);
    var minified = UglifyCSS.processFiles(allCSS, {uglyComments: true});

    console.log('success task: minify CSS');
    return  minified;
}

function updateSources($) {
    console.log("starting task: update html sources");

    $('script').remove();
    $('body').append('<script src="' + MIN_JS + '"></script>');

    $('link').each(function () {
        if ($(this).attr('rel') == 'stylesheet')
            $(this).remove();
    });

    $('head').append('<link rel="stylesheet" href="' + MIN_CSS + '">');

    var html = $.html();

    console.log("success task: update html sources");
    return  html;
}<|endoftext|>


<commit_before>'use strict';
var $ = require('jquery');
var Backbone = require('backbone');
var TranscriptionListElementView = require('./transcription_list_element_view');
var render = require('./utils').render;

/**
 * Backbone view for transcriptions list
 * @class TranscriptionsListView
 * @constructor
 * @extends Backbone.View
 */
module.exports = Backbone.View.extend({
  tagName: 'div',
  className: 'container',
  initialize: function() {
    var transcriptions = this.collection;
    this.listenTo(transcriptions, 'sync',   this.render);
    this.listenTo(transcriptions, 'destroy', this.render);
    this.listenTo(transcriptions, 'add',     this.render);

    // Temporary way to auto update on transcription status change. unit in
    // milliseconds, checking for transcriptions update every 1/2 minute.
    setInterval(function() {
      if (transcriptions.remaining().length > 0) {
        transcriptions.fetch({reset: true});
      }
    }, 30000);
  },

  render: function() {
    // if there are  transcriptions it shows
    this.$el.empty();
    this.$el.append("

Transcriptions

");
    if (!this.collection.isEmpty()) {
      this.collection.each(this.addOne, this);
      return this;
      // if there are no transcriptions it shows helpfull message to create a new one
    } else {
      this.$el.html(render('homePage'));
      return this;
    }
  },

  addOne: function(transcriptionItem) {
    var transcriptionView = new TranscriptionListElementView({model: transcriptionItem});
    this.$el.append(transcriptionView.render().el);
  }
});
<commit_msg>Add in "delete pending transcriptions" button<commit_after>'use strict';
var $ = require('jquery');
var Backbone = require('backbone');
var TranscriptionListElementView = require('./transcription_list_element_view');
var render = require('./utils').render;

/**
 * Backbone view for transcriptions list
 * @class TranscriptionsListView
 * @constructor
 * @extends Backbone.View
 */
module.exports = Backbone.View.extend({
  tagName: 'div',
  className: 'container',
  initialize: function() {
    var transcriptions = this.collection;
    this.listenTo(transcriptions, 'sync',   this.render);
    this.listenTo(transcriptions, 'destroy', this.render);
    this.listenTo(transcriptions, 'add',     this.render);

    // Temporary way to auto update on transcription status change. unit in
    // milliseconds, checking for transcriptions update every 1/2 minute.
    setInterval(function() {
      if (transcriptions.remaining().length > 0) {
        transcriptions.fetch({reset: true});
      }
    }, 30000);
  },
  events:{
    "click button.deletePendingBtn": "deletePending"
  },
  render: function() {
    // if there are  transcriptions it shows
    this.$el.empty();
    this.$el.append("

Transcriptions
");

    // add remove processing transcripts button
    this.$el.append(`
        <button type="button" class="btn btn-danger btn-xs deletePendingBtn">
          Delete Pending Transcripts
        </button>

`);

    if (!this.collection.isEmpty()) {
      this.collection.each(this.addOne, this);
      return this;
      // if there are no transcriptions it shows helpfull message to create a new one
    } else {
      this.$el.html(render('homePage'));
      return this;
    }
  },

  addOne: function(transcriptionItem) {
    var transcriptionView = new TranscriptionListElementView({model: transcriptionItem});
    this.$el.append(transcriptionView.render().el);
  },

  deletePending: function() {
    for (var i = 0; i <  appTranscription.transcriptionsList.models.length; i++) {
      if(!appTranscription.transcriptionsList.models[i].attributes.status){
        appTranscription.transcriptionsList.models[i].destroy();
      }
    }
  }
});
<|endoftext|>


<commit_before>// Sandbox for categoricalHmap
  var data = [
    {
      z: [[1, 20, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, -10, 20]],
      x: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
      y: ['Morning', 'Afternoon', 'Evening'],
      type: 'heatmap'
    }
  ];
  Plotly.newPlot('myDiv', data);
<commit_msg>2ND TRY Working topic voter 1st click; also adding previously untracked images to projectImages<commit_after><|endoftext|>


<commit_before>// Dependencies
import React from 'react';
import { changeMode } from 'focus-core/application';
import assign from 'object-assign';

import result from 'lodash/object/result';
import find from 'lodash/collection/find';
import defaultsDeep from 'lodash/object/defaultsDeep';

// Components
import { component as Field } from '../field';
import Text from '../../components/display/text';
import Button from '../../components/button';
import { component as MemoryList } from '../list';
import { component as Table } from '../../list/table/list';
import { component as List } from '../../list/selection/list';
// Mixins
import fieldComponentBehaviour from './field-component-behaviour';

export default {
    mixins: [fieldComponentBehaviour],
    /**
    * Create a field for the given property metadata.
    * @param {string} name - property name.
    * @param {object} options - An object which contains all options for the built of the field.
    * @returns {object} - A React Field.
    */
    fieldFor(name, options) {
        options = assign({}, options);
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    autocompleteSelectFor(name, { keyResolver, querySearcher }, options = {}) {
        options = assign({}, options);
        options.keyResolver = keyResolver;
        options.querySearcher = querySearcher;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    autocompleteTextFor(name, { querySearcher }, options = {}) {
        options = assign({}, options);
        options.querySearcher = querySearcher;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display two different fields, depending on wheter the user is editing the form or not
    * @param  {Object} config the configuration, with the structure {consultField: ..., editField: ...}
    * @return {Object} the rendered resulting field
    */
    dualFieldFor({ consultField, editField }) {
        return this.state.isEdit ? editField : consultField;
    },
    /**
    * Select component for the component.
    * @param {string} name - property name.
    * @param {string} listName - list name.
    * @param {object} options - options object.
    * @returns {object} - A React Field.
    */
    selectFor(name, listName, options) {
        options = options || {};
        options.listName = listName || options.listName;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display a field.
    * @param {string} name - property name.
    * @param {object} options - options object.
    * @returns {object} - A React Field.
    */
    displayFor(name, options) {
        options = options || {};
        options.isEdit = false;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display the text for a given property.
    * @param {string} name  - property name.
    * @param {object} options - Option object
    * @returns {object} - A React component.
    */
    textFor(name, options) {
        options = options || {};
        const def = (this.definition && this.definition[name]) ? this.definition[name] : {};
        const fieldProps = this._buildFieldProps(name, options, this);
        const value = this.state[name];
        const { valueKey, labelKey, values } = fieldProps;
        const _processValue = values ? result(find(values, { [valueKey || 'code']: value }), labelKey || 'label') : value;
        return (
            <Text
                formatter={options.formatter || def.formatter}
                name={options.name || `${this.definitionPath}.${name}`}
                style={options.style}
                value={_processValue}
            />
        );
    },
    /**
    * Display a list component.
    * @param {string} name - Property name.
    * @param {object} options - Options object.
    * @returns {object} - The react component for the list.
    */
    listFor(name, options) {
        options = options || {};
        options.reference = options.reference || this.state.reference;
        options.listComponent = options.listComponent || List;
        const listForProps = assign({}, options, {
            data: this.state[name],
            LineComponent: options.lineComponent || options.LineComponent || this.props.LineComponent || this.LineComponent || this.lineComponent,
            perPage: options.perPage || 5,
            reference: options.reference,
            isEdit: options.isEdit !== undefined ? options.isEdit : false
        });
        return (
            <MemoryList ref='list' {...listForProps} />
        );
    },

    /**
    * Display a table component.
    * @param {string} name - Property name.
    * @param {object} options - Options object.
    * @returns {object} - The react component for the list.
    */
    tableFor(name, options) {
        options.listComponent = options.listComponent || Table;
        return this.listFor(name, options);
    },
    /**
    * Button delete generation.
    * @returns {object} - A Reacte button.
    */
    buttonDelete() {
        const handleOnClick = () => {
            this.action.delete.call(this, this._getEntity());
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='delete'
                label='button.delete'
                shape={null}
                type='button'
            />
        );
    },
    /**
    * Edition button.
    * @returns {object} - The React component for the button.
    */
    buttonEdit() {
        const handleOnClick = () => {
            this.setState({ isEdit: !this.state.isEdit }, () => {
                changeMode('edit', 'consult');
                this.clearError();
            });
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='edit'
                label='button.edit'
                shape={null}
                type='button'
            />
        );
    },
    /**
    * Cancel button.
    * @returns {object} - The React component for the button.
    */
    buttonCancel() {
        const handleOnClick = () => {
            this.clearError();
            // Change the mode.
            // Read the state from the stores, it should contain the last data from the server.
            this.setState(defaultsDeep({ isEdit: false }, this._getStateFromStores(), this._buildResetState()), () => {
                changeMode('consult', 'edit');
            });
        };
        return (
            <Button handleOnClick={handleOnClick} icon='undo' label='button.cancel' shape={null} type='button' />
        );
    },
    /**
    * Button save generation.
    * @returns {object} - A React  save button.
    */
    buttonSave() {
        const { isLoading } = this.state;
        const handleOnClick = () => {
            if (this._validate()) {
                this.action.save.call(this, this._getEntity());
            }
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='save'
                label='button.save'
                shape={null}
                type='button'
                isLoading={isLoading}
                processLabel='button.saving'
            />
        );
    },
    /**
    * Render a field with the provided props.
    * @param  {object} fieldProps the props
    * @return {XML} rendered field
    */
    _renderField(fieldProps) {
        return (
            <Field {...fieldProps} />
        );
    }
};
<commit_msg>Form error clean-up<commit_after>// Dependencies
import React from 'react';
import { changeMode } from 'focus-core/application';
import assign from 'object-assign';

import result from 'lodash/object/result';
import find from 'lodash/collection/find';
import defaultsDeep from 'lodash/object/defaultsDeep';

// Components
import { component as Field } from '../field';
import Text from '../../components/display/text';
import Button from '../../components/button';
import { component as MemoryList } from '../list';
import { component as Table } from '../../list/table/list';
import { component as List } from '../../list/selection/list';
// Mixins
import fieldComponentBehaviour from './field-component-behaviour';

export default {
    mixins: [fieldComponentBehaviour],
    /**
    * Create a field for the given property metadata.
    * @param {string} name - property name.
    * @param {object} options - An object which contains all options for the built of the field.
    * @returns {object} - A React Field.
    */
    fieldFor(name, options) {
        options = assign({}, options);
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    autocompleteSelectFor(name, { keyResolver, querySearcher }, options = {}) {
        options = assign({}, options);
        options.keyResolver = keyResolver;
        options.querySearcher = querySearcher;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    autocompleteTextFor(name, { querySearcher }, options = {}) {
        options = assign({}, options);
        options.querySearcher = querySearcher;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display two different fields, depending on wheter the user is editing the form or not
    * @param  {Object} config the configuration, with the structure {consultField: ..., editField: ...}
    * @return {Object} the rendered resulting field
    */
    dualFieldFor({ consultField, editField }) {
        return this.state.isEdit ? editField : consultField;
    },
    /**
    * Select component for the component.
    * @param {string} name - property name.
    * @param {string} listName - list name.
    * @param {object} options - options object.
    * @returns {object} - A React Field.
    */
    selectFor(name, listName, options) {
        options = options || {};
        options.listName = listName || options.listName;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display a field.
    * @param {string} name - property name.
    * @param {object} options - options object.
    * @returns {object} - A React Field.
    */
    displayFor(name, options) {
        options = options || {};
        options.isEdit = false;
        const fieldProps = this._buildFieldProps(name, options, this);
        return this._renderField(fieldProps);
    },
    /**
    * Display the text for a given property.
    * @param {string} name  - property name.
    * @param {object} options - Option object
    * @returns {object} - A React component.
    */
    textFor(name, options) {
        options = options || {};
        const def = (this.definition && this.definition[name]) ? this.definition[name] : {};
        const fieldProps = this._buildFieldProps(name, options, this);
        const value = this.state[name];
        const { valueKey, labelKey, values } = fieldProps;
        const _processValue = values ? result(find(values, { [valueKey || 'code']: value }), labelKey || 'label') : value;
        return (
            <Text
                formatter={options.formatter || def.formatter}
                name={options.name || `${this.definitionPath}.${name}`}
                style={options.style}
                value={_processValue}
            />
        );
    },
    /**
    * Display a list component.
    * @param {string} name - Property name.
    * @param {object} options - Options object.
    * @returns {object} - The react component for the list.
    */
    listFor(name, options) {
        options = options || {};
        options.reference = options.reference || this.state.reference;
        options.listComponent = options.listComponent || List;
        const listForProps = assign({}, options, {
            data: this.state[name],
            LineComponent: options.lineComponent || options.LineComponent || this.props.LineComponent || this.LineComponent || this.lineComponent,
            perPage: options.perPage || 5,
            reference: options.reference,
            isEdit: options.isEdit !== undefined ? options.isEdit : false
        });
        return (
            <MemoryList ref='list' {...listForProps} />
        );
    },

    /**
    * Display a table component.
    * @param {string} name - Property name.
    * @param {object} options - Options object.
    * @returns {object} - The react component for the list.
    */
    tableFor(name, options) {
        options.listComponent = options.listComponent || Table;
        return this.listFor(name, options);
    },
    /**
    * Button delete generation.
    * @returns {object} - A Reacte button.
    */
    buttonDelete() {
        const handleOnClick = () => {
            this.action.delete.call(this, this._getEntity());
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='delete'
                label='button.delete'
                shape={null}
                type='button'
            />
        );
    },
    /**
    * Edition button.
    * @returns {object} - The React component for the button.
    */
    buttonEdit() {
        const handleOnClick = () => {
            this.setState({ isEdit: !this.state.isEdit }, () => {
                changeMode('edit', 'consult');
            });
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='edit'
                label='button.edit'
                shape={null}
                type='button'
            />
        );
    },
    /**
    * Cancel button.
    * @returns {object} - The React component for the button.
    */
    buttonCancel() {
        const handleOnClick = () => {
            this.clearError();
            // Change the mode.
            // Read the state from the stores, it should contain the last data from the server.
            this.setState(defaultsDeep({ isEdit: false }, this._getStateFromStores(), this._buildResetState()), () => {
                changeMode('consult', 'edit');
            });
        };
        return (
            <Button handleOnClick={handleOnClick} icon='undo' label='button.cancel' shape={null} type='button' />
        );
    },
    /**
    * Button save generation.
    * @returns {object} - A React  save button.
    */
    buttonSave() {
        const { isLoading } = this.state;
        const handleOnClick = () => {
            this.clearError();
            if (this._validate()) {
                this.action.save.call(this, this._getEntity());
            }
        };
        return (
            <Button
                handleOnClick={handleOnClick}
                icon='save'
                label='button.save'
                shape={null}
                type='button'
                isLoading={isLoading}
                processLabel='button.saving'
            />
        );
    },
    /**
    * Render a field with the provided props.
    * @param  {object} fieldProps the props
    * @return {XML} rendered field
    */
    _renderField(fieldProps) {
        return (
            <Field {...fieldProps} />
        );
    }
};
<|endoftext|>