<commit_before>'use strict';

var readJson = require('./readJson')
var Promise = require('bluebird')
var _ = require('lodash')
var add = require('./add')
var db = require('./db')
var buildDeptNum = require('./deptNum').buildDeptNum
var deptNumToCrsidCache = require('./getCourses').deptNumToCrsidCache

var logDataLoading = false

function storeCourses(item) {
	return new Promise(function(resolve, reject) {
		console.log(item.meta.path, 'called storeCourses')

		var courses = _.map(item.data.courses, function(course) {
			course.sourcePath = item.meta.path
			course.deptnum = buildDeptNum(course)
			deptNumToCrsidCache[course.deptnum] = course.crsid
			return course
		})

		db.store('courses').batch(courses)
			.then(function(results) {
				resolve(item)
			}).catch(function (records, err) {
				reject(err)
			})
	})
}

function storeArea(item) {
	return new Promise(function(resolve, reject) {
		console.log(item.meta.path, 'called storeArea')

		var area = item.data.info
		area.sourcePath = item.meta.path

		db.store('areas').put(area)
			.then(function(results) {
				resolve(item)
			})
			.catch(function(records, err) {
				reject(err)
			})
	})
}

function storeItem(item) {
	if (item.type === 'courses') {
		return storeCourses(item)
	} else if (item.type === 'areas') {
		return storeArea(item)
	}
}

function cleanPriorData(item) {
	return new Promise(function (resolve, reject) {
		var path = item.meta.path
		console.info('deleting ' + item.type + ' from ' + path)

		db.store(item.type)
			.index('sourcePath')
			.get(path)
			.then(function(items) {
				return _.map(items, function(item) {
					var result = Object.create(null)
					result[item.clbid] = null
					return result
				})
			})
			.then(function(items) {
				return db.store(item.type).batch(items)
			})
			.then(function(items) {
				localStorage.removeItem(path)
				resolve(item)
			})
			.catch(function(err) {
				reject(err)
			})
	})
}

function cacheItemHash(item) {
	return new Promise(function(resolve, reject) {
		console.info(item.meta.path + ' called cacheItemHash')
		localStorage.setItem(item.meta.path, item.meta.hash)
		resolve(item)
	})
}

var lookup = {
	'courses': 'courses',
	'areas': 'info'
}

function updateDatabase(itemType, infoFromServer) {
	infoFromServer.path = '/data/' + itemType + '/' + infoFromServer.path
	var oldHash = localStorage.getItem(infoFromServer.path)
	var newHash = infoFromServer.hash
	var itemPath = infoFromServer.path

	if (newHash === oldHash) {
		if (logDataLoading) {
			console.log('skipped ' + itemPath)
		}
		return Promise.resolve(false)
	}

	if (logDataLoading) {
		console.log('need to add ' + itemPath)
	}

	return readJson(itemPath)
		.then(function(data) {
			return {
				data: data,
				meta: infoFromServer,
				type: itemType,
				count: _.size(data[lookup[itemType]]) || 1,
			}
		})
		.then(cleanPriorData)
		.then(storeItem)
		.then(cacheItemHash)
		.catch(function(err) {
			return Promise.reject(err.stack)
		})
		.done(function(item) {
			if (logDataLoading) {
				console.log('added '+item.meta.path+' ('+item.count+' '+item.type+')')
			}
			return Promise.resolve(true)
		})
}

function loadDataFiles(infoFile) {
	console.log('load data files', infoFile)

	return Promise.all(_.map(infoFile.info, function(files) {
		return Promise.all(_.map(files, function(file) {
			return updateDatabase(infoFile.type, file)
		}))
	}))
}

/*
function loadDataFiles(infoFile) {
	console.log('load data files', infoFile)

	var progress = 0;
	var notification = new Cortex({
		message: 'Updating ' + infoFile.type,
		hasProgress: true,
		progressValue: progress,
		maxProgressValue: _.chain(infoFile.info).mapValues(_.size).reduce(add).value(),
		ident: infoFile.type
	})
	window.notifications.push(notification.val())

	return Promise.all(_.map(infoFile.info, function(files) {
		var allFilesLoadedPromise = Promise.all(_.map(files, function(file) {
			var dbUpdatedPromise = updateDatabase(infoFile.type, file)
			dbUpdatedPromise.then(function() {
				notification.progressValue.set(progress += 1)
			})
			return dbUpdatedPromise
		}))

		allFilesLoadedPromise.then(function() {
			setTimeout(notification.remove, 200)
		})

		return allFilesLoadedPromise
	}))
}
*/

function loadInfoFile(url) {
	console.log('loading', url)
	return readJson(url).then(loadDataFiles)
}

function loadData() {
	var infoFiles = [
		'/data/areas/info.json',
		'/data/courses/info.json',
	]
	return Promise.all(_.map(infoFiles, loadInfoFile))
}

module.exports = window.loadData = loadData
<commit_msg>kill an extraneous line<commit_after>'use strict';

var readJson = require('./readJson')
var Promise = require('bluebird')
var _ = require('lodash')
var add = require('./add')
var db = require('./db')
var buildDeptNum = require('./deptNum').buildDeptNum
var deptNumToCrsidCache = require('./getCourses').deptNumToCrsidCache

var logDataLoading = false

function storeCourses(item) {
	return new Promise(function(resolve, reject) {
		console.log(item.meta.path, 'called storeCourses')

		var courses = _.map(item.data.courses, function(course) {
			course.sourcePath = item.meta.path
			course.deptnum = buildDeptNum(course)
			deptNumToCrsidCache[course.deptnum] = course.crsid
			return course
		})

		db.store('courses').batch(courses)
			.then(function(results) {
				resolve(item)
			}).catch(function (records, err) {
				reject(err)
			})
	})
}

function storeArea(item) {
	return new Promise(function(resolve, reject) {
		console.log(item.meta.path, 'called storeArea')

		var area = item.data.info
		area.sourcePath = item.meta.path

		db.store('areas').put(area)
			.then(function(results) {
				resolve(item)
			})
			.catch(function(records, err) {
				reject(err)
			})
	})
}

function storeItem(item) {
	if (item.type === 'courses') {
		return storeCourses(item)
	} else if (item.type === 'areas') {
		return storeArea(item)
	}
}

function cleanPriorData(item) {
	return new Promise(function (resolve, reject) {
		var path = item.meta.path
		console.info('deleting ' + item.type + ' from ' + path)

		db.store(item.type)
			.index('sourcePath')
			.get(path)
			.then(function(items) {
				return _.map(items, function(item) {
					var result = Object.create(null)
					result[item.clbid] = null
					return result
				})
			})
			.then(function(items) {
				return db.store(item.type).batch(items)
			})
			.then(function(items) {
				localStorage.removeItem(path)
				resolve(item)
			})
			.catch(function(err) {
				reject(err)
			})
	})
}

function cacheItemHash(item) {
	return new Promise(function(resolve, reject) {
		console.info(item.meta.path + ' called cacheItemHash')
		localStorage.setItem(item.meta.path, item.meta.hash)
		resolve(item)
	})
}

var lookup = {
	'courses': 'courses',
	'areas': 'info'
}

function updateDatabase(itemType, infoFromServer) {
	infoFromServer.path = '/data/' + itemType + '/' + infoFromServer.path
	var oldHash = localStorage.getItem(infoFromServer.path)
	var newHash = infoFromServer.hash
	var itemPath = infoFromServer.path

	if (newHash === oldHash) {
		if (logDataLoading) {
			console.log('skipped ' + itemPath)
		}
		return Promise.resolve(false)
	}

	if (logDataLoading) {
		console.log('need to add ' + itemPath)
	}

	return readJson(itemPath)
		.then(function(data) {
			return {
				data: data,
				meta: infoFromServer,
				type: itemType,
				count: _.size(data[lookup[itemType]]) || 1,
			}
		})
		.then(cleanPriorData)
		.then(storeItem)
		.then(cacheItemHash)
		.catch(function(err) {
			return Promise.reject(err.stack)
		})
		.done(function(item) {
			if (logDataLoading) {
				console.log('added '+item.meta.path+' ('+item.count+' '+item.type+')')
			}
			return Promise.resolve(true)
		})
}

function loadDataFiles(infoFile) {
	console.log('load data files', infoFile)

	return Promise.all(_.map(infoFile.info, function(files) {
		return Promise.all(_.map(files, function(file) {
			return updateDatabase(infoFile.type, file)
		}))
	}))
}

/*
function loadDataFiles(infoFile) {
	console.log('load data files', infoFile)

	var progress = 0;
	var notification = new Cortex({
		message: 'Updating ' + infoFile.type,
		hasProgress: true,
		progressValue: progress,
		maxProgressValue: _.chain(infoFile.info).mapValues(_.size).reduce(add).value(),
		ident: infoFile.type
	})
	window.notifications.push(notification.val())

	return Promise.all(_.map(infoFile.info, function(files) {
		var allFilesLoadedPromise = Promise.all(_.map(files, function(file) {
			var dbUpdatedPromise = updateDatabase(infoFile.type, file)
			dbUpdatedPromise.then(function() {
				notification.progressValue.set(progress += 1)
			})
			return dbUpdatedPromise
		}))

		allFilesLoadedPromise.then(function() {
			setTimeout(notification.remove, 200)
		})

		return allFilesLoadedPromise
	}))
}
*/

function loadInfoFile(url) {
	console.log('loading', url)
	return readJson(url).then(loadDataFiles)
}

function loadData() {
	var infoFiles = [
		'/data/areas/info.json',
		'/data/courses/info.json',
	]
	return Promise.all(_.map(infoFiles, loadInfoFile))
}

module.exports = window.loadData = loadData
<|endoftext|>


<commit_before>import $ from 'jquery';
import _ from 'underscore';
import Backbone from 'backbone';

import events from 'girder/events';
import { getCurrentToken, cookie } from 'girder/auth';

let apiRoot;
let staticRoot;
var uploadHandlers = {};
var uploadChunkSize = 1024 * 1024 * 64; // 64MB

/**
 * Get the root path to the API.
 *
 * This may be an absolute path, or a path relative to the application root. It will never include
 * a trailing slash.
 *
 * @returns {string}
 */
function getApiRoot() {
    return apiRoot;
}

/**
 * Set the root path to the API.
 *
 * @param {string} root The root path for the API.
 */
function setApiRoot(root) {
    // Strip trailing slash
    apiRoot = root.replace(/\/$/, '');
}

/**
 * Get the root path to the static content.
 *
 * This may be an absolute path, or a path relative to the application root. It will never include
 * a trailing slash.
 *
 * @returns {string}
 */
function getStaticRoot() {
    return staticRoot;
}

/**
 * Set the root path to the static content.
 *
 * @param {string} root The root path for the static content.
 */
function setStaticRoot(root) {
    // Strip trailing slash
    staticRoot = root.replace(/\/$/, '');
    // publicPath would normally be set in the Webpack config file, but is not known at compile
    // time.
    __webpack_public_path__ = `${getStaticRoot()}/built/`; // eslint-disable-line no-undef, camelcase
    // Note that in theory, an ES6-style import of a file asset that occurred earlier in the import
    // resolution sequence than this module could fail to have its publicPath set at all, but the
    // typical style rules for ordering ES6-style imports ensure that this module will be loaded
    // very early in the import sequence. However, if App startup code modifies the staticRoot, then
    // any ES6-style imports will probably have the incorrect path. Ultimately though, most file
    // asset imports will occur in Pug files via require-style imports, which happen at runtime, so
    // they will always succeed.
}

// Initialize the API and static roots (at JS load time)
// This could be overridden when the App is started, but we need sensible defaults so models, etc.
// can be easily used without having to start an App or explicitly set these values
setApiRoot(
    $('#g-global-info-apiroot').text().replace('%HOST%', window.location.origin) || '/api/v1'
);
setStaticRoot(
    $('#g-global-info-staticroot').text().replace('%HOST%', window.location.origin) || '/static'
);

/**
 * Make a request to the REST API. Bind a "done" handler to the return
 * value that will be called when the response is successful. To bind a
 * custom error handler, bind a "fail" handler to the return promise,
 * which will be executed in addition to the normal behavior of logging
 * the error to the console. To override the default error handling
 * behavior, pass an "error" key in your opts object; this should be done
 * any time the server might throw an exception from validating user input,
 * e.g. logging in, registering, or generally filling out forms.
 *
 * @param {Object} opts Options for the request, most of which will be passed through to `$.ajax`.
 * @param {string} opts.url The resource path, e.g. "user/login"
 * @param {string} [opts.method='GET'] The HTTP method to invoke.
 * @param [opts.data] The query string or form parameter object.
 * @param {?Function} [opts.error] An error callback, as documented in
 *        `$.ajax <http://api.jquery.com/jQuery.ajax/>`_, or null. If not provided, this will have a
 *        default behavior of triggering a `'g:alert'` global event, with details of the error.
 * @param {string} [opts.girderToken] An alternative auth token to use for this request.
 * @returns {$.Promise} A jqXHR promise, which resolves and rejects
 *          `as documented by $.ajax<http://api.jquery.com/jQuery.ajax/#jqXHR>`_.
 */
function __restRequest(opts) {
    opts = opts || {};
    const defaults = {
        method: 'GET',
        girderToken: getCurrentToken() || cookie.find('girderToken'),

        error: (error, status) => {
            let info;
            if (error.status === 401) {
                events.trigger('g:loginUi');
                info = {
                    text: 'You must log in to view this resource',
                    type: 'warning',
                    timeout: 4000,
                    icon: 'info'
                };
            } else if (error.status === 403) {
                info = {
                    text: 'Access denied. See the console for more details.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            } else if (error.status === 0 && error.statusText === 'abort') {
                /* We expected this abort, so do nothing. */
                return;
            } else if (error.status === 500 && error.responseJSON &&
                error.responseJSON.type === 'girder') {
                info = {
                    text: error.responseJSON.message,
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                };
            } else if (status === 'parsererror') {
                info = {
                    text: 'A parser error occurred while communicating with the ' +
                          'server (did you use the correct value for `dataType`?). ' +
                          'Details have been logged in the console.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            } else {
                info = {
                    text: 'An error occurred while communicating with the ' +
                          'server. Details have been logged in the console.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            }
            events.trigger('g:alert', info);
            console.error(error.status + ' ' + error.statusText, error.responseText);
        }
    };

    // Overwrite defaults with passed opts, but do not mutate opts
    const args = _.extend({}, defaults, opts);

    if (args.path) {
        console.warn('restRequest\'s "path" option is deprecated, use "url" instead');
        args.url = args.url || args.path;
        delete args.path;
    }

    if (!args.url) {
        throw new Error('restRequest requires a "url" argument');
    }
    args.url = `${getApiRoot()}${args.url.substring(0, 1) === '/' ? '' : '/'}${args.url}`;

    if (args.girderToken) {
        args.headers = args.headers || {};
        args.headers['Girder-Token'] = args.girderToken;
        delete args.girderToken;
    }

    let jqXHR = Backbone.$.ajax(args);
    jqXHR.error = function () {
        console.warn('Use of restRequest.error is deprecated, use restRequest.fail instead.');
        return jqXHR.fail.apply(jqXHR, arguments);
    };
    return jqXHR;
}

/**
 * Make a request to the REST API.
 *
 * Provide an API to mock this single conduit connecting the client to the server.
 * While this can be done with various testing framework, choosing the right one depends on the
 * way our code is bundled (spyOn() vs. rewire(), for example). Let's provide a specific API
 * to mock restRequest nonetheless, since it is likely to be mocked the most.
 */
var restRequestMock = null;
function restRequest() {
    if (restRequestMock) {
        return restRequestMock.apply(this, arguments);
    }
    return __restRequest.apply(this, arguments);
}
function mockRestRequest(mock) {
    restRequestMock = mock;
}
function unmockRestRequest(mock) {
    restRequestMock = null;
}

// All requests from Backbone should go through restRequest, adding authentication and the API root.
Backbone.ajax = restRequest;

/* Pending rest requests are listed in this pool so that they can be aborted or
* checked if still processing. */
var restXhrPool = {};
var restXhrCount = 0;
$(document).ajaxSend(function (event, xhr) {
    restXhrCount += 1;
    xhr.girderXhrNumber = restXhrCount;
    restXhrPool[restXhrCount] = xhr;
});
$(document).ajaxComplete(function (event, xhr) {
    var num = xhr.girderXhrNumber;
    if (num && restXhrPool[num]) {
        delete restXhrPool[num];
    }
});

/* Get the number of outstanding rest requests.
 * :param category: if specified, only count those requests that have
 *                  xhr.girder[category] set to a truthy value.
 * :returns: the number of outstanding requests.
 */
function numberOutstandingRestRequests(category) {
    if (category) {
        return _.filter(restXhrPool, function (xhr) {
            return xhr.girder && xhr.girder[category];
        }).length;
    }
    return _.size(restXhrPool);
}

/* Cancel outstanding rest requests.
 * :param category: if specified, only abort those requests that have
 *                  xhr.girder[category] set to a truthy value.
 */
function cancelRestRequests(category) {
    _.each(restXhrPool, function (xhr) {
        if (category && (!xhr.girder || !xhr.girder[category])) {
            return;
        }
        if (xhr.abort) {
            xhr.abort();
        }
    });
}

/*
 * Get Upload Chunk Size
 */
function getUploadChunkSize() {
    return uploadChunkSize;
}

/*
 * Set Upload Chunk Size
 */
function setUploadChunkSize(val) {
    uploadChunkSize = val;
}

export {
    apiRoot, // deprecated
    staticRoot, // deprecated
    getApiRoot,
    setApiRoot,
    getStaticRoot,
    setStaticRoot,
    uploadHandlers,
    restRequest,
    numberOutstandingRestRequests,
    cancelRestRequests,
    mockRestRequest,
    unmockRestRequest,
    getUploadChunkSize,
    setUploadChunkSize
};
<commit_msg>Deprecate the mockRestRequest and unmockRestRequest methods<commit_after>import $ from 'jquery';
import _ from 'underscore';
import Backbone from 'backbone';

import events from 'girder/events';
import { getCurrentToken, cookie } from 'girder/auth';

let apiRoot;
let staticRoot;
var uploadHandlers = {};
var uploadChunkSize = 1024 * 1024 * 64; // 64MB

/**
 * Get the root path to the API.
 *
 * This may be an absolute path, or a path relative to the application root. It will never include
 * a trailing slash.
 *
 * @returns {string}
 */
function getApiRoot() {
    return apiRoot;
}

/**
 * Set the root path to the API.
 *
 * @param {string} root The root path for the API.
 */
function setApiRoot(root) {
    // Strip trailing slash
    apiRoot = root.replace(/\/$/, '');
}

/**
 * Get the root path to the static content.
 *
 * This may be an absolute path, or a path relative to the application root. It will never include
 * a trailing slash.
 *
 * @returns {string}
 */
function getStaticRoot() {
    return staticRoot;
}

/**
 * Set the root path to the static content.
 *
 * @param {string} root The root path for the static content.
 */
function setStaticRoot(root) {
    // Strip trailing slash
    staticRoot = root.replace(/\/$/, '');
    // publicPath would normally be set in the Webpack config file, but is not known at compile
    // time.
    __webpack_public_path__ = `${getStaticRoot()}/built/`; // eslint-disable-line no-undef, camelcase
    // Note that in theory, an ES6-style import of a file asset that occurred earlier in the import
    // resolution sequence than this module could fail to have its publicPath set at all, but the
    // typical style rules for ordering ES6-style imports ensure that this module will be loaded
    // very early in the import sequence. However, if App startup code modifies the staticRoot, then
    // any ES6-style imports will probably have the incorrect path. Ultimately though, most file
    // asset imports will occur in Pug files via require-style imports, which happen at runtime, so
    // they will always succeed.
}

// Initialize the API and static roots (at JS load time)
// This could be overridden when the App is started, but we need sensible defaults so models, etc.
// can be easily used without having to start an App or explicitly set these values
setApiRoot(
    $('#g-global-info-apiroot').text().replace('%HOST%', window.location.origin) || '/api/v1'
);
setStaticRoot(
    $('#g-global-info-staticroot').text().replace('%HOST%', window.location.origin) || '/static'
);

/**
 * Make a request to the REST API. Bind a "done" handler to the return
 * value that will be called when the response is successful. To bind a
 * custom error handler, bind a "fail" handler to the return promise,
 * which will be executed in addition to the normal behavior of logging
 * the error to the console. To override the default error handling
 * behavior, pass an "error" key in your opts object; this should be done
 * any time the server might throw an exception from validating user input,
 * e.g. logging in, registering, or generally filling out forms.
 *
 * @param {Object} opts Options for the request, most of which will be passed through to `$.ajax`.
 * @param {string} opts.url The resource path, e.g. "user/login"
 * @param {string} [opts.method='GET'] The HTTP method to invoke.
 * @param [opts.data] The query string or form parameter object.
 * @param {?Function} [opts.error] An error callback, as documented in
 *        `$.ajax <http://api.jquery.com/jQuery.ajax/>`_, or null. If not provided, this will have a
 *        default behavior of triggering a `'g:alert'` global event, with details of the error.
 * @param {string} [opts.girderToken] An alternative auth token to use for this request.
 * @returns {$.Promise} A jqXHR promise, which resolves and rejects
 *          `as documented by $.ajax<http://api.jquery.com/jQuery.ajax/#jqXHR>`_.
 */
let restRequest = function (opts) {
    opts = opts || {};
    const defaults = {
        method: 'GET',
        girderToken: getCurrentToken() || cookie.find('girderToken'),

        error: (error, status) => {
            let info;
            if (error.status === 401) {
                events.trigger('g:loginUi');
                info = {
                    text: 'You must log in to view this resource',
                    type: 'warning',
                    timeout: 4000,
                    icon: 'info'
                };
            } else if (error.status === 403) {
                info = {
                    text: 'Access denied. See the console for more details.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            } else if (error.status === 0 && error.statusText === 'abort') {
                /* We expected this abort, so do nothing. */
                return;
            } else if (error.status === 500 && error.responseJSON &&
                error.responseJSON.type === 'girder') {
                info = {
                    text: error.responseJSON.message,
                    type: 'warning',
                    timeout: 5000,
                    icon: 'info'
                };
            } else if (status === 'parsererror') {
                info = {
                    text: 'A parser error occurred while communicating with the ' +
                          'server (did you use the correct value for `dataType`?). ' +
                          'Details have been logged in the console.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            } else {
                info = {
                    text: 'An error occurred while communicating with the ' +
                          'server. Details have been logged in the console.',
                    type: 'danger',
                    timeout: 5000,
                    icon: 'attention'
                };
            }
            events.trigger('g:alert', info);
            console.error(error.status + ' ' + error.statusText, error.responseText);
        }
    };

    // Overwrite defaults with passed opts, but do not mutate opts
    const args = _.extend({}, defaults, opts);

    if (args.path) {
        console.warn('restRequest\'s "path" option is deprecated, use "url" instead');
        args.url = args.url || args.path;
        delete args.path;
    }

    if (!args.url) {
        throw new Error('restRequest requires a "url" argument');
    }
    args.url = `${getApiRoot()}${args.url.substring(0, 1) === '/' ? '' : '/'}${args.url}`;

    if (args.girderToken) {
        args.headers = args.headers || {};
        args.headers['Girder-Token'] = args.girderToken;
        delete args.girderToken;
    }

    let jqXHR = Backbone.$.ajax(args);
    jqXHR.error = function () {
        console.warn('Use of restRequest.error is deprecated, use restRequest.fail instead.');
        return jqXHR.fail.apply(jqXHR, arguments);
    };
    return jqXHR;
};

const _originalRestRequest = restRequest;
/**
 * @deprecated: will be removed in v3
 */
function mockRestRequest(mock) {
    restRequest = mock;
}
/**
 * @deprecated: will be removed in v3
 */
function unmockRestRequest() {
    restRequest = _originalRestRequest;
}

// All requests from Backbone should go through restRequest, adding authentication and the API root.
Backbone.ajax = restRequest;

/* Pending rest requests are listed in this pool so that they can be aborted or
* checked if still processing. */
var restXhrPool = {};
var restXhrCount = 0;
$(document).ajaxSend(function (event, xhr) {
    restXhrCount += 1;
    xhr.girderXhrNumber = restXhrCount;
    restXhrPool[restXhrCount] = xhr;
});
$(document).ajaxComplete(function (event, xhr) {
    var num = xhr.girderXhrNumber;
    if (num && restXhrPool[num]) {
        delete restXhrPool[num];
    }
});

/* Get the number of outstanding rest requests.
 * :param category: if specified, only count those requests that have
 *                  xhr.girder[category] set to a truthy value.
 * :returns: the number of outstanding requests.
 */
function numberOutstandingRestRequests(category) {
    if (category) {
        return _.filter(restXhrPool, function (xhr) {
            return xhr.girder && xhr.girder[category];
        }).length;
    }
    return _.size(restXhrPool);
}

/* Cancel outstanding rest requests.
 * :param category: if specified, only abort those requests that have
 *                  xhr.girder[category] set to a truthy value.
 */
function cancelRestRequests(category) {
    _.each(restXhrPool, function (xhr) {
        if (category && (!xhr.girder || !xhr.girder[category])) {
            return;
        }
        if (xhr.abort) {
            xhr.abort();
        }
    });
}

/*
 * Get Upload Chunk Size
 */
function getUploadChunkSize() {
    return uploadChunkSize;
}

/*
 * Set Upload Chunk Size
 */
function setUploadChunkSize(val) {
    uploadChunkSize = val;
}

export {
    apiRoot, // deprecated
    staticRoot, // deprecated
    getApiRoot,
    setApiRoot,
    getStaticRoot,
    setStaticRoot,
    uploadHandlers,
    restRequest,
    numberOutstandingRestRequests,
    cancelRestRequests,
    mockRestRequest,
    unmockRestRequest,
    getUploadChunkSize,
    setUploadChunkSize
};
<|endoftext|>


<commit_before>import { describe, PropTypes } from 'react-desc';

import { getAvailableAtBadge } from '../../utils';

export const doc = ResponsiveContext => {
  const DocumentedResponsiveContext = describe(ResponsiveContext)
    .availableAt(getAvailableAtBadge('ResponsiveContext'))
    .description(
      `A means of providing different rendering behavior based on the
      screen resolution.`,
    )
    .usage(
      "import { ResponsiveContext } from 'grommet';\n" +
        '<ResponsiveContext.Consumer />\n{resolution => ()}',
    );

  DocumentedResponsiveContext.propTypes = {
    children: PropTypes.func.description(
      `Render function that will be called with the current screen resolution
      size (e.g our base theme of size 'small', 'medium', 'large').
      The size value will be derived from global.breakpoints entry
      in the theme object.`,
    ),
  };

  return DocumentedResponsiveContext;
};

export const themeDoc = {
  'global.breakpoints': {
    description: `The possible breakpoints that could affect border, direction,
gap, margin, pad, and round. The default values help to optimize content for
mobile, tablet, and computer.`,
    type: 'object',
    defaultValue: `{
    small: {
      value: '768px',
      borderSize: {
        xsmall: '1px',
        small: '2px',
        medium: '4px',
        large: '6px',
        xlarge: '12px',
      },
      edgeSize: {
        none: '0px',
        hair: '1px',
        xxsmall: '2px',
        xsmall: '3px',
        small: '6px',
        medium: '12px',
        large: '24px',
        xlarge: '48px',
      },
      size: {
        xxsmall: '24px',
        xsmall: '48px',
        small: '96px',
        medium: '192px',
        large: '384px',
        xlarge: '768px',
        full: '100%',
      },
    },
    medium: {
      value: '1536px',
    },
    large: {},
  }`,
  },
};
<commit_msg>Updated ResponsiveContext doc to use hooks. (#3428)<commit_after>import { describe, PropTypes } from 'react-desc';

import { getAvailableAtBadge } from '../../utils';

export const doc = ResponsiveContext => {
  const DocumentedResponsiveContext = describe(ResponsiveContext)
    .availableAt(getAvailableAtBadge('ResponsiveContext'))
    .description(
      `A means of providing different rendering behavior based on the
      screen resolution.`,
    )
    .usage(
      `import { ResponsiveContext } from 'grommet'
       const Example = () => {
         const size = React.useContext(ResponsiveContext);
         return (
           <Box pad="medium">
             <Text>{size}</Text>
           </Box>
         );
       }`,
    );

  DocumentedResponsiveContext.propTypes = {
    children: PropTypes.func.description(
      `Render function that will be called with the current screen resolution
      size (e.g our base theme of size 'small', 'medium', 'large').
      The size value will be derived from global.breakpoints entry
      in the theme object.`,
    ),
  };

  return DocumentedResponsiveContext;
};

export const themeDoc = {
  'global.breakpoints': {
    description: `The possible breakpoints that could affect border, direction,
gap, margin, pad, and round. The default values help to optimize content for
mobile, tablet, and computer.`,
    type: 'object',
    defaultValue: `{
    small: {
      value: '768px',
      borderSize: {
        xsmall: '1px',
        small: '2px',
        medium: '4px',
        large: '6px',
        xlarge: '12px',
      },
      edgeSize: {
        none: '0px',
        hair: '1px',
        xxsmall: '2px',
        xsmall: '3px',
        small: '6px',
        medium: '12px',
        large: '24px',
        xlarge: '48px',
      },
      size: {
        xxsmall: '24px',
        xsmall: '48px',
        small: '96px',
        medium: '192px',
        large: '384px',
        xlarge: '768px',
        full: '100%',
      },
    },
    medium: {
      value: '1536px',
    },
    large: {},
  }`,
  },
};
<|endoftext|>


<commit_before>/* eslint-disable no-await-in-loop */
import React from 'react'
import { isFunction } from 'utils/is'
import config from '../config'
import api from '../backendAPI'
import { stepFactory, i18n } from '../utils'
import { loadPackagesByType, mountPackagesByType } from '../components/Plugins/actions'
import CodingSDK from '../CodingSDK'
import state from './state'
import pluginUrls from '../../.plugins.json'

function checkEnable (enable) {
  if (enable === undefined) {
    return true
  }
  if (isFunction(enable)) {
    return enable(config)
  }
  return Boolean(enable)
}

async function initialize () {
  const step = stepFactory()
  let stepNum = 2
  await step('[0] prepare data', async () => {
    window.CodingSDK = CodingSDK
    window.React = React
    window.i18n = i18n
    window.extension = f => null
    window.refs = {}
    window.config = config
    return true
  })

  await step('[1] load initialize package', async() => {
    await loadPackagesByType('init', state)
    return true
  })

  await step('load step from settings', async() => {
    for (const value of state.values()) {
      if (checkEnable(value.enable)) {
        await step(`[${stepNum++}] ${value.desc}`, value.func)
      }
    }
    return true
  })

  await step(`[${stepNum++}] load required package`,
  async () => {
    await loadPackagesByType('Required')
    mountPackagesByType('init')
    return true
  })

  if (config.packageDev) {
    await step(`[${stepNum++}] enable package server hotreload`,
    () => {
      if (pluginUrls && pluginUrls.length) {
        pluginUrls.forEach((pluginUrl) => {
          api.enablePackageHotReload(pluginUrl)
        })
      } else {
        api.enablePackageHotReload()
      }
      return true
    })
  }

  return step
}

export default initialize
<commit_msg>支持初始化步骤 goto 方法<commit_after>/* eslint-disable no-await-in-loop */
import React from 'react'
import { isFunction, isBoolean, isString } from 'utils/is'
import config from '../config'
import api from '../backendAPI'
import { stepFactory, i18n } from '../utils'
import { loadPackagesByType, mountPackagesByType } from '../components/Plugins/actions'
import CodingSDK from '../CodingSDK'
import state from './state'
import pluginUrls from '../../.plugins.json'

function closestTo (arr, key, isPrev) {
  const offsetIndex = isPrev ? -1 : 1
  const current = arr.indexOf(key)
  return arr[current + offsetIndex]
}

function checkEnable (enable) {
  if (enable === undefined) {
    return true
  }
  if (isFunction(enable)) {
    return enable(config)
  }
  return Boolean(enable)
}

async function initialize () {
  const step = stepFactory()
  let stepNum = 2
  await step('[0] prepare data', async () => {
    window.CodingSDK = CodingSDK
    window.React = React
    window.i18n = i18n
    window.extension = f => null
    window.refs = {}
    window.config = config
    return true
  })

  await step('[1] load initialize package', async() => {
    await loadPackagesByType('init', state)
    return true
  })

  await step('load step from settings', async() => {
    async function goto (key, hasNext = true) {
      if (!hasNext) {
        return true
      }
      const nextKey = await step(`[${stepNum++}] ${state.get(key).desc}`, state.get(key).func)
      if (nextKey === undefined || isBoolean(nextKey)) {
        const next = closestTo(state.keys(), key)
        return nextKey && goto(next, !!next)
      }
      if (isString(nextKey)) {
        return goto(nextKey)
      }
    }
    return goto(state.keys()[0])
  })

  await step(`[${stepNum++}] load required package`,
  async () => {
    await loadPackagesByType('Required')
    mountPackagesByType('init')
    return true
  })

  if (config.packageDev) {
    await step(`[${stepNum++}] enable package server hotreload`,
    () => {
      if (pluginUrls && pluginUrls.length) {
        pluginUrls.forEach((pluginUrl) => {
          api.enablePackageHotReload(pluginUrl)
        })
      } else {
        api.enablePackageHotReload()
      }
      return true
    })
  }

  return step
}

export default initialize
<|endoftext|>


<commit_before>function jaysonCtrl($scope, $firebaseObject, $firebaseArray, $compile, $http, $timeout, $cordovaCamera, $ionicPlatform) {
  $scope.client = {};
  var rootRef = firebase.database().ref();
  var arrRef = rootRef.child('JaysonSampleClient');

  $scope.testvar = $firebaseArray(arrRef);
  $scope.addClient = function () {
    $scope.testvar.$add({name: $scope.client.name, gender:$scope.client.gender}).then(function(ref) {});
    $scope.client.name = null;
  }

  $scope.toggleCamera = function() {
    if ($scope.client.PICperm) {
    	options = {
    		quality : 25,
    		targetWidth : 1024,
    		targetHeight : 1024,
    		sourceType : 1, // 0:PHOTOLIBRARY, 1:CAMERA, 2:SAVEDPHOTOALBUM
    		correctOrientation : true,
    		destinationType : 0, // 0:DATA_URL, 1:FILE_URI, 2:NATIVE_URI
    		encodingType : 0, // 0:JPEG, 1:PNG
    		allowEdit : false
    	};

    	$ionicPlatform.ready(function () {
    		if (!navigator.camera) {
    			// Load image if unable to get camera
    			console.log("error getting camera");
    		} else {
    			$cordovaCamera.getPicture(options).then(function (imageData) {
    				$scope.picture = "data:image/jpeg;base64," + imageData;
    				var myBLOB = atob(imageData);

    				for (var i = 0; i < myBLOB.length; i++) {
    					myBLOB[i] = myBLOB.charCodeAt(i);
    				}

    				myBLOB = new Uint8Array(myBLOB);

    				myBLOB = new BLOB([myBLOB], {type : contentType});

            $scope.picBLOB = myBLOB;
            alert($scope.picBLOB);

    			}, function (err) {
    				console.log("Camera Failed: " + err);
    			});
    		}
    	});
    }
  };
};
angular.module("SHARKZ").controller("jaysonCtrl", ["$scope", "$firebaseObject", "$firebaseArray", "$compile", "$http", "$timeout", "$cordovaCamera", "$ionicPlatform", jaysonCtrl]);
<commit_msg>file upload (#21)<commit_after>function jaysonCtrl($scope, $firebaseObject, $firebaseArray, $compile, $http, $timeout, $cordovaCamera, $ionicPlatform) {
  $scope.client = {};
  var rootRef = firebase.database().ref();
  var arrRef = rootRef.child('JaysonSampleClient');

  $scope.testvar = $firebaseArray(arrRef);
  $scope.addClient = function () {
    $scope.testvar.$add({name: $scope.client.name, gender:$scope.client.gender}).then(function(ref) {});
    $scope.client.name = null;
  }

  $scope.addClient = function() {

    var storageRef = firebase.storage().ref();
    var uploadRef = storageRef.child('PUTSOMETHINGHEREJAYSON.jpg');

    uploadRef.put($scope.picBLOB).then(function(ret){console.log("success")}, function(error){console.log("failed: " + error)});
  }

  $scope.toggleCamera = function() {
    if ($scope.client.PICperm) {
    	options = {
    		quality : 25,
    		targetWidth : 1024,
    		targetHeight : 1024,
    		sourceType : 1, // 0:PHOTOLIBRARY, 1:CAMERA, 2:SAVEDPHOTOALBUM
    		correctOrientation : true,
    		destinationType : 0, // 0:DATA_URL, 1:FILE_URI, 2:NATIVE_URI
    		encodingType : 0, // 0:JPEG, 1:PNG
    		allowEdit : false
    	};

    	$ionicPlatform.ready(function () {
    		if (!navigator.camera) {
    			// Load image if unable to get camera
    			console.log("error getting camera");

    		} else {
    			$cordovaCamera.getPicture(options).then(function (imageData) {
    				$scope.picture = "data:image/jpeg;base64," + imageData;
    				var myBLOB = atob(imageData);

            var myBLOBarray = new Array(myBLOB.length);
    				for (var i = 0; i < myBLOB.length; i++) {
    					myBLOBarray[i] = myBLOB.charCodeAt(i);
    				}

    				var myBLOBuint = new Uint8Array(myBLOBarray);

            var picBLOB = new Blob([myBLOBuint], [{contentType : 'image/jpeg'}]);

            $scope.picBLOB = picBLOB;

    			}, function (err) {
    				console.log("Camera Failed: " + err);
    			});
    		}
    	});
    }
  };
};
angular.module("SHARKZ").controller("jaysonCtrl", ["$scope", "$firebaseObject", "$firebaseArray", "$compile", "$http", "$timeout", "$cordovaCamera", "$ionicPlatform", jaysonCtrl]);
<|endoftext|>


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

/**
 * @fileoverview A base menu class that supports key and mouse events. The menu
 * can be bound to an existing HTML structure or can generate its own DOM.
 *
 * To decorate, the menu should be bound to an element containing children
 * with the classname 'goog-menuitem'.  HRs will be classed as separators.
 *
 * Decorate Example:
 *

 *
Google

 *
Yahoo

 *
MSN

 *

 *
New...

 *

 *


<commit_before>// import sampleOutput from 'json!../sampleData/sampleOutput.json';
import { mapboxClient } from '../components/MapboxClient';
import { find } from 'lodash';

export const FETCH_VA_FACILITY = 'FETCH_VA_FACILITY';
export const FETCH_VA_FACILITIES = 'FETCH_VA_FACILITIES';
export const LOCATION_UPDATED = 'LOCATION_UPDATED';
export const SEARCH_QUERY_UPDATED = 'SEARCH_QUERY_UPDATED';
export const SEARCH_SUCCEEDED = 'SEARCH_SUCCEEDED';
export const SEARCH_FAILED = 'SEARCH_FAILED';
export const SEARCH_STARTED = 'SEARCH_STARTED';

export function updateSearchQuery(query) {
  return {
    type: SEARCH_QUERY_UPDATED,
    payload: {
      ...query,
    }
  };
}

export function updateLocation(propertyPath, value) {
  return {
    type: LOCATION_UPDATED,
    propertyPath,
    value
  };
}
const mockFacility = {
  id: 539,
  type: 'va_health_facility',
  attributes: {
    visnId: 20,
    name: 'Portland VA Medical Center-Vancouver',
    classification: 'VA Medical Center (VAMC)',
    address: {
      building: null,
      street: '1601 East 4th Plain Boulevard',
      suite: null,
      city: 'Vancouver',
      state: 'WA',
      zip: '98661',
      zip4: '3753'
    },
    phone: {
      main: '360-759-1901 x',
      fax: '360-690-0864 x',
      afterHours: '360-696-4061 x',
      patientAdvocate: '503-273-5308 x',
      enrollmentCoordinator: '503-273-5069 x',
      pharmacy: '503-273-5183 x',
    },
    hours: {
      monday: '730AM-430PM',
      tuesday: '730AM-630PM',
      wednesday: '730AM-430PM',
      thursday: '730AM-430PM',
      friday: '730AM-430PM',
      saturday: '800AM-1000AM',
      sunday: '-',
    },
    services: [
      ['Audiology', []],
      ['DentalServices', []],
      ['DiagnosticServices', ['ImagingAndRadiology']],
      ['EyeCare', []],
      ['MentalHealthCare', ['OutpatientMHCare', 'OutpatientSpecMHCare',
        'VocationalAssistance'
      ]],
      ['OutpatientSurgicalSpecialty', ['Podiatry']],
      ['PrimaryCare', []],
      ['Rehabilitation', []],
      ['WellnessAndPreventativeCare', []]
    ],
    lat: 45.63941626,
    'long': -122.65528736,
  }
};

export function fetchVAFacility(id, facility = null) {
  if (facility) {
    return {
      type: FETCH_VA_FACILITY,
      payload: mockFacility,
    };
  }

  return {
    type: FETCH_VA_FACILITY,
    payload: {
      ...mockFacility,
      id,
    },
  };
}

export function fetchVAFacilities(bounds) {
  const mockResults = [...Array(10)].map((_, i) => {
    return {
      ...mockFacility,
      id: i + 1,
      lat: bounds.latitude + (Math.random() / 25 * (Math.floor(Math.random() * 2) === 1 ? 1 : -1)),
      'long': bounds.longitude + (Math.random() / 25 * (Math.floor(Math.random() * 2) === 1 ? 1 : -1)),
    };
  });

  return {
    type: FETCH_VA_FACILITIES,
    payload: mockResults,
  };
}

export function searchWithAddress(query) {
  return dispatch => {
    dispatch({
      type: SEARCH_STARTED,
      payload: {
        active: true,
      },
    });

    mapboxClient.geocodeForward(query.searchString, (err, res) => {
      const coordinates = res.features[0].center;
      const zipCode = find(res.features[0].context, (v) => {
        return v.id.includes('postcode');
      }).text;

      if (!err) {
        dispatch({
          type: SEARCH_QUERY_UPDATED,
          payload: {
            ...query,
            context: zipCode,
            position: {
              latitude: coordinates[1],
              longitude: coordinates[0],
            },
          }
        });

        // TODO (bshyong): replace this with a call to the API
        dispatch(fetchVAFacilities({
          latitude: coordinates[1],
          longitude: coordinates[0],
        }));
      } else {
        dispatch({
          type: SEARCH_FAILED,
          err,
        });
      }
    });
  };
}

export function searchWithCoordinates(bounds) {
  // TODO (bshyong): replace this with a call to the API
  return dispatch => {
    dispatch({
      type: SEARCH_STARTED,
      payload: {
        active: true,
      },
    });

    dispatch(fetchVAFacilities({
      latitude: bounds.latitude,
      longitude: bounds.longitude,
    }));
  };
}
<commit_msg>Catch edge case when only zipcodes are entered<commit_after>// import sampleOutput from 'json!../sampleData/sampleOutput.json';
import { mapboxClient } from '../components/MapboxClient';
import { find } from 'lodash';

export const FETCH_VA_FACILITY = 'FETCH_VA_FACILITY';
export const FETCH_VA_FACILITIES = 'FETCH_VA_FACILITIES';
export const LOCATION_UPDATED = 'LOCATION_UPDATED';
export const SEARCH_QUERY_UPDATED = 'SEARCH_QUERY_UPDATED';
export const SEARCH_SUCCEEDED = 'SEARCH_SUCCEEDED';
export const SEARCH_FAILED = 'SEARCH_FAILED';
export const SEARCH_STARTED = 'SEARCH_STARTED';

export function updateSearchQuery(query) {
  return {
    type: SEARCH_QUERY_UPDATED,
    payload: {
      ...query,
    }
  };
}

export function updateLocation(propertyPath, value) {
  return {
    type: LOCATION_UPDATED,
    propertyPath,
    value
  };
}
const mockFacility = {
  id: 539,
  type: 'va_health_facility',
  attributes: {
    visnId: 20,
    name: 'Portland VA Medical Center-Vancouver',
    classification: 'VA Medical Center (VAMC)',
    address: {
      building: null,
      street: '1601 East 4th Plain Boulevard',
      suite: null,
      city: 'Vancouver',
      state: 'WA',
      zip: '98661',
      zip4: '3753'
    },
    phone: {
      main: '360-759-1901 x',
      fax: '360-690-0864 x',
      afterHours: '360-696-4061 x',
      patientAdvocate: '503-273-5308 x',
      enrollmentCoordinator: '503-273-5069 x',
      pharmacy: '503-273-5183 x',
    },
    hours: {
      monday: '730AM-430PM',
      tuesday: '730AM-630PM',
      wednesday: '730AM-430PM',
      thursday: '730AM-430PM',
      friday: '730AM-430PM',
      saturday: '800AM-1000AM',
      sunday: '-',
    },
    services: [
      ['Audiology', []],
      ['DentalServices', []],
      ['DiagnosticServices', ['ImagingAndRadiology']],
      ['EyeCare', []],
      ['MentalHealthCare', ['OutpatientMHCare', 'OutpatientSpecMHCare',
        'VocationalAssistance'
      ]],
      ['OutpatientSurgicalSpecialty', ['Podiatry']],
      ['PrimaryCare', []],
      ['Rehabilitation', []],
      ['WellnessAndPreventativeCare', []]
    ],
    lat: 45.63941626,
    'long': -122.65528736,
  }
};

export function fetchVAFacility(id, facility = null) {
  if (facility) {
    return {
      type: FETCH_VA_FACILITY,
      payload: mockFacility,
    };
  }

  return {
    type: FETCH_VA_FACILITY,
    payload: {
      ...mockFacility,
      id,
    },
  };
}

export function fetchVAFacilities(bounds) {
  const mockResults = [...Array(10)].map((_, i) => {
    return {
      ...mockFacility,
      id: i + 1,
      lat: bounds.latitude + (Math.random() / 25 * (Math.floor(Math.random() * 2) === 1 ? 1 : -1)),
      'long': bounds.longitude + (Math.random() / 25 * (Math.floor(Math.random() * 2) === 1 ? 1 : -1)),
    };
  });

  return {
    type: FETCH_VA_FACILITIES,
    payload: mockResults,
  };
}

export function searchWithAddress(query) {
  return dispatch => {
    dispatch({
      type: SEARCH_STARTED,
      payload: {
        active: true,
      },
    });

    mapboxClient.geocodeForward(query.searchString, (err, res) => {
      const coordinates = res.features[0].center;
      const zipCode = (find(res.features[0].context, (v) => {
        return v.id.includes('postcode');
      }) || {}).text || res.features[0].place_name;

      if (!err) {
        dispatch({
          type: SEARCH_QUERY_UPDATED,
          payload: {
            ...query,
            context: zipCode,
            position: {
              latitude: coordinates[1],
              longitude: coordinates[0],
            },
          }
        });

        // TODO (bshyong): replace this with a call to the API
        dispatch(fetchVAFacilities({
          latitude: coordinates[1],
          longitude: coordinates[0],
        }));
      } else {
        dispatch({
          type: SEARCH_FAILED,
          err,
        });
      }
    });
  };
}

export function searchWithCoordinates(bounds) {
  // TODO (bshyong): replace this with a call to the API
  return dispatch => {
    dispatch({
      type: SEARCH_STARTED,
      payload: {
        active: true,
      },
    });

    dispatch(fetchVAFacilities({
      latitude: bounds.latitude,
      longitude: bounds.longitude,
    }));
  };
}
<|endoftext|>


<commit_before>import React from "react";
import ReactDOM from "react-dom";
import { Catalog, ContentLoader } from "catalog";

const pages = [
  {
    path: "/",
    title: "Welcome",
    content: ContentLoader(() => import("./WELCOME.md"))
  }
];

ReactDOM.render(
  <Catalog title="Catalog" pages={pages} />,
  document.getElementById("catalog")
);
<commit_msg>Fix setup template<commit_after>import React from "react";
import ReactDOM from "react-dom";
import { Catalog, pageLoader } from "catalog";

const pages = [
  {
    path: "/",
    title: "Welcome",
    content: pageLoader(() => import("./WELCOME.md"))
  }
];

ReactDOM.render(
  <Catalog title="Catalog" pages={pages} />,
  document.getElementById("catalog")
);
<|endoftext|>


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

'use strict';

const {URL} = require('url');
const createCurlsSubdomain = require('./AmpCurlUrlGenerator');

/**
 * Translates the canonicalUrl to the AMP Cache equivalent, for a given AMP Cache.
 * Example:
 * createCacheUrl('cdn.ampproject.org', 'https://hello-world.com')
 * Should resolve: 'https://hello--world-com.cdn.ampproject.org/c/s/hello-world.com'
 *
 * @param {string} domainSuffix the AMP Cache domain suffix
 * @param {string} url the canonical URL
 * @return {!Promise<string>} The converted AMP cache URL
 */
function createCacheUrl(domainSuffix, url) {
  const canonicalUrl = new URL(url);
  let pathSegment = _getResourcePath(canonicalUrl.pathname);
  pathSegment += canonicalUrl.protocol === 'https:' ? '/s/' : '/';

  return createCurlsSubdomain(canonicalUrl.toString()).then((curlsSubdomain) => {
    const cacheUrl = new URL(url);
    cacheUrl.protocol = 'https';
    cacheUrl.hostname = curlsSubdomain + '.' + domainSuffix;
    cacheUrl.pathname = pathSegment + canonicalUrl.hostname + canonicalUrl.pathname;
    return cacheUrl.toString();
  }).catch((err) => {
    reject(err);
  });
}

/**
 * Returns the AMP Cache path, based on the mime type of the file that is being loaded.
 * @param {string} pathname the pathname on the canonical url.
 */
function _getResourcePath(pathname) {
  const imageExtensions = require('./ImageExtensions');
  const fontExtensions = require('./FontExtensions');

  if (imageExtensions.isPathNameAnImage(pathname)) {
    return '/i';
  }

  if (fontExtensions.isPathNameAFont(pathname)) {
    return '/r';
  }

  // Default to document
  return '/c';
}

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

'use strict';

const {URL} = require('url');
const createCurlsSubdomain = require('./AmpCurlUrlGenerator');

/**
 * Translates the canonicalUrl to the AMP Cache equivalent, for a given AMP Cache.
 * Example:
 * createCacheUrl('cdn.ampproject.org', 'https://hello-world.com')
 * Should resolve: 'https://hello--world-com.cdn.ampproject.org/c/s/hello-world.com'
 *
 * @param {string} domainSuffix the AMP Cache domain suffix
 * @param {string} url the canonical URL
 * @return {!Promise<string>} The converted AMP cache URL
 */
function createCacheUrl(domainSuffix, url) {
  const canonicalUrl = new URL(url);
  let pathSegment = _getResourcePath(canonicalUrl.pathname);
  pathSegment += canonicalUrl.protocol === 'https:' ? '/s/' : '/';

  return createCurlsSubdomain(canonicalUrl.toString()).then((curlsSubdomain) => {
    const cacheUrl = new URL(url);
    cacheUrl.protocol = 'https';
    cacheUrl.hostname = curlsSubdomain + '.' + domainSuffix;
    cacheUrl.pathname = pathSegment + canonicalUrl.hostname + canonicalUrl.pathname;
    return cacheUrl.toString();
  });
}

/**
 * Returns the AMP Cache path, based on the mime type of the file that is being loaded.
 * @param {string} pathname the pathname on the canonical url.
 */
function _getResourcePath(pathname) {
  const imageExtensions = require('./ImageExtensions');
  const fontExtensions = require('./FontExtensions');

  if (imageExtensions.isPathNameAnImage(pathname)) {
    return '/i';
  }

  if (fontExtensions.isPathNameAFont(pathname)) {
    return '/r';
  }

  // Default to document
  return '/c';
}

/** @module AmpUrl */
module.exports = createCacheUrl;
<|endoftext|>


<commit_before>/**
 * This module handles add-layers events and layer-toggle events. tI basically
 * proxies the CartoDB JavaScript API for adding and removing CartoDB layers
 * to and from the map.
 */
mol.modules.map.tiles = function(mol) {

    mol.map.tiles = {};

    /**
     * Based on the CartoDB point density gallery example by Andrew Hill at
     * Vizzuality (andrew@vizzuality.com).
     *
     * @see http://developers.cartodb.com/gallery/maps/densitygrid.html
     */
    mol.map.tiles.TileEngine = mol.mvp.Engine.extend({
        init: function(proxy, bus, map) {
            this.proxy = proxy;
            this.bus = bus;
            this.map = map;
            this.gmap_events = [];
            this.addEventHandlers();
        },

        addEventHandlers: function() {
            var self = this;

            /**
             * Handler for when the layer-toggle event is fired. This renders
             * the layer on the map if visible, and removes it if not visible.
             * The event.layer is a layer object {id, name, type, source}. event.showing
             * is true if visible, false otherwise.
             */
             this.bus.addHandler(
                'layer-toggle',
                function(event) {
                        var showing = event.showing,
                            layer = event.layer,
                            params = null,
                            e = null;

                        if (showing) {
                            self.map.overlayMapTypes.forEach(
                                function(mt, index) {
                                    if (mt != undefined && mt.name == layer.id) {
                                        params = {
                                            layer: layer,
                                            opacity: mt.opacity_visible
                                        };
                                        e = new mol.bus.Event('layer-opacity', params);
                                        self.bus.fireEvent(e);
                                        //if(maptype.interaction != undefined) {
                                        //    maptype.interaction.add();
                                        //    maptype.interaction.clickAction="full"
                                        //}
                                        return;
                                    }
                                }
                            );
                            //self.renderTiles([layer]);
                        } else { // Remove layer from map.
                            self.map.overlayMapTypes.forEach(
                                function(mt, index) {
                                    if (mt != undefined && mt.name == layer.id) {
                                        mt.opacity_visible = mt.opacity;
                                        params = {
                                            layer: layer,
                                            opacity: 0
                                        };
                                        e = new mol.bus.Event(
                                            'layer-opacity',
                                            params
                                        );
                                        self.bus.fireEvent(e);
                                        if(mt.interaction != undefined) {
                                            mt.interaction.remove();
                                            mt.interaction.clickAction="";
                                        }
                                        //self.map.overlayMapTypes.removeAt(index);
                                    }
                                }
                            );
                        }
                    }
                );
                /**
                 * Handler for changing layer opacity. The event.opacity is a
                 * number between 0 and 1.0 and the event.layer is an object
                 * {id, name, source, type}.
                 */
                this.bus.addHandler(
                    'layer-opacity',
                    function(event) {
                        var layer = event.layer,
                            opacity = event.opacity;

                        if (opacity === undefined) {
                            return;
                        }

                        self.map.overlayMapTypes.forEach(
                            function(maptype, index) {
                                if (maptype.name === layer.id) {
                                    maptype.setOpacity(opacity);
                                }
                            }
                        );
                    }
                );

                /**
                 * Handler for applying cartocss style to a layer.
                 */
                this.bus.addHandler(
                    'apply-layer-style',
                    function(event) {
                        var layer = event.layer,
                            style = event.style;

                        if(layer.type == 'points') {
                            return;
                        }

                        console.log("apply-layer-style");
                        console.log(style);

                        self.map.overlayMapTypes.forEach(
                            function(maptype, index) {
                                //find the overlaymaptype to style
                                if (maptype.name === layer.id) {
                                    console.log("match");

                                    //remove it from the map
                                    self.map.overlayMapTypes.removeAt(index);
                                    //add the style
                                    layer.tile_style = style;
                                    //make the layer
                                    self.getTile(layer);
                                    //fix the layer order
                                    self.map.overlayMapTypes.forEach(
                                        function(newmaptype, newindex) {
                                            var mt;
                                            if(newmaptype.name === layer.id) {
                                                mt = self.map.overlayMapTypes.removeAt(newindex);
                                                self.map.overlayMapTypes.insertAt(index, mt);
                                                return
                                            }
                                        }
                                    );
                                }
                            }
                        );

                    }
                );

                /**
                 * Handler for when the add-layers event is fired. This renders
                 * the layers on the map by firing a add-map-layer event. The
                 * event.layers is an array of layer objects {name:, type:}.
                 */
                this.bus.addHandler(
                    'add-layers',
                    function(event) {
                        self.renderTiles(event.layers);
                    }
                );

                /**
                 * Handler for when the remove-layers event is fired. This
                 * functions removes all layers from the Google Map. The
                 * event.layers is an array of layer objects {id}.
                 */
                    this.bus.addHandler(
                    'remove-layers',
                    function(event) {
                        var layers = event.layers,
                            mapTypes = self.map.overlayMapTypes;

                        _.each(
                            layers,
                            function(layer) { // "lid" is short for layer id.
                                var lid = layer.id;
                                mapTypes.forEach(
                                    function(mt, index) {
                                        if (mt != undefined && mt.name === lid) {
                                            if(mt.interaction != undefined) {
                                                mt.interaction.remove();
                                            }
                                            mapTypes.removeAt(index);
                                        }
                                    }
                                );
                            }
                        );
                    }
                );

                    /**
                     * Handler for when the reorder-layers event is fired. This
                     * renders the layers according to the list of layers
                     * provided
                     */
                    this.bus.addHandler(
                         'reorder-layers',
                         function(event) {
                              var layers = event.layers,
                            mapTypes = self.map.overlayMapTypes;

                              _.each(
                                   layers,
                                   function(lid) { // "lid" is short for layerId.
                                        mapTypes.forEach(
                                             function(mt, index) {
                                                  if ((mt != undefined) &&
                                                      (mt.name === lid)) {
                                                      mapTypes.removeAt(index);
                                                      mapTypes.insertAt(0, mt);
                                                  }
                                             }
                                        );
                                   }
                              );
                         }
                    );
            },

            /**
             * Renders an array a tile layers.
             *
             * @param layers the array of layer objects {name, type}
             */
            renderTiles: function(layers) {
                var overlays = this.map.overlayMapTypes.getArray(),
                    newLayers = this.filterLayers(layers, overlays),
                    self = this;

                _.each(
                    newLayers,
                    function(layer) {
                        var maptype = self.getTile(layer);
                    },
                    self
                );
            },
            /**
             * Returns an array of layer objects that are not already on the
             * map.
             *
             * @param layers an array of layer object {id, name, type, source}.
             * @params overlays an array of wax connectors.
             */
            filterLayers: function(layers, overlays) {
                var layerIds = _.map(
                        layers,
                        function(layer) {
                            return layer.id;
                        }
                    ),
                    overlayIds = _.map(
                        overlays,
                        function(overlay) {
                            return overlay.name;
                        }
                    ),
                    ids = _.without(layerIds, overlayIds);

                return _.filter(
                    layers,
                    function(layer) {
                        return (_.indexOf(ids, layer.id) != -1);
                    },
                    this
                );
            },

            /**
             * Closure around the layer that returns the ImageMapType for the
             * tile.
             */
            getTile: function(layer) {
                var name = layer.name,
                    type = layer.type,
                    self = this,
                    maptype = new mol.map.tiles.CartoDbTile(
                                layer,
                                layer.style_table,
                                this.map
                            );

                maptype.layer.params.layer.onbeforeload = function (){
                    self.bus.fireEvent(
                        new mol.bus.Event(
                            "show-loading-indicator",
                            {source : layer.id}
                        )
                    )
                };

                maptype.layer.params.layer.onafterload = function (){
                    self.bus.fireEvent(
                        new mol.bus.Event(
                            "hide-loading-indicator",
                            {source : layer.id}
                        )
                    )
                };
            }
        }
     );

    mol.map.tiles.CartoDbTile = Class.extend(
        {
            init: function(layer, table, map) {
                var sql =  "" +
                    "SELECT * FROM " +
                    " get_mol_tile('{0}','{1}','{2}','{3}')".format(
                        layer.source,
                        layer.type,
                        layer.name,
                        layer.dataset_id
                    ),
                    hostname =  mol.services.cartodb.tileApi.host,
                    style_table_name = layer.style_table;
                    info_query = sql;
                    meta_query = "" +
                        "SELECT * FROM get_feature_metadata(TEXT('{0}'))",
                    infowindow = true,
                    hostname = (hostname === 'localhost') ?
                       '{0}:8080'.format(hostname) : hostname;

                //jeremy's original code got rid of tile_style variable
                //used layer.tile_style

                console.log("CartoDbTile");
                console.log(layer.dataset_id);

                this.layer = new google.maps.CartoDBLayer({
                        tile_name: layer.id,
                        tile_style: layer.tile_style,
                        hostname: hostname,
                        map_canvas: 'map_container',
                        map: map,
                        user_name: 'mol',
                        table_name: table,
                        mol_layer: layer,
                        style_table_name: layer.dataset_id,
                        query: sql,
                        info_query: info_query,
                        meta_query: meta_query,
                        map_style: false,
                        infowindow: infowindow,
                        opacity: layer.opacity
                });
            }
        }
    );
};<commit_msg>Adding hardcoded default layer styles.<commit_after>/**
 * This module handles add-layers events and layer-toggle events. tI basically
 * proxies the CartoDB JavaScript API for adding and removing CartoDB layers
 * to and from the map.
 */
mol.modules.map.tiles = function(mol) {

    mol.map.tiles = {};

    /**
     * Based on the CartoDB point density gallery example by Andrew Hill at
     * Vizzuality (andrew@vizzuality.com).
     *
     * @see http://developers.cartodb.com/gallery/maps/densitygrid.html
     */
    mol.map.tiles.TileEngine = mol.mvp.Engine.extend({
        init: function(proxy, bus, map) {
            this.proxy = proxy;
            this.bus = bus;
            this.map = map;
            this.gmap_events = [];
            this.addEventHandlers();
        },

        addEventHandlers: function() {
            var self = this;

            /**
             * Handler for when the layer-toggle event is fired. This renders
             * the layer on the map if visible, and removes it if not visible.
             * The event.layer is a layer object {id, name, type, source}. event.showing
             * is true if visible, false otherwise.
             */
             this.bus.addHandler(
                'layer-toggle',
                function(event) {
                        var showing = event.showing,
                            layer = event.layer,
                            params = null,
                            e = null;

                        if (showing) {
                            self.map.overlayMapTypes.forEach(
                                function(mt, index) {
                                    if (mt != undefined && mt.name == layer.id) {
                                        params = {
                                            layer: layer,
                                            opacity: mt.opacity_visible
                                        };
                                        e = new mol.bus.Event('layer-opacity', params);
                                        self.bus.fireEvent(e);
                                        //if(maptype.interaction != undefined) {
                                        //    maptype.interaction.add();
                                        //    maptype.interaction.clickAction="full"
                                        //}
                                        return;
                                    }
                                }
                            );
                            //self.renderTiles([layer]);
                        } else { // Remove layer from map.
                            self.map.overlayMapTypes.forEach(
                                function(mt, index) {
                                    if (mt != undefined && mt.name == layer.id) {
                                        mt.opacity_visible = mt.opacity;
                                        params = {
                                            layer: layer,
                                            opacity: 0
                                        };
                                        e = new mol.bus.Event(
                                            'layer-opacity',
                                            params
                                        );
                                        self.bus.fireEvent(e);
                                        if(mt.interaction != undefined) {
                                            mt.interaction.remove();
                                            mt.interaction.clickAction="";
                                        }
                                        //self.map.overlayMapTypes.removeAt(index);
                                    }
                                }
                            );
                        }
                    }
                );
                /**
                 * Handler for changing layer opacity. The event.opacity is a
                 * number between 0 and 1.0 and the event.layer is an object
                 * {id, name, source, type}.
                 */
                this.bus.addHandler(
                    'layer-opacity',
                    function(event) {
                        var layer = event.layer,
                            opacity = event.opacity;

                        if (opacity === undefined) {
                            return;
                        }

                        self.map.overlayMapTypes.forEach(
                            function(maptype, index) {
                                if (maptype.name === layer.id) {
                                    maptype.setOpacity(opacity);
                                }
                            }
                        );
                    }
                );

                /**
                 * Handler for applying cartocss style to a layer.
                 */
                this.bus.addHandler(
                    'apply-layer-style',
                    function(event) {
                        var layer = event.layer,
                            style = event.style;

                        if(layer.type == 'points') {
                            return;
                        }

                        console.log("apply-layer-style");
                        console.log(style);

                        self.map.overlayMapTypes.forEach(
                            function(maptype, index) {
                                //find the overlaymaptype to style
                                if (maptype.name === layer.id) {
                                    console.log("match");

                                    //remove it from the map
                                    self.map.overlayMapTypes.removeAt(index);
                                    //add the style
                                    layer.tile_style = style;
                                    //make the layer
                                    self.getTile(layer);
                                    //fix the layer order
                                    self.map.overlayMapTypes.forEach(
                                        function(newmaptype, newindex) {
                                            var mt;
                                            if(newmaptype.name === layer.id) {
                                                mt = self.map.overlayMapTypes.removeAt(newindex);
                                                self.map.overlayMapTypes.insertAt(index, mt);
                                                return
                                            }
                                        }
                                    );
                                }
                            }
                        );

                    }
                );

                /**
                 * Handler for when the add-layers event is fired. This renders
                 * the layers on the map by firing a add-map-layer event. The
                 * event.layers is an array of layer objects {name:, type:}.
                 */
                this.bus.addHandler(
                    'add-layers',
                    function(event) {
                        self.renderTiles(event.layers);
                    }
                );

                /**
                 * Handler for when the remove-layers event is fired. This
                 * functions removes all layers from the Google Map. The
                 * event.layers is an array of layer objects {id}.
                 */
                    this.bus.addHandler(
                    'remove-layers',
                    function(event) {
                        var layers = event.layers,
                            mapTypes = self.map.overlayMapTypes;

                        _.each(
                            layers,
                            function(layer) { // "lid" is short for layer id.
                                var lid = layer.id;
                                mapTypes.forEach(
                                    function(mt, index) {
                                        if (mt != undefined && mt.name === lid) {
                                            if(mt.interaction != undefined) {
                                                mt.interaction.remove();
                                            }
                                            mapTypes.removeAt(index);
                                        }
                                    }
                                );
                            }
                        );
                    }
                );

                    /**
                     * Handler for when the reorder-layers event is fired. This
                     * renders the layers according to the list of layers
                     * provided
                     */
                    this.bus.addHandler(
                         'reorder-layers',
                         function(event) {
                              var layers = event.layers,
                            mapTypes = self.map.overlayMapTypes;

                              _.each(
                                   layers,
                                   function(lid) { // "lid" is short for layerId.
                                        mapTypes.forEach(
                                             function(mt, index) {
                                                  if ((mt != undefined) &&
                                                      (mt.name === lid)) {
                                                      mapTypes.removeAt(index);
                                                      mapTypes.insertAt(0, mt);
                                                  }
                                             }
                                        );
                                   }
                              );
                         }
                    );
            },

            /**
             * Renders an array a tile layers.
             *
             * @param layers the array of layer objects {name, type}
             */
            renderTiles: function(layers) {
                var overlays = this.map.overlayMapTypes.getArray(),
                    newLayers = this.filterLayers(layers, overlays),
                    self = this;

                _.each(
                    newLayers,
                    function(layer) {
                        var maptype = self.getTile(layer);
                    },
                    self
                );
            },
            /**
             * Returns an array of layer objects that are not already on the
             * map.
             *
             * @param layers an array of layer object {id, name, type, source}.
             * @params overlays an array of wax connectors.
             */
            filterLayers: function(layers, overlays) {
                var layerIds = _.map(
                        layers,
                        function(layer) {
                            return layer.id;
                        }
                    ),
                    overlayIds = _.map(
                        overlays,
                        function(overlay) {
                            return overlay.name;
                        }
                    ),
                    ids = _.without(layerIds, overlayIds);

                return _.filter(
                    layers,
                    function(layer) {
                        return (_.indexOf(ids, layer.id) != -1);
                    },
                    this
                );
            },

            /**
             * Closure around the layer that returns the ImageMapType for the
             * tile.
             */
            getTile: function(layer) {
                var name = layer.name,
                    type = layer.type,
                    self = this,
                    maptype = new mol.map.tiles.CartoDbTile(
                                layer,
                                layer.style_table,
                                this.map
                            );

                maptype.layer.params.layer.onbeforeload = function (){
                    self.bus.fireEvent(
                        new mol.bus.Event(
                            "show-loading-indicator",
                            {source : layer.id}
                        )
                    )
                };

                maptype.layer.params.layer.onafterload = function (){
                    self.bus.fireEvent(
                        new mol.bus.Event(
                            "hide-loading-indicator",
                            {source : layer.id}
                        )
                    )
                };
            }
        }
     );

    mol.map.tiles.CartoDbTile = Class.extend(
        {
            init: function(layer, table, map) {
                var sql =  "" +
                    "SELECT * FROM " +
                    " get_mol_tile('{0}','{1}','{2}','{3}')".format(
                        layer.source,
                        layer.type,
                        layer.name,
                        layer.dataset_id
                    ),
                    hostname =  mol.services.cartodb.tileApi.host,
                    style_table_name = layer.style_table;
                    info_query = sql;
                    meta_query = "" +
                        "SELECT * FROM get_feature_metadata(TEXT('{0}'))",
                    infowindow = true,
                    hostname = (hostname === 'localhost') ?
                       '{0}:8080'.format(hostname) : hostname;

                if(layer.tile_style == undefined) {
                    layer.tile_style = this.getDefaultStyle(layer);
                }

                this.layer = new google.maps.CartoDBLayer({
                        tile_name: layer.id,
                        tile_style: layer.tile_style,
                        hostname: hostname,
                        map_canvas: 'map_container',
                        map: map,
                        user_name: 'mol',
                        table_name: table,
                        mol_layer: layer,
                        style_table_name: layer.dataset_id,
                        query: sql,
                        info_query: info_query,
                        meta_query: meta_query,
                        map_style: false,
                        infowindow: infowindow,
                        opacity: layer.opacity
                });
            },

            getDefaultStyle: function(layer) {
                var style;

                //this will be replaced by a server call in the future
                if(layer.style_table == "points_style") {
                    if(layer.type == "localinv") {
                        style = '#' + layer.dataset_id + '{' +
                                'marker-fill: #6A0085;' +
                                'marker-line-color: #000000;' +
                                'marker-line-width: 1;' +
                                'marker-line-opacity: 1.0;' +
                                'marker-width:3;' +
                                'marker-allow-overlap:true;' +
                                '}';
                    } else {
                        style = '#' + layer.dataset_id + '{' +
                                'marker-fill: #a62a16;' +
                                'marker-line-color: #ffffff;' +
                                'marker-line-width: 1;' +
                                'marker-line-opacity: 1.0;' +
                                'marker-width:3;' +
                                'marker-allow-overlap:true;' +
                                '}';
                    }
                } else {
                    if(layer.source == "iucn") {
                        style = '#' + layer.dataset_id + '{' +
                                'line-color: #000000;' +
                                'line-opacity: 1.0;' +
                                'line-width: 0;' +
                                'polygon-opacity:1.0;' +
                                '  [seasonality=1] {' +
                                '    polygon-fill:#9C0;' +
                                '  }' +
                                '  [seasonality=2] {' +
                                '    polygon-fill:#FC0;' +
                                '  }' +
                                '  [seasonality=3] {' +
                                '    polygon-fill:#006BB4;' +
                                '  }' +
                                '  [seasonality=4] {' +
                                '    polygon-fill:#E39C5B;' +
                                '  }' +
                                '  [seasonality=5] {' +
                                '    polygon-fill:#E25B5B;' +
                                '  }' +
                                '}';
                    } else if (layer.source == "jetz") {
                        style = '#' + layer.dataset_id + '{' +
                                'line-color: #000000;' +
                                'line-opacity: 1.0;' +
                                'line-width: 0;' +
                                'polygon-opacity:1.0;' +
                                '  [seasonality=1] {' +
                                '    polygon-fill:#FC0;' +
                                '  }' +
                                '  [seasonality=2] {' +
                                '    polygon-fill:#9C0;' +
                                '  }' +
                                '  [seasonality=3] {' +
                                '    polygon-fill:#006BB4;' +
                                '  }' +
                                '  [seasonality=4] {' +
                                '    polygon-fill:#E25B5B;' +
                                '  }' +
                                '}';
                    } else if (layer.type == 'regionalchecklist') {
                        style = '#' + layer.dataset_id + '{' +
                                'line-color: #000000;' +
                                'line-opacity: 0.5;' +
                                'line-width: 1;' +
                                'polygon-fill: #000000;' +
                                'polygon-opacity:1.0;' +
                                '}';
                    } else if (layer.type == 'localinv') {
                        style = '#' + layer.dataset_id + '{' +
                                'line-color: #000000;' +
                                'line-opacity: 1.0;' +
                                'line-width: 1;' +
                                'polygon-fill: #6A0085;' +
                                'polygon-opacity:1.0;' +
                                '}';
                    } else {
                        style = '#' + layer.dataset_id + '{' +
                                'line-color: #000000;' +
                                'line-opacity: 0.50;' +
                                'line-width: 1;' +
                                'polygon-fill: #F60;' +
                                'polygon-opacity:1.0;' +
                                '}';
                    }
                }

                return style;
            }
        }
    );
};<|endoftext|>