<commit_before>// Making a Simple Site Work Offline with ServiceWorker | CSS-Tricks - http://bit.ly/2MvGURI

"use strict";

console.log('WORKER: executing.');

/* A version number is useful when updating the worker logic,
   allowing you to remove outdated cache entries during the update.
*/
var sha = 'ef44b1ba813fec59fcb4f63a0152f670f5a32f7a';
var version = sha.substr(0, 8) + '::';

/* These resources will be downloaded and cached by the service worker
   during the installation process. If any resource fails to be downloaded,
   then the service worker won't be installed either.
*/
var offlineFundamentals = [
  './',
  './script.js',
  './theme.css',
  './presentation.md',
  './γλώσσα.js',
  './favicon.ico',
//'./books/aepp.pdf',
//'./books/tetradio.pdf',
//'./books/odigies-meletis-mathiti.pdf',
//'./books/pliroforiki.pdf'
];

/* The install event fires when the service worker is first installed.
   You can use this event to prepare the service worker to be able to serve
   files while visitors are offline.
*/
self.addEventListener("install", function(event) {
  console.log('WORKER: install event in progress.');
  /* Using event.waitUntil(p) blocks the installation process on the provided
     promise. If the promise is rejected, the service worker won't be installed.
  */
  event.waitUntil(
    /* The caches built-in is a promise-based API that helps you cache responses,
       as well as finding and deleting them.
    */
    caches
      /* You can open a cache by name, and this method returns a promise. We use
         a versioned cache name here so that we can remove old cache entries in
         one fell swoop later, when phasing out an older service worker.
      */
      .open(version + 'fundamentals')
      .then(function(cache) {
        /* After the cache is opened, we can fill it with the offline fundamentals.
           The method below will add all resources in `offlineFundamentals` to the
           cache, after making requests for them.
        */
        return cache.addAll(offlineFundamentals);
      })
      .then(function() {
        console.log('WORKER: install completed');
      })
  );
});

/* The fetch event fires whenever a page controlled by this service worker requests
   a resource. This isn't limited to `fetch` or even XMLHttpRequest. Instead, it
   comprehends even the request for the HTML page on first load, as well as JS and
   CSS resources, fonts, any images, etc.
*/
self.addEventListener("fetch", function(event) {
  console.log('WORKER: fetch event in progress.');

  /* We should only cache GET requests, and deal with the rest of method in the
     client-side, by handling failed POST,PUT,PATCH,etc. requests.
  */
  if (event.request.method !== 'GET') {
    /* If we don't block the event as shown below, then the request will go to
       the network as usual.
    */
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }
  /* Similar to event.waitUntil in that it blocks the fetch event on a promise.
     Fulfillment result will be used as the response, and rejection will end in a
     HTTP response indicating failure.
  */
  event.respondWith(
    caches
      /* This method returns a promise that resolves to a cache entry matching
         the request. Once the promise is settled, we can then provide a response
         to the fetch request.
      */
      .match(event.request)
      .then(function(cached) {
        /* Even if the response is in our cache, we go to the network as well.
           This pattern is known for producing "eventually fresh" responses,
           where we return cached responses immediately, and meanwhile pull
           a network response and store that in the cache.

           Read more:
           https://ponyfoo.com/articles/progressive-networking-serviceworker
        */
        var networked = fetch(event.request)
          // We handle the network request with success and failure scenarios.
          .then(fetchedFromNetwork, unableToResolve)
          // We should catch errors on the fetchedFromNetwork handler as well.
          .catch(unableToResolve);

        /* We return the cached response immediately if there is one, and fall
           back to waiting on the network as usual.
        */
        console.log('WORKER: fetch event', cached ? '(cached)' : '(network)', event.request.url);
        return cached || networked;

        function fetchedFromNetwork(response) {
          /* We copy the response before replying to the network request.
             This is the response that will be stored on the ServiceWorker cache.
          */
          var cacheCopy = response.clone();

          console.log('WORKER: fetch response from network.', event.request.url);

          caches
            // We open a cache to store the response for this request.
            .open(version + 'pages')
            .then(function add(cache) {
              /* We store the response for this request. It'll later become
                 available to caches.match(event.request) calls, when looking
                 for cached responses.
              */
              cache.put(event.request, cacheCopy);
            })
            .then(function() {
              console.log('WORKER: fetch response stored in cache.', event.request.url);
            });

          // Return the response so that the promise is settled in fulfillment.
          return response;
        }

        /* When this method is called, it means we were unable to produce a response
           from either the cache or the network. This is our opportunity to produce
           a meaningful response even when all else fails. It's the last chance, so
           you probably want to display a "Service Unavailable" view or a generic
           error response.
        */
        function unableToResolve () {
          /* There's a couple of things we can do here.
             - Test the Accept header and then return one of the `offlineFundamentals`
               e.g: `return caches.match('/some/cached/image.png')`
             - You should also consider the origin. It's easier to decide what
               "unavailable" means for requests against your origins than for requests
               against a third party, such as an ad provider.
             - Generate a Response programmaticaly, as shown below, and return that.
          */

          console.log('WORKER: fetch request failed in both cache and network.');

          /* Here we're creating a response programmatically. The first parameter is the
             response body, and the second one defines the options for the response.
          */
          return new Response('
Service Unavailable
', {
            status: 503,
            statusText: 'Service Unavailable',
            headers: new Headers({
              'Content-Type': 'text/html'
            })
          });
        }
      })
  );
});

/* The activate event fires after a service worker has been successfully installed.
   It is most useful when phasing out an older version of a service worker, as at
   this point you know that the new worker was installed correctly. In this example,
   we delete old caches that don't match the version in the worker we just finished
   installing.
*/
self.addEventListener("activate", function(event) {
  /* Just like with the install event, event.waitUntil blocks activate on a promise.
     Activation will fail unless the promise is fulfilled.
  */
  console.log('WORKER: activate event in progress.');

  event.waitUntil(
    caches
      /* This method returns a promise which will resolve to an array of available
         cache keys.
      */
      .keys()
      .then(function (keys) {
        // We return a promise that settles when all outdated caches are deleted.
        return Promise.all(
          keys
            .filter(function (key) {
              // Filter by keys that don't start with the latest version prefix.
              return !key.startsWith(version);
            })
            .map(function (key) {
              /* Return a promise that's fulfilled
                 when each outdated cache is deleted.
              */
              return caches.delete(key);
            })
        );
      })
      .then(function() {
        console.log('WORKER: activate completed.');
      })
  );
});
<commit_msg>[DEVOPS] Set CACHE_KEY<commit_after>// Making a Simple Site Work Offline with ServiceWorker | CSS-Tricks - http://bit.ly/2MvGURI

"use strict";

console.log('WORKER: executing.');

/* A version number is useful when updating the worker logic,
   allowing you to remove outdated cache entries during the update.
*/
var sha = '0243c31e0dafb1642e898a93709ce4ae0f058fbe';
var version = sha.substr(0, 8) + '::';

/* These resources will be downloaded and cached by the service worker
   during the installation process. If any resource fails to be downloaded,
   then the service worker won't be installed either.
*/
var offlineFundamentals = [
  './',
  './script.js',
  './theme.css',
  './presentation.md',
  './γλώσσα.js',
  './favicon.ico',
//'./books/aepp.pdf',
//'./books/tetradio.pdf',
//'./books/odigies-meletis-mathiti.pdf',
//'./books/pliroforiki.pdf'
];

/* The install event fires when the service worker is first installed.
   You can use this event to prepare the service worker to be able to serve
   files while visitors are offline.
*/
self.addEventListener("install", function(event) {
  console.log('WORKER: install event in progress.');
  /* Using event.waitUntil(p) blocks the installation process on the provided
     promise. If the promise is rejected, the service worker won't be installed.
  */
  event.waitUntil(
    /* The caches built-in is a promise-based API that helps you cache responses,
       as well as finding and deleting them.
    */
    caches
      /* You can open a cache by name, and this method returns a promise. We use
         a versioned cache name here so that we can remove old cache entries in
         one fell swoop later, when phasing out an older service worker.
      */
      .open(version + 'fundamentals')
      .then(function(cache) {
        /* After the cache is opened, we can fill it with the offline fundamentals.
           The method below will add all resources in `offlineFundamentals` to the
           cache, after making requests for them.
        */
        return cache.addAll(offlineFundamentals);
      })
      .then(function() {
        console.log('WORKER: install completed');
      })
  );
});

/* The fetch event fires whenever a page controlled by this service worker requests
   a resource. This isn't limited to `fetch` or even XMLHttpRequest. Instead, it
   comprehends even the request for the HTML page on first load, as well as JS and
   CSS resources, fonts, any images, etc.
*/
self.addEventListener("fetch", function(event) {
  console.log('WORKER: fetch event in progress.');

  /* We should only cache GET requests, and deal with the rest of method in the
     client-side, by handling failed POST,PUT,PATCH,etc. requests.
  */
  if (event.request.method !== 'GET') {
    /* If we don't block the event as shown below, then the request will go to
       the network as usual.
    */
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }
  /* Similar to event.waitUntil in that it blocks the fetch event on a promise.
     Fulfillment result will be used as the response, and rejection will end in a
     HTTP response indicating failure.
  */
  event.respondWith(
    caches
      /* This method returns a promise that resolves to a cache entry matching
         the request. Once the promise is settled, we can then provide a response
         to the fetch request.
      */
      .match(event.request)
      .then(function(cached) {
        /* Even if the response is in our cache, we go to the network as well.
           This pattern is known for producing "eventually fresh" responses,
           where we return cached responses immediately, and meanwhile pull
           a network response and store that in the cache.

           Read more:
           https://ponyfoo.com/articles/progressive-networking-serviceworker
        */
        var networked = fetch(event.request)
          // We handle the network request with success and failure scenarios.
          .then(fetchedFromNetwork, unableToResolve)
          // We should catch errors on the fetchedFromNetwork handler as well.
          .catch(unableToResolve);

        /* We return the cached response immediately if there is one, and fall
           back to waiting on the network as usual.
        */
        console.log('WORKER: fetch event', cached ? '(cached)' : '(network)', event.request.url);
        return cached || networked;

        function fetchedFromNetwork(response) {
          /* We copy the response before replying to the network request.
             This is the response that will be stored on the ServiceWorker cache.
          */
          var cacheCopy = response.clone();

          console.log('WORKER: fetch response from network.', event.request.url);

          caches
            // We open a cache to store the response for this request.
            .open(version + 'pages')
            .then(function add(cache) {
              /* We store the response for this request. It'll later become
                 available to caches.match(event.request) calls, when looking
                 for cached responses.
              */
              cache.put(event.request, cacheCopy);
            })
            .then(function() {
              console.log('WORKER: fetch response stored in cache.', event.request.url);
            });

          // Return the response so that the promise is settled in fulfillment.
          return response;
        }

        /* When this method is called, it means we were unable to produce a response
           from either the cache or the network. This is our opportunity to produce
           a meaningful response even when all else fails. It's the last chance, so
           you probably want to display a "Service Unavailable" view or a generic
           error response.
        */
        function unableToResolve () {
          /* There's a couple of things we can do here.
             - Test the Accept header and then return one of the `offlineFundamentals`
               e.g: `return caches.match('/some/cached/image.png')`
             - You should also consider the origin. It's easier to decide what
               "unavailable" means for requests against your origins than for requests
               against a third party, such as an ad provider.
             - Generate a Response programmaticaly, as shown below, and return that.
          */

          console.log('WORKER: fetch request failed in both cache and network.');

          /* Here we're creating a response programmatically. The first parameter is the
             response body, and the second one defines the options for the response.
          */
          return new Response('
Service Unavailable
', {
            status: 503,
            statusText: 'Service Unavailable',
            headers: new Headers({
              'Content-Type': 'text/html'
            })
          });
        }
      })
  );
});

/* The activate event fires after a service worker has been successfully installed.
   It is most useful when phasing out an older version of a service worker, as at
   this point you know that the new worker was installed correctly. In this example,
   we delete old caches that don't match the version in the worker we just finished
   installing.
*/
self.addEventListener("activate", function(event) {
  /* Just like with the install event, event.waitUntil blocks activate on a promise.
     Activation will fail unless the promise is fulfilled.
  */
  console.log('WORKER: activate event in progress.');

  event.waitUntil(
    caches
      /* This method returns a promise which will resolve to an array of available
         cache keys.
      */
      .keys()
      .then(function (keys) {
        // We return a promise that settles when all outdated caches are deleted.
        return Promise.all(
          keys
            .filter(function (key) {
              // Filter by keys that don't start with the latest version prefix.
              return !key.startsWith(version);
            })
            .map(function (key) {
              /* Return a promise that's fulfilled
                 when each outdated cache is deleted.
              */
              return caches.delete(key);
            })
        );
      })
      .then(function() {
        console.log('WORKER: activate completed.');
      })
  );
});
<|endoftext|>


<commit_before>/*
 * twitter-entities.js
 * This function converts a tweet with "entity" metadata
 * from plain text to linkified HTML.
 *
 * See the documentation here: http://dev.twitter.com/pages/tweet_entities
 * Basically, add ?include_entities=true to your timeline call
 *
 * Copyright 2010, Wade Simmons
 * Licensed under the MIT license
 * http://wades.im/mons
 *
 * Modified for SuccessWhale by Ian Renton
 *
 * Requires jQuery
 */

function linkify_entities(content) {

    // If we have an "escaped text", use it for preference as the entities are designed
    // to line up with this one.
    if (content.escapedtext) {
      content.text = content.escapedtext;
    }

    // This is very naive, should find a better way to parse this
    var index_map = {};

    // Replace links with properly linked HTML
    if (typeof content.links !== 'undefined') {
      $.each(content.links, function(i,entry) {
          if (typeof entry.indices !== 'undefined') {
              index_map[entry.indices[0]] = [entry.indices[1], function(text) {
                  // If there's a preview, this will be handled separately so just remove the section of the text that refers to it. Otherwise, preserve the text and link it up by appling an A tag.
                  if (typeof entry.preview === 'undefined') {
                    return ""+entry.title+"";
                  }
                  else {
                    return "";
                  }}];
          }
      });
    }

    // Replace hashtags with properly linked HTML
    if (typeof content.hashtags !== 'undefined') {
      $.each(content.hashtags, function(i,entry) {
          index_map[entry.indices[0]] = [entry.indices[1], function(text) {return "#"+entry.text+"";}];
      });
    }

    // Replace usernames with properly linked HTML
    if (typeof content.usernames !== 'undefined') {
      $.each(content.usernames, function(i,entry) {
          index_map[entry.indices[0]] = [entry.indices[1], function(text) {return "@"+entry.user+"";}];
      });
    }

    var result = "";
    var last_i = 0;
    var i = 0;

    // iterate through the string looking for matches in the index_map
    for (i=0; i < content.text.length; ++i) {
        var ind = index_map[i];
        if (ind) {
            var end = ind[0];
            var func = ind[1];
            if (i > last_i) {
                result += content.text.substring(last_i, i);
            }
            result += func(content.text.substring(i, end));
            i = end - 1;
            last_i = end;
        }
    }

    if (i > last_i) {
        result += content.text.substring(last_i, i);
    }

    // Add a "source" link if we just have a single link with no indices for replacing text
    if ((typeof content.links !== 'undefined') && (content.links.length===1) && (typeof content.links[0].indices === 'undefined')) {
      result += '
';
      if (content.links[0].title !== null) {
        result += content.links[0].title;
      }
      result += '';
    }

    // Add media previews
    if (content.links) {
      for (i=0; i<content.links.length; i++)
      {
        if (typeof content.links[i].preview !== 'undefined') {
          result += '

';
        }
      }
    }

    return result;
}
<commit_msg>Properly fix the Twitter entity / escaped item text bug<commit_after>/*
 * twitter-entities.js
 * This function converts a tweet with "entity" metadata
 * from plain text to linkified HTML.
 *
 * See the documentation here: http://dev.twitter.com/pages/tweet_entities
 * Basically, add ?include_entities=true to your timeline call
 *
 * Copyright 2010, Wade Simmons
 * Licensed under the MIT license
 * http://wades.im/mons
 *
 * Modified for SuccessWhale by Ian Renton
 *
 * Requires jQuery
 */

function linkify_entities(content) {

    // If we have an "escaped text", use it for preference as the entities are designed
    // to line up with this one.
    if (typeof content.escapedtext !== 'undefined') {
      itemtext = content.escapedtext;
    } else {
      itemtext = content.text;
    }

    // This is very naive, should find a better way to parse this
    var index_map = {};

    // Replace links with properly linked HTML
    if (typeof content.links !== 'undefined') {
      $.each(content.links, function(i,entry) {
          if (typeof entry.indices !== 'undefined') {
              index_map[entry.indices[0]] = [entry.indices[1], function(itemtext) {
                  // If there's a preview, this will be handled separately so just remove the section of the text that refers to it. Otherwise, preserve the text and link it up by appling an A tag.
                  if (typeof entry.preview === 'undefined') {
                    return ""+entry.title+"";
                  }
                  else {
                    return "";
                  }}];
          }
      });
    }

    // Replace hashtags with properly linked HTML
    if (typeof content.hashtags !== 'undefined') {
      $.each(content.hashtags, function(i,entry) {
          index_map[entry.indices[0]] = [entry.indices[1], function(itemtext) {return "#"+entry.text+"";}];
      });
    }

    // Replace usernames with properly linked HTML
    if (typeof content.usernames !== 'undefined') {
      $.each(content.usernames, function(i,entry) {
          index_map[entry.indices[0]] = [entry.indices[1], function(itemtext) {return "@"+entry.user+"";}];
      });
    }

    var result = "";
    var last_i = 0;
    var i = 0;

    // iterate through the string looking for matches in the index_map
    for (i=0; i < itemtext.length; ++i) {
        var ind = index_map[i];
        if (ind) {
            var end = ind[0];
            var func = ind[1];
            if (i > last_i) {
                result += itemtext.substring(last_i, i);
            }
            result += func(itemtext.substring(i, end));
            i = end - 1;
            last_i = end;
        }
    }

    if (i > last_i) {
        result += itemtext.substring(last_i, i);
    }

    // Add a "source" link if we just have a single link with no indices for replacing text
    if ((typeof content.links !== 'undefined') && (content.links.length===1) && (typeof content.links[0].indices === 'undefined')) {
      result += '
';
      if (content.links[0].title !== null) {
        result += content.links[0].title;
      }
      result += '';
    }

    // Add media previews
    if (content.links) {
      for (i=0; i<content.links.length; i++)
      {
        if (typeof content.links[i].preview !== 'undefined') {
          result += '

';
        }
      }
    }

    return result;
}
<|endoftext|>


<commit_before>
'use strict';
module.exports =
  angular
  .module('diUser.service', [])
  .factory('userService', function() {

  var
    defaults = {
      enableAutoSave:   true,
      enableWordsCount: true,
      enableNightMode:  false
    },
    service = {
      profile: {},
      save:    save,
      restore: restore
    };

  service.restore();

  return service;

  //////////////////////////////

  function save() {
    localStorage.setItem('profile', angular.toJson(service.profile));
  }

  function restore() {
    service.profile = angular.fromJson(localStorage.getItem('profile')) || defaults;
    return service.profile;
  }

});
<commit_msg>fix parsing old profile of v2<commit_after>
'use strict';
module.exports =
  angular
  .module('diUser.service', [])
  .factory('userService', function(diNotify) {

  var
    defaults = {
      enableAutoSave:   true,
      enableWordsCount: true,
      enableNightMode:  false
    },
    service = {
      profile: {},
      save:    save,
      restore: restore
    };

  service.restore();

  return service;

  //////////////////////////////

  function save() {
    localStorage.setItem('profileV3', angular.toJson(service.profile));
  }

  function restore() {
    service.profile = angular.fromJson(localStorage.getItem('profileV3')) || defaults;
    return service.profile;
  }

});
<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

wn.ui.toolbar.Toolbar = Class.extend({
	init: function() {
		this.make();
		//this.make_modules();
		this.make_file();
		wn.ui.toolbar.recent = new wn.ui.toolbar.RecentDocs();
		wn.ui.toolbar.bookmarks = new wn.ui.toolbar.Bookmarks();
		this.make_tools();
		this.set_user_name();
		this.make_logout();
		this.make_notification();

		$('.dropdown-toggle').dropdown();

		$(document).trigger('toolbar_setup');

		// clear all custom menus on page change
		$(document).on("page-change", function() {
			$("header .navbar .custom-menu").remove();
		})
	},
	make: function() {
		$('header').append('
\

\

\
					<button type="button" class="navbar-toggle" data-toggle="collapse" \
						data-target=".navbar-responsive-collapse">\
						\
						\
						\
					</button>\
					\

\

\

\

\
					\

\

\
							\

\

\

\

\

\

\

');
	},
	make_home: function() {
		$('.navbar-brand').attr('href', "#");
	},

	make_notification: function() {
		$('.navbar .navbar-right').append('
\
			0\

\

\

');

		$(document).on("notification-update", function() {
			wn.ui.toolbar.update_notifications();
		})
	},

	// make_modules: function() {
	// 	$('
\
	// 		'+wn._("Modules")+'\
	//
\
	//
\
	//
').prependTo('.navbar .nav:first');
	//
	// 	var modules_list = wn.user.get_desktop_items().sort();
	// 	var menu_list = $(".navbar .modules");
	//
	// 	var _get_list_item = function(m) {
	// 		args = {
	// 			module: m,
	// 			module_page: wn.modules[m].link,
	// 			module_label: wn._(wn.modules[m].label || m),
	// 			icon: wn.modules[m].icon
	// 		}
	//
	// 		return repl('
\
	// 			%(module_label)s
', args);
	// 	}
	//
	// 	// desktop
	// 	$('
 '
	// 		+ wn._("Desktop") + '
\
	//

').appendTo(menu_list)
	//
	// 	// add to dropdown
	// 	$.each(modules_list,function(i, m) {
	// 		if(m!='Setup') {
	// 			menu_list.append(_get_list_item(m));
	// 		}
	// 	})
	//
	// 	// setup for system manager
	// 	if(user_roles.indexOf("System Manager")!=-1) {
	// 		menu_list.append('
' + _get_list_item("Setup"));
	// 	}
	//
	// },

	make_file: function() {
		wn.ui.toolbar.new_dialog = new wn.ui.toolbar.NewDialog();
		wn.ui.toolbar.search = new wn.ui.toolbar.Search();
		wn.ui.toolbar.report = new wn.ui.toolbar.Report();
		$('.navbar .nav:first').append('
\
			'+wn._("File")+'\

\

\
					 '+wn._('New')+'...
\

\
					 '+wn._('Search')+'...
\

\
					 '+wn._('Report')+'...
\

\

');
	},

	make_tools: function() {
		$('.navbar .nav:first').append('
\
			'+wn._("Tools")+'\

\

\
					 '
					+wn._('Clear Cache & Refresh')+'
\

\
					 '
					+wn._('About')+'
\

 '
					+wn._('Attributions')+'
\

\

');

		if(has_common(user_roles,['Administrator','System Manager'])) {
			$('#toolbar-tools').append('
 '
				+wn._('Download Backup')+'
');
		}
	},
	set_user_name: function() {
		var fn = user_fullname;
		if(fn.length > 15) fn = fn.substr(0,12) + '...';
		$('#toolbar-user-link').html(fn + '');
	},

	make_logout: function() {
		// logout
		$('#toolbar-user').append('
\
			 '+wn._('Logout')+'
');
	}
});

wn.ui.toolbar.update_notifications = function() {
	var total = 0;
	var doctypes = keys(wn.boot.notification_info.open_count_doctype).sort();
	var modules = keys(wn.boot.notification_info.open_count_module).sort();

	$("#navbar-notification").empty();

	$.each(modules, function(i, module) {
		var count = wn.boot.notification_info.open_count_module[module];
		if(count) {
			$(repl('
\
				\
					%(count)s \
				 %(module)s
', {
					module: module,
					count: count,
					icon: wn.modules[module].icon
				}))
				.appendTo("#navbar-notification")
					.find("a")
					.attr("data-module", module)
					.css({"min-width":"200px"})
					.on("click", function() {
						wn.set_route(wn.modules[$(this).attr("data-module")].link);
					});
			total += count;
		}
	});

	if(total) {
		$('

').appendTo("#navbar-notification");
	}

	$.each(doctypes, function(i, doctype) {
		var count = wn.boot.notification_info.open_count_doctype[doctype];
		if(count) {
			$(repl('
\
				\
					%(count)s \
				 %(doctype)s
', {
					doctype: doctype,
					icon: wn.boot.doctype_icons[doctype],
					count: count
				}))
				.appendTo("#navbar-notification")
					.find("a")
					.attr("data-doctype", doctype)
					.css({"min-width":"200px"})
					.on("click", function() {
						wn.views.show_open_count_list(this);
					});
			total += count;
		}
	});

	$(".navbar-new-comments")
		.html(total)
		.toggleClass("navbar-new-comments-true", total ? true : false);

}

wn.ui.toolbar.clear_cache = function() {
	localStorage && localStorage.clear();
	$c('webnotes.sessions.clear',{},function(r,rt){
		if(!r.exc) {
			show_alert(r.message);
			location.reload();
		}
	});
	return false;
}

wn.ui.toolbar.download_backup = function() {
	msgprint(wn._("Your download is being built, this may take a few moments..."));
	return $c('webnotes.utils.backups.get_backup',{},function(r,rt) {});
	return false;
}

wn.ui.toolbar.show_about = function() {
	try {
		wn.ui.misc.about();
	} catch(e) {
		console.log(e);
	}
	return false;
}

wn.ui.toolbar.show_banner = function(msg) {
	return $('

').html(msg).appendTo($('header'));
}<commit_msg>[minor] fixed erpnext.org urls<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

wn.ui.toolbar.Toolbar = Class.extend({
	init: function() {
		this.make();
		//this.make_modules();
		this.make_file();
		wn.ui.toolbar.recent = new wn.ui.toolbar.RecentDocs();
		wn.ui.toolbar.bookmarks = new wn.ui.toolbar.Bookmarks();
		this.make_tools();
		this.set_user_name();
		this.make_logout();
		this.make_notification();

		$('.dropdown-toggle').dropdown();

		$(document).trigger('toolbar_setup');

		// clear all custom menus on page change
		$(document).on("page-change", function() {
			$("header .navbar .custom-menu").remove();
		})
	},
	make: function() {
		$('header').append('
\

\

\
					<button type="button" class="navbar-toggle" data-toggle="collapse" \
						data-target=".navbar-responsive-collapse">\
						\
						\
						\
					</button>\
					\

\

\

\

\
					\

\

\
							\

\

\

\

\

\

\

');
	},
	make_home: function() {
		$('.navbar-brand').attr('href', "#");
	},

	make_notification: function() {
		$('.navbar .navbar-right').append('
\
			0\

\

\

');

		$(document).on("notification-update", function() {
			wn.ui.toolbar.update_notifications();
		})
	},

	// make_modules: function() {
	// 	$('
\
	// 		'+wn._("Modules")+'\
	//
\
	//
\
	//
').prependTo('.navbar .nav:first');
	//
	// 	var modules_list = wn.user.get_desktop_items().sort();
	// 	var menu_list = $(".navbar .modules");
	//
	// 	var _get_list_item = function(m) {
	// 		args = {
	// 			module: m,
	// 			module_page: wn.modules[m].link,
	// 			module_label: wn._(wn.modules[m].label || m),
	// 			icon: wn.modules[m].icon
	// 		}
	//
	// 		return repl('
\
	// 			%(module_label)s
', args);
	// 	}
	//
	// 	// desktop
	// 	$('
 '
	// 		+ wn._("Desktop") + '
\
	//

').appendTo(menu_list)
	//
	// 	// add to dropdown
	// 	$.each(modules_list,function(i, m) {
	// 		if(m!='Setup') {
	// 			menu_list.append(_get_list_item(m));
	// 		}
	// 	})
	//
	// 	// setup for system manager
	// 	if(user_roles.indexOf("System Manager")!=-1) {
	// 		menu_list.append('
' + _get_list_item("Setup"));
	// 	}
	//
	// },

	make_file: function() {
		wn.ui.toolbar.new_dialog = new wn.ui.toolbar.NewDialog();
		wn.ui.toolbar.search = new wn.ui.toolbar.Search();
		wn.ui.toolbar.report = new wn.ui.toolbar.Report();
		$('.navbar .nav:first').append('
\
			'+wn._("File")+'\

\

\
					 '+wn._('New')+'...
\

\
					 '+wn._('Search')+'...
\

\
					 '+wn._('Report')+'...
\

\

');
	},

	make_tools: function() {
		$('.navbar .nav:first').append('
\
			'+wn._("Tools")+'\

\

\
					 '
					+wn._('Clear Cache & Refresh')+'
\

\
					 '
					+wn._('About')+'
\

 '
					+wn._('Attributions')+'
\

\

');

		if(has_common(user_roles,['Administrator','System Manager'])) {
			$('#toolbar-tools').append('
 '
				+wn._('Download Backup')+'
');
		}
	},
	set_user_name: function() {
		var fn = user_fullname;
		if(fn.length > 15) fn = fn.substr(0,12) + '...';
		$('#toolbar-user-link').html(fn + '');
	},

	make_logout: function() {
		// logout
		$('#toolbar-user').append('
\
			 '+wn._('Logout')+'
');
	}
});

wn.ui.toolbar.update_notifications = function() {
	var total = 0;
	var doctypes = keys(wn.boot.notification_info.open_count_doctype).sort();
	var modules = keys(wn.boot.notification_info.open_count_module).sort();

	$("#navbar-notification").empty();

	$.each(modules, function(i, module) {
		var count = wn.boot.notification_info.open_count_module[module];
		if(count) {
			$(repl('
\
				\
					%(count)s \
				 %(module)s
', {
					module: module,
					count: count,
					icon: wn.modules[module].icon
				}))
				.appendTo("#navbar-notification")
					.find("a")
					.attr("data-module", module)
					.css({"min-width":"200px"})
					.on("click", function() {
						wn.set_route(wn.modules[$(this).attr("data-module")].link);
					});
			total += count;
		}
	});

	if(total) {
		$('

').appendTo("#navbar-notification");
	}

	$.each(doctypes, function(i, doctype) {
		var count = wn.boot.notification_info.open_count_doctype[doctype];
		if(count) {
			$(repl('
\
				\
					%(count)s \
				 %(doctype)s
', {
					doctype: doctype,
					icon: wn.boot.doctype_icons[doctype],
					count: count
				}))
				.appendTo("#navbar-notification")
					.find("a")
					.attr("data-doctype", doctype)
					.css({"min-width":"200px"})
					.on("click", function() {
						wn.views.show_open_count_list(this);
					});
			total += count;
		}
	});

	$(".navbar-new-comments")
		.html(total)
		.toggleClass("navbar-new-comments-true", total ? true : false);

}

wn.ui.toolbar.clear_cache = function() {
	localStorage && localStorage.clear();
	$c('webnotes.sessions.clear',{},function(r,rt){
		if(!r.exc) {
			show_alert(r.message);
			location.reload();
		}
	});
	return false;
}

wn.ui.toolbar.download_backup = function() {
	msgprint(wn._("Your download is being built, this may take a few moments..."));
	return $c('webnotes.utils.backups.get_backup',{},function(r,rt) {});
	return false;
}

wn.ui.toolbar.show_about = function() {
	try {
		wn.ui.misc.about();
	} catch(e) {
		console.log(e);
	}
	return false;
}

wn.ui.toolbar.show_banner = function(msg) {
	return $('

').html(msg).appendTo($('header'));
}<|endoftext|>


<commit_before>/**
 * Namespace: Util.OSM
 */
OpenLayers.Util.OSM = {};

/**
 * Constant: MISSING_TILE_URL
 * {String} URL of image to display for missing tiles
 */
OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png";

/**
 * Property: originalOnImageLoadError
 * {Function} Original onImageLoadError function.
 */
OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;

/**
 * Function: onImageLoadError
 */
OpenLayers.Util.onImageLoadError = function() {
    if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
        this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
    } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
        // do nothing - this layer is transparent
    } else {
        OpenLayers.Util.OSM.originalOnImageLoadError;
    }
};

/**
 * Class: OpenLayers.Layer.OSM.Mapnik
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.Mapnik
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
            "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
            "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
});

/**
 * Class: OpenLayers.Layer.OSM.Osmarender
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.Osmarender
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
            "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
            "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 18, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
});

/**
 * Class: OpenLayers.Layer.OSM.CycleMap
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.CycleMap
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png",
            "http://b.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png",
            "http://c.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
});
<commit_msg>Update cyclemap layer to use new tile server<commit_after>/**
 * Namespace: Util.OSM
 */
OpenLayers.Util.OSM = {};

/**
 * Constant: MISSING_TILE_URL
 * {String} URL of image to display for missing tiles
 */
OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png";

/**
 * Property: originalOnImageLoadError
 * {Function} Original onImageLoadError function.
 */
OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;

/**
 * Function: onImageLoadError
 */
OpenLayers.Util.onImageLoadError = function() {
    if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
        this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
    } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
        // do nothing - this layer is transparent
    } else {
        OpenLayers.Util.OSM.originalOnImageLoadError;
    }
};

/**
 * Class: OpenLayers.Layer.OSM.Mapnik
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.Mapnik
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
            "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
            "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
});

/**
 * Class: OpenLayers.Layer.OSM.Osmarender
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.Osmarender
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
            "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
            "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 18, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
});

/**
 * Class: OpenLayers.Layer.OSM.CycleMap
 *
 * Inherits from:
 *  - <OpenLayers.Layer.OSM>
 */
OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
    /**
     * Constructor: OpenLayers.Layer.OSM.CycleMap
     *
     * Parameters:
     * name - {String}
     * options - {Object} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, options) {
        var url = [
            "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
            "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
            "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"
        ];
        options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
        var newArguments = [name, url, options];
        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
    },

    CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
});
<|endoftext|>


<commit_before>import _ from 'lodash';
import AggResponseTabifyTabifyProvider from 'ui/agg_response/tabify/tabify';
import uiModules from 'ui/modules';
import chrome from 'ui/chrome';
const Mustache = require('mustache')
const module = uiModules.get('kibana/transform_vis', ['kibana']);

require('plugins/transform_vis/directives/refresh_hack');

module.controller('TransformVisController', function ($scope, $sce, Private, timefilter, es, config, indexPatterns) {

    const queryFilter = Private(require('ui/filter_bar/query_filter'));
    const dashboardContext = Private(require('plugins/timelion/services/dashboard_context'));

    $scope.options = chrome.getInjected('transformVisOptions');

    $scope.refreshConfig = function() {

	indexPatterns.get($scope.vis.params.outputs.indexpattern).then( function (indexPattern) {
		$scope.vis.indexPattern = indexPattern;
	}).then($scope.search);

    }

    $scope.search = function() {

	console.log("preparing search");
	var context = dashboardContext();
	var index = $scope.vis.params.outputs.indexpattern;

	// This is part of what should be a wider config validation
	if (!(typeof index === 'string' || index instanceof String)) {
		$scope.vis.display = "No Index Pattern";
		return;
        }

	if ($scope.vis.indexPattern.timeFieldName) {
	 const timefilterdsl = { range:{} };
	 timefilterdsl.range[$scope.vis.indexPattern.timeFieldName] = { gte: timefilter.time.from, lte: timefilter.time.to };
	 context.bool.must.push(timefilterdsl);
	}

        var body = $scope.vis.params.outputs.querydsl.replace("\"_DASHBOARD_CONTEXT_\"",JSON.stringify(context));

	es.search({
		index: index,
		body: JSON.parse(body)
	}, function (error, response) {
		if (error) {
		 $scope.vis.display = "Error (See Console)";
		 console.log("Elasticsearch Query Error", error);
		} else {
	          if ($scope.options.allow_unsafe) {
			response.meta = eval($scope.vis.params.outputs.meta);
	   	  }
		  var formula = $scope.vis.params.outputs.formula;
                  $scope.vis.display = Mustache.render(formula, response);
		}
	});

    };

    $scope.$watchCollection('vis.params.outputs', $scope.refreshConfig);

     // When the expression updates
    $scope.$watchMulti(['vis.params.expression', 'vis.params.interval'], $scope.search);

    // When the time filter changes
    $scope.$listen(timefilter, 'fetch', $scope.search);

    // When a filter is added to the filter bar?
    $scope.$listen(queryFilter, 'fetch', $scope.search);

    // When auto refresh happens
    $scope.$on('courier:searchRefresh', $scope.search);

    // From the hack directive
    $scope.$on('fetch', $scope.search);

    $scope.$on('renderComplete', event => {
      event.stopPropagation();
      $element.trigger('renderComplete');
    });

});

module.controller('TransformVisEditorController', function ($scope, indexPatterns) {

    $scope.options = chrome.getInjected('transformVisOptions');

    indexPatterns.getIds().then( function(list) {
	    $scope.indexPatternOptions = list;
    });;

   $scope.$watch('vis.params.outputs.indexpattern', function() {
	    indexPatterns.get($scope.vis.params.outputs.indexpattern).then( function (indexPattern) {
		$scope.savedVis.searchSource.set('index', indexPattern);
		$scope.vis.indexPattern = indexPattern;
	    });;
    });

});
<commit_msg>removed debug<commit_after>import _ from 'lodash';
import AggResponseTabifyTabifyProvider from 'ui/agg_response/tabify/tabify';
import uiModules from 'ui/modules';
import chrome from 'ui/chrome';
const Mustache = require('mustache')
const module = uiModules.get('kibana/transform_vis', ['kibana']);

require('plugins/transform_vis/directives/refresh_hack');

module.controller('TransformVisController', function ($scope, $sce, Private, timefilter, es, config, indexPatterns) {

    const queryFilter = Private(require('ui/filter_bar/query_filter'));
    const dashboardContext = Private(require('plugins/timelion/services/dashboard_context'));

    $scope.options = chrome.getInjected('transformVisOptions');

    $scope.refreshConfig = function() {

	indexPatterns.get($scope.vis.params.outputs.indexpattern).then( function (indexPattern) {
		$scope.vis.indexPattern = indexPattern;
	}).then($scope.search);

    }

    $scope.search = function() {

	var context = dashboardContext();
	var index = $scope.vis.params.outputs.indexpattern;

	// This is part of what should be a wider config validation
	if (!(typeof index === 'string' || index instanceof String)) {
		$scope.vis.display = "No Index Pattern";
		return;
        }

	if ($scope.vis.indexPattern.timeFieldName) {
	 const timefilterdsl = { range:{} };
	 timefilterdsl.range[$scope.vis.indexPattern.timeFieldName] = { gte: timefilter.time.from, lte: timefilter.time.to };
	 context.bool.must.push(timefilterdsl);
	}

        var body = $scope.vis.params.outputs.querydsl.replace("\"_DASHBOARD_CONTEXT_\"",JSON.stringify(context));

	es.search({
		index: index,
		body: JSON.parse(body)
	}, function (error, response) {
		if (error) {
		 $scope.vis.display = "Error (See Console)";
		 console.log("Elasticsearch Query Error", error);
		} else {
	          if ($scope.options.allow_unsafe) {
			response.meta = eval($scope.vis.params.outputs.meta);
	   	  }
		  var formula = $scope.vis.params.outputs.formula;
                  $scope.vis.display = Mustache.render(formula, response);
		}
	});

    };

    $scope.$watchCollection('vis.params.outputs', $scope.refreshConfig);

     // When the expression updates
    $scope.$watchMulti(['vis.params.expression', 'vis.params.interval'], $scope.search);

    // When the time filter changes
    $scope.$listen(timefilter, 'fetch', $scope.search);

    // When a filter is added to the filter bar?
    $scope.$listen(queryFilter, 'fetch', $scope.search);

    // When auto refresh happens
    $scope.$on('courier:searchRefresh', $scope.search);

    // From the hack directive
    $scope.$on('fetch', $scope.search);

    $scope.$on('renderComplete', event => {
      event.stopPropagation();
      $element.trigger('renderComplete');
    });

});

module.controller('TransformVisEditorController', function ($scope, indexPatterns) {

    $scope.options = chrome.getInjected('transformVisOptions');

    indexPatterns.getIds().then( function(list) {
	    $scope.indexPatternOptions = list;
    });;

   $scope.$watch('vis.params.outputs.indexpattern', function() {
	    indexPatterns.get($scope.vis.params.outputs.indexpattern).then( function (indexPattern) {
		$scope.savedVis.searchSource.set('index', indexPattern);
		$scope.vis.indexPattern = indexPattern;
	    });;
    });

});
<|endoftext|>


<commit_before>import WRISerializer from 'wri-json-api-serializer';

// utils
import { WRIAPI } from 'utils/axios';
import { logger } from 'utils/logs';

/**
 * Get all tags
 */
export const fetchAllTags = (params = {
  env: process.env.API_ENV,
  application: process.application.APPLICATIONS
}) => {
  logger.info('Fetch all tags');
  return WRIAPI.get('graph/query/list-concepts',
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    }
  )
  .then(response => WRISerializer(response.data))
  .catch((response) => {
    const { status, statusText } = response;
    logger.error(`Error fetching all tags: ${status}: ${statusText}`);
    throw new Error(`Error fetching all tags: ${status}: ${statusText}`);
  });
};

/**
 * Get inferred tags
 */
export const fetchInferredTags = (tags) => {
  logger.info('Fetch inferred tags');
  return WRIAPI.get('graph/query/concepts-inferred?concepts=${tags}',
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    }
  )
  .then(response => WRISerializer(response.data))
  .catch((response) => {
    const { status, statusText } = response;
    logger.error(`Error fetching inferred tags: ${tags} ${status}: ${statusText}`);
    throw new Error(`Error inferred tags: ${tags} ${status}: ${statusText}`);
  });
};

/**
* Get dataset tags
*/
export const fetchDatasetTags = (datasetId, params = {
  env: process.env.API_ENV,
  application: process.application.APPLICATIONS
}) => {
  logger.info(`Fetch dataset tags: ${datasetId}`);
  return WRIAPI.get('dataset/${datasetId}/vocabulary',
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    }
  )
  .then(response => WRISerializer(response.data))
  .catch((response) => {
    const { status, statusText } = response;
    logger.error(`Error fetching dataset tags ${datasetId}: ${status}: ${statusText}`);
    throw new Error(`Error fetching dataset tags ${datasetId}: ${status}: ${statusText}`);
  });
};

/**
* Update dataset tags
*/
export const updateDatasetTags = (datasetId, tags, token, usePatch = false) => {
  logger.info(`Update dataset tags: ${datasetId}`);

  if (usePatch) {
    return WRIAPI.patch(`dataset/${datasetId}/vocabulary/knowledge_graph`,
      {
        tags,
        application: process.env.APPLICATIONS,
        env: process.env.API_ENV
      },
      { Authorization: token })
      .then(response => WRISerializer(response.data))
      .catch((response) => {
        const { status, statusText } = response;
        logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
        throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
      });
  } else {
    if (tags.length > 0) {
      return WRIAPI.put(`dataset/${datasetId}/vocabulary`,
        {
          knowledge_graph: {
            tags,
            application: process.env.APPLICATIONS,
            env: process.env.API_ENV
          }
        },
        { Authorization: token })
        .then(response => WRISerializer(response.data))
        .catch((response) => {
          const { status, statusText } = response;
          logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
          throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
        });
    } else {
      return WRIAPI.delete(`dataset/${datasetId}/vocabulary/knowledge_graph`,
        {
          headers: {
            Authorization: token
          },
          params: {
            application: process.env.APPLICATIONS,
            env: process.env.API_ENV
          }
        })
        .then(response => WRISerializer(response.data))
        .catch((response) => {
          const { status, statusText } = response;
          logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
          throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
        });
    }
  }
};

/**
 * Send a request to count a view to the dataset
 * @param {string} datasetId Dataset ID
 * @param {string} [token] User token
 * @returns {Promise<void>}
 */
export const countDatasetView = (datasetId, token, params = {
  env: process.env.API_ENV,
  application: process.env.APPLICATIONS
}) => {
  logger.info('Count dataset view');
  return WRIAPI.post(`graph/dataset/${datasetId}/visited`,
    {},
    {
      headers: {
        Authorization: token
      },
      params
    }
  ).catch((response) => {
    const { status, statusText } = response;
    logger.error(`Error in count dataset view ${datasetId}: ${status}: ${statusText}`);
    throw new Error(`Error in count dataset view ${datasetId}: ${status}: ${statusText}`);
  });;
};

/**
 * Get the list of most viewed datasets
 * @returns {Promise<string[]>} List of sorted ids
 */
getMostViewedDatasets() {
  return fetch(
    `${process.env.WRI_API_URL}/graph/query/most-viewed?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
    { headers: { 'Upgrade-Insecure-Requests': 1 } }

  )
    .then((res) => {
      if (res.ok) return res.json();
      throw new Error('Unable to fetch the most viewed datasets');
    })
    .then(res => res.data.map(d => d.dataset));
}

/**
 * Get the list of most favourited datasets
 * @returns {Promise<string[]>} List of sorted ids
 */
getMostFavoritedDatasets() {
  return fetch(
    `${process.env.WRI_API_URL}/graph/query/most-liked-datasets?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
    { headers: { 'Upgrade-Insecure-Requests': 1 } }

  )
    .then((res) => {
      if (res.ok) return res.json();
      throw new Error('Unable to fetch the most favourited datasets');
    })
    .then(res => res.data.map(d => d.id));
}

export default {
  fetchMostViewedDatasets,
  fetchMostFavoritedDatasets,
  countDatasetView,
  updateDatasetTags,
  fetchDatasetTags,
  fetchInferredTags,
  fetchAllTags
};
<commit_msg>all endpoints from graph service refactored<commit_after>import WRISerializer from 'wri-json-api-serializer';

// utils
import { WRIAPI } from 'utils/axios';
import { logger } from 'utils/logs';

/**
 * Get all tags
 */
export const fetchAllTags = (params = {
  env: process.env.API_ENV,
  application: process.application.APPLICATIONS
}) => {
  logger.info('Fetch all tags');
  return WRIAPI.get('graph/query/list-concepts',
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error fetching all tags: ${status}: ${statusText}`);
      throw new Error(`Error fetching all tags: ${status}: ${statusText}`);
    });
};

/**
 * Get inferred tags
 */
export const fetchInferredTags = (tags, params = {
  application: process.env.APPLICATIONS,
  env: process.env.API_ENV
}) => {
  logger.info('Fetch inferred tags');
  return WRIAPI.get(`graph/query/concepts-inferred?concepts=${tags}`,
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error fetching inferred tags: ${tags} ${status}: ${statusText}`);
      throw new Error(`Error inferred tags: ${tags} ${status}: ${statusText}`);
    });
};

/**
* Get dataset tags
*/
export const fetchDatasetTags = (datasetId, params = {
  env: process.env.API_ENV,
  application: process.application.APPLICATIONS
}) => {
  logger.info(`Fetch dataset tags: ${datasetId}`);
  return WRIAPI.get(`dataset/${datasetId}/vocabulary`,
    {
      headers: { 'Upgrade-Insecure-Requests': 1 },
      params
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error fetching dataset tags ${datasetId}: ${status}: ${statusText}`);
      throw new Error(`Error fetching dataset tags ${datasetId}: ${status}: ${statusText}`);
    });
};

/**
* Update dataset tags
*/
export const updateDatasetTags = (datasetId, tags, token, usePatch = false) => {
  logger.info(`Update dataset tags: ${datasetId}`);

  if (usePatch) {
    return WRIAPI.patch(`dataset/${datasetId}/vocabulary/knowledge_graph`,
      {
        tags,
        application: process.env.APPLICATIONS,
        env: process.env.API_ENV
      },
      { Authorization: token })
      .then(response => WRISerializer(response.data))
      .catch((response) => {
        const { status, statusText } = response;
        logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
        throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
      });
  }
  if (tags.length > 0) {
    return WRIAPI.put(`dataset/${datasetId}/vocabulary`,
      {
        knowledge_graph: {
          tags,
          application: process.env.APPLICATIONS,
          env: process.env.API_ENV
        }
      },
      { Authorization: token })
      .then(response => WRISerializer(response.data))
      .catch((response) => {
        const { status, statusText } = response;
        logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
        throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
      });
  }
  return WRIAPI.delete(`dataset/${datasetId}/vocabulary/knowledge_graph`,
    {
      headers: { Authorization: token },
      params: {
        application: process.env.APPLICATIONS,
        env: process.env.API_ENV
      }
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
      throw new Error(`Error updating dataset tags ${datasetId}: ${status}: ${statusText}`);
    });
};

/**
 * Send a request to count a view to the dataset
 * @param {string} datasetId Dataset ID
 * @param {string} [token] User token
 * @returns {Promise<void>}
 */
export const countDatasetView = (datasetId, token, params = {
  env: process.env.API_ENV,
  application: process.env.APPLICATIONS
}) => {
  logger.info('Count dataset view');
  return WRIAPI.post(`graph/dataset/${datasetId}/visited`,
    {},
    {
      headers: { Authorization: token },
      params
    })
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error in count dataset view ${datasetId}: ${status}: ${statusText}`);
      throw new Error(`Error in count dataset view ${datasetId}: ${status}: ${statusText}`);
    });
};

/**
 * Get the list of most viewed datasets
 * @returns {Promise<string[]>} List of sorted ids
 */
export const fetchMostViewedDatasets = (params = {
  env: process.env.API_ENV,
  application: process.env.APPLICATIONS
}) => {
  logger.info('Fetch most viewed datasets');
  return WRIAPI.get('graph/query/most-viewed',
    {
      params,
      headers: { 'Upgrade-Insecure-Requests': 1 }
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error fetching most viewed datasets: ${status}: ${statusText}`);
      throw new Error(`Error fetching most viewed datasets: ${status}: ${statusText}`);
    });
};

/**
 * Get the list of most favourited datasets
 * @returns {Promise<string[]>} List of sorted ids
 */
export const fetchMostFavoritedDatasets = (params = {
  env: process.env.API_ENV,
  application: process.env.APPLICATIONS
}) => {
  logger.info('Fetch most favorited datasets');
  return WRIAPI.get('graph/query/most-liked-datasets',
    {
      params,
      headers: { 'Upgrade-Insecure-Requests': 1 }
    })
    .then(response => WRISerializer(response.data))
    .catch((response) => {
      const { status, statusText } = response;
      logger.error(`Error fetching most favorited datasets: ${status}: ${statusText}`);
      throw new Error(`Error fetching most favorited datasets: ${status}: ${statusText}`);
    });
};

export default {
  fetchMostViewedDatasets,
  fetchMostFavoritedDatasets,
  countDatasetView,
  updateDatasetTags,
  fetchDatasetTags,
  fetchInferredTags,
  fetchAllTags
};
<|endoftext|>


<commit_before>import 'isomorphic-fetch';
import { get, post } from 'utils/request';
import WRISerializer from 'wri-json-api-serializer';

// utils
import { WRIAPI } from 'utils/axios';
import { logger } from 'utils/logs';

export default class LayersService {
  constructor(options = {}) {
    this.opts = options;
  }

  // getColumns({ dataset }) {
  //   return new Promise((resolve, reject) => {
  //     get({
  //       url: `${process.env.WRI_API_URL}/fields/${dataset}?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
  //       headers: [{
  //         key: 'Content-Type',
  //         value: 'application/json'
  //       }, {
  //         key: 'Authorization',
  //         value: this.opts.authorization
  //       }],
  //       onSuccess: (response) => {
  //         const fieldsObj = response.fields;

  //         const parsedData = {
  //           tableName: response.tableName,
  //           fields: ((fieldsObj && Object.keys(fieldsObj)) || []).map((fKey) => {
  //             const { type } = fieldsObj[fKey] || null;
  //             return { label: fKey || '', value: fKey || '', type };
  //           })
  //         };
  //         resolve({ ...parsedData });
  //       },
  //       onError: (error) => {
  //         reject(error);
  //       }
  //     });
  //   });
  // }

  saveData({ type, body, id, dataset }) {
    return new Promise((resolve, reject) => {
      post({
        url: `${process.env.WRI_API_URL}/dataset/${dataset}/layer/${id}`,
        type,
        body: {
          ...body,
          ...type !== 'PATCH' && { application: [process.env.APPLICATIONS] }
        },
        headers: [{
          key: 'Content-Type',
          value: 'application/json'
        }, {
          key: 'Authorization',
          value: this.opts.authorization
        }],
        onSuccess: (response) => {
          resolve({
            ...response.data.attributes,
            id: response.data.id
          });
        },
        onError: (error) => {
          reject(error);
        }
      });
    });
  }
}

/**
 * Fetchs layers according to params.
 *
 * @param {Object[]} params - params sent to the API.
 * @returns {Object[]} array of serialized layers.
 */
export const fetchLayers = (params = {}, headers = {}, _meta = false) => {
  logger.info('fetches layers');

  return WRIAPI.get('/layer', {
    headers: {
      ...WRIAPI.defaults.headers,
      // TO-DO: forces the API to not cache, this should be removed at some point
      'Upgrade-Insecure-Requests': 1,
      ...headers
    },
    params: {
      env: process.env.API_ENV,
      application: process.env.APPLICATIONS,
      ...params
    },
    transformResponse: [].concat(
      WRIAPI.defaults.transformResponse,
      (({ data, meta }) => ({ layers: data, meta }))
    )
  })
    .then((response) => {
      const { status, statusText, data } = response;
      const { layers, meta } = data;

      if (status >= 300) {
        logger.error('Error fetching layers:', `${status}: ${statusText}`);
        throw new Error(statusText);
      }

      if (_meta) {
        return {
          layers: WRISerializer({ data: layers }),
          meta
        };
      }

      return WRISerializer({ data: layers });
    })
    .catch((response) => {
      const { status, statusText } = response;

      logger.error(`Error fetching layers: ${status}: ${statusText}`);
      throw new Error(`Error fetching layers: ${status}: ${statusText}`);
    });
};

/**
 * Fetches a layer according to widget id and params.
 *
 * @param {String} id - layer id.
 * @param {Object[]} params - params sent to the API.
 * @returns {Object[]} - serialized specific layer.
 */

export const fetchLayer = (id, params = {}) => {
  if (!id) throw Error('layer id is mandatory to perform this fetching.');
  logger.info(`Fetches layer: ${id}`);

  return WRIAPI.get(`/layer/${id}`, {
    headers: {
      ...WRIAPI.defaults.headers,
      // TO-DO: forces the API to not cache, this should be removed at some point
      'Upgrade-Insecure-Requests': 1
    },
    params: {
      application: process.env.APPLICATIONS,
      env: process.env.API_ENV,
      ...params
    },
    transformResponse: [].concat(
      WRIAPI.defaults.transformResponse,
      ({ data }) => data
    )
  }).then((response) => {
    const { status, statusText, data } = response;

    if (status >= 300) {
      if (status === 404) {
        logger.debug(`Layer '${id}' not found, ${status}: ${statusText}`);
      } else {
        logger.error('Error fetching layer:', `${status}: ${statusText}`);
      }
      throw new Error(statusText);
    }
    return WRISerializer({ data });
  }).catch(({ response }) => {
    const { status, statusText } = response;
    logger.error('Error fetching layer:', `${status}: ${statusText}`);
    throw new Error('Error fetching layer:', `${status}: ${statusText}`);
  });
};

/**
 * Deletes a specified layer.
 * This fetch needs authentication.
 *
 * @param {*} id - layer ID to be deleted.
 * @param {string} token - user's token.
 * @returns {Object} fetch response.
 */
export const deleteLayer = (layerId, datasetId, token) => {
  logger.info(`deletes layer: ${layerId}`);

  return WRIAPI.delete(`/dataset/${datasetId}/layer/${layerId}`, {
    headers: {
      ...WRIAPI.defaults.headers,
      Authorization: token
    }
  })
    .then((response) => {
      const { status, statusText } = response;

      if (status >= 300) {
        if (status === 404) {
          logger.debug(`Layer '${layerId}' not found, ${status}: ${statusText}`);
        } else {
          logger.error(`Error deleting layer: ${layerId}: ${status}: ${statusText}`);
        }
        throw new Error(statusText);
      }
      return response;
    })
    .catch(({ response }) => {
      const { status, statusText } = response;

      logger.error(`Error deleting layer ${layerId}: ${status}: ${statusText}`);
      throw new Error(`Error deleting layer ${layerId}: ${status}: ${statusText}`);
    });
};
<commit_msg>Fix eslint errors and remove isomorphic-fetch<commit_after>import { post } from 'utils/request';
import WRISerializer from 'wri-json-api-serializer';

// utils
import { WRIAPI } from 'utils/axios';
import { logger } from 'utils/logs';

export default class LayersService {
  constructor(options = {}) {
    this.opts = options;
  }

  // getColumns({ dataset }) {
  //   return new Promise((resolve, reject) => {
  //     get({
  // eslint-disable-next-line max-len
  //       url: `${process.env.WRI_API_URL}/fields/${dataset}?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
  //       headers: [{
  //         key: 'Content-Type',
  //         value: 'application/json'
  //       }, {
  //         key: 'Authorization',
  //         value: this.opts.authorization
  //       }],
  //       onSuccess: (response) => {
  //         const fieldsObj = response.fields;

  //         const parsedData = {
  //           tableName: response.tableName,
  //           fields: ((fieldsObj && Object.keys(fieldsObj)) || []).map((fKey) => {
  //             const { type } = fieldsObj[fKey] || null;
  //             return { label: fKey || '', value: fKey || '', type };
  //           })
  //         };
  //         resolve({ ...parsedData });
  //       },
  //       onError: (error) => {
  //         reject(error);
  //       }
  //     });
  //   });
  // }

  saveData({ type, body, id, dataset }) {
    return new Promise((resolve, reject) => {
      post({
        url: `${process.env.WRI_API_URL}/dataset/${dataset}/layer/${id}`,
        type,
        body: {
          ...body,
          ...type !== 'PATCH' && { application: [process.env.APPLICATIONS] }
        },
        headers: [{
          key: 'Content-Type',
          value: 'application/json'
        }, {
          key: 'Authorization',
          value: this.opts.authorization
        }],
        onSuccess: (response) => {
          resolve({
            ...response.data.attributes,
            id: response.data.id
          });
        },
        onError: (error) => {
          reject(error);
        }
      });
    });
  }
}

/**
 * Fetchs layers according to params.
 *
 * @param {Object[]} params - params sent to the API.
 * @returns {Object[]} array of serialized layers.
 */
export const fetchLayers = (params = {}, headers = {}, _meta = false) => {
  logger.info('fetches layers');

  return WRIAPI.get('/layer', {
    headers: {
      ...WRIAPI.defaults.headers,
      // TO-DO: forces the API to not cache, this should be removed at some point
      'Upgrade-Insecure-Requests': 1,
      ...headers
    },
    params: {
      env: process.env.API_ENV,
      application: process.env.APPLICATIONS,
      ...params
    },
    transformResponse: [].concat(
      WRIAPI.defaults.transformResponse,
      (({ data, meta }) => ({ layers: data, meta }))
    )
  })
    .then((response) => {
      const { status, statusText, data } = response;
      const { layers, meta } = data;

      if (status >= 300) {
        logger.error('Error fetching layers:', `${status}: ${statusText}`);
        throw new Error(statusText);
      }

      if (_meta) {
        return {
          layers: WRISerializer({ data: layers }),
          meta
        };
      }

      return WRISerializer({ data: layers });
    })
    .catch((response) => {
      const { status, statusText } = response;

      logger.error(`Error fetching layers: ${status}: ${statusText}`);
      throw new Error(`Error fetching layers: ${status}: ${statusText}`);
    });
};

/**
 * Fetches a layer according to widget id and params.
 *
 * @param {String} id - layer id.
 * @param {Object[]} params - params sent to the API.
 * @returns {Object[]} - serialized specific layer.
 */

export const fetchLayer = (id, params = {}) => {
  if (!id) throw Error('layer id is mandatory to perform this fetching.');
  logger.info(`Fetches layer: ${id}`);

  return WRIAPI.get(`/layer/${id}`, {
    headers: {
      ...WRIAPI.defaults.headers,
      // TO-DO: forces the API to not cache, this should be removed at some point
      'Upgrade-Insecure-Requests': 1
    },
    params: {
      application: process.env.APPLICATIONS,
      env: process.env.API_ENV,
      ...params
    },
    transformResponse: [].concat(
      WRIAPI.defaults.transformResponse,
      ({ data }) => data
    )
  }).then((response) => {
    const { status, statusText, data } = response;

    if (status >= 300) {
      if (status === 404) {
        logger.debug(`Layer '${id}' not found, ${status}: ${statusText}`);
      } else {
        logger.error('Error fetching layer:', `${status}: ${statusText}`);
      }
      throw new Error(statusText);
    }
    return WRISerializer({ data });
  }).catch(({ response }) => {
    const { status, statusText } = response;
    logger.error('Error fetching layer:', `${status}: ${statusText}`);
    throw new Error('Error fetching layer:', `${status}: ${statusText}`);
  });
};

/**
 * Deletes a specified layer.
 * This fetch needs authentication.
 *
 * @param {*} id - layer ID to be deleted.
 * @param {string} token - user's token.
 * @returns {Object} fetch response.
 */
export const deleteLayer = (layerId, datasetId, token) => {
  logger.info(`deletes layer: ${layerId}`);

  return WRIAPI.delete(`/dataset/${datasetId}/layer/${layerId}`, {
    headers: {
      ...WRIAPI.defaults.headers,
      Authorization: token
    }
  })
    .then((response) => {
      const { status, statusText } = response;

      if (status >= 300) {
        if (status === 404) {
          logger.debug(`Layer '${layerId}' not found, ${status}: ${statusText}`);
        } else {
          logger.error(`Error deleting layer: ${layerId}: ${status}: ${statusText}`);
        }
        throw new Error(statusText);
      }
      return response;
    })
    .catch(({ response }) => {
      const { status, statusText } = response;

      logger.error(`Error deleting layer ${layerId}: ${status}: ${statusText}`);
      throw new Error(`Error deleting layer ${layerId}: ${status}: ${statusText}`);
    });
};
<|endoftext|>


<commit_before>/**! github.com/bfontaine/shortjs -- MIT license */
(function( root, factory ) {

  if (typeof define == 'function' && define.amd) {
    define(factory);
  } else if (typeof exports == 'object') {
    module.exports = factory();
  } else {
    root.short = factory();
  }

})( this, function() {
  "use strict";

  var filters = [];

  var short = function short( text, opts ) {
    return short.filter( text, opts );
  };

  short.addFilter = function addFilter( pattern, fn ) {
    filters.push([pattern, fn]);
  };

  short.filter = function filter( text, opts ) {
    var len = filters.length,
        i = 0,
        f, res;

    opts = opts || {};

    for (; i<len; i++) {
      f = filters[i];

      if (f[0].test(text)) {
        res = f[1](text, opts);
        if (res !== false) {
          text = res;
        }
      }
    }

    return text;
  };

  /* Builtin Filters */

  // short numbers
  short.addFilter(/^\d+(?:\.\d+)?$/, (function() {
    var units = [
          { suffix: "P", factor: 1e15 },
          { suffix: "T", factor: 1e12 },
          { suffix: "G", factor: 1e9 },
          { suffix: "M", factor: 1e6 },
          { suffix: "k", factor: 1e3 },
        ],

        unitsLen = units.length;

    for (var i=0; i<unitsLen; i++) {
      // if a number is higher than this number, we use this prefix. For 'k',
      // it's 600 (0.6k), for 'M' it's 600'000, etc.
      units[i].threshold = units[i].factor/10 * 6;
    }

    function roundOneDecimal( n ) {
      return (0|(n * 10)) / 10;
    }

    return function( text, opts ) {
      var n = +text,
          unit;

      if (isNaN(n)) {
        return false;
      }

      for (var i=0; i<unitsLen; i++) {
        unit = units[i];

        if (n > unit.threshold) {
          n = roundOneDecimal(n/unit.factor);

          if (n%1 === 0 && opts.forcePoint) {
              n = "" + n + ".0";
          }

          return "" + n + unit.suffix;
        }
      }

      return "" + roundOneDecimal(n);
    };
  })());

  return short;

});
<commit_msg>0.6 threshold removed<commit_after>/**! github.com/bfontaine/shortjs -- MIT license */
(function( root, factory ) {

  if (typeof define == 'function' && define.amd) {
    define(factory);
  } else if (typeof exports == 'object') {
    module.exports = factory();
  } else {
    root.short = factory();
  }

})( this, function() {
  "use strict";

  var filters = [];

  var short = function short( text, opts ) {
    return short.filter( text, opts );
  };

  short.addFilter = function addFilter( pattern, fn ) {
    filters.push([pattern, fn]);
  };

  short.filter = function filter( text, opts ) {
    var len = filters.length,
        i = 0,
        f, res;

    opts = opts || {};

    for (; i<len; i++) {
      f = filters[i];

      if (f[0].test(text)) {
        res = f[1](text, opts);
        if (res !== false) {
          text = res;
        }
      }
    }

    return text;
  };

  /* Builtin Filters */

  // short numbers
  short.addFilter(/^\d+(?:\.\d+)?$/, (function() {
    var units = [
          { suffix: "P", factor: 1e15 },
          { suffix: "T", factor: 1e12 },
          { suffix: "G", factor: 1e9 },
          { suffix: "M", factor: 1e6 },
          { suffix: "k", factor: 1e3 },
        ],

        unitsLen = units.length;

    function roundOneDecimal( n ) {
      return (0|(n * 10)) / 10;
    }

    return function( text, opts ) {
      var n = +text,
          unit;

      if (isNaN(n)) {
        return false;
      }

      for (var i=0; i<unitsLen; i++) {
        unit = units[i];

        if (n >= unit.factor) {
          n = roundOneDecimal(n/unit.factor);

          if (n%1 === 0 && opts.forcePoint) {
              n = "" + n + ".0";
          }

          return "" + n + unit.suffix;
        }
      }

      return "" + roundOneDecimal(n);
    };
  })());

  return short;

});
<|endoftext|>


<commit_before>/*  Canvas implementation of raycaster based on example at
 *  http://lodev.org/cgtutor/raycasting.html
 */
(function (canvas) {
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
world = {
    ceilColor: "rgb(9,9,59)",
    floorColor: "rgb(128,128,179)",
    wallColors: [
    [170, 142, 57],   // default
    [52, 52, 119],     // 1
    [41, 79, 109],     // 2
    [75, 45, 115],     // 3
    [86, 86, 149]  // 4
  ],
  map: [
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
  ]
};
var player = {
    x: 22,
    y: 12,
    dirX: -1,
    dirY: 0,
};
var camera = {
    planeX: 0,
    planeY: 0.67
};

var render = function () {
    var cameraX,
        rayPosX, rayPosY,
        rayDirX, rayDirY,
        mapX, mapY,
        sideDistX, sideDistY,
        deltaDistX, deltaDistY,
        perpWallDist,
        stepX, stepY,
        hit, side, mapTile,
        lineHeight,
        drawStart, drawEnd,
        color, oldColor;
    ctx.save();
    ctx.lineWidth = 1.1; // fix subpixel glitches;
    ctx.clearRect(0,0,canvasWidth,canvasHeight);
    ctx.fillStyle = world.ceilColor; //ceiling
    ctx.fillRect(0,0,canvasWidth,canvasHeight / 2);
    ctx.fillStyle = world.floorColor; //floor
    ctx.fillRect(0,canvasHeight / 2,canvasWidth,canvasHeight);
    ctx.beginPath();
    for (var x = 0.5; x < canvasWidth; x++) {
        cameraX = 2 * x / canvasWidth - 1;
        rayPosX = player.x;
        rayPosY = player.y;
        rayDirX = player.dirX + camera.planeX * cameraX;
        rayDirY = player.dirY + camera.planeY * cameraX;
        mapX = parseInt(rayPosX);
        mapY = parseInt(rayPosY);
        deltaDistX = Math.sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
        deltaDistY = Math.sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
        hit = 0;
        stepX = (rayDirX < 0) ? -1 : 1;
        stepY = (rayDirY < 0) ? -1 : 1;
        sideDistX = (rayDirX < 0) ? (rayPosX - mapX) * deltaDistX : (mapX + 1 - rayPosX) * deltaDistX;
        sideDistY = (rayDirY < 0) ? (rayPosY - mapY) * deltaDistY : (mapY + 1 - rayPosY) * deltaDistY;
        while (hit === 0) {
            if (sideDistX < sideDistY)
            {
                sideDistX += deltaDistX;
                mapX += stepX;
                side = 0;
            }
            else
            {
                sideDistY += deltaDistY;
                mapY += stepY;
                side = 1;
            }
            if (world.map[mapX][mapY] > 0) hit = 1;
        }
        perpWallDist = (side === 0) ?
            Math.abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) :
            Math.abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
        lineHeight = Math.abs(parseInt(canvasHeight / perpWallDist));
        drawStart = Math.max(0, -lineHeight / 2 + canvasHeight / 2);
        drawEnd = Math.min(canvasHeight - 1, lineHeight / 2 + canvasHeight / 2);
        mapTile = world.map[mapX][mapY];
        if (mapTile > 0 && mapTile < world.wallColors.length) {
            color = world.wallColors[mapTile].slice(0);
        } else {
            color = world.wallColors[0].slice(0);
        }
        if (side === 1) {
            color[0] = parseInt(color[0] / 2);
            color[1] = parseInt(color[1] / 2);
            color[2] = parseInt(color[2] / 2);
        }
        color = "rgb(" + color.join(",") + ")";
        if (oldColor && color !== oldColor) {
            ctx.strokeStyle = oldColor;
            ctx.stroke();
            ctx.closePath();
            ctx.beginPath();
        }
        ctx.moveTo(x, drawStart);
        ctx.lineTo(x, drawEnd);
        oldColor = color;
    }
    ctx.strokeStyle = color;
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
};

var w = window;
var keysDown = {};
var requestAnimationFrame = w.requestAnimationFrame ||
    w.webkitRequestAnimationFrame ||
    w.msRequestAnimationFrame ||
    w.mozRequestAnimationFrame ||
    w.oRequestAnimationFrame;

addEventListener("keydown", function (e) {
    keysDown[e.keyCode] = true;
}, false);

addEventListener("keyup", function (e) {
    delete keysDown[e.keyCode];
}, false);

var update = function(modifier) {
    var moveSpeed =  modifier * 5;
    var rotSpeed =  modifier * 3;
    var oldDirX, oldPlaneX;
    if (38 in keysDown) { // up
        if (world.map[parseInt(player.x + player.dirX * moveSpeed)][parseInt(player.y)] === 0) {
            player.x += player.dirX * moveSpeed;
        }
        if(world.map[parseInt(player.x)][parseInt(player.y + player.dirY * moveSpeed)] === 0) {
             player.y += player.dirY * moveSpeed;
        }
    }
    if (40 in keysDown) { // down
        if (world.map[parseInt(player.x - player.dirX * moveSpeed)][parseInt(player.y)] === 0) {
            player.x -= player.dirX * moveSpeed;
        }
        if(world.map[parseInt(player.x)][parseInt(player.y - player.dirY * moveSpeed)] === 0) {
             player.y -= player.dirY * moveSpeed;
        }
    }
    if (39 in keysDown) { // right
      oldDirX = player.dirX;
      player.dirX = player.dirX * Math.cos(-rotSpeed) - player.dirY * Math.sin(-rotSpeed);
      player.dirY = oldDirX * Math.sin(-rotSpeed) + player.dirY * Math.cos(-rotSpeed);
      oldPlaneX = camera.planeX;
      camera.planeX = camera.planeX * Math.cos(-rotSpeed) - camera.planeY * Math.sin(-rotSpeed);
      camera.planeY = oldPlaneX * Math.sin(-rotSpeed) + camera.planeY * Math.cos(-rotSpeed);
    }
    if (37 in keysDown) { // left
      oldDirX = player.dirX;
      player.dirX = player.dirX * Math.cos(rotSpeed) - player.dirY * Math.sin(rotSpeed);
      player.dirY = oldDirX * Math.sin(rotSpeed) + player.dirY * Math.cos(rotSpeed);
      oldPlaneX = camera.planeX;
      camera.planeX = camera.planeX * Math.cos(rotSpeed) - camera.planeY * Math.sin(rotSpeed);
      camera.planeY = oldPlaneX * Math.sin(rotSpeed) + camera.planeY * Math.cos(rotSpeed);
    }
};

var main = function () {
    var now = Date.now();
    var delta = now - then;
    update(delta / 1000);
    render();
    then = now;
    requestAnimationFrame(main);
};
var then = Date.now();
main();

}(canvas));<commit_msg>Add distance-based shading<commit_after>/*  Canvas implementation of raycaster based on examples at
 *  http://lodev.org/cgtutor/raycasting.html and
 *  http://www.permadi.com/tutorial/raycast/index.html
 */

(function (canvas) {
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
world = {
    ceilColor: "rgb(9,9,59)",
    floorColor: "rgb(128,128,179)",
    wallColors: [
    [170, 142, 57],   // default
    [52, 52, 119],     // 1
    [41, 79, 109],     // 2
    [75, 45, 115],     // 3
    [86, 86, 149]  // 4
  ],
  map: [
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1],
    [1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
  ]
};
var player = {
    x: 22,
    y: 12,
    dirX: -1,
    dirY: 0,
};
var camera = {
    planeX: 0,
    planeY: 0.67
};

var render = function () {
    var cameraX,
        rayPosX, rayPosY,
        rayDirX, rayDirY,
        mapX, mapY,
        sideDistX, sideDistY,
        deltaDistX, deltaDistY,
        perpWallDist,
        stepX, stepY,
        hit, side, mapTile,
        lineHeight, brightness,
        drawStart, drawEnd,
        color, oldColor;
    ctx.save();
    ctx.lineCaps = "square";
    ctx.clearRect(0,0,canvasWidth,canvasHeight);
    ctx.fillStyle = world.ceilColor; //ceiling
    ctx.fillRect(0.5,0.5,canvasWidth,canvasHeight / 2 + 0.5);
    ctx.fillStyle = world.floorColor; //floor
    ctx.fillRect(0.5,canvasHeight / 2 - 0.5,canvasWidth,canvasHeight);
    ctx.beginPath();
    for (var x = 0.5; x < canvasWidth; x++) {
        cameraX = 2 * x / canvasWidth - 1;
        rayPosX = player.x;
        rayPosY = player.y;
        rayDirX = player.dirX + camera.planeX * cameraX;
        rayDirY = player.dirY + camera.planeY * cameraX;
        mapX = parseInt(rayPosX);
        mapY = parseInt(rayPosY);
        deltaDistX = Math.sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
        deltaDistY = Math.sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
        hit = 0;
        stepX = (rayDirX < 0) ? -1 : 1;
        stepY = (rayDirY < 0) ? -1 : 1;
        sideDistX = (rayDirX < 0) ? (rayPosX - mapX) * deltaDistX : (mapX + 1 - rayPosX) * deltaDistX;
        sideDistY = (rayDirY < 0) ? (rayPosY - mapY) * deltaDistY : (mapY + 1 - rayPosY) * deltaDistY;
        while (hit === 0) {
            if (sideDistX < sideDistY)
            {
                sideDistX += deltaDistX;
                mapX += stepX;
                side = 0;
            }
            else
            {
                sideDistY += deltaDistY;
                mapY += stepY;
                side = 1;
            }
            if (world.map[mapX][mapY] > 0) hit = 1;
        }
        perpWallDist = (side === 0) ?
            Math.abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) :
            Math.abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
        lineHeight = Math.abs(parseInt(canvasHeight / perpWallDist));
        drawStart = Math.max(0, -lineHeight / 2 + canvasHeight / 2);
        drawEnd = Math.min(canvasHeight - 1, lineHeight / 2 + canvasHeight / 2);
        mapTile = world.map[mapX][mapY];
        if (mapTile > 0 && mapTile < world.wallColors.length) {
            color = world.wallColors[mapTile].slice(0);
        } else {
            color = world.wallColors[0].slice(0);
        }
        if (side === 1) {
            color[0] = parseInt(color[0] / 2);
            color[1] = parseInt(color[1] / 2);
            color[2] = parseInt(color[2] / 2);
        }
        brightness = Math.min(1, 1/perpWallDist * 4);
        color[0] = parseInt(color[0] * brightness);
        color[1] = parseInt(color[1] * brightness);
        color[2] = parseInt(color[2] * brightness);
        color = "rgb(" + color.join(",") + ")";
        if (oldColor && color !== oldColor) {
            ctx.strokeStyle = oldColor;
            ctx.stroke();
            ctx.closePath();
            ctx.beginPath();
        }
        ctx.moveTo(x, drawStart);
        ctx.lineTo(x, drawEnd);
        oldColor = color;
    }
    ctx.strokeStyle = color;
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
};

var w = window;
var keysDown = {};
var requestAnimationFrame = w.requestAnimationFrame ||
    w.webkitRequestAnimationFrame ||
    w.msRequestAnimationFrame ||
    w.mozRequestAnimationFrame ||
    w.oRequestAnimationFrame;

addEventListener("keydown", function (e) {
    keysDown[e.keyCode] = true;
}, false);

addEventListener("keyup", function (e) {
    delete keysDown[e.keyCode];
}, false);

var update = function(modifier) {
    var moveSpeed =  modifier * 5;
    var rotSpeed =  modifier * 3;
    var oldDirX, oldPlaneX;
    if (38 in keysDown) { // up
        if (world.map[parseInt(player.x + player.dirX * moveSpeed)][parseInt(player.y)] === 0) {
            player.x += player.dirX * moveSpeed;
        }
        if(world.map[parseInt(player.x)][parseInt(player.y + player.dirY * moveSpeed)] === 0) {
             player.y += player.dirY * moveSpeed;
        }
    }
    if (40 in keysDown) { // down
        if (world.map[parseInt(player.x - player.dirX * moveSpeed)][parseInt(player.y)] === 0) {
            player.x -= player.dirX * moveSpeed;
        }
        if(world.map[parseInt(player.x)][parseInt(player.y - player.dirY * moveSpeed)] === 0) {
             player.y -= player.dirY * moveSpeed;
        }
    }
    if (39 in keysDown) { // right
      oldDirX = player.dirX;
      player.dirX = player.dirX * Math.cos(-rotSpeed) - player.dirY * Math.sin(-rotSpeed);
      player.dirY = oldDirX * Math.sin(-rotSpeed) + player.dirY * Math.cos(-rotSpeed);
      oldPlaneX = camera.planeX;
      camera.planeX = camera.planeX * Math.cos(-rotSpeed) - camera.planeY * Math.sin(-rotSpeed);
      camera.planeY = oldPlaneX * Math.sin(-rotSpeed) + camera.planeY * Math.cos(-rotSpeed);
    }
    if (37 in keysDown) { // left
      oldDirX = player.dirX;
      player.dirX = player.dirX * Math.cos(rotSpeed) - player.dirY * Math.sin(rotSpeed);
      player.dirY = oldDirX * Math.sin(rotSpeed) + player.dirY * Math.cos(rotSpeed);
      oldPlaneX = camera.planeX;
      camera.planeX = camera.planeX * Math.cos(rotSpeed) - camera.planeY * Math.sin(rotSpeed);
      camera.planeY = oldPlaneX * Math.sin(rotSpeed) + camera.planeY * Math.cos(rotSpeed);
    }
};

var main = function () {
    var now = Date.now();
    var delta = now - then;
    update(delta / 1000);
    render();
    then = now;
    requestAnimationFrame(main);
};
var then = Date.now();
main();

}(canvas));<|endoftext|>