<commit_before>/*jshint esversion: 6, node: true */
const express = require("express");
const router = module.exports = express.Router();
const pandoc = require("node-pandoc");
const latexGenerator = require("../lib/latex-generator");
const databaseInterface = require("../lib/database");
const resolutionFormat = require("../public/js/resolutionFormat");
const tokenProcessor = require("../lib/token");

const inspect = ((spect) => {
  return (obj) => console.log(spect(obj, {
    colors: true,
    depth: null,
    breakLength: 0
  }));
})(require("util").inspect);

//register callback to get collections on load
let resolutions, access, db;
databaseInterface.onload = (loadedDb) => {
  resolutions = loadedDb.collection("resolutions");
  access = loadedDb.collection("access");
  db = loadedDb;
};

//sends an error and logs it
function issueError(status, res, msg) {
  msg = "error: " + msg;
  console.error(msg);
  res.status(status).send(msg);
}

//deals with token in URL and calls callback if token present in db
function checkToken(req, res, callback) {
  //get token from params
  const token = req.params.token;

  //must be "token" type and be valid
  if (token.length && token[0] === "@" && tokenProcessor.check(token)) {
    //load corresponding resolution
    resolutions.findOne({ token: token }).toArray((err, documents) => {
      if (documents.length) {
        //call callback with gotten document
        callback(token, documents[0]);
      } else {
        issueError(400, "token wrong");
      }
    });
  } else {
    issueError(400, "token invalid");
  }
}

//deals with access code in POST and checks permissions
function checkCode(req, res, callback) {
  //get code from params
  const code = req.body.code;

  //must be "code" type and be valid
  if (code.length && code[0] === "!" && tokenProcessor.check(code)) {
    //load corresponding access entry
    access.findOne({ code: code }).toArray((err, documents) => {
      //code found
      if (documents.length) {
        //call callback with gotten code doc
        callback(documents[0]);
      } else {
        issueError(400, "code wrong");
      }
    });
  } else {
    issueError(400, "code invalid");
  }
}

//checks if given permission code doc allows access to given resolution doc
function checkPermissionMatch(resolution, permission) {
  //check permission and stage matching conditions
  return
    //chair accesses always
    permission.level === "CH" ||
    //allow if at active editing state and has delegate permission
    resolution.stage <= 1 && permission.level === "DE" ||
    //allow AP or FC if at their respective stages
    resolution.stage === 2 && permission.level === "AP" ||
    resolution.stage === 3 && permission.level === "FC";
}

//deals with resolutions in req.body and checks them against the format
function checkBodyRes(req, res, callback) {
  //needs to be present
  if (req.body && typeof req.body === "object") {
    if (resolutionFormat.check(req.body)) {
      callback(req.body);
    } else {
      issueError(400, "format invalid");
    }
  } else {
    issueError(400, "nothing sent");
  }
}

//makes the argument string for file for the pandoc cli interface to put the file into
function makePandocArgs(token) {
  return "-o public/" + token + "/out.pdf --template=public/template.latex";
}

//POST (responds with link, no view) render pdf
router.post("/renderpdf/:token", function(req, res) {
  //check for token and save new resolution content
  checkToken((token, doc) => {
    //render gotten resolution to pdf
    pandoc(latexGenerator(doc.content), makePandocArgs(token), (pandocErr, pandocResult) => {
      //throw error if occured
      if (pandocErr) {
        throw pandocErr;
      }

      //send rendered html
      res.send("out.pdf");
    });
  });
});

//GET (no view, processor) redirects to editor page with new registered token
router.get("/new", function(req, res) {
  //make new token

});

//POST (no view) save resolution
router.post("/save/:token", function(req, res) {
  //require resolution content to be present and valid
  checkBodyRes(req, res, (resolution) => {
    //check for token and save new resolution content
    checkToken((token) => {
      //save new document
      resolutions.updateOne(
        { token: token },
        { $set: { content: resolution } }
      ).then(() => res.send("ok"), () => issueError(500, "can't save"));
    });
  });
});

//POST (no view) show editor and thereby load
router.post("/load/:token", function(req, res) {
  //check for token and save new resolution content
  checkToken((token, doc) => {
    //send resolution to client, remove database wrapper
    res.send(doc.content);
  });
});
<commit_msg>create resolution path processor<commit_after>/*jshint esversion: 6, node: true */
const express = require("express");
const router = module.exports = express.Router();
const pandoc = require("node-pandoc");
const latexGenerator = require("../lib/latex-generator");
const databaseInterface = require("../lib/database");
const resolutionFormat = require("../public/js/resolutionFormat");
const tokenProcessor = require("../lib/token");

const inspect = ((spect) => {
  return (obj) => console.log(spect(obj, {
    colors: true,
    depth: null,
    breakLength: 0
  }));
})(require("util").inspect);

//register callback to get collections on load
let resolutions, access, db;
databaseInterface.onload = (loadedDb) => {
  resolutions = loadedDb.collection("resolutions");
  access = loadedDb.collection("access");
  db = loadedDb;
};

//sends an error and logs it
function issueError(status, res, msg) {
  msg = "error: " + msg;
  console.error(msg);
  res.status(status).send(msg);
}

//deals with token in URL and calls callback if token present in db
function checkToken(req, res, modifyResolution, callback) {
  //if only three args, callback is in modifyResolution
  let doModify = false;
  if (arguments.length === 3) {
    callback = modifyResolution;

    //set flag to use findOneAndModify instead
    doModify = true;
  }

  //get token from params
  const token = req.params.token;

  //must be "token" type and be valid
  if (token.length && token[0] === "@" && tokenProcessor.check(token)) {
    //load corresponding resolution
    (doModify ? //modify as well if flag set
     resolutions.findOne({ token: token }) :
     resolutions.findOneAndModify({ token: token }, modifyResolution, { returnOriginal: false })
    ).toArray((err, documents) => {
      if (documents.length) {
        //call callback with gotten document
        callback(token, documents[0]);
      } else {
        issueError(400, "token wrong");
      }
    });
  } else {
    issueError(400, "token invalid");
  }
}

//deals with access code in POST and checks permissions
function checkCode(req, res, callback) {
  //get code from params
  const code = req.body.code;

  //must be "code" type and be valid
  if (code.length && code[0] === "!" && tokenProcessor.check(code)) {
    //load corresponding access entry
    access.findOne({ code: code }).toArray((err, documents) => {
      //code found
      if (documents.length) {
        //call callback with gotten code doc
        callback(documents[0]);
      } else {
        issueError(400, "code wrong");
      }
    });
  } else {
    issueError(400, "code invalid");
  }
}

//checks if given permission code doc allows access to given resolution doc
function checkPermissionMatch(resolution, permission) {
  //check permission and stage matching conditions
  return permission.level === "CH" || //chair access always ok
    //allow if at active editing state and has delegate permission
    resolution.stage <= 1 && permission.level === "DE" ||
    //allow AP or FC if at their respective stages
    resolution.stage === 2 && permission.level === "AP" ||
    resolution.stage === 3 && permission.level === "FC";
}

//deals with resolutions in req.body and checks them against the format
function checkBodyRes(req, res, callback) {
  //needs to be present
  if (req.body && typeof req.body === "object") {
    if (resolutionFormat.check(req.body)) {
      callback(req.body);
    } else {
      issueError(400, "format invalid");
    }
  } else {
    issueError(400, "nothing sent");
  }
}

//makes the argument string for file for the pandoc cli interface to put the file into
function makePandocArgs(token) {
  return "-o public/" + token + "/out.pdf --template=public/template.latex";
}

//POST (responds with link, no view) render pdf
router.post("/renderpdf/:token", function(req, res) {
  //check for token and save new resolution content
  checkToken(req, res, (token, doc) => {
    //render gotten resolution to pdf
    pandoc(latexGenerator(doc.content), makePandocArgs(token), (pandocErr, pandocResult) => {
      //throw error if occured
      if (pandocErr) {
        throw pandocErr;
      }

      //send rendered html
      res.send("out.pdf");
    });
  });
});

//GET (no view, processor) redirects to editor page with new registered token
router.get("/new", function(req, res) {
  //make new token
  const token = tokenProcessor.makeToken();

  //get now
  const timeNow = Date.now();

  //put new resolution into database
  resolutions.insertOne({
    token: token, //identifier
    created: timeNow, //time of creation
    changed: timeNow, //last tiem it was changed
    stageHistory: [ timeNow ], //index is resolution stage, time when reached that stage
    renderHistory: [], //logs pdf render events
    stage: 0 //current workflow stage (see phase 2 notes)
  }).then(() => {
    //redirect to editor page (because URL is right then)
    res.redirect("/editor/" + token);
  });
});

//POST (no view) save resolution
router.post("/save/:token", function(req, res) {
  //require resolution content to be present and valid
  checkBodyRes(req, res, (resolution) => {
    //check for token and save new resolution content
    checkToken(req, res, (token) => {
      //save new document
      resolutions.updateOne(
        { token: token },
        {
          $set: { content: resolution },
          $currentDate: { changed: true }
        }
      ).then(() => res.send("ok"), () => issueError(500, "can't save"));
    });
  });
});

//GET (editor view) redirected to here to send back editor with set token
router.get("/editor/:token", function(req, res) {
  //check for token
  checkToken(req, res, (token) => {
    //send rendered editor page with token set
    res.render("editor", { token: token });
  });
});

//POST (no view) (request from editor after being started with set token) send resolution data
router.post("/load/:token", function(req, res) {
  //check for token and save new resolution content
  checkToken(req, res, (token, doc) => {
    //send resolution to client, remove database wrapper
    res.send(doc.content);
  });
});
<|endoftext|>


<commit_before>GCMRC.Organizations = {
	"CIDA" : {
		displayName : "USGS Center for Integrated Data Analytics",
		url : "https://cida.usgs.gov",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-cida.gif",
			width : 80,
			height : 80
		}
	},
	"USGSGCMR" : {
		displayName : "Grand Canyon Monitoring and Research Center",
		url : "https://www.gcmrc.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSCOWC" : {
		displayName : "Colorado Water Science Center",
		url : "https://co.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSUTWC" : {
		displayName : "Utah Water Science Center",
		url : "https://ut.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSTXWC" : {
		displayName : "Texas Water Science Center",
		url : "https://tx.usgs.gov",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSAZWC" : {
		displayName : "Arizona Water Science Center",
		url : "https://az.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"UTSU" : {
		displayName : "Utah State University",
		url : "https://www.usu.edu/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usu.gif",
			width : 106,
			height : 40
		}
	},
	"USBR" : {
		displayName : "Bureau of Reclaimation",
		url : "https://www.usbr.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usbr.gif",
			width : 88,
			height : 40
		}
	},
	"NPS" : {
		displayName : "National Park Service",
		url : "https://www.nps.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-nps.gif",
			width : 34,
			height : 40
		}
	},
	"BLM" : {
		displayName : "Bureau of Land Management",
		url : "https://www.blm.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-blm.gif",
			width : 43,
			height : 40
		}
	},
	"CEC" : {
		displayName : "Commission for Environmental Cooperation",
		url : "https://www.cec.org/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-cec.gif",
			width : 45,
			height : 40
		}
	},
	"USIBWC" : {
		displayName : "U.S. International Boundary and Water Commission",
		url : "https://www.ibwc.gov/home.html",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-ibwc.jpg",
			width : 40,
			height : 40
		}
	},
	"IIUABC" : {
		displayName : "Instituto de Ingeniería UABC",
		url : "https://institutodeingenieria.uabc.mx/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-iiuabc.jpg",
			width : 136,
			height : 102
		}
	}
};

<commit_msg>removing some external links that aren't https compliant yet or not required to be<commit_after>GCMRC.Organizations = {
	"CIDA" : {
		displayName : "USGS Center for Integrated Data Analytics",
		url : "https://cida.usgs.gov",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-cida.gif",
			width : 80,
			height : 80
		}
	},
	"USGSGCMR" : {
		displayName : "Grand Canyon Monitoring and Research Center",
		url : "https://www.gcmrc.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSCOWC" : {
		displayName : "Colorado Water Science Center",
		url : "http://co.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSUTWC" : {
		displayName : "Utah Water Science Center",
		url : "http://ut.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSTXWC" : {
		displayName : "Texas Water Science Center",
		url : "https://tx.usgs.gov",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"USGSAZWC" : {
		displayName : "Arizona Water Science Center",
		url : "http://az.water.usgs.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usgs.gif",
			width : 80,
			height : 21
		}
	},
	"UTSU" : {
		displayName : "Utah State University",
		url : "http://www.usu.edu/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usu.gif",
			width : 106,
			height : 40
		}
	},
	"USBR" : {
		displayName : "Bureau of Reclaimation",
		url : "https://www.usbr.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-usbr.gif",
			width : 88,
			height : 40
		}
	},
	"NPS" : {
		displayName : "National Park Service",
		url : "https://www.nps.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-nps.gif",
			width : 34,
			height : 40
		}
	},
	"BLM" : {
		displayName : "Bureau of Land Management",
		url : "https://www.blm.gov/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-blm.gif",
			width : 43,
			height : 40
		}
	},
	"CEC" : {
		displayName : "Commission for Environmental Cooperation",
		url : "http://www.cec.org/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-cec.gif",
			width : 45,
			height : 40
		}
	},
	"USIBWC" : {
		displayName : "U.S. International Boundary and Water Commission",
		url : "http://www.ibwc.gov/home.html",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-ibwc.jpg",
			width : 40,
			height : 40
		}
	},
	"IIUABC" : {
		displayName : "Instituto de Ingeniería UABC",
		url : "http://institutodeingenieria.uabc.mx/",
		logo : {
			url : CONFIG.relativePath + "app/sources/source-iiuabc.jpg",
			width : 136,
			height : 102
		}
	}
};

<|endoftext|>


<commit_before>;( function() {

	"use strict";

	App.Models.ChartModel = Backbone.Model.extend( {

		//urlRoot: Global.rootUrl + '/charts/',
		//urlRoot: Global.rootUrl + '/data/config/',
		url: function() {
			if( $("#form-view").length ) {
				if( this.id ) {
					//editing existing
					return Global.rootUrl + "/charts/" + this.id;
				} else {
					//saving new
					return Global.rootUrl + "/charts";
				}

			} else {
				return Global.rootUrl + "/data/config/" + this.id;
			}
		},

		defaults: {
			"cache": true,
			"selected-countries": [],
			"tabs": [ "chart", "data", "sources" ],
			"line-type": "2",
			"chart-description": "",
			"chart-dimensions": [],
			"variables": [],
			"y-axis": {},
			"x-axis": {},
			"margins": { top: 10, left: 60, bottom: 10, right: 10 },
			"unit": "",
			"iframe-width": "100%",
			"iframe-height": "100%"
		},

		initialize: function() {

		},

		addSelectedCountry: function( country ) {

			//make sure we're using object, not associative array
			/*if( $.isArray( this.get( "selected-countries" ) ) ) {
				//we got empty array from db, convert to object
				this.set( "selected-countries", {} );
			}*/
			var selectedCountries = this.get( "selected-countries" );
			selectedCountries.push( country );
			//selectedCountries[ country.id ] = country;
			this.trigger( "change:selected-countries" );
			this.trigger( "change" );

		},

		updateSelectedCountry: function( countryId, color ) {

			var country = this.findCountryById( countryId );
			if( country ) {
				country.color = color;
				this.trigger( "change:selected-countries" );
				this.trigger( "change" );
			}

		},

		removeSelectedCountry: function( countryId ) {

			var country = this.findCountryById( countryId );
			if( country ) {
				var selectedCountries = this.get( "selected-countries" ),
					countryIndex = _.indexOf( selectedCountries, country );
				selectedCountries.splice( countryIndex, 1 );
				this.trigger( "change:selected-countries" );
				this.trigger( "change" );
			}

		},

		findCountryById: function( countryId ) {

			var selectedCountries = this.get( "selected-countries" ),
				country = _.findWhere( selectedCountries, { id: countryId.toString() } );
			return country;

		},

		setAxisConfig: function( axisName, prop, value ) {

			var axis = this.get( axisName );
			if( axis ) {
				axis[ prop ] = value;
			}
			this.trigger( "change" );

		},

		updateVariables: function( newVar ) {
			//copy array
			var variables = this.get( "variables" ).slice(),
				varInArr = _.find( variables, function( v ){ return v.id == newVar.id; })

			if( !varInArr ) {
				variables.push( newVar );
				this.set( "variables", variables );
			}
		},

		removeVariable: function( varIdToRemove ) {
			//copy array
			var variables = this.get( "variables" ).slice(),
				varInArr = _.find( variables, function( v ){ return v.id == newVar.id; })

			if( !varInArr ) {
				variables.push( newVar );
				this.set( "variables", variables );
			}
		}

	} );

})();<commit_msg>fixed not saving y-axis, x-axis when receiving empty object<commit_after>;( function() {

	"use strict";

	App.Models.ChartModel = Backbone.Model.extend( {

		//urlRoot: Global.rootUrl + '/charts/',
		//urlRoot: Global.rootUrl + '/data/config/',
		url: function() {
			if( $("#form-view").length ) {
				if( this.id ) {
					//editing existing
					return Global.rootUrl + "/charts/" + this.id;
				} else {
					//saving new
					return Global.rootUrl + "/charts";
				}

			} else {
				return Global.rootUrl + "/data/config/" + this.id;
			}
		},

		defaults: {
			"cache": true,
			"selected-countries": [],
			"tabs": [ "chart", "data", "sources" ],
			"line-type": "2",
			"chart-description": "",
			"chart-dimensions": [],
			"variables": [],
			"y-axis": {},
			"x-axis": {},
			"margins": { top: 10, left: 60, bottom: 10, right: 10 },
			"unit": "",
			"iframe-width": "100%",
			"iframe-height": "100%"
		},

		initialize: function() {

		},

		addSelectedCountry: function( country ) {

			//make sure we're using object, not associative array
			/*if( $.isArray( this.get( "selected-countries" ) ) ) {
				//we got empty array from db, convert to object
				this.set( "selected-countries", {} );
			}*/
			if( $.isArray( this.get( "y-axis" ) ) ) {
				//we got empty array from db, convert to object
				this.set( "y-axis", {} );
			}
			if( $.isArray( this.get( "x-axis" ) ) ) {
				//we got empty array from db, convert to object
				this.set( "x-axis", {} );
			}
			var selectedCountries = this.get( "selected-countries" );
			selectedCountries.push( country );
			//selectedCountries[ country.id ] = country;
			this.trigger( "change:selected-countries" );
			this.trigger( "change" );

		},

		updateSelectedCountry: function( countryId, color ) {

			var country = this.findCountryById( countryId );
			if( country ) {
				country.color = color;
				this.trigger( "change:selected-countries" );
				this.trigger( "change" );
			}

		},

		removeSelectedCountry: function( countryId ) {

			var country = this.findCountryById( countryId );
			if( country ) {
				var selectedCountries = this.get( "selected-countries" ),
					countryIndex = _.indexOf( selectedCountries, country );
				selectedCountries.splice( countryIndex, 1 );
				this.trigger( "change:selected-countries" );
				this.trigger( "change" );
			}

		},

		findCountryById: function( countryId ) {

			var selectedCountries = this.get( "selected-countries" ),
				country = _.findWhere( selectedCountries, { id: countryId.toString() } );
			return country;

		},

		setAxisConfig: function( axisName, prop, value ) {

			var axis = this.get( axisName );
			if( axis ) {
				axis[ prop ] = value;
			}
			this.trigger( "change" );

		},

		updateVariables: function( newVar ) {
			//copy array
			var variables = this.get( "variables" ).slice(),
				varInArr = _.find( variables, function( v ){ return v.id == newVar.id; } );

			if( !varInArr ) {
				variables.push( newVar );
				this.set( "variables", variables );
			}
		},

		removeVariable: function( varIdToRemove ) {
			//copy array
			var variables = this.get( "variables" ).slice(),
				varInArr = _.find( variables, function( v ){ return v.id == newVar.id; } );

			if( !varInArr ) {
				variables.push( newVar );
				this.set( "variables", variables );
			}
		}

	} );

})();<|endoftext|>


<commit_before>//import fs from 'fs';
//import path from 'path';
import gulp from 'gulp';
import mainBowerFiles from 'main-bower-files';
/*
import pkg from '../../package.json';
import bower from '../../bower.json';

bower.name = pkg.name || bower.name;
bower.description = pkg.description || bower.description;
bower.version = pkg.version || bower.version;
fs.writeFileSync(path.resolve(__dirname, '../../bower.json'), JSON.stringify(bower, null, 2));
*/

const mainBowerFilesConfig = {
    base: 'bower_components/',
    dest: 'src/web/vendor/',
    options: {
        checkExistence: true,
        debugging: true,
        paths: {
            bowerDirectory: 'bower_components',
            bowerrc: '.bowerrc',
            bowerJson: 'bower.json'
        }
    }
};

export default (options) => {
    gulp.task('bower', () => {
        return gulp.src(mainBowerFiles(mainBowerFilesConfig.options), { base: mainBowerFilesConfig.base })
            .pipe(gulp.dest(mainBowerFilesConfig.dest));
    });
};
<commit_msg>Bower is no longer needed<commit_after><|endoftext|>


<commit_before>import {
  withLitHtml,
  html,
  props,
  define,
  hasNativeShadowDomSupport,
  convertSchemaToProps,
} from '@bolt/core';
import { styleMap } from 'lit-html/directives/style-map.js';
import { classMap } from 'lit-html/directives/class-map.js';
import styles from './animate.scss';
import schema from '../animate.schema';

/**
 * @event BoltAnimationWrapper#bolt-animate:end:in
 */

/**
 * @event BoltAnimationWrapper#bolt-animate:end:out
 */

export const EVENTS = {
  END_IN: 'bolt-animate:end:in',
  END_OUT: 'bolt-animate:end:out',
};

export const ANIM_STAGES = {
  INITIAL: 'INITIAL',
  IN: 'IN',
  IDLE: 'IDLE',
  OUT: 'OUT',
};

@define
class BoltAnimate extends withLitHtml() {
  static is = 'bolt-animate';

  static props = convertSchemaToProps(schema);

  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    this.schema = schema;
    this._animStage = ANIM_STAGES.INITIAL;
    /** @type {CSSStyleDeclaration} */
    this._animStyle = {};
    this.hasAnimIn = false;
    this.hasAnimIdle = false;
    this.hasAnimOut = false;

    return self;
  }

  _processProps() {
    const { in: inAnim, idle, out } = this.props;
    this.hasAnimIn = typeof inAnim === 'string' && inAnim !== 'none';
    this.hasAnimIdle = typeof idle === 'string' && idle !== 'none';
    this.hasAnimOut = typeof out === 'string' && out !== 'none';
  }

  connectedCallback() {
    super.connectedCallback();
    this._processProps();

    if (this.hasAnimIn) {
      this._animStyle = {
        animationName: null,
        opacity: this.props.initialAppearance === 'hidden' ? '0' : null,
      };
    } else {
      if (this.hasAnimIdle) {
        this._triggerAnimIdle();
      }
    }
  }

  _triggerAnim(id) {
    let isTriggered = false;
    switch (id) {
      case ANIM_STAGES.IN:
        if (this.hasAnimIn) {
          this._applyAnim({
            animationName: this.props.in,
            animationDuration: this.props.inDuration,
            animationDelay: this.props.inDelay,
            animationTimingFunction: this.props.inEasing,
          });
          isTriggered = true;
        }
        break;
      case ANIM_STAGES.IDLE:
        if (this.hasAnimIdle) {
          this._applyAnim({
            animationName: this.props.idle,
            animationDuration: this.props.idleDuration,
            animationDelay: this.props.idleDelay,
            animationTimingFunction: 'linear',
            animationFillMode: 'none',
            animationIterationCount: 'infinite',
          });
          isTriggered = true;
        }
        break;
      case ANIM_STAGES.OUT:
        if (this.hasAnimOut) {
          this._applyAnim({
            animationName: this.props.out,
            animationDuration: this.props.outDuration,
            animationDelay: this.props.outDelay,
            animationTimingFunction: this.props.outEasing,
          });
          isTriggered = true;
        }
        break;
    }

    if (isTriggered) {
      this._animStage = ANIM_STAGES[id];
      this.triggerUpdate();
      if (this.props.showMeta) {
        this.setAttribute('meta-stage', this._animStage);
      }
    }
    return isTriggered;
  }

  _applyAnim({
    animationName,
    animationDuration,
    animationDelay,
    animationFillMode = 'both',
    animationTimingFunction,
    animationIterationCount = '1',
  }) {
    this._animStyle = {
      animationName,
      animationDuration: `${animationDuration}ms`,
      animationDelay: `${animationDelay}ms`,
      animationFillMode,
      animationTimingFunction,
      animationIterationCount,
    };
  }

  triggerAnimIn() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.IN);
    // console.log(`triggered in`, { hadAnim });
    return hadAnim;
  }

  triggerAnimOut() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.OUT);
    // console.log(`triggered out`, { hadAnim });
    return hadAnim;
  }

  _triggerAnimIdle() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.IDLE);
    // console.log(`triggered idle`, { hadAnim });
    return hadAnim;
  }

  /**
   * @param {string} eventName
   * @param {Object} [detail]
   * @see EVENTS
   * @fires bolt-animate:end:in
   * @fires bolt-animate:end:out
   */
  _emitEvent(eventName, detail = {}) {
    const myEvent = new CustomEvent(eventName, {
      bubbles: true,
      composed: true,
      detail,
    });
    console.debug(`event: ${eventName}`);
    this.dispatchEvent(myEvent);
  }

  _handleAnimEndEvent(event) {
    const { animationName } = event;
    const isAnimIn = this.props.in === animationName;
    const isAnimIdle = this.props.idle === animationName;
    const isAnimOut = this.props.out === animationName;

    if (isAnimIn) {
      this._emitEvent(EVENTS.END_IN);
      this._triggerAnimIdle();
    } else if (isAnimIdle) {
      // don't care
    } else if (isAnimOut) {
      this._emitEvent(EVENTS.END_OUT);
    } else {
      console.error('Unknown animation ended!', {
        event,
      });
    }
    event.stopPropagation();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // console.debug('attributeChangedCallback', { name, oldValue, newValue });
    // can trigger re-render
    super.attributeChangedCallback(name, oldValue, newValue);
    this._processProps();
    switch (this._animStage) {
      case ANIM_STAGES.IN:
        this.triggerAnimIn();
        break;
      case ANIM_STAGES.IDLE:
        this._triggerAnimIdle();
        break;
      case ANIM_STAGES.OUT:
        this.triggerAnimOut();
        break;
    }
  }

  render() {
    const classes = {
      'c-bolt-animate': true,
    };

    return html`
      ${this.addStyles([styles])}
      <div
        class="${classMap(classes)}"
        @animationend=${e => this._handleAnimEndEvent(e)}
        style=${styleMap(this._animStyle)}
      >
        ${this.slot('default')}
      </div>
    `;
  }
}

export { BoltAnimate };
<commit_msg>fix(bolt-animate): safari animation fixes<commit_after>import {
  withLitHtml,
  html,
  props,
  define,
  hasNativeShadowDomSupport,
  convertSchemaToProps,
} from '@bolt/core';
import { styleMap } from 'lit-html/directives/style-map.js';
import { classMap } from 'lit-html/directives/class-map.js';
import styles from './animate.scss';
import schema from '../animate.schema';

/**
 * @event BoltAnimationWrapper#bolt-animate:end:in
 */

/**
 * @event BoltAnimationWrapper#bolt-animate:end:out
 */

export const EVENTS = {
  END_IN: 'bolt-animate:end:in',
  END_OUT: 'bolt-animate:end:out',
};

export const ANIM_STAGES = {
  INITIAL: 'INITIAL',
  IN: 'IN',
  IDLE: 'IDLE',
  OUT: 'OUT',
};

@define
class BoltAnimate extends withLitHtml() {
  static is = 'bolt-animate';

  static props = convertSchemaToProps(schema);

  constructor(self) {
    self = super(self);
    self.useShadow = hasNativeShadowDomSupport;
    this.schema = schema;
    this._animStage = ANIM_STAGES.INITIAL;
    /** @type {CSSStyleDeclaration} */
    this._animStyle = {};
    this.hasAnimIn = false;
    this.hasAnimIdle = false;
    this.hasAnimOut = false;

    return self;
  }

  _processProps() {
    const { in: inAnim, idle, out } = this.props;
    this.hasAnimIn = typeof inAnim === 'string' && inAnim !== 'none';
    this.hasAnimIdle = typeof idle === 'string' && idle !== 'none';
    this.hasAnimOut = typeof out === 'string' && out !== 'none';
  }

  connectedCallback() {
    super.connectedCallback();
    this._processProps();

    if (this.hasAnimIn) {
      this._animStyle = {
        animationName: null,
        opacity: this.props.initialAppearance === 'hidden' ? '0' : null,
      };
    } else {
      if (this.hasAnimIdle) {
        this._triggerAnimIdle();
      }
    }
  }

  _triggerAnim(id) {
    let isTriggered = false;
    switch (id) {
      case ANIM_STAGES.IN:
        if (this.hasAnimIn) {
          this._applyAnim({
            animationName: this.props.in,
            animationDuration: this.props.inDuration,
            animationDelay: this.props.inDelay,
            animationTimingFunction: this.props.inEasing,
          });
          isTriggered = true;
        }
        break;
      case ANIM_STAGES.IDLE:
        if (this.hasAnimIdle) {
          this._applyAnim({
            animationName: this.props.idle,
            animationDuration: this.props.idleDuration,
            animationDelay: this.props.idleDelay,
            animationTimingFunction: 'linear',
            animationFillMode: 'none',
            animationIterationCount: 'infinite',
          });
          isTriggered = true;
        }
        break;
      case ANIM_STAGES.OUT:
        if (this.hasAnimOut) {
          this._applyAnim({
            animationName: this.props.out,
            animationDuration: this.props.outDuration,
            animationDelay: this.props.outDelay,
            animationTimingFunction: this.props.outEasing,
          });
          isTriggered = true;
        }
        break;
    }

    if (isTriggered) {
      this._animStage = ANIM_STAGES[id];
      this.triggerUpdate();
      if (this.props.showMeta) {
        this.setAttribute('meta-stage', this._animStage);
      }
    }
    return isTriggered;
  }

  _applyAnim({
    animationName,
    animationDuration,
    animationDelay,
    animationFillMode = 'both',
    animationTimingFunction,
    animationIterationCount = '1',
  }) {
    this._animStyle = {
      animationName,
      // Safari breaks with 0ms animation-duration
      animationDuration: `${Math.max(1, animationDuration)}ms`,
      animationFillMode,
      animationTimingFunction,
      animationIterationCount,
    };

    // Safari breaks with 0ms animation-delay
    if (animationDelay > 0) {
      this._animStyle.animationDelay = `${animationDelay}ms`;
    }
  }

  triggerAnimIn() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.IN);
    // console.log(`triggered in`, { hadAnim });
    return hadAnim;
  }

  triggerAnimOut() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.OUT);
    // console.log(`triggered out`, { hadAnim });
    return hadAnim;
  }

  _triggerAnimIdle() {
    const hadAnim = this._triggerAnim(ANIM_STAGES.IDLE);
    // console.log(`triggered idle`, { hadAnim });
    return hadAnim;
  }

  /**
   * @param {string} eventName
   * @param {Object} [detail]
   * @see EVENTS
   * @fires bolt-animate:end:in
   * @fires bolt-animate:end:out
   */
  _emitEvent(eventName, detail = {}) {
    const myEvent = new CustomEvent(eventName, {
      bubbles: true,
      composed: true,
      detail,
    });
    console.debug(`event: ${eventName}`);
    this.dispatchEvent(myEvent);
  }

  _handleAnimEndEvent(event) {
    const { animationName } = event;
    const isAnimIn = this.props.in === animationName;
    const isAnimIdle = this.props.idle === animationName;
    const isAnimOut = this.props.out === animationName;

    if (isAnimIn) {
      this._emitEvent(EVENTS.END_IN);
      this._triggerAnimIdle();
    } else if (isAnimIdle) {
      // don't care
    } else if (isAnimOut) {
      this._emitEvent(EVENTS.END_OUT);
    } else {
      console.error('Unknown animation ended!', {
        event,
      });
    }
    event.stopPropagation();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // console.debug('attributeChangedCallback', { name, oldValue, newValue });
    // can trigger re-render
    super.attributeChangedCallback(name, oldValue, newValue);
    this._processProps();
    switch (this._animStage) {
      case ANIM_STAGES.IN:
        this.triggerAnimIn();
        break;
      case ANIM_STAGES.IDLE:
        this._triggerAnimIdle();
        break;
      case ANIM_STAGES.OUT:
        this.triggerAnimOut();
        break;
    }
  }

  render() {
    const classes = {
      'c-bolt-animate': true,
    };

    return html`
      ${this.addStyles([styles])}
      <div
        class="${classMap(classes)}"
        @animationend=${e => this._handleAnimEndEvent(e)}
        style=${styleMap(this._animStyle)}
      >
        ${this.slot('default')}
      </div>
    `;
  }
}

export { BoltAnimate };
<|endoftext|>


<commit_before>Router = function () {
  this.globals = [];
  this.subscriptions = Function.prototype;

  this._routeMap = {};
  this._tracker = null;
  this._current = {};
  this._currentTracker = new Tracker.Dependency();
  this._globalRoute = new Route(this);

  this._middleware = [];
  this._updateCallbacks();

  // indicate it's okay (or not okay) to run the tracker
  // when doing subscriptions
  this.safeToRun = false;
}

Router.prototype.route = function(path, options) {
  var self = this;
  var route = new Route(this, path, options);
  this._routeMap[path] = route;

  route._handler = this._createCallback(path, function (context, next) {
    self._current = {
      path: path,
      context: context,
      params: context.params,
      route: route
    };

    // pick states from url
    var states = self._qs.parse(context.querystring);
    self._globalRoute._states = _.pick(states, self.globals);
    self._current.route._states = _.omit(states, this.globals);

    self._invalidateTracker();
  });

  this._updateCallbacks();

  return route;
};

Router.prototype.go = function(path) {
  this._page(path);
};

Router.prototype.current = function() {
  this._currentTracker.depend();
  return this._current;
};

Router.prototype.middleware = function(middlewareFn) {
  var mw = this._createCallback('*', function (ctx, next) {
    middlewareFn(ctx.pathname, next);
  });

  this._middleware.push(mw);
  this._updateCallbacks();
  return this;
};

Router.prototype.getState = function(name) {
  if(_.contains(this.globals, name)) {
    return this._globalRoute._states[name];
  } else if(this._current.route) {
    return this._current.route._states[name];
  } else {
    // nothing to return
  }
};

Router.prototype.getAllStates = function() {
  var locals = this._current.route ? this._current.route._states : {};
  return _.extend({}, locals, this._globalRoute._states);
};

Router.prototype.setState = function(name, value) {
  if(_.contains(this.globals, name)) {
    this._globalRoute._states[name] = value;
    this._invalidateTracker();
  } else if(this._current.route) {
    this._current.route._states[name] = value;
    this._invalidateTracker();
  } else {
    // nothing to set
  }
};

Router.prototype.removeState = function(name) {
  if(_.contains(this.globals, name)) {
    delete this._globalRoute._states[name];
    this._invalidateTracker();
  } else if(this._current.route) {
    delete this._current.route._states[name];
    this._invalidateTracker();
  } else {
    // nothing to remove
  }
};

Router.prototype.clearStates = function() {
  if(this._current.route) {
    this._current.route._states = {};
  }

  this._globalRoute._states = {};
  this._invalidateTracker();
};

Router.prototype.ready = function() {
  var currentRoute = this.current().route;
  if(!currentRoute) return false;

  if(arguments.length == 0) {
    var subscriptions = _.values(currentRoute.getAllSubscriptions());
  } else {
    var subscriptions = _.map(arguments, function(subName) {
      return currentRoute.getSubscription(subName);
    });
  }

  for(var lc = 0; lc<subscriptions.length; lc++) {
    var sub = subscriptions[lc];
    if(!sub) {
      return false;
    } else if(sub.ready() == false) {
      return false;
    }
  }

  return true;
};

Router.prototype.notfound = function(options) {
  var self = this;
  var route = new Route(this, '*', options);

  route._handler = this._createCallback('*', function (context, next) {
    self._current = {
      path: '*',
      context: context,
      params: context.params,
      route: route
    };

    self._invalidateTracker();
  });

  this._notfound = route;
  this._updateCallbacks();
};

Router.prototype.initialize = function() {
  var self = this;

  this._middleware.push(this._createCallback('*', function (ctx, next) {
    setTimeout(function() {
      var str = location.search.slice(1);
      ctx.params.query = self._qs.parse(str);
      next();
    }, 0);
  }));

  this._updateCallbacks();

  // main autorun function
  this._tracker = Tracker.autorun(function () {
    if(!self._current.route) return;
    var route = self._current.route;
    var context = self._current.context;

    if(!self.safeToRun) {
      var message =
        "You can't use reactive data sources like Session" +
        " inside the `.subscriptions` method!";
      throw new Error(message);
    }

    var states = self.getAllStates();
    if(!_.isEmpty(states)) {
      var query = self._qs.stringify(states);
      history.replaceState({}, '', location.pathname + '?' + query);
    }

    // We need to run subscriptions inside a Tracker
    // to stop subs when switching between routes
    // But we don't need to run this tracker with
    // other reactive changes inside the .subscription method
    // We tackle this with the `safeToRun` variable
    self.subscriptions.call(self._globalRoute, context.params);
    route.subscriptions(context.params);

    // otherwise, computations inside action will trigger to re-run
    // this computation. which we do not need.
    Tracker.nonreactive(function() {
      route.action(context.params);
    });

    self._currentTracker.changed();
    self.safeToRun = false;
  });

  // initialize
  this._page();
};

Router.prototype._invalidateTracker = function() {
  this.safeToRun = true;
  this._tracker.invalidate();
};

Router.prototype._createCallback = function(path, handler) {
  var route = new this._page.Route(path);
  return route.middleware(handler);
};

Router.prototype._updateCallbacks = _.debounce(function () {
  var callbacks = [];

  // add route middleware
  _.each(this._routeMap, function (route) {
    callbacks = callbacks.concat(route._middleware);
  });

  // add global middleware
  callbacks = callbacks.concat(this._middleware);

  // add route handlers
  _.each(this._routeMap, function (route) {
    callbacks.push(route._handler);
  });

  // add default 'not found' handler
  if(this._notfound) {
    callbacks.push(this._notfound._handler);
  }

  // set pagejs callbacks array
  this._page.callbacks = callbacks;
}, 0);

Router.prototype._page = window.page;
delete window.page;

Router.prototype._qs = qs;
<commit_msg>remove debounce since it cause issues for rendering   since it runs on a different eventloop, while trigger are fired   no route is there to accept it's logic<commit_after>Router = function () {
  this.globals = [];
  this.subscriptions = Function.prototype;

  this._routeMap = {};
  this._tracker = null;
  this._current = {};
  this._currentTracker = new Tracker.Dependency();
  this._globalRoute = new Route(this);

  this._middleware = [];
  this._updateCallbacks();

  // indicate it's okay (or not okay) to run the tracker
  // when doing subscriptions
  this.safeToRun = false;
}

Router.prototype.route = function(path, options) {
  var self = this;
  var route = new Route(this, path, options);
  this._routeMap[path] = route;

  route._handler = this._createCallback(path, function (context, next) {
    self._current = {
      path: path,
      context: context,
      params: context.params,
      route: route
    };

    // pick states from url
    var states = self._qs.parse(context.querystring);
    self._globalRoute._states = _.pick(states, self.globals);
    self._current.route._states = _.omit(states, this.globals);

    self._invalidateTracker();
  });

  this._updateCallbacks();

  return route;
};

Router.prototype.go = function(path) {
  this._page(path);
};

Router.prototype.current = function() {
  this._currentTracker.depend();
  return this._current;
};

Router.prototype.middleware = function(middlewareFn) {
  var mw = this._createCallback('*', function (ctx, next) {
    middlewareFn(ctx.pathname, next);
  });

  this._middleware.push(mw);
  this._updateCallbacks();
  return this;
};

Router.prototype.getState = function(name) {
  if(_.contains(this.globals, name)) {
    return this._globalRoute._states[name];
  } else if(this._current.route) {
    return this._current.route._states[name];
  } else {
    // nothing to return
  }
};

Router.prototype.getAllStates = function() {
  var locals = this._current.route ? this._current.route._states : {};
  return _.extend({}, locals, this._globalRoute._states);
};

Router.prototype.setState = function(name, value) {
  if(_.contains(this.globals, name)) {
    this._globalRoute._states[name] = value;
    this._invalidateTracker();
  } else if(this._current.route) {
    this._current.route._states[name] = value;
    this._invalidateTracker();
  } else {
    // nothing to set
  }
};

Router.prototype.removeState = function(name) {
  if(_.contains(this.globals, name)) {
    delete this._globalRoute._states[name];
    this._invalidateTracker();
  } else if(this._current.route) {
    delete this._current.route._states[name];
    this._invalidateTracker();
  } else {
    // nothing to remove
  }
};

Router.prototype.clearStates = function() {
  if(this._current.route) {
    this._current.route._states = {};
  }

  this._globalRoute._states = {};
  this._invalidateTracker();
};

Router.prototype.ready = function() {
  var currentRoute = this.current().route;
  if(!currentRoute) return false;

  if(arguments.length == 0) {
    var subscriptions = _.values(currentRoute.getAllSubscriptions());
  } else {
    var subscriptions = _.map(arguments, function(subName) {
      return currentRoute.getSubscription(subName);
    });
  }

  for(var lc = 0; lc<subscriptions.length; lc++) {
    var sub = subscriptions[lc];
    if(!sub) {
      return false;
    } else if(sub.ready() == false) {
      return false;
    }
  }

  return true;
};

Router.prototype.notfound = function(options) {
  var self = this;
  var route = new Route(this, '*', options);

  route._handler = this._createCallback('*', function (context, next) {
    self._current = {
      path: '*',
      context: context,
      params: context.params,
      route: route
    };

    self._invalidateTracker();
  });

  this._notfound = route;
  this._updateCallbacks();
};

Router.prototype.initialize = function() {
  var self = this;

  this._middleware.push(this._createCallback('*', function (ctx, next) {
    setTimeout(function() {
      var str = location.search.slice(1);
      ctx.params.query = self._qs.parse(str);
      next();
    }, 0);
  }));

  this._updateCallbacks();

  // main autorun function
  this._tracker = Tracker.autorun(function () {
    if(!self._current.route) return;
    var route = self._current.route;
    var context = self._current.context;

    if(!self.safeToRun) {
      var message =
        "You can't use reactive data sources like Session" +
        " inside the `.subscriptions` method!";
      throw new Error(message);
    }

    var states = self.getAllStates();
    if(!_.isEmpty(states)) {
      var query = self._qs.stringify(states);
      history.replaceState({}, '', location.pathname + '?' + query);
    }

    // We need to run subscriptions inside a Tracker
    // to stop subs when switching between routes
    // But we don't need to run this tracker with
    // other reactive changes inside the .subscription method
    // We tackle this with the `safeToRun` variable
    self.subscriptions.call(self._globalRoute, context.params);
    route.subscriptions(context.params);

    // otherwise, computations inside action will trigger to re-run
    // this computation. which we do not need.
    Tracker.nonreactive(function() {
      route.action(context.params);
    });

    self._currentTracker.changed();
    self.safeToRun = false;
  });

  // initialize
  this._page();
};

Router.prototype._invalidateTracker = function() {
  this.safeToRun = true;
  this._tracker.invalidate();
};

Router.prototype._createCallback = function(path, handler) {
  var route = new this._page.Route(path);
  return route.middleware(handler);
};

Router.prototype._updateCallbacks = function () {
  var callbacks = [];

  // add route middleware
  _.each(this._routeMap, function (route) {
    callbacks = callbacks.concat(route._middleware);
  });

  // add global middleware
  callbacks = callbacks.concat(this._middleware);

  // add route handlers
  _.each(this._routeMap, function (route) {
    callbacks.push(route._handler);
  });

  // add default 'not found' handler
  if(this._notfound) {
    callbacks.push(this._notfound._handler);
  }

  // set pagejs callbacks array
  this._page.callbacks = callbacks;
};

Router.prototype._page = window.page;
delete window.page;

Router.prototype._qs = qs;
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare", "dojo/_base/lang",
	"dojo/dom-class", "dojo/dom-construct", "dojo/on", "dojo/request",
	"dojo/fx/easing",
	"dijit/_WidgetBase",
	"dojox/charting/Chart2D", "./PATRICTheme", "dojox/charting/action2d/MoveSlice", "dojox/charting/action2d/Tooltip",
	"dojox/charting/plot2d/Bars", "./SummaryWidget"

], function(declare, lang,
			domClass, domConstruct, on, xhr,
			easing,
			WidgetBase,
			Chart2D, Theme, MoveSlice, ChartTooltip,
			Bars, SummaryWidget){

	return declare([SummaryWidget], {
		dataModel: "genome",
		query: "",
		view: "table",
		baseQuery: "&eq(reference_genome,*)&select(reference_genome,genome_name,genome_id)&limit(25000)&facet((field,reference_genome),(mincount,1))&json(nl,map)",
		columns: [
			{label: "Type", field: "reference_genome"},
			{label: "Genome Name", field: "genome_name", renderCell: function(obj, val, node){
				node.innerHTML = '' + val + '';
			}}
		],
		processData: function(res){
			var chartLabels = this._chartLabels = [];

			if(!res || !res.facet_counts || !res.facet_counts.facet_fields || !res.facet_counts.facet_fields.reference_genome){
				console.error("INVALID SUMMARY DATA");
				return;
			}

			this._tableData = res.response.docs;
			var d = res.facet_counts.facet_fields.reference_genome; // now key-value pair

			var data = {};
			Object.keys(d).forEach(function(key){
				data[key] = [{source: key, x: 1, y: d[key]}];
			});

			// console.log(data);
			this.set('data', data);
		},

		render_chart: function(){

			if(!this.chart){
				this.chart = new Chart2D(this.chartNode)
					.setTheme(Theme)
					.addPlot("default", {
						type: "ClusteredColumns",
						markers: true,
						gap: 3,
						label: true,
						labelStyle: "outside",
						animate: {duration: 1000, easing: easing.linear}
					})
					.addAxis("x", {
						majorLabels: false,
						minorTicks: false,
						minorLabels: false,
						microTicks: false,
						labels: this._chartLabels
					})
					.addAxis("y", {
						vertical: true,
						majorTicks: false,
						natural: true,
						minorTicks: false
					});
					// .addSeries("source", this.data);

				Object.keys(this.data).forEach(lang.hitch(this, function(key){
					this.chart.addSeries(key, this.data[key]);
				}));

				new ChartTooltip(this.chart, "default", {
					text: function(o){
						var d = o.run.data[o.index];
						return d.source + " (" + d.y + ")"
					}
				});

				this.chart.render();
			}else{

				Object.keys(this.data).forEach(lang.hitch(this, function(key){
					this.chart.updateSeries(key, this.data[key]);
				}));
				this.chart.render();
			}
		},

		render_table: function(){
			this.inherited(arguments);

			this.grid.refresh();
			this.grid.renderArray(this._tableData);
		}
	})
});<commit_msg>fix chart not rendering<commit_after>define([
	"dojo/_base/declare", "dojo/_base/lang",
	"dojo/dom-class", "dojo/dom-construct", "dojo/on", "dojo/request",
	"dojo/fx/easing",
	"dijit/_WidgetBase",
	"dojox/charting/Chart2D", "./PATRICTheme", "dojox/charting/action2d/MoveSlice", "dojox/charting/plot2d/Pie", "dojox/charting/action2d/Tooltip",
	"dojox/charting/plot2d/Bars", "./SummaryWidget"

], function(declare, lang,
			domClass, domConstruct, on, xhr,
			easing,
			WidgetBase,
			Chart2D, Theme, MoveSlice, Pie, ChartTooltip,
			Bars, SummaryWidget){

	return declare([SummaryWidget], {
		dataModel: "genome",
		query: "",
		view: "table",
		baseQuery: "&eq(reference_genome,*)&select(reference_genome,genome_name,genome_id)&limit(25000)&facet((field,reference_genome),(mincount,1))&json(nl,map)",
		columns: [
			{label: "Type", field: "reference_genome"},
			{label: "Genome Name", field: "genome_name", renderCell: function(obj, val, node){
				node.innerHTML = '' + val + '';
			}}
		],
		processData: function(res){

			if(!res || !res.facet_counts || !res.facet_counts.facet_fields || !res.facet_counts.facet_fields.reference_genome){
				console.error("INVALID SUMMARY DATA");
				return;
			}

			this._tableData = res.response.docs;
			var d = res.facet_counts.facet_fields.reference_genome; // now key-value pair

			var data = [];
			Object.keys(d).forEach(function(key){
				data.push({text: key + " (" + d[key] + ")", x: key, y: d[key]});
			});

			this.set('data', data);
		},

		render_chart: function(){

			if(!this.chart){

				this.DonutChart = declare(Pie, {
					render: function(dim, offsets){
						this.inherited(arguments);

						var rx = (dim.width - offsets.l - offsets.r) / 2,
							ry = (dim.height - offsets.t - offsets.b) / 2,
							r = Math.min(rx, ry) / 2;
						var circle = {
							cx: offsets.l + rx,
							cy: offsets.t + ry,
							r: "30px"
						};
						var s = this.group;

						s.createCircle(circle).setFill("#fff").setStroke("#fff");
					}
				});

				this.chart = new Chart2D(this.chartNode)
					.setTheme(Theme)
					.addPlot("default", {
						type: this.DonutChart,
						radius: 70,
						stroke: "black",
						label: true,
						labelStyle: "columns"
					});

				this.chart.addSeries('x', this.data);
				this.chart.render();
			}else{

				this.chart.updateSeries('x', this.data);
				this.chart.render();
			}
		},

		render_table: function(){
			this.inherited(arguments);

			this.grid.refresh();
			this.grid.renderArray(this._tableData);
		}
	})
});<|endoftext|>


<commit_before>'use strict';

import path from 'path';
import del from 'del';

export default function(gulp, plugins, args, config, taskTarget, browserSync) {
  let dirs = config.directories;

  // Clean
  gulp.task('clean', (done)=>{
		del.sync([
	    path.join(dirs.temporary),
	    path.join(dirs.destination)
	  ]);
	  done();
  });
}
<commit_msg>clean task doesn't delete the docs folder any more<commit_after>'use strict';

import path from 'path';
import del from 'del';

export default function(gulp, plugins, args, config, taskTarget, browserSync) {
  let dirs = config.directories;

  // Clean
  gulp.task('clean', (done)=>{
		del.sync([
	    path.join(dirs.temporary),
	  ]);
	  done();
  });
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Converts the standard Strapi REST query params to a moe usable format for querying
 * You can read more here: https://strapi.io/documentation/developer-docs/latest/developer-resources/content-api/content-api.html#filters
 */

const _ = require('lodash');

// const BOOLEAN_OPERATORS = ['or', 'and'];
const QUERY_OPERATORS = ['_where', '_or', '_and'];

class InvalidOrderError extends Error {
  constructor() {
    super();
    this.message = 'Invalid order. order can only be one of asc|desc|ASC|DESC';
  }
}
class InvalidSortError extends Error {
  constructor() {
    super();
    this.message =
      'Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort object';
  }
}

const validateOrder = order => {
  if (!['asc', 'desc'].includes(order.toLocaleLowerCase())) {
    throw new InvalidOrderError();
  }
};

/**
 * Sort query parser
 * @param {string} sortQuery - ex: id:asc,price:desc
 */
const convertSortQueryParams = sortQuery => {
  if (typeof sortQuery === 'string') {
    return sortQuery.split(',').map(value => convertSingleSortQueryParam(value));
  }

  if (Array.isArray(sortQuery)) {
    return sortQuery.flatMap(sortValue => convertSortQueryParams(sortValue));
  }

  if (_.isPlainObject(sortQuery)) {
    return convertNestedSortQueryParam(sortQuery);
  }

  throw new InvalidSortError();
};

const convertSingleSortQueryParam = sortQuery => {
  // split field and order param with default order to ascending
  const [field, order = 'asc'] = sortQuery.split(':');

  if (field.length === 0) {
    throw new Error('Field cannot be empty');
  }

  validateOrder(order);

  return _.set({}, field, order);
};

const convertNestedSortQueryParam = sortQuery => {
  const transformedSort = {};
  for (const field in sortQuery) {
    const order = sortQuery[field];

    // this is a deep sort
    if (_.isPlainObject(order)) {
      transformedSort[field] = convertNestedSortQueryParam(order);
    } else {
      validateOrder(order);
      transformedSort[field] = order;
    }
  }

  return transformedSort;
};

/**
 * Start query parser
 * @param {string} startQuery - ex: id:asc,price:desc
 */
const convertStartQueryParams = startQuery => {
  const startAsANumber = _.toNumber(startQuery);

  if (!_.isInteger(startAsANumber) || startAsANumber < 0) {
    throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
  }

  return startAsANumber;
};

/**
 * Limit query parser
 * @param {string} limitQuery - ex: id:asc,price:desc
 */
const convertLimitQueryParams = limitQuery => {
  const limitAsANumber = _.toNumber(limitQuery);

  if (!_.isInteger(limitAsANumber) || (limitAsANumber !== -1 && limitAsANumber < 0)) {
    throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
  }

  return limitAsANumber;
};

class InvalidPopulateError extends Error {
  constructor() {
    super();
    this.message =
      'Invalid populate parameter. Expected a string, an array of strings, a populate object';
  }
}

// NOTE: we could support foo.* or foo.bar.* etc later on
const convertPopulateQueryParams = (populate, depth = 0) => {
  if (depth === 0 && populate === '*') {
    return true;
  }

  if (typeof populate === 'string') {
    return populate.split(',').map(value => _.trim(value));
  }

  if (Array.isArray(populate)) {
    // map convert
    return populate.flatMap(value => {
      if (typeof value !== 'string') {
        throw new InvalidPopulateError();
      }

      return value.split(',').map(value => _.trim(value));
    });
  }

  if (_.isPlainObject(populate)) {
    const transformedPopulate = {};
    for (const key in populate) {
      transformedPopulate[key] = convertNestedPopulate(populate[key]);
    }
    return transformedPopulate;
  }

  throw new InvalidPopulateError();
};

const convertNestedPopulate = subPopulate => {
  if (subPopulate === '*') {
    return true;
  }

  if (_.isBoolean(subPopulate)) {
    return subPopulate;
  }

  if (!_.isPlainObject(subPopulate)) {
    throw new Error(`Invalid nested populate. Expected '*' or an object`);
  }

  // TODO: We will need to consider a way to add limitation / pagination
  const { sort, filters, fields, populate } = subPopulate;

  const query = {};

  if (sort) {
    query.orderBy = convertSortQueryParams(sort);
  }

  if (filters) {
    query.where = convertFiltersQueryParams(filters);
  }

  if (fields) {
    query.select = convertFieldsQueryParams(fields);
  }

  if (populate) {
    query.populate = convertPopulateQueryParams(populate);
  }

  return query;
};

const convertFieldsQueryParams = (fields, depth = 0) => {
  if (depth === 0 && fields === '*') {
    return undefined;
  }

  if (typeof fields === 'string') {
    const fieldsValues = fields.split(',').map(value => _.trim(value));
    return _.uniq(['id', ...fieldsValues]);
  }

  if (Array.isArray(fields)) {
    // map convert
    const fieldsValues = fields.flatMap(value => convertPopulateQueryParams(value, depth + 1));
    return _.uniq(['id', ...fieldsValues]);
  }

  throw new Error('Invalid fields parameter. Expected a string or an array of strings');
};

// NOTE: We could validate the parameters are on existing / non private attributes
const convertFiltersQueryParams = filters => filters;

// TODO: migrate
const VALID_REST_OPERATORS = [
  'eq',
  'ne',
  'in',
  'nin',
  'contains',
  'ncontains',
  'containss',
  'ncontainss',
  'lt',
  'lte',
  'gt',
  'gte',
  'null',
];

module.exports = {
  convertSortQueryParams,
  convertStartQueryParams,
  convertLimitQueryParams,
  convertPopulateQueryParams,
  convertFiltersQueryParams,
  convertFieldsQueryParams,
  VALID_REST_OPERATORS,
  QUERY_OPERATORS,
};
<commit_msg>Fix typos<commit_after>'use strict';

/**
 * Converts the standard Strapi REST query params to a more usable format for querying
 * You can read more here: https://strapi.io/documentation/developer-docs/latest/developer-resources/content-api/content-api.html#filters
 */

const _ = require('lodash');

const QUERY_OPERATORS = ['_where', '_or', '_and'];

class InvalidOrderError extends Error {
  constructor() {
    super();
    this.message = 'Invalid order. order can only be one of asc|desc|ASC|DESC';
  }
}
class InvalidSortError extends Error {
  constructor() {
    super();
    this.message =
      'Invalid sort parameter. Expected a string, an array of strings, a sort object or an array of sort objects';
  }
}

const validateOrder = order => {
  if (!['asc', 'desc'].includes(order.toLocaleLowerCase())) {
    throw new InvalidOrderError();
  }
};

/**
 * Sort query parser
 * @param {string} sortQuery - ex: id:asc,price:desc
 */
const convertSortQueryParams = sortQuery => {
  if (typeof sortQuery === 'string') {
    return sortQuery.split(',').map(value => convertSingleSortQueryParam(value));
  }

  if (Array.isArray(sortQuery)) {
    return sortQuery.flatMap(sortValue => convertSortQueryParams(sortValue));
  }

  if (_.isPlainObject(sortQuery)) {
    return convertNestedSortQueryParam(sortQuery);
  }

  throw new InvalidSortError();
};

const convertSingleSortQueryParam = sortQuery => {
  // split field and order param with default order to ascending
  const [field, order = 'asc'] = sortQuery.split(':');

  if (field.length === 0) {
    throw new Error('Field cannot be empty');
  }

  validateOrder(order);

  return _.set({}, field, order);
};

const convertNestedSortQueryParam = sortQuery => {
  const transformedSort = {};
  for (const field in sortQuery) {
    const order = sortQuery[field];

    // this is a deep sort
    if (_.isPlainObject(order)) {
      transformedSort[field] = convertNestedSortQueryParam(order);
    } else {
      validateOrder(order);
      transformedSort[field] = order;
    }
  }

  return transformedSort;
};

/**
 * Start query parser
 * @param {string} startQuery
 */
const convertStartQueryParams = startQuery => {
  const startAsANumber = _.toNumber(startQuery);

  if (!_.isInteger(startAsANumber) || startAsANumber < 0) {
    throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`);
  }

  return startAsANumber;
};

/**
 * Limit query parser
 * @param {string} limitQuery
 */
const convertLimitQueryParams = limitQuery => {
  const limitAsANumber = _.toNumber(limitQuery);

  if (!_.isInteger(limitAsANumber) || (limitAsANumber !== -1 && limitAsANumber < 0)) {
    throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`);
  }

  return limitAsANumber;
};

class InvalidPopulateError extends Error {
  constructor() {
    super();
    this.message =
      'Invalid populate parameter. Expected a string, an array of strings, a populate object';
  }
}

// NOTE: we could support foo.* or foo.bar.* etc later on
const convertPopulateQueryParams = (populate, depth = 0) => {
  if (depth === 0 && populate === '*') {
    return true;
  }

  if (typeof populate === 'string') {
    return populate.split(',').map(value => _.trim(value));
  }

  if (Array.isArray(populate)) {
    // map convert
    return populate.flatMap(value => {
      if (typeof value !== 'string') {
        throw new InvalidPopulateError();
      }

      return value.split(',').map(value => _.trim(value));
    });
  }

  if (_.isPlainObject(populate)) {
    const transformedPopulate = {};
    for (const key in populate) {
      transformedPopulate[key] = convertNestedPopulate(populate[key]);
    }
    return transformedPopulate;
  }

  throw new InvalidPopulateError();
};

const convertNestedPopulate = subPopulate => {
  if (subPopulate === '*') {
    return true;
  }

  if (_.isBoolean(subPopulate)) {
    return subPopulate;
  }

  if (!_.isPlainObject(subPopulate)) {
    throw new Error(`Invalid nested populate. Expected '*' or an object`);
  }

  // TODO: We will need to consider a way to add limitation / pagination
  const { sort, filters, fields, populate } = subPopulate;

  const query = {};

  if (sort) {
    query.orderBy = convertSortQueryParams(sort);
  }

  if (filters) {
    query.where = convertFiltersQueryParams(filters);
  }

  if (fields) {
    query.select = convertFieldsQueryParams(fields);
  }

  if (populate) {
    query.populate = convertPopulateQueryParams(populate);
  }

  return query;
};

const convertFieldsQueryParams = (fields, depth = 0) => {
  if (depth === 0 && fields === '*') {
    return undefined;
  }

  if (typeof fields === 'string') {
    const fieldsValues = fields.split(',').map(value => _.trim(value));
    return _.uniq(['id', ...fieldsValues]);
  }

  if (Array.isArray(fields)) {
    // map convert
    const fieldsValues = fields.flatMap(value => convertFieldsQueryParams(value, depth + 1));
    return _.uniq(['id', ...fieldsValues]);
  }

  throw new Error('Invalid fields parameter. Expected a string or an array of strings');
};

// NOTE: We could validate the parameters are on existing / non private attributes
const convertFiltersQueryParams = filters => filters;

// TODO: migrate
const VALID_REST_OPERATORS = [
  'eq',
  'ne',
  'in',
  'nin',
  'contains',
  'ncontains',
  'containss',
  'ncontainss',
  'lt',
  'lte',
  'gt',
  'gte',
  'null',
];

module.exports = {
  convertSortQueryParams,
  convertStartQueryParams,
  convertLimitQueryParams,
  convertPopulateQueryParams,
  convertFiltersQueryParams,
  convertFieldsQueryParams,
  VALID_REST_OPERATORS,
  QUERY_OPERATORS,
};
<|endoftext|>


<commit_before>import { getCurrentShader, getShaderConfig, getShaderViewport } from 'reducers'
import { SHADER_ENUM } from 'javascript/config'
import setUniformValue from 'webgl-utilities/setUniformValue'
import msaaCoordinates from 'webgl-utilities/msaaCoordinates'

import assign from 'lodash/assign'
import forEach from 'lodash/forEach'

const { requestAnimationFrame } = window

let time = 0 // Date.now() & Math.pow(2, 21) - 1;
export default ({ canvas, context, shader, program, store }) => function renderFrame () {
  /* eslint-disable no-multi-spaces, key-spacing */
  const state = store.getState()

  const currentShader = getCurrentShader(state)
  if (shader === currentShader) {
    const { center, range } = getShaderViewport(state, currentShader)
    const config            = getShaderConfig(state, currentShader)

    if (config.speed) {
      time += parseFloat(config.speed)
    } else {
      time += 0.016
    }

    const uniformValues = assign({}, config, {
      shader: SHADER_ENUM[currentShader],
      center: [center.x, center.y],
      range:  [range.x, range.y],
      resolution: [
        window.innerWidth,
        window.innerHeight
      ],
      julia_c: [
        -0.795 + Math.sin(time / 2000) / 40,
        0.2321 + Math.cos(time / 1330) / 40
      ],
      msaa_coordinates: msaaCoordinates[config.supersamples],
      time: time
    })

    context.useProgram(program)
    forEach(uniformValues, (uniformValue, uniformName) => {
      setUniformValue(uniformName, uniformValue, context, program)
    })

    context.drawArrays(context.TRIANGLE_STRIP, 0, 4)

    resize({ canvas, context })

    requestAnimationFrame(renderFrame)
  }
  /* eslint-enable no-multi-spaces, key-spacing */
}

function resize ({ canvas, context }) {
  /* http://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html */
  const WIDTH = window.innerWidth
  const HEIGHT = window.innerHeight

  if (canvas.width !== WIDTH || canvas.height !== HEIGHT) {
    canvas.width = WIDTH
    canvas.height = HEIGHT

    context.viewport(0, 0, WIDTH, HEIGHT)
  }
}
<commit_msg>restores Date.now() start time rather than 0 start time<commit_after>import { getCurrentShader, getShaderConfig, getShaderViewport } from 'reducers'
import { SHADER_ENUM } from 'javascript/config'
import setUniformValue from 'webgl-utilities/setUniformValue'
import msaaCoordinates from 'webgl-utilities/msaaCoordinates'

import assign from 'lodash/assign'
import forEach from 'lodash/forEach'

const { requestAnimationFrame } = window

let time = Date.now()
export default ({ canvas, context, shader, program, store, startTime = Date.now() }) => function renderFrame () {
  /* eslint-disable no-multi-spaces, key-spacing */
  const state = store.getState()

  const currentShader = getCurrentShader(state)
  if (shader === currentShader) {
    const { center, range } = getShaderViewport(state, currentShader)
    const config            = getShaderConfig(state, currentShader)

    if (config.speed) {
      time += parseFloat(config.speed)
    } else {
      time += 0.016
    }

    const uniformValues = assign({}, config, {
      shader: SHADER_ENUM[currentShader],
      center: [center.x, center.y],
      range:  [range.x, range.y],
      resolution: [
        window.innerWidth,
        window.innerHeight
      ],
      julia_c: [
        -0.795 + Math.sin(time / 2000) / 40,
        0.2321 + Math.cos(time / 1330) / 40
      ],
      msaa_coordinates: msaaCoordinates[config.supersamples],
      time: time - startTime // large times won't convert to float 32 well
    })

    context.useProgram(program)
    forEach(uniformValues, (uniformValue, uniformName) => {
      setUniformValue(uniformName, uniformValue, context, program)
    })

    context.drawArrays(context.TRIANGLE_STRIP, 0, 4)

    resize({ canvas, context })

    requestAnimationFrame(renderFrame)
  }
  /* eslint-enable no-multi-spaces, key-spacing */
}

function resize ({ canvas, context }) {
  /* http://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html */
  const WIDTH = window.innerWidth
  const HEIGHT = window.innerHeight

  if (canvas.width !== WIDTH || canvas.height !== HEIGHT) {
    canvas.width = WIDTH
    canvas.height = HEIGHT

    context.viewport(0, 0, WIDTH, HEIGHT)
  }
}
<|endoftext|>


<commit_before>import { fetchArticleByUrl } from './../../../app/actions/article';
import { getArticle } from './../../../app/selectors/article';
import { getUser } from './../../../app/selectors/user';
import { isLoggedIn } from './../../../app/utils/userUtils';

import icon16 from './../../assets/img/icon-16.png';
import icon32 from './../../assets/img/icon-32.png';
import icon128 from './../../assets/img/icon-128.png';

import icon16Saved from './../../assets/img/icon-16-saved.png';
import icon32Saved from './../../assets/img/icon-32-saved.png';
import icon128Saved from './../../assets/img/icon-128-saved.png';

const setBadge = (tabId, saved, read) => {
  if (saved) {
    chrome.browserAction.setIcon({
      path: { 16: icon16Saved, 32: icon32Saved, 128: icon128Saved },
      tabId,
    });
  } else {
    chrome.browserAction.setIcon({
      path: { 16: icon16, 32: icon32, 128: icon128 },
      tabId,
    });
  }

  if (read) {
    chrome.browserAction.setBadgeBackgroundColor({ color: '#ff4081', tabId });
    chrome.browserAction.setBadgeText({ text: ' ', tabId });
  } else {
    chrome.browserAction.setBadgeText({ text: '', tabId });
  }
};

export const tabHandler = (store) => (tabId, url) => {
  const state = store.getState();
  const user = getUser(state);

  if (isLoggedIn(user)) {
    setBadge(tabId, false, false);
    store.dispatch(fetchArticleByUrl(url)).then(() => {
      const article = getArticle(state, url);

      setBadge(tabId, article.get('id'), article.get('read'));
    });
  } else {
    setBadge(tabId, false, false);
  }
};
<commit_msg>Don't fetch article status if already in store<commit_after>import { fetchArticleByUrl } from './../../../app/actions/article';
import { getArticle } from './../../../app/selectors/article';
import { getUser } from './../../../app/selectors/user';
import { isLoggedIn } from './../../../app/utils/userUtils';

import icon16 from './../../assets/img/icon-16.png';
import icon32 from './../../assets/img/icon-32.png';
import icon128 from './../../assets/img/icon-128.png';

import icon16Saved from './../../assets/img/icon-16-saved.png';
import icon32Saved from './../../assets/img/icon-32-saved.png';
import icon128Saved from './../../assets/img/icon-128-saved.png';

const setBadge = (tabId, saved, read) => {
  if (saved) {
    chrome.browserAction.setIcon({
      path: { 16: icon16Saved, 32: icon32Saved, 128: icon128Saved },
      tabId,
    });
  } else {
    chrome.browserAction.setIcon({
      path: { 16: icon16, 32: icon32, 128: icon128 },
      tabId,
    });
  }

  if (read) {
    chrome.browserAction.setBadgeBackgroundColor({ color: '#ff4081', tabId });
    chrome.browserAction.setBadgeText({ text: ' ', tabId });
  } else {
    chrome.browserAction.setBadgeText({ text: '', tabId });
  }
};

export const tabHandler = (store) => (tabId, url) => {
  const state = store.getState();
  const user = getUser(state);

  if (isLoggedIn(user)) {
    const article = getArticle(state, url);

    setBadge(tabId, article.get('id'), article.get('read'));

    if (!article.get('url')) {
      store.dispatch(fetchArticleByUrl(url));
    }
  } else {
    setBadge(tabId, false, false);
  }
};
<|endoftext|>


<commit_before>
fcViews.resourceDay = ResourceDayView;

function ResourceDayView(element, calendar) {
	var t = this;

	// exports
	t.render = render;

	// imports
	ResourceView.call(t, element, calendar, 'resourceDay');
	var opt = t.opt;
	var renderBasic = t.renderBasic;
	var formatDates = calendar.formatDates;
	var getResources = t.getResources;

	function render(date, delta) {
		if (delta) {
			addDays(date, delta * 1);
		}

		var start = addMinutes(cloneDate(date, true),parseTime(opt('minTime')));
		var end = addMinutes(cloneDate(start), (parseTime(opt('maxTime'))-parseTime(opt('minTime'))));
		var visStart = cloneDate(start);
		var visEnd = cloneDate(end);
		var weekends = opt('weekends');
		if (!weekends) {
			skipWeekend(visStart);
			skipWeekend(visEnd, -1, true);
		}
		t.title = formatDates(
			visStart,
			addDays(cloneDate(visEnd), -1),
			opt('titleFormat')
		);
		t.start = start;
		t.end = end;
		t.visStart = visStart;
		t.visEnd = visEnd;

		var cols = Math.round((visEnd - visStart) / 1000 / 60 / opt('slotMinutes'));

		renderBasic(getResources.length, getResources.length, cols, false);
	}

}
<commit_msg>Fixed a bug where day was not calculated correctly when used weekends false with resourceDay view<commit_after>
fcViews.resourceDay = ResourceDayView;

function ResourceDayView(element, calendar) {
	var t = this;

	// exports
	t.render = render;

	// imports
	ResourceView.call(t, element, calendar, 'resourceDay');
	var opt = t.opt;
	var renderBasic = t.renderBasic;
	var formatDates = calendar.formatDates;
	var getResources = t.getResources;

	function render(date, delta) {
		if (delta) {
			addDays(date, delta * 1);
			if (!opt('weekends')) skipWeekend(date, delta < 0 ? -1 : 1);
		}

		var start = addMinutes(cloneDate(date, true),parseTime(opt('minTime')));
		var end = addMinutes(cloneDate(start), (parseTime(opt('maxTime'))-parseTime(opt('minTime'))));
		var visStart = cloneDate(start);
		var visEnd = cloneDate(end);

		t.title = formatDates(
			visStart,
			addDays(cloneDate(visEnd), -1),
			opt('titleFormat')
		);
		t.start = start;
		t.end = end;
		t.visStart = visStart;
		t.visEnd = visEnd;

		var cols = Math.round((visEnd - visStart) / 1000 / 60 / opt('slotMinutes'));
		renderBasic(getResources.length, getResources.length, cols, false);
	}

}
<|endoftext|>


<commit_before>// @flow
import React, {Component} from 'react'
import RemoteComponent from './remote-component'
import {connect} from 'react-redux'
import {onClose, startTimer, stopTimer, getProfile} from '../../actions/tracker'

import type {TypedState} from '../../constants/reducer'
import type {TrackerOrNonUserState} from '../../constants/tracker'
import type {Action} from '../../constants/types/flux'

type Props = {
  onClose: (username: string) => void,
  started: boolean,
  errorRetry: (username: string) => void,
  startTimer: () => void,
  stopTimer: () => Action,
  trackers: {[key: string]: TrackerOrNonUserState},
}

class RemoteTracker extends Component<void, Props, void> {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.trackers !== this.props.trackers
  }

  render() {
    const {trackers} = this.props
    const windowsOpts = {height: 470, width: 320}

    return (

        {Object.keys(trackers)
          .filter(username => !trackers[username].closed)
          .map(username => (
            <RemoteComponent
              positionBottomRight={true}
              windowsOpts={windowsOpts}
              title={`tracker - ${username}`}
              waitForState={true}
              ignoreNewProps={true}
              hidden={trackers[username].hidden}
              onRemoteClose={() => this.props.onClose(username)}
              component="tracker"
              username={username}
              startTimer={this.props.startTimer}
              errorRetry={() => this.props.errorRetry(username)}
              stopTimer={this.props.stopTimer}
              selectorParams={username}
              key={username}
            />
          ))}

    )
  }
}

type OwnProps = {}

export default connect(
  (state: TypedState, op: OwnProps) => ({
    started: state.tracker.serverStarted,
    trackers: state.tracker.trackers,
  }),
  (dispatch: any, op: OwnProps) => ({
    startTimer: () => dispatch(startTimer()),
    stopTimer: () => dispatch(stopTimer()),
    errorRetry: (username: string) => {
      dispatch(getProfile(username, true))
    },
    onClose: (username: string) => {
      dispatch(onClose(username))
    },
  })
)(RemoteTracker)
<commit_msg>limit visible trackers (#7635)<commit_after>// @flow
import React, {Component} from 'react'
import RemoteComponent from './remote-component'
import {connect} from 'react-redux'
import {onClose, startTimer, stopTimer, getProfile} from '../../actions/tracker'

import type {TypedState} from '../../constants/reducer'
import type {TrackerOrNonUserState} from '../../constants/tracker'
import type {Action} from '../../constants/types/flux'

type Props = {
  onClose: (username: string) => void,
  started: boolean,
  errorRetry: (username: string) => void,
  startTimer: () => void,
  stopTimer: () => Action,
  trackers: {[key: string]: TrackerOrNonUserState},
}

const MAX_TRACKERS = 5

class RemoteTracker extends Component<void, Props, void> {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.trackers !== this.props.trackers
  }

  render() {
    const {trackers} = this.props
    const windowsOpts = {height: 470, width: 320}

    return (

        {Object.keys(trackers)
          .filter(username => !trackers[username].closed)
          .slice(0, MAX_TRACKERS)
          .map(username => (
            <RemoteComponent
              positionBottomRight={true}
              windowsOpts={windowsOpts}
              title={`tracker - ${username}`}
              waitForState={true}
              ignoreNewProps={true}
              hidden={trackers[username].hidden}
              onRemoteClose={() => this.props.onClose(username)}
              component="tracker"
              username={username}
              startTimer={this.props.startTimer}
              errorRetry={() => this.props.errorRetry(username)}
              stopTimer={this.props.stopTimer}
              selectorParams={username}
              key={username}
            />
          ))}

    )
  }
}

type OwnProps = {}

export default connect(
  (state: TypedState, op: OwnProps) => ({
    started: state.tracker.serverStarted,
    trackers: state.tracker.trackers,
  }),
  (dispatch: any, op: OwnProps) => ({
    startTimer: () => dispatch(startTimer()),
    stopTimer: () => dispatch(stopTimer()),
    errorRetry: (username: string) => {
      dispatch(getProfile(username, true))
    },
    onClose: (username: string) => {
      dispatch(onClose(username))
    },
  })
)(RemoteTracker)
<|endoftext|>