<commit_before>"use strict";

const PouchDB = require("pouchdb-browser")
const _ = require("ramda")

// PouchDB.debug.enable("*")
PouchDB.debug.disable()
PouchDB.plugin(require('pouchdb-find'))
PouchDB.plugin(require('pouchdb-upsert'))

const removeNilValuedKeys = value =>
    _.when(_.is(Object),
        _.compose(_.map(removeNilValuedKeys), _.reject(_.isNil))
    )(value)

export default async (dbName, indices = []) => {
    const db = new PouchDB(dbName)
    let syncTracker = null;

    function createIndex(index) {
        return db.createIndex(index)
        // .then(console.log)
    }

    async function deleteIndices() {
        const existingCustomIndices = _.filter(_.prop("ddoc"), (await db.getIndexes()).indexes)
        return await Promise.all(_.map(_.bind(db.deleteIndex, db), existingCustomIndices))
    }

    function bulkDocs(docs) {
        return db.bulkDocs(docs)
    }

    async function upsert(id, doc) {
        //noinspection UnnecessaryLocalVariableJS
        const upsertResult = await db.upsert(id, oldDoc => {

            const cleanNewDoc = ((doc, oldDoc) => {
                const mergeOldDocRev = _.merge(_.__, {_rev: oldDoc._rev})

                const isRevEmpty = _.propSatisfies(_.isEmpty, "_rev")

                return _
                    .compose(
                        _.when(isRevEmpty, mergeOldDocRev),
                        removeNilValuedKeys
                    )(doc)

            })(doc, oldDoc)

            const cleanOldDoc = removeNilValuedKeys(oldDoc)

            const areDocsSame = _.equals(cleanNewDoc, cleanOldDoc)

            console.log("doc diff", _.merge(cleanOldDoc, {}), _.merge(cleanNewDoc, {}))

            if (areDocsSame) {
                console.log("upsert: ignoring update since docs are same: ", areDocsSame)
                return
            }
            console.log("upsert: adding new doc since docs are *not* same", cleanNewDoc, cleanOldDoc)
            return cleanNewDoc
        })
        console.log("upsert: result", upsertResult)
        return upsertResult
    }

    function startRemoteSync(remoteUrl = "http://localhost:12321", prefix = "", dbName_ = dbName) {
        const dbNameWithPrefix = `${prefix}${dbName_}`
        console.log(`starting sync for ${dbNameWithPrefix}`)
        const remoteURL = `${remoteUrl}/${dbNameWithPrefix}`;
        if (syncTracker) {
            syncTracker.cancel()
        }
        const tracker = db
            .sync(remoteURL,
                {live: true, retry: true},
                (error, result) => {
                    if (error) {
                        console.error(`PLDB: sync err ${dbName_}`, error)
                    } else {
                        console.info("PLDB: sync complete = ", result)
                    }

                })
        syncTracker = tracker
        return tracker
    }

    const find = async options => (await db.find(options)).docs

    function allDocs() {
        db.allDocs()
    }

    async function deleteAllDocs() {
        function remove(doc) {
            return db.put(_.merge(doc, {_deleted: true}))
        }

        return Promise.all(_.map(remove, await allDocs()))
    }

    // await deleteIndices();
    await Promise.all(_.map(createIndex, indices))

    function onChange(callback) {
        return db.changes({
            since: 'now',
            live: true,
            include_docs: true,
        }).on('change', function (change) {
            // console.log("change", change)
            callback(change.doc)
        }).on('complete', function (info) {
            // changes() was canceled
        }).on('error', function (err) {
            console.log(err);
        });
    }

    return {
        find,
        deleteAllDocs,
        bulkDocs,
        _db: db,
        upsert,
        deleteIndices,
        allDocs,
        startRemoteSync,
        findAll: () => find({selector: {"_id": {"$ne": null}}}),
        onChange,
        changes: _.bind(db.changes, db),
        name: dbName
    }
}

<commit_msg>[fix] firebase sync infinite upsert bug<commit_after>"use strict";

const PouchDB = require("pouchdb-browser")
const _ = require("ramda")

// PouchDB.debug.enable("*")
PouchDB.debug.disable()
PouchDB.plugin(require('pouchdb-find'))
PouchDB.plugin(require('pouchdb-upsert'))

const removeNilValuedKeys = value =>
    _.when(_.is(Object),
        _.compose(_.map(removeNilValuedKeys), _.reject(_.isNil))
    )(value)

export default async (dbName, indices = []) => {
    const db = new PouchDB(dbName)
    let syncTracker = null;

    function createIndex(index) {
        return db.createIndex(index)
        // .then(console.log)
    }

    async function deleteIndices() {
        const existingCustomIndices = _.filter(_.prop("ddoc"), (await db.getIndexes()).indexes)
        return await Promise.all(_.map(_.bind(db.deleteIndex, db), existingCustomIndices))
    }

    function bulkDocs(docs) {
        return db.bulkDocs(docs)
    }

    async function upsert(id, doc) {
        //noinspection UnnecessaryLocalVariableJS
        const upsertResult = await db.upsert(id, oldDoc => {

            const cleanNewDoc = ((doc, oldDoc) => {
                const mergeOldDocRev = _.merge(_.__, {_rev: oldDoc._rev})
                const isRevEmpty = _.propSatisfies(_.isEmpty, "_rev")
                return _
                    .compose(
                        _.when(isRevEmpty, mergeOldDocRev),
                        removeNilValuedKeys
                    )(doc)

            })(doc, oldDoc)

            const cleanOldDoc = removeNilValuedKeys(oldDoc)
            const areDocsSame = _.equals(cleanNewDoc, cleanOldDoc)

            if (areDocsSame) {
                console.log("upsert: ignoring update since docs are same: ", areDocsSame)
                return
            }
            /*console.log("upsert: adding new doc since docs are *not* same: immutable diff: ",
                _.merge(cleanOldDoc, {})
                , _.merge(cleanNewDoc, {})
            )*/
            return cleanNewDoc
        })
        console.log("upsert: result", upsertResult)
        return upsertResult
    }

    function startRemoteSync(remoteUrl = "http://localhost:12321", prefix = "", dbName_ = dbName) {
        const dbNameWithPrefix = `${prefix}${dbName_}`
        console.log(`starting sync for ${dbNameWithPrefix}`)
        const remoteURL = `${remoteUrl}/${dbNameWithPrefix}`;
        if (syncTracker) {
            syncTracker.cancel()
        }
        const tracker = db
            .sync(remoteURL,
                {live: true, retry: true},
                (error, result) => {
                    if (error) {
                        console.error(`PLDB: sync err ${dbName_}`, error)
                    } else {
                        console.info("PLDB: sync complete = ", result)
                    }

                })
        syncTracker = tracker
        return tracker
    }

    const find = async options => (await db.find(options)).docs

    function allDocs() {
        db.allDocs()
    }

    async function deleteAllDocs() {
        function remove(doc) {
            return db.put(_.merge(doc, {_deleted: true}))
        }

        return Promise.all(_.map(remove, await allDocs()))
    }

    // await deleteIndices();
    await Promise.all(_.map(createIndex, indices))

    function onChange(callback) {
        return db.changes({
            since: 'now',
            live: true,
            include_docs: true,
        }).on('change', function (change) {
            // console.log("change", change)
            callback(change.doc)
        }).on('complete', function (info) {
            // changes() was canceled
        }).on('error', function (err) {
            console.log(err);
        });
    }

    return {
        find,
        deleteAllDocs,
        bulkDocs,
        _db: db,
        upsert,
        deleteIndices,
        allDocs,
        startRemoteSync,
        findAll: () => find({selector: {"_id": {"$ne": null}}}),
        onChange,
        changes: _.bind(db.changes, db),
        name: dbName
    }
}

<|endoftext|>


<commit_before>import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

export default new VueRouter({
  routes: [
    {
      path: '/config',
      component: require('../pages/Config')
    },
    {
      path: '/',
      component: require('../layout/Default'),
      children: [
        {
          path: '/',
          component: require('../pages/Dashboard')
        },
        {
          path: '/collections',
          component: require('../pages/Collections')
        },
        {
          name: 'collection',
          path: '/collections/:id',
          component: require('../pages/Collection')
        },
        {
          name: 'collection-data',
          path: '/collections/:id/data',
          component: require('../pages/CollectionData')
        },
        {
          path: '/endpoints',
          component: require('../pages/Endpoints')
        },
        {
          name: 'endpoint',
          path: '/endpoints/:path',
          component: require('../pages/Endpoint')
        },
        {
          name: 'endpoint-reference',
          path: '/endpoints/:path/reference',
          component: require('../pages/Endpoint')
        },
        {
          path: '/documentation',
          component: require('../pages/Documentation')
        },
        {
          path: '/stats',
          component: require('../pages/Stats')
        }
      ]
    }
  ]
})
<commit_msg>Added childroutes to endpoint component<commit_after>import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

export default new VueRouter({
  routes: [
    {
      path: '/config',
      component: require('../pages/Config')
    },
    {
      path: '/',
      component: require('../layout/Default'),
      children: [
        {
          path: '/',
          component: require('../pages/Dashboard')
        },
        {
          path: '/collections',
          component: require('../pages/Collections')
        },
        {
          name: 'collection',
          path: '/collections/:id',
          component: require('../pages/Collection')
        },
        {
          name: 'collection-data',
          path: '/collections/:id/data',
          component: require('../pages/CollectionData')
        },
        {
          path: '/endpoints',
          component: require('../pages/Endpoints'),
          children: [
            {
              path: '/',
              component: require('../components/EndpointFormView')
            },
            {
              name: 'endpoint',
              path: '/endpoints/:path',
              component: require('../components/EndpointMethodView')
            },
            {
              name: 'endpoint-reference',
              path: '/endpoints/:path/reference',
              component: require('../components/EndpointMethodView')
            }
          ]
        },
        {
          path: '/documentation',
          component: require('../pages/Documentation')
        },
        {
          path: '/stats',
          component: require('../pages/Stats')
        }
      ]
    }
  ]
})
<|endoftext|>


<commit_before>var _ = require('lodash'),
	ffmpeg = require('fluent-ffmpeg');
var ShowImporter = require('../importers/ShowImporter.js');
var traktConfig = require('../../config/trakt');
var directoriesConfig = require('../../config/directories');
module.exports = function home(app, models){
	app.get('/shows', function(req, res){
		var Show = models.Show;
		if(req.isAuthenticated()){
			Show.find(function(err, shows){
				res.render('shows/index', {
					shows: shows
				});
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/show/:show', function(req, res){
		var Show = models.Show,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Show.findOne({url: req.params.show}, function(err, show){
				if(!show || show.length == 0){
					return res.render('error.html', {
						message: 'Show not found'
					});
				}
				//console.log(show)
				if(show && show.seasons){
					show.seasons = show.seasons.sort(function(a, b){
							if(a.season > b.season){
								return 1;
							}else if(a.season < b.season){
								return -1;
							}
							return 0;
					});
				}
				Episode.find({'show': show._id}, function(err, episodes){
					if(err){
						console.log(err);
					}
					//console.log('lol', episodes)
					var seasons = {};
					_.each(episodes, function (el){
						var s = el.season,
							e = el.episode;
						if(!seasons[s]){
							seasons[s] = {};
							seasons[s].num = s;
						}
						var season = seasons[s];
						if(!season.episodes){
							season.episodes = [];
						}
						if(show && show.seasons){
							if(show.seasons && show.seasons[s] && show.seasons[s].episodes){
								el = _.merge(el, show.seasons[s].episodes[e-1])
								//console.log(show.seasons[s].episodes[e])
							}
						}
						season.episodes.push(el)
					});
					seasons = _.each(seasons, function(season){
						if(season){
							season.episodes = season.episodes.sort(function(a, b){
								if(a.episode > b.episode){
									return 1;
								}else if(a.episode < b.episode){
									return -1;
								}
								return 0;
							});
						}
					});
					res.render('shows/single', {
						show: show,
						seasons: seasons
					});
				})
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/watch/:episodeId', function(req, res){
		var dir = directoriesConfig.tv,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Episode
			.findOne({'_id': req.params.episodeId})
			.populate('show')
			.exec(function(err, ep){
				console.log(ep)
				res.render('shows/episode', {
					show: {},
					ep: ep
				});
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/transcode/:episodeId', function(req, res){
		var dir = directoriesConfig.tv,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Episode
			.findOne({'_id': req.params.episodeId})
			.populate('show')
			.exec(function(err, ep){
				if(ep && ep.file){
					var options = [
						'-threads 0',
						'-coder 0',
						'-flags -loop',
						'-pix_fmt yuv420p',
						'-subq 0',
						'-sc_threshold 0',
						'-keyint_min 150',
						'-deinterlace',
						'-maxrate 10000000',
						'-bufsize 10000000',
						'-acodec aac',
						'-strict experimental',
						'-frag_duration 1000',
						'-movflags +frag_keyframe+empty_moov',
						'-profile:v baseline'
					];
					// High quality, not lossless
					options.push('-g 52', '-crf 22', '-ar 48000', '-ab 320k');
					res.contentType('video/mp4');
					console.log(ep.file)
					var proc = ffmpeg({source: dir + ep.file})
					.format('h264')
					.audioCodec('aac')
					.addOptions(options)
					.on('start', function(commandLine) {
						console.log('Spawned Ffmpeg with command: ' + commandLine);
					})
					.on('end', function(){
						console.log('file has been converted succesfully');
					})
					.on('error', function(err){
						console.log('an error happened: ' + err.message);
					})
					.pipe(res, {end:true});

				}
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/import', function(req, res){
		var dir = directoriesConfig.tv,
			importer = new ShowImporter(traktConfig.apiKey, models);
		importer.importAll(dir, function(){});
		res.end();
	});
};<commit_msg>Use mp4<commit_after>var _ = require('lodash'),
	ffmpeg = require('fluent-ffmpeg');
var ShowImporter = require('../importers/ShowImporter.js');
var traktConfig = require('../../config/trakt');
var directoriesConfig = require('../../config/directories');
module.exports = function home(app, models){
	app.get('/shows', function(req, res){
		var Show = models.Show;
		if(req.isAuthenticated()){
			Show.find(function(err, shows){
				res.render('shows/index', {
					shows: shows
				});
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/show/:show', function(req, res){
		var Show = models.Show,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Show.findOne({url: req.params.show}, function(err, show){
				if(!show || show.length == 0){
					return res.render('error.html', {
						message: 'Show not found'
					});
				}
				//console.log(show)
				if(show && show.seasons){
					show.seasons = show.seasons.sort(function(a, b){
							if(a.season > b.season){
								return 1;
							}else if(a.season < b.season){
								return -1;
							}
							return 0;
					});
				}
				Episode.find({'show': show._id}, function(err, episodes){
					if(err){
						console.log(err);
					}
					//console.log('lol', episodes)
					var seasons = {};
					_.each(episodes, function (el){
						var s = el.season,
							e = el.episode;
						if(!seasons[s]){
							seasons[s] = {};
							seasons[s].num = s;
						}
						var season = seasons[s];
						if(!season.episodes){
							season.episodes = [];
						}
						if(show && show.seasons){
							if(show.seasons && show.seasons[s] && show.seasons[s].episodes){
								el = _.merge(el, show.seasons[s].episodes[e-1])
								//console.log(show.seasons[s].episodes[e])
							}
						}
						season.episodes.push(el)
					});
					seasons = _.each(seasons, function(season){
						if(season){
							season.episodes = season.episodes.sort(function(a, b){
								if(a.episode > b.episode){
									return 1;
								}else if(a.episode < b.episode){
									return -1;
								}
								return 0;
							});
						}
					});
					res.render('shows/single', {
						show: show,
						seasons: seasons
					});
				})
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/watch/:episodeId', function(req, res){
		var dir = directoriesConfig.tv,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Episode
			.findOne({'_id': req.params.episodeId})
			.populate('show')
			.exec(function(err, ep){
				console.log(ep)
				res.render('shows/episode', {
					show: {},
					ep: ep
				});
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/transcode/:episodeId', function(req, res){
		var dir = directoriesConfig.tv,
			Episode = models.Episode;
		if(req.isAuthenticated()){
			Episode
			.findOne({'_id': req.params.episodeId})
			.populate('show')
			.exec(function(err, ep){
				if(ep && ep.file){
					var options = [
						'-threads 0',
						'-coder 0',
						'-flags -loop',
						'-pix_fmt yuv420p',
						'-subq 0',
						'-sc_threshold 0',
						'-keyint_min 150',
						'-deinterlace',
						'-maxrate 10000000',
						'-bufsize 10000000',
						'-acodec aac',
						'-strict experimental',
						'-frag_duration 1000',
						'-movflags +frag_keyframe+empty_moov',
						'-profile:v baseline'
					];
					// High quality, not lossless
					options.push('-g 52', '-crf 22', '-ar 48000', '-ab 320k');
					res.contentType('video/mp4');
					console.log(ep.file)
					var proc = ffmpeg({source: dir + ep.file})
					.format('mp4')
					.audioCodec('aac')
					.addOptions(options)
					.on('start', function(commandLine) {
						console.log('Spawned Ffmpeg with command: ' + commandLine);
					})
					.on('end', function(){
						console.log('file has been converted succesfully');
					})
					.on('error', function(err){
						console.log('an error happened: ' + err.message);
					})
					.pipe(res, {end:true});

				}
			});
		}else{
			res.redirect('/auth/login');
		}
	});
	app.get('/import', function(req, res){
		var dir = directoriesConfig.tv,
			importer = new ShowImporter(traktConfig.apiKey, models);
		importer.importAll(dir, function(){});
		res.end();
	});
};<|endoftext|>


<commit_before>import express from 'express';
import * as users from '../controllers/user-controller';

const router = express.Router(); // eslint-disable-line new-cap

function respondGetAll(res) {
  users.getAll()
    .then(allUsers => {
      res.json(allUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get list of users' });
    });
}

const DEFAULT_PAGE_SIZE = 10;
function respondGetPage(res, pageNumber, pageSize) {
  users.getPage(pageNumber, pageSize || DEFAULT_PAGE_SIZE)
    .then(pageOfUsers => {
      res.json(pageOfUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get page of users' });
    });
}

function respondGetByVanity(res, vanityName) {
  users.getByVanityName(vanityName)
    .then(user => {
      user ? res.json(user) : res.status(404).json({ error: 'No such user' });
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get user' });
    });
}

function respondGetMany(res, manyIds) {
  const ids = manyIds.split(',');
  users.getManyByIds(ids)
    .then(manyUsers => {
      res.json(manyUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get list of users' });
    });
}

router.get('/', (req, res) => {
  const pageNumber = req.query.page;
  const pageSize = req.query.page_size;

  const vanityName = req.query.vanity_name;
  const manyIds = req.query.ids;

  if (vanityName) {
    respondGetByVanity(res, vanityName);
  } else if (manyIds) {
    respondGetMany(res, manyIds);
  } else if (pageNumber) {
    respondGetPage(res, pageNumber, pageSize);
  } else {
    respondGetAll(res);
  }
});

router.get('/:id', (req, res) => {
  const id = req.params.id;
  users.getById(id)
    .then(user => {
      user ? res.json(user) : res.status(404).json({ error: 'No such user' });
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get user' });
    });
});

export default router;
<commit_msg>Ids are now coerced to numbers from query string<commit_after>import express from 'express';
import * as users from '../controllers/user-controller';

const router = express.Router(); // eslint-disable-line new-cap

function respondGetAll(res) {
  users.getAll()
    .then(allUsers => {
      res.json(allUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get list of users' });
    });
}

const DEFAULT_PAGE_SIZE = 10;
function respondGetPage(res, pageNumber, pageSize) {
  users.getPage(pageNumber, pageSize || DEFAULT_PAGE_SIZE)
    .then(pageOfUsers => {
      res.json(pageOfUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get page of users' });
    });
}

function respondGetByVanity(res, vanityName) {
  users.getByVanityName(vanityName)
    .then(user => {
      user ? res.json(user) : res.status(404).json({ error: 'No such user' });
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get user' });
    });
}

function respondGetMany(res, manyIds) {
  const ids = manyIds.split(',').map(id => Number(id));
  users.getManyByIds(ids)
    .then(manyUsers => {
      res.json(manyUsers);
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get list of users' });
    });
}

router.get('/', (req, res) => {
  const pageNumber = req.query.page;
  const pageSize = req.query.page_size;

  const vanityName = req.query.vanity_name;
  const manyIds = req.query.ids;

  if (vanityName) {
    respondGetByVanity(res, vanityName);
  } else if (manyIds) {
    respondGetMany(res, manyIds);
  } else if (pageNumber) {
    respondGetPage(res, pageNumber, pageSize);
  } else {
    respondGetAll(res);
  }
});

router.get('/:id', (req, res) => {
  const id = req.params.id;
  users.getById(id)
    .then(user => {
      user ? res.json(user) : res.status(404).json({ error: 'No such user' });
    })
    .catch(() => {
      res.status(500).json({ error: 'Could not get user' });
    });
});

export default router;
<|endoftext|>


<commit_before>var m = require('mithril')
var Navbar         = require('../../components/navbar/navbar.js')
var Phases         = require('../../components/phases/phases.js')
var OutcomesGraph  = require('../../components/outcomesGraph/outcomesGraph.js')
var Messaging      = require('../../components/messaging/messaging.js')
var CurrentApps        = require('../../components/currentApps/currentApps.js')

//Models
var allApps = require('../../models/allApps.model.js')

exports.controller = function () {
  allApps.fetch()
}

exports.view = function(ctrl) {
  var apps = allApps.all()

  return m('.container', [
    m('h1.center-align', 'Student Outcomes'),
    // m.component(OutcomesGraph),
    // m.component(Phases),
    // m.component(Messaging),
    m.component(CurrentApps, {apps: apps})
  ])
}<commit_msg>navbar home and student routes working<commit_after>var m = require('mithril')
var Navbar         = require('../../components/navbar/navbar.js')
// var Phases         = require('../../components/phases/phases.js')
var OutcomesGraph  = require('../../components/outcomesGraph/outcomesGraph.js')
var Messaging      = require('../../components/messaging/messaging.js')
var CurrentApps        = require('../../components/currentApps/currentApps.js')

//Models
var allApps = require('../../models/allApps.model.js')

exports.controller = function () {
  allApps.fetch()
}

exports.view = function(ctrl) {
  var apps = allApps.all()

  return m('.container', [
    m('h1.center-align', 'Student Outcomes'),
    // m.component(OutcomesGraph),
    // m.component(Phases),
    // m.component(Messaging),
    m.component(CurrentApps, {apps: apps})
  ])
}<|endoftext|>


<commit_before>'use strict';

openfdaviz.controller('SearchController', ['$scope', '$http', '$stateParams', "leafletData", function ($scope, $http, $stateParams, leafletData) {

  var Categories = {
    FOODS: 0, DRUGS: 1, DEVICES: 2
  };
  // Keep track of how many points are being displayed on the heatmap after filtering
  // for each category so the tabs of the results pane match
  $scope.counts = {
    foods: 0,
    drugs: 0,
    devices: 0
  };

  //Setting up the Leaflet Directive
  var mapZoom = 1;

  $scope.fdaVizMapCenter = {
    lat: 0,
    lng: 0,
    zoom: mapZoom
  };
  $scope.defaults = {
    maxZoom: 10,
    minZoom: 1
  };
  $scope.layers = {
    baselayers: {
      xyz: {
        name: 'OpenStreetMap (XYZ)',
        url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        type: 'xyz'
      }
    },
    overlays: {
      foods: {
        name: 'Food',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      },
      drugs: {
        name: 'Drugs',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      },
      devices: {
        name: 'Devices',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      }
    }

  };

  function init() {
    angular.element(document).ready(function () {
      bindEvents();
    });
  }

  function bindEvents() {
    $("#closeModalButton").on("click", function () {
      $("#detailModal").modal('hide');
    });
  }

  $scope.showModal = function (result) {
    $scope.modal.selectedItem = result;
    $('#detailModal').modal('show');
  };

  $scope.$on("$destroy", function () {
    $(document).off('show.bs.modal', '#detailModal');
  });

  $scope.activeResultsTab = 'foods';

  var startDate = new Date("December 31, 1970");
  var endDate = new Date();
  $scope.input = {
    searchText: $stateParams.query
  };
  $scope.query = $stateParams.query;
  $scope.devicesQueryInProgress = false;
  $scope.drugsQueryInProgress = false;
  $scope.foodsQueryInProgress = false;
  $scope.modal = {
    selectedItem: {}
  };

  var emptyResults = {
    drugs: [],
    devices: [],
    foods: []
  };

  $scope.results = emptyResults;

  $scope.handleKeypress = function ($event) {
    if ($event.keyCode === 13) {
      $scope.runQuery();
    }
  };

  $scope.activateResultsTab = function (activeTab) {
    $scope.activeResultsTab = activeTab;
  };

  angular.element(document).ready(function () {
    $scope.$on('dateChange', function (event, data) {
      startDate = data.minDate;
      endDate = data.maxDate;
      _updateAllResults();
    });
  });

  $scope.runQuery = function () {
    $stateParams.query = $scope.input.searchText = $('#searchText').val();
    $scope.layers.overlays.foods.data = [];
    $scope.layers.overlays.drugs.data = [];
    $scope.layers.overlays.devices.data = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;

    setQueryState();
    $.when.apply($, [queryDrugs(), queryFoods(), queryDevices()]).done([_updateAllResults]);
  };

  function setQueryState() {
    $scope.devicesQueryInProgress = true;
    $scope.drugsQueryInProgress = true;
    $scope.foodsQueryInProgress = true;
    $scope.results.drugs = [];
    $scope.results.foods = [];
    $scope.results.devices = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;
  }

  var generalQuery = function () {
    $stateParams.query = $scope.input.searchText;
    var deferred = $.Deferred();

    setQueryState();
    $http.get(config.resources.general + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        $scope.results.drugs = resp.drug || [];
        $scope.results.devices = resp.device || [];
        $scope.results.foods = resp.food || [];
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting drugs");
      });
    return deferred;
  };
  $.when(generalQuery()).done([_updateAllResults]);

  function queryDrugs() {
    var deferred = $.Deferred();
    $http.get(config.resources.drugs + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.drugs = resp;
        }
        handleDrugsResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting drugs");
        $scope.drugsQueryInProgress = false;
      });
    return deferred;
    // current: status: '' || []
    // ideal: status: '', drug: [], food: [], device: []
  }

  function queryFoods() {
    var deferred = $.Deferred();
    $http.get(config.resources.foods + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.foods = resp;
        }
        handleFoodsResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting foods");
        $scope.foodsQueryInProgress = false;
      });
    return deferred;
  }

  function queryDevices() {
    var deferred = $.Deferred();
    $http.get(config.resources.devices + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.devices = resp;
        }
        handleDevicesResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting devices");
        $scope.devicesQueryInProgress = false;
      });
    return deferred;
  }

  function handleFoodsResponse() {
    $scope.foodsQueryInProgress = false;

    // Plot food geodata points
    if ($scope.results.foods) {
      _addPointsToHeatmap(Categories.FOODS, $scope.results.foods, $scope.layers.overlays.foods.data);
      refreshMap();
    }
  }

  function handleDrugsResponse() {
    $scope.drugsQueryInProgress = false;

    // Plot drug geodata points
    if ($scope.results.drugs) {
      _addPointsToHeatmap(Categories.DRUGS, $scope.results.drugs, $scope.layers.overlays.drugs.data);
      refreshMap();
    }
  }

  function handleDevicesResponse() {
    $scope.devicesQueryInProgress = false;

    // Plot device geodata points
    if ($scope.results.devices) {
      _addPointsToHeatmap(Categories.DEVICES, $scope.results.devices, $scope.layers.overlays.devices.data);
      refreshMap();
    }
  }

  function _filterSearchResults(category) {
    for (var i in category) {
      if (typeof category[i].isDisplayable === "undefined") {
        category[i].isDisplayable = true;
      }
      if (typeof category[i].report_date !== "undefined") {
        if (!_isDateInBounds(category[i].report_date)) {
          category[i].isDisplayable = false;
        } else {
          category[i].isDisplayable = true;
        }
      }
    }
  }

  function _updateAllResults() {
    $scope.layers.overlays.foods.data = [];
    $scope.layers.overlays.drugs.data = [];
    $scope.layers.overlays.devices.data = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;

    if ($scope.results.foods) {
      _filterSearchResults($scope.results.foods);
    }
    if ($scope.results.drugs) {
      _filterSearchResults($scope.results.drugs);
    }
    if ($scope.results.devices) {
      _filterSearchResults($scope.results.devices);
    }

    handleDrugsResponse();
    handleFoodsResponse();
    handleDevicesResponse();

    refreshMap();
  }

  function refreshMap() {
    $scope.layers.overlays.foods.doRefresh = true;
    $scope.layers.overlays.drugs.doRefresh = true;
    $scope.layers.overlays.devices.doRefresh = true;
    // This is what people currently recommend to get the map to update immediately
    leafletData.getMap().then(function (map) {
      map.invalidateSize();
    });
  }

  function _addPointsToHeatmap(label, category, layerData) {
    var perturbRadius = 0.004;
    for (var i in category) {
      if (category[i].isDisplayable &&
          typeof category[i].GeoLocation !== "undefined" &&
          typeof category[i].GeoLocation.lat !== "undefined" &&
          typeof category[i].GeoLocation.lng !== "undefined") {
        var lat = Number(category[i].GeoLocation.lat);
        var lng = Number(category[i].GeoLocation.lng);
        var latLng = [lat, lng];
        // Since the heatmap doesn't change when there are duplicate points,
        // perturb duplicate points a little so there is a visible difference
        // in the heatmap
        _perturbDuplicatePoints(layerData, latLng, perturbRadius);
        _incrementDisplayCount(label, category[i]);
        layerData.push(latLng);
      }
    }
  }

  function _incrementDisplayCount(label, categoryElement) {
    if (categoryElement.isDisplayable) {
      switch (label) {
        case Categories.FOODS:
          $scope.counts.foods += 1;
          break;
        case Categories.DRUGS:
          $scope.counts.drugs += 1;
          break;
        case Categories.DEVICES:
          $scope.counts.devices += 1;
          break;
        default:
          break;
      }
    }
  }

  function _perturbDuplicatePoints(layerData, latLng, radius) {
    for (var j = 0; j < layerData.length; j++) {
      if (latLng[0] === layerData[j][0] &&
        latLng[1] === layerData[j][1]) {
        latLng = _perturbPointPair(latLng, radius);
        break;
      }
    }
  }

  function _perturbPointPair(latLng, radius) {
    // Spread duplicate points in a small circle around the point
    var angle = 2 * Math.PI * Math.random();
    latLng[0] += radius * Math.sin(angle);
    latLng[1] += radius * Math.cos(angle);
    return latLng;
  }

  function _isDateInBounds(dateToCheckString) {
    var reYear = /((19|20)\d{2})/;
    var dateToCheckYear = Number(dateToCheckString.match(reYear)[0]);
    var startDateYear = Number(startDate.getFullYear().toString());
    var endDateYear = Number(endDate.getFullYear().toString());
    var dateToCheckMonth = Number(dateToCheckString.substring(4, 6));
    var startDateMonth = Number(startDate.getMonth().toString())+1;
    var endDateMonth = Number(endDate.getMonth().toString())+1;
    var dateToCheckDay = Number(dateToCheckString.substring(6, 8));
    var startDateDay = Number(startDate.getDate().toString());
    var endDateDay = Number(endDate.getDate().toString());

    if (!_isYearInBounds(dateToCheckYear, startDateYear, endDateYear)) {
      return false;
    }
    else if (!_isMonthWithinStartBound(dateToCheckYear, startDateYear, dateToCheckMonth, startDateMonth)) {
      return false;
    }
    else if (!_isMonthWithinEndBound(dateToCheckYear, endDateYear, dateToCheckMonth, endDateMonth)) {
      return false;
    }
    else if (!_isDayWithinStartBound(dateToCheckMonth, startDateMonth, dateToCheckDay, startDateDay)) {
      return false;
    }
    else if (!_isDayWithinEndBound(dateToCheckMonth, endDateMonth, dateToCheckDay, endDateDay)) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isYearInBounds(dateToCheckYear, startDateYear, endDateYear) {
    if ( (dateToCheckYear < startDateYear) || (dateToCheckYear > endDateYear) ) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isMonthWithinStartBound(dateToCheckYear, startDateYear, dateToCheckMonth, startDateMonth) {
    if (dateToCheckYear === startDateYear && dateToCheckMonth < startDateMonth) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isMonthWithinEndBound(dateToCheckYear, endDateYear, dateToCheckMonth, endDateMonth) {
    if (dateToCheckYear === endDateYear && dateToCheckMonth > endDateMonth) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isDayWithinStartBound(dateToCheckMonth, startDateMonth, dateToCheckDay, startDateDay) {
    if (dateToCheckMonth === startDateMonth && dateToCheckDay < startDateDay) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isDayWithinEndBound(dateToCheckMonth, endDateMonth, dateToCheckDay, endDateDay) {
    if (dateToCheckMonth === endDateMonth && dateToCheckDay > endDateDay) {
      return false;
    }
    else {
      return true;
    }
  }

  init();

}]);<commit_msg>Refactoring for sonar<commit_after>'use strict';

openfdaviz.controller('SearchController', ['$scope', '$http', '$stateParams', "leafletData", function ($scope, $http, $stateParams, leafletData) {

  var Categories = {
    FOODS: 0, DRUGS: 1, DEVICES: 2
  };
  // Keep track of how many points are being displayed on the heatmap after filtering
  // for each category so the tabs of the results pane match
  $scope.counts = {
    foods: 0,
    drugs: 0,
    devices: 0
  };

  //Setting up the Leaflet Directive
  var mapZoom = 1;

  $scope.fdaVizMapCenter = {
    lat: 0,
    lng: 0,
    zoom: mapZoom
  };
  $scope.defaults = {
    maxZoom: 10,
    minZoom: 1
  };
  $scope.layers = {
    baselayers: {
      xyz: {
        name: 'OpenStreetMap (XYZ)',
        url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        type: 'xyz'
      }
    },
    overlays: {
      foods: {
        name: 'Food',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      },
      drugs: {
        name: 'Drugs',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      },
      devices: {
        name: 'Devices',
        type: 'heat',
        data: [],
        layerOptions: {
          radius: 8,
          blur: 5,
          minOpacity: 0.7
        },
        visible: true,
        doRefresh: true
      }
    }

  };

  function init() {
    angular.element(document).ready(function () {
      bindEvents();
    });
  }

  function bindEvents() {
    $("#closeModalButton").on("click", function () {
      $("#detailModal").modal('hide');
    });
  }

  $scope.showModal = function (result) {
    $scope.modal.selectedItem = result;
    $('#detailModal').modal('show');
  };

  $scope.$on("$destroy", function () {
    $(document).off('show.bs.modal', '#detailModal');
  });

  $scope.activeResultsTab = 'foods';

  var startDate = new Date("December 31, 2003");
  var endDate = new Date("December 31, 2014");
  $scope.input = {
    searchText: $stateParams.query
  };
  $scope.query = $stateParams.query;
  $scope.devicesQueryInProgress = false;
  $scope.drugsQueryInProgress = false;
  $scope.foodsQueryInProgress = false;
  $scope.modal = {
    selectedItem: {}
  };

  var emptyResults = {
    drugs: [],
    devices: [],
    foods: []
  };

  $scope.results = emptyResults;

  $scope.handleKeypress = function ($event) {
    if ($event.keyCode === 13) {
      $scope.runQuery();
    }
  };

  $scope.activateResultsTab = function (activeTab) {
    $scope.activeResultsTab = activeTab;
  };

  angular.element(document).ready(function () {
    $scope.$on('dateChange', function (event, data) {
      startDate = data.minDate;
      endDate = data.maxDate;
      _updateAllResults();
    });
  });

  $scope.runQuery = function () {
    $stateParams.query = $scope.input.searchText = $('#searchText').val();
    $scope.layers.overlays.foods.data = [];
    $scope.layers.overlays.drugs.data = [];
    $scope.layers.overlays.devices.data = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;

    setQueryState();
    $.when.apply($, [queryDrugs(), queryFoods(), queryDevices()]).done([_updateAllResults]);
  };

  function setQueryState() {
    $scope.devicesQueryInProgress = true;
    $scope.drugsQueryInProgress = true;
    $scope.foodsQueryInProgress = true;
    $scope.results.drugs = [];
    $scope.results.foods = [];
    $scope.results.devices = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;
  }

  var generalQuery = function () {
    $stateParams.query = $scope.input.searchText;
    var deferred = $.Deferred();

    setQueryState();
    $http.get(config.resources.general + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        $scope.results.drugs = resp.drug || [];
        $scope.results.devices = resp.device || [];
        $scope.results.foods = resp.food || [];
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting drugs");
      });
    return deferred;
  };
  $.when(generalQuery()).done([_updateAllResults]);

  function queryDrugs() {
    var deferred = $.Deferred();
    $http.get(config.resources.drugs + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.drugs = resp;
        }
        handleDrugsResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting drugs");
        $scope.drugsQueryInProgress = false;
      });
    return deferred;
    // current: status: '' || []
    // ideal: status: '', drug: [], food: [], device: []
  }

  function queryFoods() {
    var deferred = $.Deferred();
    $http.get(config.resources.foods + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.foods = resp;
        }
        handleFoodsResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting foods");
        $scope.foodsQueryInProgress = false;
      });
    return deferred;
  }

  function queryDevices() {
    var deferred = $.Deferred();
    $http.get(config.resources.devices + '?query=' + $scope.input.searchText)
      .success(function (resp) {
        if (!resp.error) {
          $scope.results.devices = resp;
        }
        handleDevicesResponse();
        deferred.resolve();
      })
      .error(function () {
        console.log("error requesting devices");
        $scope.devicesQueryInProgress = false;
      });
    return deferred;
  }

  function handleFoodsResponse() {
    $scope.foodsQueryInProgress = false;

    // Plot food geodata points
    if ($scope.results.foods) {
      _filterSearchResults($scope.results.foods);
      _addPointsToHeatmap(Categories.FOODS, $scope.results.foods, $scope.layers.overlays.foods.data);
      refreshMap();
    }
  }

  function handleDrugsResponse() {
    $scope.drugsQueryInProgress = false;

    // Plot drug geodata points
    if ($scope.results.drugs) {
      _filterSearchResults($scope.results.drugs);
      _addPointsToHeatmap(Categories.DRUGS, $scope.results.drugs, $scope.layers.overlays.drugs.data);
      refreshMap();
    }
  }

  function handleDevicesResponse() {
    $scope.devicesQueryInProgress = false;

    // Plot device geodata points
    if ($scope.results.devices) {
      _filterSearchResults($scope.results.devices);
      _addPointsToHeatmap(Categories.DEVICES, $scope.results.devices, $scope.layers.overlays.devices.data);
      refreshMap();
    }
  }

  function _filterSearchResults(category) {
    for (var i in category) {
      if (typeof category[i].isDisplayable === "undefined") {
        category[i].isDisplayable = false;
      }
      if (typeof category[i].report_date !== "undefined") {
        if (!_isDateInBounds(category[i].report_date)) {
          category[i].isDisplayable = false;
        } else {
          category[i].isDisplayable = true;
        }
      }
    }
  }

  function _updateAllResults() {
    $scope.layers.overlays.foods.data = [];
    $scope.layers.overlays.drugs.data = [];
    $scope.layers.overlays.devices.data = [];
    $scope.counts.foods = 0;
    $scope.counts.drugs = 0;
    $scope.counts.devices = 0;

    handleDrugsResponse();
    handleFoodsResponse();
    handleDevicesResponse();
  }

  function refreshMap() {
    $scope.layers.overlays.foods.doRefresh = true;
    $scope.layers.overlays.drugs.doRefresh = true;
    $scope.layers.overlays.devices.doRefresh = true;
    // This is what people currently recommend to get the map to update immediately
    leafletData.getMap().then(function (map) {
      map.invalidateSize();
    });
  }

  function _addPointsToHeatmap(label, category, layerData) {
    var perturbRadius = 0.004;
    for (var i in category) {
      if (category[i].isDisplayable &&
          typeof category[i].GeoLocation !== "undefined" &&
          typeof category[i].GeoLocation.lat !== "undefined" &&
          typeof category[i].GeoLocation.lng !== "undefined") {
        var lat = Number(category[i].GeoLocation.lat);
        var lng = Number(category[i].GeoLocation.lng);
        var latLng = [lat, lng];
        // Since the heatmap doesn't change when there are duplicate points,
        // perturb duplicate points a little so there is a visible difference
        // in the heatmap
        _perturbDuplicatePoints(layerData, latLng, perturbRadius);
        _incrementDisplayCount(label, category[i]);
        layerData.push(latLng);
      }
    }
  }

  function _incrementDisplayCount(label, categoryElement) {
    if (categoryElement.isDisplayable) {
      switch (label) {
        case Categories.FOODS:
          $scope.counts.foods += 1;
          break;
        case Categories.DRUGS:
          $scope.counts.drugs += 1;
          break;
        case Categories.DEVICES:
          $scope.counts.devices += 1;
          break;
        default:
          break;
      }
    }
  }

  function _perturbDuplicatePoints(layerData, latLng, radius) {
    for (var j = 0; j < layerData.length; j++) {
      if (latLng[0] === layerData[j][0] &&
        latLng[1] === layerData[j][1]) {
        latLng = _perturbPointPair(latLng, radius);
        break;
      }
    }
  }

  function _perturbPointPair(latLng, radius) {
    // Spread duplicate points in a small circle around the point
    var angle = 2 * Math.PI * Math.random();
    latLng[0] += radius * Math.sin(angle);
    latLng[1] += radius * Math.cos(angle);
    return latLng;
  }

  function _isDateInBounds(dateToCheckString) {
    var reYear = /((19|20)\d{2})/;
    var dateToCheckYear = Number(dateToCheckString.match(reYear)[0]);
    var startDateYear = Number(startDate.getFullYear().toString());
    var endDateYear = Number(endDate.getFullYear().toString());
    var dateToCheckMonth = Number(dateToCheckString.substring(4, 6));
    var startDateMonth = Number(startDate.getMonth().toString());
    var endDateMonth = Number(endDate.getMonth().toString());
    var dateToCheckDay = Number(dateToCheckString.substring(6, 8));
    var startDateDay = Number(startDate.getDate().toString());
    var endDateDay = Number(endDate.getDate().toString());

    if (!_isYearInBounds(dateToCheckYear, startDateYear, endDateYear)) {
      return false;
    }
    else if (!_isMonthWithinBounds(dateToCheckYear, startDateYear, endDateYear, dateToCheckMonth, startDateMonth, endDateMonth)) {
      return false;
    }
    else if (!_isDayWithinBounds(dateToCheckMonth, startDateMonth, endDateMonth, dateToCheckDay, startDateDay, endDateDay)) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isYearInBounds(dateToCheckYear, startDateYear, endDateYear) {
    if ( (dateToCheckYear < startDateYear) || (dateToCheckYear > endDateYear) ) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isMonthWithinBounds(dateToCheckYear, startDateYear, endDateYear, dateToCheckMonth, startDateMonth, endDateMonth) {
    if ((dateToCheckYear === startDateYear) && (dateToCheckMonth < startDateMonth)) {
      return false;
    }
    else if((dateToCheckYear === endDateYear) && (dateToCheckMonth > endDateMonth)) {
      return false;
    }
    else {
      return true;
    }
  }

  function _isDayWithinBounds(dateToCheckMonth, startDateMonth, endDateMonth, dateToCheckDay, startDateDay, endDateDay) {
    if ((dateToCheckMonth === startDateMonth) && (dateToCheckDay < startDateDay)) {
      return false;
    }
    else if ((dateToCheckMonth === endDateMonth) && (dateToCheckDay > endDateDay)) {
      return false;
    }
    else {
      return true;
    }
  }

  init();

}]);<|endoftext|>


<commit_before>angular.module('ledita-app')
.controller('LdEditCtrl',
['$scope', '$routeParams', '$location', 'TypeaheadHelper', 'LDService', 'LDEditService', 'Home',
function($scope, $routeParams, $location, TypeaheadHelper, LDService, LDEditService, Home) {

	$scope.ldid = $routeParams.ldid;
	$scope.selectedQcers = {};

    LDEditService.getLearningDesign($scope.ldid, function(res) {
        $scope.learningDesign = res;
        initLdPublicationFlag($scope.learningDesign.ld_publication);
        Home.getQcers(function(res) {
	        $scope.qceropts = res;
        	initSelectedQcers()
	    }, function(err) {
	        $scope.qcerError = err;
	    });
    }, function(err) {
        $location.path('/');
    });

    initLdPublicationFlag = function(ld_publication) {
    	if (ld_publication === 0) {
    		$scope.ldPublicationFlag = false;
    	} else {
    		$scope.ldPublicationFlag = true;
    	}
    };

    initSelectedQcers = function() {
		$scope.selectedQcers = LDEditService.generateSelectedQcers($scope.learningDesign.qcers, $scope.qceropts);
		console.log('$scope.selectedQcers: ' + JSON.stringify($scope.selectedQcers));
    };

    LDService.getActivities($scope.ldid, function(res) {
        $scope.levels = res;
    }, function(err) {
        $scope.error = "Failed to fetch learning design activities.";
        $scope.alertMsg = err;
    });

    Home.getQcers(function(res) {
        $scope.qceropts = res;
    }, function(err) {
        $scope.qcerError = err;
    });

    $scope.getScopes = function(scope) {
    	return TypeaheadHelper.getScopes(scope);
  	};

  	$scope.getSubjects = function(subject) {
    	return TypeaheadHelper.getSubjects(subject);
  	};

  	$scope.getObjectives = function(objective) {
    	return TypeaheadHelper.getObjectives(objective);
  	};

    $scope.updateLdName = function() {
    	var modifiedLdName = $scope.learningDesign.ld_name;
    	if (modifiedLdName && modifiedLdName.length > 0) {
    		LDEditService.updateLdName($scope.ldid, {ldName: modifiedLdName},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateLdScope = function() {
    	var modifiedLdScope = $scope.learningDesign.ld_scope;
    	if (modifiedLdScope && modifiedLdScope.length > 0) {
    		LDEditService.updateLdScope($scope.ldid, {ldScope: modifiedLdScope},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateStudentsDescr = function() {
    	var modifiedStudentsDescr = $scope.learningDesign.ld_students_profile;
    	if (modifiedStudentsDescr && modifiedStudentsDescr.length > 0) {
    		LDEditService.updateStudentsDescr($scope.ldid, {studentsDescr: modifiedStudentsDescr},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateLdPublication = function() {
    	if ($scope.ldPublicationFlag) {
    		LDEditService.updateLdPublic($scope.ldid,
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	} else {
    		LDEditService.updateLdPrivate($scope.ldid,
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	}
    };

    $scope.getBoxClass = function(node) {
      return LDService.getBoxClass(node);
    };

    $scope.getGroupBoxClass = function(node) {
        return LDService.getGroupBoxClass(node);
    };

    $scope.isBtnActive = function (data) {
       if (data == true)
       return "btnActive";
   }                      ;

    $scope.open = function (node) {
        $scope.shouldBeOpen = true;
        var selectedNode;
        $scope.selectedNode = node;
        $scope.selectedNode.displayName = node.node_name || node.group_child_name;
        return selectedNode;
    };

    $scope.close = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.shouldBeOpen = false;
    };

    $scope.opts = {
        backdropFade: true,
        dialogFade:true
    };

    $scope.createActivity = function (node) {
        $scope.addActivity = true;
    };

    $scope.closeAddActivity = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addActivity = false;
    };

    $scope.optsAddActivity = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

 	$scope.createGroup = function (node) {
        $scope.addGroup = true;
    };

    $scope.closeAddGroup = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addGroup = false;
    };

    $scope.optsAddGroup = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

    $scope.addingLD = function (node) {
        $scope.addLD = true;
    };

    $scope.closeAddLD = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addLD = false;
    };

    $scope.optsAddLD = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

    $scope.createResource = function (node) {
        $scope.addResource = true;
    };

    $scope.closeAddResource = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addResource = false;
        $scope.addActivity = true;
    };

    $scope.optsAddResource = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

}]);<commit_msg>#28 remove unneeded parameter from controller method<commit_after>angular.module('ledita-app')
.controller('LdEditCtrl',
['$scope', '$routeParams', '$location', 'TypeaheadHelper', 'LDService', 'LDEditService', 'Home',
function($scope, $routeParams, $location, TypeaheadHelper, LDService, LDEditService, Home) {

	$scope.ldid = $routeParams.ldid;
	$scope.selectedQcers = {};

    LDEditService.getLearningDesign($scope.ldid, function(res) {
        $scope.learningDesign = res;
        initLdPublicationFlag();
        Home.getQcers(function(res) {
	        $scope.qceropts = res;
        	initSelectedQcers()
	    }, function(err) {
	        $scope.qcerError = err;
	    });
    }, function(err) {
        $location.path('/');
    });

    initLdPublicationFlag = function() {
    	if ($scope.learningDesign.ld_publication === 0) {
    		$scope.ldPublicationFlag = false;
    	} else {
    		$scope.ldPublicationFlag = true;
    	}
    };

    initSelectedQcers = function() {
		$scope.selectedQcers = LDEditService.generateSelectedQcers(
			$scope.learningDesign.qcers, $scope.qceropts);
    };

    LDService.getActivities($scope.ldid, function(res) {
        $scope.levels = res;
    }, function(err) {
        $scope.error = "Failed to fetch learning design activities.";
        $scope.alertMsg = err;
    });

    Home.getQcers(function(res) {
        $scope.qceropts = res;
    }, function(err) {
        $scope.qcerError = err;
    });

    $scope.getScopes = function(scope) {
    	return TypeaheadHelper.getScopes(scope);
  	};

  	$scope.getSubjects = function(subject) {
    	return TypeaheadHelper.getSubjects(subject);
  	};

  	$scope.getObjectives = function(objective) {
    	return TypeaheadHelper.getObjectives(objective);
  	};

    $scope.updateLdName = function() {
    	var modifiedLdName = $scope.learningDesign.ld_name;
    	if (modifiedLdName && modifiedLdName.length > 0) {
    		LDEditService.updateLdName($scope.ldid, {ldName: modifiedLdName},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateLdScope = function() {
    	var modifiedLdScope = $scope.learningDesign.ld_scope;
    	if (modifiedLdScope && modifiedLdScope.length > 0) {
    		LDEditService.updateLdScope($scope.ldid, {ldScope: modifiedLdScope},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateStudentsDescr = function() {
    	var modifiedStudentsDescr = $scope.learningDesign.ld_students_profile;
    	if (modifiedStudentsDescr && modifiedStudentsDescr.length > 0) {
    		LDEditService.updateStudentsDescr($scope.ldid, {studentsDescr: modifiedStudentsDescr},
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	};
    };

    $scope.updateLdPublication = function() {
    	if ($scope.ldPublicationFlag) {
    		LDEditService.updateLdPublic($scope.ldid,
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	} else {
    		LDEditService.updateLdPrivate($scope.ldid,
	        function(res) {
	        },
	        function(err) {
	            $scope.ldUpdateErrors = err; // TODO UI to display these
	        });
    	}
    };

    $scope.getBoxClass = function(node) {
      return LDService.getBoxClass(node);
    };

    $scope.getGroupBoxClass = function(node) {
        return LDService.getGroupBoxClass(node);
    };

    $scope.isBtnActive = function (data) {
       if (data == true)
       return "btnActive";
   }                      ;

    $scope.open = function (node) {
        $scope.shouldBeOpen = true;
        var selectedNode;
        $scope.selectedNode = node;
        $scope.selectedNode.displayName = node.node_name || node.group_child_name;
        return selectedNode;
    };

    $scope.close = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.shouldBeOpen = false;
    };

    $scope.opts = {
        backdropFade: true,
        dialogFade:true
    };

    $scope.createActivity = function (node) {
        $scope.addActivity = true;
    };

    $scope.closeAddActivity = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addActivity = false;
    };

    $scope.optsAddActivity = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

 	$scope.createGroup = function (node) {
        $scope.addGroup = true;
    };

    $scope.closeAddGroup = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addGroup = false;
    };

    $scope.optsAddGroup = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

    $scope.addingLD = function (node) {
        $scope.addLD = true;
    };

    $scope.closeAddLD = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addLD = false;
    };

    $scope.optsAddLD = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

    $scope.createResource = function (node) {
        $scope.addResource = true;
    };

    $scope.closeAddResource = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.addResource = false;
        $scope.addActivity = true;
    };

    $scope.optsAddResource = {
        backdropFade: true,
        dialogFade:true,
        backdropClick:false
    };

}]);<|endoftext|>


<commit_before>/*! NProgress (c) 2013, Rico Sta. Cruz
 *  http://ricostacruz.com/nprogress */

;(function(factory) {

  if (typeof module === 'object') {
    module.exports = factory(this.jQuery || require('dom'));
  } else {
    this.NProgress = factory(this.jQuery);
  }

})(function($) {
  var NProgress = {};

  NProgress.version = '0.1.0';

  var Settings = NProgress.settings = {
    minimum: 0.08,
    easing: 'ease',
    positionUsing: '',
    speed: 200,
    trickle: true,
    trickleRate: 0.02,
    trickleSpeed: 800,
    showSpinner: true,
    template: '

'
  };

  /**
   * Updates configuration.
   *
   *     NProgress.configure({
   *       minimum: 0.1
   *     });
   */
  NProgress.configure = function(options) {
    $.extend(Settings, options);
    return this;
  };

  /**
   * Last number.
   */

  NProgress.status = null;

  /**
   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
   *
   *     NProgress.set(0.4);
   *     NProgress.set(1.0);
   */

  NProgress.set = function(n) {
    var started = NProgress.isStarted();

    n = clamp(n, Settings.minimum, 1);
    NProgress.status = (n === 1 ? null : n);

    var $progress = NProgress.render(!started),
        $bar      = $progress.find('[role="bar"]'),
        speed     = Settings.speed,
        ease      = Settings.easing;

    $progress[0].offsetWidth; /* Repaint */

    $progress.queue(function(next) {
      // Set positionUsing if it hasn't already been set
      if (Settings.positionUsing == '') Settings.positionUsing = NProgress.getPositioningCSS();

      // Add transition
      $bar.css(barPositionCSS(n, speed, ease));

      if (n === 1) {
        // Fade out
        $progress.css({ transition: 'none', opacity: 1 });
        $progress[0].offsetWidth; /* Repaint */

        setTimeout(function() {
          $progress.css({ transition: 'all '+speed+'ms linear', opacity: 0 });
          setTimeout(function() {
            NProgress.remove();
            next();
          }, speed);
        }, speed);
      } else {
        setTimeout(next, speed);
      }
    });

    return this;
  };

  NProgress.isStarted = function() {
    return typeof NProgress.status === 'number';
  };

  /**
   * Shows the progress bar.
   * This is the same as setting the status to 0%, except that it doesn't go backwards.
   *
   *     NProgress.start();
   *
   */
  NProgress.start = function() {
    if (!NProgress.status) NProgress.set(0);

    var work = function() {
      setTimeout(function() {
        if (!NProgress.status) return;
        NProgress.trickle();
        work();
      }, Settings.trickleSpeed);
    };

    if (Settings.trickle) work();

    return this;
  };

  /**
   * Hides the progress bar.
   * This is the *sort of* the same as setting the status to 100%, with the
   * difference being `done()` makes some placebo effect of some realistic motion.
   *
   *     NProgress.done();
   *
   * If `true` is passed, it will show the progress bar even if its hidden.
   *
   *     NProgress.done(true);
   */

  NProgress.done = function(force) {
    if (!force && !NProgress.status) return this;

    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  };

  /**
   * Increments by a random amount.
   */

  NProgress.inc = function(amount) {
    var n = NProgress.status;

    if (!n) {
      return NProgress.start();
    } else {
      if (typeof amount !== 'number') {
        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
      }

      n = clamp(n + amount, 0, 0.994);
      return NProgress.set(n);
    }
  };

  NProgress.trickle = function() {
    return NProgress.inc(Math.random() * Settings.trickleRate);
  };

  /**
   * (Internal) renders the progress bar markup based on the `template`
   * setting.
   */

  NProgress.render = function(fromStart) {
    if (NProgress.isRendered()) return $("#nprogress");
    $('html').addClass('nprogress-busy');

    var $el = $("
")
      .html(Settings.template);

    var perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0);

    $el.find('[role="bar"]').css({
      transition: 'all 0 linear',
      transform: 'translate3d('+perc+'%,0,0)'
    });

    if(!Settings.showSpinner) $el.find('.spinner').hide();

    $el.appendTo(document.body);

    return $el;
  };

  /**
   * Removes the element. Opposite of render().
   */

  NProgress.remove = function() {
    $('html').removeClass('nprogress-busy');
    $('#nprogress').remove();
  };

  /**
   * Checks if the progress bar is rendered.
   */

  NProgress.isRendered = function() {
    return ($("#nprogress").length > 0);
  };

  /**
   * Determine which positioning CSS rule to use.
   */
  NProgress.getPositioningCSS = function() {
    // Sniff on document.body.style
    var bodyStyle = document.body.style;

    // Sniff prefixes
    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
                       ('MozTransform' in bodyStyle) ? 'Moz' :
                       ('msTransform' in bodyStyle) ? 'ms' :
                       ('OTransform' in bodyStyle) ? 'O' : '';

    if (vendorPrefix + 'Perspective' in bodyStyle) {
      // Modern browsers with 3D support, e.g. Webkit, IE10
      return 'translate3d';
    } else if (vendorPrefix + 'Transform' in bodyStyle) {
      // Browsers without 3D support, e.g. IE9
      return 'translate';
    } else {
      // Browsers without translate() support, e.g. IE7-8
      return 'margin';
    }
  }

  /**
   * Helpers
   */

  function clamp(n, min, max) {
    if (n < min) return min;
    if (n > max) return max;
    return n;
  }

  /**
   * (Internal) converts a percentage (`0..1`) to a bar translateX
   * percentage (`-100%..0%`).
   */

  function toBarPerc(n) {
    return (-1 + n) * 100;
  }

  /**
   * (Internal) returns the correct CSS for changing the bar's
   * position given an n percentage, and speed and ease from Settings
   */

  function barPositionCSS(n, speed, ease) {
    var barCSS;

    if (Settings.positionUsing == 'translate3d') {
      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
    } else if (Settings.positionUsing == 'translate') {
      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
    } else {
      barCSS = { 'margin-left': toBarPerc(n)+'%' };
    }

    barCSS.transition = 'all '+speed+'ms '+ease;

    return barCSS;
  }

  return NProgress;
});

<commit_msg>Add [role=spinner] to identify the spinner element (See #5, #9).<commit_after>/*! NProgress (c) 2013, Rico Sta. Cruz
 *  http://ricostacruz.com/nprogress */

;(function(factory) {

  if (typeof module === 'object') {
    module.exports = factory(this.jQuery || require('dom'));
  } else {
    this.NProgress = factory(this.jQuery);
  }

})(function($) {
  var NProgress = {};

  NProgress.version = '0.1.0';

  var Settings = NProgress.settings = {
    minimum: 0.08,
    easing: 'ease',
    positionUsing: '',
    speed: 200,
    trickle: true,
    trickleRate: 0.02,
    trickleSpeed: 800,
    showSpinner: true,
    template: '

'
  };

  /**
   * Updates configuration.
   *
   *     NProgress.configure({
   *       minimum: 0.1
   *     });
   */
  NProgress.configure = function(options) {
    $.extend(Settings, options);
    return this;
  };

  /**
   * Last number.
   */

  NProgress.status = null;

  /**
   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
   *
   *     NProgress.set(0.4);
   *     NProgress.set(1.0);
   */

  NProgress.set = function(n) {
    var started = NProgress.isStarted();

    n = clamp(n, Settings.minimum, 1);
    NProgress.status = (n === 1 ? null : n);

    var $progress = NProgress.render(!started),
        $bar      = $progress.find('[role="bar"]'),
        speed     = Settings.speed,
        ease      = Settings.easing;

    $progress[0].offsetWidth; /* Repaint */

    $progress.queue(function(next) {
      // Set positionUsing if it hasn't already been set
      if (Settings.positionUsing == '') Settings.positionUsing = NProgress.getPositioningCSS();

      // Add transition
      $bar.css(barPositionCSS(n, speed, ease));

      if (n === 1) {
        // Fade out
        $progress.css({ transition: 'none', opacity: 1 });
        $progress[0].offsetWidth; /* Repaint */

        setTimeout(function() {
          $progress.css({ transition: 'all '+speed+'ms linear', opacity: 0 });
          setTimeout(function() {
            NProgress.remove();
            next();
          }, speed);
        }, speed);
      } else {
        setTimeout(next, speed);
      }
    });

    return this;
  };

  NProgress.isStarted = function() {
    return typeof NProgress.status === 'number';
  };

  /**
   * Shows the progress bar.
   * This is the same as setting the status to 0%, except that it doesn't go backwards.
   *
   *     NProgress.start();
   *
   */
  NProgress.start = function() {
    if (!NProgress.status) NProgress.set(0);

    var work = function() {
      setTimeout(function() {
        if (!NProgress.status) return;
        NProgress.trickle();
        work();
      }, Settings.trickleSpeed);
    };

    if (Settings.trickle) work();

    return this;
  };

  /**
   * Hides the progress bar.
   * This is the *sort of* the same as setting the status to 100%, with the
   * difference being `done()` makes some placebo effect of some realistic motion.
   *
   *     NProgress.done();
   *
   * If `true` is passed, it will show the progress bar even if its hidden.
   *
   *     NProgress.done(true);
   */

  NProgress.done = function(force) {
    if (!force && !NProgress.status) return this;

    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  };

  /**
   * Increments by a random amount.
   */

  NProgress.inc = function(amount) {
    var n = NProgress.status;

    if (!n) {
      return NProgress.start();
    } else {
      if (typeof amount !== 'number') {
        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
      }

      n = clamp(n + amount, 0, 0.994);
      return NProgress.set(n);
    }
  };

  NProgress.trickle = function() {
    return NProgress.inc(Math.random() * Settings.trickleRate);
  };

  /**
   * (Internal) renders the progress bar markup based on the `template`
   * setting.
   */

  NProgress.render = function(fromStart) {
    if (NProgress.isRendered()) return $("#nprogress");
    $('html').addClass('nprogress-busy');

    var $el = $("
")
      .html(Settings.template);

    var perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0);

    $el.find('[role="bar"]').css({
      transition: 'all 0 linear',
      transform: 'translate3d('+perc+'%,0,0)'
    });

    if (!Settings.showSpinner)
      $el.find('[role="spinner"]').remove();

    $el.appendTo(document.body);

    return $el;
  };

  /**
   * Removes the element. Opposite of render().
   */

  NProgress.remove = function() {
    $('html').removeClass('nprogress-busy');
    $('#nprogress').remove();
  };

  /**
   * Checks if the progress bar is rendered.
   */

  NProgress.isRendered = function() {
    return ($("#nprogress").length > 0);
  };

  /**
   * Determine which positioning CSS rule to use.
   */
  NProgress.getPositioningCSS = function() {
    // Sniff on document.body.style
    var bodyStyle = document.body.style;

    // Sniff prefixes
    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
                       ('MozTransform' in bodyStyle) ? 'Moz' :
                       ('msTransform' in bodyStyle) ? 'ms' :
                       ('OTransform' in bodyStyle) ? 'O' : '';

    if (vendorPrefix + 'Perspective' in bodyStyle) {
      // Modern browsers with 3D support, e.g. Webkit, IE10
      return 'translate3d';
    } else if (vendorPrefix + 'Transform' in bodyStyle) {
      // Browsers without 3D support, e.g. IE9
      return 'translate';
    } else {
      // Browsers without translate() support, e.g. IE7-8
      return 'margin';
    }
  }

  /**
   * Helpers
   */

  function clamp(n, min, max) {
    if (n < min) return min;
    if (n > max) return max;
    return n;
  }

  /**
   * (Internal) converts a percentage (`0..1`) to a bar translateX
   * percentage (`-100%..0%`).
   */

  function toBarPerc(n) {
    return (-1 + n) * 100;
  }

  /**
   * (Internal) returns the correct CSS for changing the bar's
   * position given an n percentage, and speed and ease from Settings
   */

  function barPositionCSS(n, speed, ease) {
    var barCSS;

    if (Settings.positionUsing == 'translate3d') {
      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
    } else if (Settings.positionUsing == 'translate') {
      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
    } else {
      barCSS = { 'margin-left': toBarPerc(n)+'%' };
    }

    barCSS.transition = 'all '+speed+'ms '+ease;

    return barCSS;
  }

  return NProgress;
});

<|endoftext|>


<commit_before>define(["leaflet", "proposal-popup-view", "underscore"],
       function(L, ProposalPopupView, _) {
           function projectTypeIcon(p) {
               var cat = p.category.replace(/[&.]+/g, "")
                       .replace(/[\s-]+/g, "_")
                       .toLowerCase();
               return "/static/images/icon/" + cat + ".png";
           }

           function getBadgeClassName(proposal) {
               var isHovered = proposal.get("_hovered"),
                   isSelected = proposal.get("_selected"),
                   project = proposal.getProject();

               return [
                   "proposal-marker",
                   isHovered ? "marker-hovered" : "",
                   isSelected ? "marker-selected" : "",
                   project ? "project-marker" : ""
               ].join(" ");
           }

           function getBadgeHTML(proposal) {
               var project = proposal.getProject(),
                   html = "";

               // if (project) {
               //     html =
               //         "";
               // }

               return html;
           }

           function getBadge(proposal) {
               return L.divIcon({
                   className: getBadgeClassName(proposal),
                   iconSize: L.point(30, 30),
                   html: getBadgeHTML(proposal)
               });
           }

           return L.Marker.extend({
               initialize: function(proposal, zoom) {
                   var loc = proposal.get("location");

                   if (loc) {
                       L.Marker.prototype.initialize.call(
                           this, loc,
                           {icon: getBadge(proposal),
                            riseOnHover: true,
                            title: proposal.get("address")});
                   }
                   this.proposal = proposal;
                   this.zoomed = zoom;

                   var self = this;
                   proposal
                       .on("change:location", _.bind(this.locationChanged, this))
                       .on("change:_hovered", _.bind(this.updateIcon, this))
                       .on("change:_selected", _.bind(this.onSelected, this));

                   return this;
               },

               getModel: function() {
                   return this.proposal;
               },

               locationChanged: function(proposal, loc) {
                   if (loc)
                       this.setLatLng(loc);
               },

               updateIcon: function(proposal) {
                   if (_.isNumber(this.zoomed))
                       this.setZoomed(this.zoomed);
                   else
                       this.setIcon(getBadge(proposal));
               },

               onSelected: function(proposal) {
                   var loc = proposal.get("location"),
                       view = new ProposalPopupView({ model: proposal });
                   this.updateIcon(proposal);
                   L.popup({className: "proposal-info-popup",
                            minWidth: 300,
                            maxWidth: 300,
                            autoPanPaddingTopLeft: L.point(5, 15)})
                       .setLatLng(loc)
                       .setContent(view.render().el)
                       .openOn(this._map);
               },

               setZoomed: function(n) {
                   var proposal = this.proposal,
                       factor = Math.pow(2, n),
                       size = L.point(100*factor, 75*factor),
                       html = ["",
                               "
", getBadgeHTML(proposal), "
"].join(""),
                       className = proposal.get("_selected") ? " marker-selected" : "";

                   this.setIcon(L.divIcon({
                       className: "zoomed-proposal-marker" + className,
                       iconSize: size,
                       html: html
                   }));

                   this.zoomed = n;
               },

               unsetZoomed: function() {
                   this.setIcon(getBadge(this.proposal));
                   this.zoomed = null;
               }
           });
       });
<commit_msg>Hide proposal popup when the proposal is unselected<commit_after>define(["leaflet", "proposal-popup-view", "underscore"],
       function(L, ProposalPopupView, _) {
           function projectTypeIcon(p) {
               var cat = p.category.replace(/[&.]+/g, "")
                       .replace(/[\s-]+/g, "_")
                       .toLowerCase();
               return "/static/images/icon/" + cat + ".png";
           }

           function getBadgeClassName(proposal) {
               var isHovered = proposal.get("_hovered"),
                   isSelected = proposal.get("_selected"),
                   project = proposal.getProject();

               return [
                   "proposal-marker",
                   isHovered ? "marker-hovered" : "",
                   isSelected ? "marker-selected" : "",
                   project ? "project-marker" : ""
               ].join(" ");
           }

           function getBadgeHTML(proposal) {
               var project = proposal.getProject(),
                   html = "";

               // if (project) {
               //     html =
               //         "";
               // }

               return html;
           }

           function getBadge(proposal) {
               return L.divIcon({
                   className: getBadgeClassName(proposal),
                   iconSize: L.point(30, 30),
                   html: getBadgeHTML(proposal)
               });
           }

           return L.Marker.extend({
               initialize: function(proposal, zoom) {
                   var loc = proposal.get("location");

                   if (loc) {
                       L.Marker.prototype.initialize.call(
                           this, loc,
                           {icon: getBadge(proposal),
                            riseOnHover: true,
                            title: proposal.get("address")});
                   }
                   this.proposal = proposal;
                   this.zoomed = zoom;

                   var self = this;
                   proposal
                       .on("change:location", _.bind(this.locationChanged, this))
                       .on("change:_hovered", _.bind(this.updateIcon, this))
                       .on("change:_selected", _.bind(this.onSelected, this));

                   return this;
               },

               getModel: function() {
                   return this.proposal;
               },

               locationChanged: function(proposal, loc) {
                   if (loc)
                       this.setLatLng(loc);
               },

               updateIcon: function(proposal) {
                   if (_.isNumber(this.zoomed))
                       this.setZoomed(this.zoomed);
                   else
                       this.setIcon(getBadge(proposal));
               },

               onSelected: function(proposal, isSelected) {
                   this.updateIcon(proposal);

                   if (isSelected) {
                       var loc = proposal.get("location"),
                       view = new ProposalPopupView({ model: proposal }),
                       popup = this.getPopup();

                       if (!popup) {
                           popup =
                               L.popup({className: "proposal-info-popup",
                                        minWidth: 300,
                                        maxWidth: 300,
                                        autoPanPaddingTopLeft: L.point(5, 15)});
                           popup.setContent(view.render().el);

                           this.bindPopup(popup);
                       }
                       this.openPopup();
                   } else {
                       this.closePopup().unbindPopup();
                   }
               },

               setZoomed: function(n) {
                   var proposal = this.proposal,
                       factor = Math.pow(2, n),
                       size = L.point(100*factor, 75*factor),
                       html = ["",
                               "
", getBadgeHTML(proposal), "
"].join(""),
                       className = proposal.get("_selected") ? " marker-selected" : "";

                   this.setIcon(L.divIcon({
                       className: "zoomed-proposal-marker" + className,
                       iconSize: size,
                       html: html
                   }));

                   this.zoomed = n;
               },

               unsetZoomed: function() {
                   this.setIcon(getBadge(this.proposal));
                   this.zoomed = null;
               }
           });
       });
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import moment from 'moment';
import { Container, Header, Loader, Message, Link } from 'semantic-ui-react';
import { getAllReceivedMessages } from '../../../actions/inboxActions';

class Inbox extends Component {

  componentDidMount() {
    this.props.dispatch(getAllReceivedMessages(this.props.userId));
  }

  convertTime(time) {
    return moment(time).fromNow();
  }

  render() {
    const { isFetching, allMessages } = this.props;

    if (isFetching) {
      return <Loader active inline="centered" />;
    }

    return (
      <Container textAlign="center">
        -- Inbox --

        <Container textAlign="left">
          {
            allMessages && allMessages.map(message =>
              <Message key={message.id}>
                <Message.Header>{message.title}</Message.Header>
                <Message.Content>Received {this.convertTime(message.createdAt)}</Message.Content>
              </Message>,
            )
          }
        </Container>
      </Container>
    );
  }
}

const mapStateToProps = (state) => {
  const { isFetching, allMessages } = state.inbox;
  const { id } = state.auth.loggedInUser;
  const userId = id;

  return {
    userId,
    allMessages,
    isFetching,
  };
};

Inbox.propTypes = {
  userId: React.PropTypes.number.isRequired,
  isFetching: React.PropTypes.bool.isRequired,
  allMessages: React.PropTypes.array.isRequired,
  dispatch: React.PropTypes.func.isRequired,
};

export default connect(mapStateToProps)(Inbox);
<commit_msg>Modify Inbox to use the MessagesTable component<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import moment from 'moment';
import { Container, Header, Loader, Message, Modal } from 'semantic-ui-react';
import { getAllReceivedMessages } from '../../../actions/inboxActions';
import MessagesTable from './MessagesTable';

class Inbox extends Component {

  componentDidMount() {
    this.props.dispatch(getAllReceivedMessages(this.props.userId));
  }

  convertTime(time) {
    return moment(time).fromNow();
  }

  render() {
    const { isFetching, allMessages } = this.props;

    if (isFetching) {
      return <Loader active inline="centered" />;
    }

    return (
      <Container textAlign="center">
        -- Inbox --

        <Container textAlign="left">
          <MessagesTable allMessages={allMessages} convertTime={this.convertTime} />
        </Container>
      </Container>
    );
  }
}

const mapStateToProps = (state) => {
  const { isFetching, allMessages } = state.inbox;
  const { id } = state.auth.loggedInUser;
  const userId = id;

  return {
    userId,
    allMessages,
    isFetching,
  };
};

Inbox.propTypes = {
  userId: React.PropTypes.number.isRequired,
  isFetching: React.PropTypes.bool.isRequired,
  allMessages: React.PropTypes.array.isRequired,
  dispatch: React.PropTypes.func.isRequired,
};

export default connect(mapStateToProps)(Inbox);
<|endoftext|>


<commit_before>import React from "react";
import { map } from "lodash-es";
import { push } from "react-router-redux";
import { connect } from "react-redux";
import { LinkContainer } from "react-router-bootstrap";
import { FormControl, FormGroup, InputGroup } from "react-bootstrap";

import CreateSubtraction from "./Create";
import SubtractionItem from "./Item";
import { Alert, Button, Icon, LoadingPlaceholder, NoneFound, ViewHeader } from "../../base";
import { createFindURL, getFindTerm, checkAdminOrPermission } from "../../utils";

const SubtractionList = (props) => {

    if (props.documents === null) {
        return <LoadingPlaceholder />;
    }

    let subtractionComponents = map(props.documents, document =>
        <SubtractionItem
            key={document.id}
            {...document}
        />
    );

    if (!subtractionComponents.length) {
        subtractionComponents = <NoneFound noun="subtractions" noListGroup />;
    }

    let alert;

    if (!props.ready_host_count && !props.total_count) {
        alert = (
            <Alert bsStyle="warning" icon="info-circle">

                    A host genome must be added before samples can be created and analyzed.

            </Alert>
        );
    }

    return (

            <ViewHeader title="Subtraction" totalCount={props.total_count} />

            {alert}

                <FormGroup>
                    <InputGroup>
                        <InputGroup.Addon>
                            <Icon name="search" />
                        </InputGroup.Addon>
                        <FormControl
                            type="text"
                            value={props.term}
                            onChange={props.onFind}
                            placeholder="Name"
                        />
                    </InputGroup>
                </FormGroup>

                {props.canModify ? (
                    <LinkContainer to={{state: {createSubtraction: true}}}>
                        <Button bsStyle="primary" icon="plus-square" tip="Create" />
                    </LinkContainer>
                ) : null}

                {subtractionComponents}

            <CreateSubtraction />

    );
};

const mapStateToProps = (state) => ({
    ...state.subtraction,
    term: getFindTerm(),
    canModify: checkAdminOrPermission(state.account.administrator, state.account.permissions, "modify_subtraction")
});

const mapDispatchToProps = (dispatch) => ({

    onFind: (e) => {
        const url = createFindURL({find: e.target.value});
        dispatch(push(url.pathname + url.search));
    }

});

export default connect(mapStateToProps, mapDispatchToProps)(SubtractionList);
<commit_msg>Convert subtractions list view to scrolling list<commit_after>import React from "react";
import { connect } from "react-redux";
import { LinkContainer } from "react-router-bootstrap";
import { FormControl, FormGroup, InputGroup } from "react-bootstrap";

import CreateSubtraction from "./Create";
import SubtractionItem from "./Item";
import { Alert, Button, Icon, NoneFound, ViewHeader, ScrollList } from "../../base";
import { checkAdminOrPermission } from "../../utils";
import { filterSubtractions, listSubtractions } from "../actions";

const SubtractionToolbar = ({ term, onFilter, canModify }) => (

        <FormGroup>
            <InputGroup>
                <InputGroup.Addon>
                    <Icon name="search" />
                </InputGroup.Addon>
                <FormControl
                    type="text"
                    value={term}
                    onChange={onFilter}
                    placeholder="Name"
                />
            </InputGroup>
        </FormGroup>

        {canModify ? (
            <LinkContainer to={{state: {createSubtraction: true}}}>
                <Button bsStyle="primary" icon="plus-square" tip="Create" />
            </LinkContainer>
        ) : null}

);

class SubtractionList extends React.Component {

    componentDidMount () {
        if (!this.props.fetched) {
            this.props.loadNextPage(1);
        }
    }

    rowRenderer = (index) => (
        <SubtractionItem
            key={this.props.documents[index].id}
            {...this.props.documents[index]}
        />
    );

    render () {

        let subtractionComponents;
        let alert;

        if (this.props.documents && !this.props.documents.length) {
            subtractionComponents = (

                    <NoneFound noun="subtractions" noListGroup />

            );
        } else {
            subtractionComponents = (
                <ScrollList
                    hasNextPage={this.props.page < this.props.page_count}
                    isNextPageLoading={this.props.isLoading}
                    isLoadError={this.props.errorLoad}
                    list={this.props.documents}
                    refetchPage={this.props.refetchPage}
                    loadNextPage={this.props.loadNextPage}
                    page={this.props.page}
                    rowRenderer={this.rowRenderer}
                />
            );
        }

        if (!this.props.ready_host_count && !this.props.total_count) {
            alert = (
                <Alert bsStyle="warning" icon="info-circle">

                        A host genome must be added before samples can be created and analyzed.

                </Alert>
            );
        }

        return (

                <ViewHeader title="Subtraction" totalCount={this.props.total_count} />

                {alert}

                <SubtractionToolbar
                    term={this.props.filter}
                    onFilter={this.props.onFilter}
                    canModify={this.props.canModify}
                />

                {subtractionComponents}

                <CreateSubtraction />

        );
    }
}

const mapStateToProps = (state) => ({
    ...state.subtraction,
    canModify: checkAdminOrPermission(state.account.administrator, state.account.permissions, "modify_subtraction")
});

const mapDispatchToProps = (dispatch) => ({

    onFilter: (e) => {
        dispatch(filterSubtractions(e.target.value));
    },

    loadNextPage: (page) => {
        if (page) {
            dispatch(listSubtractions(page));
        }
    }

});

export default connect(mapStateToProps, mapDispatchToProps)(SubtractionList);
<|endoftext|>


<commit_before>Template._editProfile.events({
  'touchstart .update-perfil' : function(form){
    form.preventDefault();
    console.log(form);
    var name = document.querySelector("#name").value;
    var email = document.querySelector("#mail").value;
    if(!name || !email){
        console.log('necessario preencher os campos obrigatorios');
    }else{
        Meteor.remote.call('updatePerfil',
            [
                222,
                name,
                email,
                localStorage.getItem('Meteor.userId')
            ],
            function(error, result){
                if(!result){
                    console.log('algo deu errado.');
                }else{
                    console.log('atualizado com sucesso.')
                }
            }
        );
    }
  }
});

Template._editProfile.helpers({
    user: function(){
        return [User.findOne({_id:localStorage.getItem('Meteor.userId'), status:1})];
    }
});<commit_msg>perfil user<commit_after>Template._editProfile.events({
  'touchstart .update-perfil' : function(form){
    form.preventDefault();
    var name = document.querySelector("#name").value;
    var email = document.querySelector("#mail").value;
    if(!name || !email){
        console.log('necessario preencher os campos obrigatorios');
    }else{
        Meteor.remote.call('updatePerfil',
            [
                222,
                name,
                email,
                localStorage.getItem('Meteor.userId')
            ],
            function(error, result){
                if(!result){
                    console.log('algo deu errado.');
                }else{
                    console.log('atualizado com sucesso.')
                }
            }
        );
    }
  }
});

Template._editProfile.helpers({
    user: function(){
        return [User.findOne({_id:localStorage.getItem('Meteor.userId'), status:1})];
    }
});<|endoftext|>


<commit_before>import Metatags from '/imports/Metatags.js';

Router.map(function () {
	this.route('framePropose', {
		path: '/frame/propose',
		template: 'framePropose',
		layoutTemplate: 'frameLayout',
		waitOn: () => Meteor.subscribe('regions'),
		data: function() {
			// HACK: Fix up predicates for our use
			// They are not currently exported so we use
			// CoursePredicates.region instead of Predicates.id.
			const predicates =
				{ region: CoursePredicates.region
				, group: CoursePredicates.region
				};

			const params = Filtering(predicates).read(this.params.query).done();
			const data = params.toParams();
			data.isFrame = true;
			return data;
		},
		onAfterAction() {
			Metatags.setCommonTags(
				mf('course.propose.windowtitle', 'Propose new course')
			);
		}
	});
});
<commit_msg>fix filter construction<commit_after>import Metatags from '/imports/Metatags.js';
import '/imports/Predicates.js';

Router.map(function () {
	this.route('framePropose', {
		path: '/frame/propose',
		template: 'framePropose',
		layoutTemplate: 'frameLayout',
		waitOn: () => Meteor.subscribe('regions'),
		data: function() {
			const predicates =
				{ region: Predicates.id
				, group: Predicates.id
				};

			const params = Filtering(predicates).read(this.params.query).done();
			const data = params.toParams();
			data.isFrame = true;
			return data;
		},
		onAfterAction() {
			Metatags.setCommonTags(
				mf('course.propose.windowtitle', 'Propose new course')
			);
		}
	});
});
<|endoftext|>