<commit_before>var shownMessages = {};

function removeColors (index, css) {
    return (css.match (/(^|\s)bg-\S+/g) || []).join(' ');
}

function removeMetaColors (index, css) {
    return (css.match (/(^|\s)color-\S+/g) || []).join(' ');
}

function colorize($scope)
{
	var $target = $scope || $(document);
	$.each(palette, function (index, value){
		var $items = $target.find('.'+index);
		$items.removeClass(removeColors)
            .addClass(value);
	});
	return true;
}

function initHelp() // called from script.js
{
	$.each( ambitiApplicativiHelps, function(index, value){
		   $('#ambitiApplicativi span[data-toggle="tooltip"]').attr(index, value);
    });
	$.each( bozzeHelps, function(index, value){
		   $('#bozze span[data-toggle="tooltip"]').attr(index, value);
    });
	$.each( chiuseHelps, function(index, value){
		   $('#chiuse span[data-toggle="tooltip"]').attr(index, value);
	});
	$.each( legendaHelps, function(index, value){
		   $('#legenda span[data-toggle="tooltip"]').attr(index, value);
	});
}

function showMessages(messages)
{
	$.each(messages, function(index, value){
		if (!(value.id in shownMessages))
		{
			window.console&&console.log('Messaggio pubblico: '+value.message);

			var options = toastr.options;
			toastr.options.hideDuration = "5000";
			toastr.options.progressBar = true;
			toastr.options.preventDuplicates = true;

			if(value.warning)
				toastr["warning"](value.message);
			else
				toastr["info"](value.message);

			toastr.options = options;
			shownMessages[value.id] = value.message;
		}
	});
}

function updateTicket(v, $li){
	$li.attr('data-ticket-id', v['TicketID']);
	$li.find('*[data-name="Title"]').not('[data-prop]').empty().html(v['Title']);
	$li.find('*[data-name="ArticleNum"]').not('[data-prop]').empty().html(v['ArticleNum']);
	$li.find('.queue-color').removeClass(removeMetaColors).addClass(v['QueueColor']);
	$li.find('*[data-name="QueueName"][data-prop]').each(function(){
		$(this).prop($(this).data('prop'), $(this).prop($(this).data('prop')).split(':')[0] +': '+ v['QueueName']);});

	$li.find('*[data-name="Author"][data-prop]').each(function(){
		var author = v['Author'];
		if(author === getUser().email)
		{
			author = getUser().name;
			$(this).parent('div').addClass('alert-warning');
		} else {
			$(this).parent('div').removeClass('alert-warning');
		}
		$(this).prop($(this).data('prop'), $(this).prop($(this).data('prop')).split(':')[0] +': '+ author);
	});

	var $button = $li.find('button[data-toggle]');
	$button.attr('data-service-id', v['ServiceId']);
	$button.attr('data-queue-id', v['QueueID']);
	$button.attr('data-queue-name', v['QueueName']);
	$button.attr('data-queue-color', v['QueueColor']);
	$button.attr('data-articles', v['ArticleNum']);
	$button.attr('data-id', v['TicketID']);
	$button.attr('data-num', v['TicketNumber']);
	$button.prop('data-ticket-title', v['Title']);
	$button.prop('data-ticket-desc', v['Article'][0]['Body']);

	var priorityId = parseInt(v['Article'][0]['PriorityID']) >= 4;
	$button.prop('data-ticket-priority', priorityId);
	if (priorityId)
	{
		$li.find('.tag-urgent').removeClass('hidden');
	}

	var stateId = parseInt(v['StateID']);
	switch (stateId) {
	case 1: //new
		$li.find('.tag-new').removeClass('hidden');
		break;
	case 2: //success
		$li.find('.badge.alert-danger').addClass('hidden');
		$li.find('.badge.alert-success').removeClass('hidden');
		break;
	case 3: //unsuccess
		$li.find('.badge.alert-success').addClass('hidden');
		$li.find('.badge.alert-danger').removeClass('hidden');
		break;
	default:
		$li.find('.tag-working').removeClass('hidden');
		$li.find('.badge.alert-success').addClass('hidden');
		$li.find('.badge.alert-danger').addClass('hidden');
	}
}

function populate(data){
    var bozze = [], chiuse = [];
    var $bozzeTicket = $('.bozze-ticket');
    var $chiuseTicket = $('.chiuse-ticket');
    var $bozzeEmpty = $('#bozze_empty');
    var $chiuseEmpty = $('#chiuse_empty');

    var counters = {};

    if('messages' in data && data.messages.length)
    	showMessages(data['messages']);

    // generazione liste di visualizzazione
    $.each(bozzeStateIds, function(k,id){
        if(id in data) $.merge(bozze, data[id]);});
    $.each(chiuseStateIds, function(k,id){
        if(id in data) $.merge(chiuse, data[id]);});

    var func = function(a, b){
    	  var aTime = a['Changed'];
    	  var bTime = b['Changed'];
    	  return ((aTime < bTime) ? -1 : ((aTime > bTime) ? 1 : 0));
    	}
    bozze.sort(func);
    chiuse.sort(func);

    // aggiornamento contatori
    $.each(bozze, function(k,v){
    		var id = 'q'+v['QueueOrder']+'_bozze';
    		var tot = 'tot_bozze';
    		counters[id] = (id in counters)?counters[id]+1:1;
    		counters[tot] = (tot in counters)?counters[tot]+1:1;
		});
    $.each(chiuse, function(k,v){
			var id = 'q'+v['QueueOrder']+'_chiuse';
			var tot = 'tot_chiuse';
			counters[id] = (id in counters)?counters[id]+1:1;
			counters[tot] = (tot in counters)?counters[tot]+1:1;
		});
    // reset
	$('[data-name="counter"]').text(0);
    $.each(counters, function(k,v){
    	$('#'+k).text(v+"");});

    if (bozze.length)
        $bozzeEmpty.addClass('hidden');
    else
        $bozzeEmpty.removeClass('hidden');
    if (chiuse.length)
        $chiuseEmpty.addClass('hidden');
    else
        $chiuseEmpty.removeClass('hidden');

    var $currentList = [];
	$.each(bozze, function(k,v){
    		var $li = $bozzeTicket.siblings("li[data-ticket-id='"+v['TicketID']+"']");
    		if ($li.length){
    			// update
    			updateTicket(v, $li);
    			$bozzeEmpty.after($li);
    		}else{
    			// create
		        $li = $bozzeTicket.clone();
		        $bozzeEmpty.after($li);
		        $li.removeClass('bozze-ticket');
		        $li.toggleClass('hidden');
		        updateTicket(v, $li);
    		}
    		$.merge($currentList,$li);
		});
	$bozzeTicket.siblings("li").not($currentList).not('#bozze_empty').remove();

    $currentList = [];
	$.each(chiuse, function(k,v){
    		var $li = $chiuseTicket.siblings("li[data-ticket-id='"+v['TicketID']+"']");
    		if ($li.length){
    			// update
    			updateTicket(v, $li);
    			$chiuseEmpty.after($li);
    		}else{
    			// create
		        $li = $chiuseTicket.clone();
		        $chiuseEmpty.after($li);
		        $li.removeClass('chiuse-ticket');
		        $li.toggleClass('hidden');
		        updateTicket(v, $li);
    		}
    		$.merge($currentList,$li);
		});
	$chiuseTicket.siblings("li").not($currentList).not('#chiuse_empty').remove();
}

function updateCategory (q, $categoria){
	$categoria
		.attr('id', 'q'+q['order'])
		.removeClass('color-?')
		.addClass('color-'+q['order']);

	$categoria.find('p[data-name="name"]')
	   .text(q['name']);
	$categoria.find('#qN_bozze')
	   .attr('id', 'q'+q['order']+'_bozze');
	$categoria.find('#qN_chiuse')
	   .attr('id', 'q'+q['order']+'_chiuse');

	var $button = $categoria.find('button[data-toggle]');
	$button
		.attr('data-service-id', q['service_id'])
		.attr('data-queue-id', q['id'])
		.attr('data-queue-name', q['name'])
		.attr('data-queue-color', 'color-'+q['order']);

	if (q['filters']){
		$button
			.attr('data-target', '#filterModal')
			.prop('data-filters', q['filters']);
	}else{
		$button.attr('data-target', '#ticketModal');
	}

	return $categoria;
}

function prepare(categories, $target){
    var $cat = $target.find('.mock');
    if (categories.length){
    	$target.find('#cat_empty').addClass('hidden');
    }else{
    	$target.find('#cat_empty').removeClass('hidden');
	}
	$.each(categories, function(k,c){
		// create
        var $clone = $cat.clone().removeClass('mock').removeClass('hidden');
        $target.append(updateCategory(c, $clone));
	});
}

function content(){
	var user = getUser();
	if (user && user.email)
	{
		var $catList = $('#catList');
		if (!$catList.find('li.mock').siblings().not('#cat_empty').length){
			$.ajax({
				url:			category_url,
				type:			"POST",
				datatype:		"json",
				data:{
					username:		user.username,
					email:			user.email,
					queues:			getQueues(),
				},
				async: true,
				success: function(data, status) {
					window.console&&console.log(data); // for debugging
					prepare(data, $catList);
					colorize();
				},
				error: function(data, status) { window.console&&console.log('<ajaxConsole ERROR> '+data+' <ajaxConsole ERROR>'); },
			});
		}
		$.ajax({
			url:			ticket_url,
			type:			"POST",
			datatype:		"json",
			data:{
				username:		user.username,
				email:			user.email,
				queues:			getQueues(),
			},
			async: true, // default true
			success: function(data, status) {
				window.console&&console.log(data); // for debugging
				populate(data);
				colorize();
			},
			error: function(data, status) { window.console&&console.log('<ajaxConsole ERROR> '+data+' <ajaxConsole ERROR>'); },
		});
	}
}
<commit_msg>bacheca messages are distinguished by display mode too: top full width<commit_after>var shownMessages = {};

function removeColors (index, css) {
    return (css.match (/(^|\s)bg-\S+/g) || []).join(' ');
}

function removeMetaColors (index, css) {
    return (css.match (/(^|\s)color-\S+/g) || []).join(' ');
}

function colorize($scope)
{
	var $target = $scope || $(document);
	$.each(palette, function (index, value){
		var $items = $target.find('.'+index);
		$items.removeClass(removeColors)
            .addClass(value);
	});
	return true;
}

function initHelp() // called from script.js
{
	$.each( ambitiApplicativiHelps, function(index, value){
		   $('#ambitiApplicativi span[data-toggle="tooltip"]').attr(index, value);
    });
	$.each( bozzeHelps, function(index, value){
		   $('#bozze span[data-toggle="tooltip"]').attr(index, value);
    });
	$.each( chiuseHelps, function(index, value){
		   $('#chiuse span[data-toggle="tooltip"]').attr(index, value);
	});
	$.each( legendaHelps, function(index, value){
		   $('#legenda span[data-toggle="tooltip"]').attr(index, value);
	});
}

function showMessages(messages)
{
	$.each(messages, function(index, value){
		if (!(value.id in shownMessages))
		{
			window.console&&console.log('Messaggio di bacheca: '+value.message);

			var options = $.extend(true, {}, toastr.options);
			toastr.options.hideDuration = "5000";
			toastr.options.progressBar = true;
			toastr.options.preventDuplicates = true;
			toastr.options.positionClass = "toast-top-full-width";

			if(value.warning)
				toastr["warning"](value.message);
			else
				toastr["info"](value.message);

			toastr.options = options;
			shownMessages[value.id] = value.message;
		}
	});
}

function updateTicket(v, $li){
	$li.attr('data-ticket-id', v['TicketID']);
	$li.find('*[data-name="Title"]').not('[data-prop]').empty().html(v['Title']);
	$li.find('*[data-name="ArticleNum"]').not('[data-prop]').empty().html(v['ArticleNum']);
	$li.find('.queue-color').removeClass(removeMetaColors).addClass(v['QueueColor']);
	$li.find('*[data-name="QueueName"][data-prop]').each(function(){
		$(this).prop($(this).data('prop'), $(this).prop($(this).data('prop')).split(':')[0] +': '+ v['QueueName']);});

	$li.find('*[data-name="Author"][data-prop]').each(function(){
		var author = v['Author'];
		if(author === getUser().email)
		{
			author = getUser().name;
			$(this).parent('div').addClass('alert-warning');
		} else {
			$(this).parent('div').removeClass('alert-warning');
		}
		$(this).prop($(this).data('prop'), $(this).prop($(this).data('prop')).split(':')[0] +': '+ author);
	});

	var $button = $li.find('button[data-toggle]');
	$button.attr('data-service-id', v['ServiceId']);
	$button.attr('data-queue-id', v['QueueID']);
	$button.attr('data-queue-name', v['QueueName']);
	$button.attr('data-queue-color', v['QueueColor']);
	$button.attr('data-articles', v['ArticleNum']);
	$button.attr('data-id', v['TicketID']);
	$button.attr('data-num', v['TicketNumber']);
	$button.prop('data-ticket-title', v['Title']);
	$button.prop('data-ticket-desc', v['Article'][0]['Body']);

	var priorityId = parseInt(v['Article'][0]['PriorityID']) >= 4;
	$button.prop('data-ticket-priority', priorityId);
	if (priorityId)
	{
		$li.find('.tag-urgent').removeClass('hidden');
	}

	var stateId = parseInt(v['StateID']);
	switch (stateId) {
	case 1: //new
		$li.find('.tag-new').removeClass('hidden');
		break;
	case 2: //success
		$li.find('.badge.alert-danger').addClass('hidden');
		$li.find('.badge.alert-success').removeClass('hidden');
		break;
	case 3: //unsuccess
		$li.find('.badge.alert-success').addClass('hidden');
		$li.find('.badge.alert-danger').removeClass('hidden');
		break;
	default:
		$li.find('.tag-working').removeClass('hidden');
		$li.find('.badge.alert-success').addClass('hidden');
		$li.find('.badge.alert-danger').addClass('hidden');
	}
}

function populate(data){
    var bozze = [], chiuse = [];
    var $bozzeTicket = $('.bozze-ticket');
    var $chiuseTicket = $('.chiuse-ticket');
    var $bozzeEmpty = $('#bozze_empty');
    var $chiuseEmpty = $('#chiuse_empty');

    var counters = {};

    if('messages' in data && data.messages.length)
    	showMessages(data['messages']);

    // generazione liste di visualizzazione
    $.each(bozzeStateIds, function(k,id){
        if(id in data) $.merge(bozze, data[id]);});
    $.each(chiuseStateIds, function(k,id){
        if(id in data) $.merge(chiuse, data[id]);});

    var func = function(a, b){
    	  var aTime = a['Changed'];
    	  var bTime = b['Changed'];
    	  return ((aTime < bTime) ? -1 : ((aTime > bTime) ? 1 : 0));
    	}
    bozze.sort(func);
    chiuse.sort(func);

    // aggiornamento contatori
    $.each(bozze, function(k,v){
    		var id = 'q'+v['QueueOrder']+'_bozze';
    		var tot = 'tot_bozze';
    		counters[id] = (id in counters)?counters[id]+1:1;
    		counters[tot] = (tot in counters)?counters[tot]+1:1;
		});
    $.each(chiuse, function(k,v){
			var id = 'q'+v['QueueOrder']+'_chiuse';
			var tot = 'tot_chiuse';
			counters[id] = (id in counters)?counters[id]+1:1;
			counters[tot] = (tot in counters)?counters[tot]+1:1;
		});
    // reset
	$('[data-name="counter"]').text(0);
    $.each(counters, function(k,v){
    	$('#'+k).text(v+"");});

    if (bozze.length)
        $bozzeEmpty.addClass('hidden');
    else
        $bozzeEmpty.removeClass('hidden');
    if (chiuse.length)
        $chiuseEmpty.addClass('hidden');
    else
        $chiuseEmpty.removeClass('hidden');

    var $currentList = [];
	$.each(bozze, function(k,v){
    		var $li = $bozzeTicket.siblings("li[data-ticket-id='"+v['TicketID']+"']");
    		if ($li.length){
    			// update
    			updateTicket(v, $li);
    			$bozzeEmpty.after($li);
    		}else{
    			// create
		        $li = $bozzeTicket.clone();
		        $bozzeEmpty.after($li);
		        $li.removeClass('bozze-ticket');
		        $li.toggleClass('hidden');
		        updateTicket(v, $li);
    		}
    		$.merge($currentList,$li);
		});
	$bozzeTicket.siblings("li").not($currentList).not('#bozze_empty').remove();

    $currentList = [];
	$.each(chiuse, function(k,v){
    		var $li = $chiuseTicket.siblings("li[data-ticket-id='"+v['TicketID']+"']");
    		if ($li.length){
    			// update
    			updateTicket(v, $li);
    			$chiuseEmpty.after($li);
    		}else{
    			// create
		        $li = $chiuseTicket.clone();
		        $chiuseEmpty.after($li);
		        $li.removeClass('chiuse-ticket');
		        $li.toggleClass('hidden');
		        updateTicket(v, $li);
    		}
    		$.merge($currentList,$li);
		});
	$chiuseTicket.siblings("li").not($currentList).not('#chiuse_empty').remove();
}

function updateCategory (q, $categoria){
	$categoria
		.attr('id', 'q'+q['order'])
		.removeClass('color-?')
		.addClass('color-'+q['order']);

	$categoria.find('p[data-name="name"]')
	   .text(q['name']);
	$categoria.find('#qN_bozze')
	   .attr('id', 'q'+q['order']+'_bozze');
	$categoria.find('#qN_chiuse')
	   .attr('id', 'q'+q['order']+'_chiuse');

	var $button = $categoria.find('button[data-toggle]');
	$button
		.attr('data-service-id', q['service_id'])
		.attr('data-queue-id', q['id'])
		.attr('data-queue-name', q['name'])
		.attr('data-queue-color', 'color-'+q['order']);

	if (q['filters']){
		$button
			.attr('data-target', '#filterModal')
			.prop('data-filters', q['filters']);
	}else{
		$button.attr('data-target', '#ticketModal');
	}

	return $categoria;
}

function prepare(categories, $target){
    var $cat = $target.find('.mock');
    if (categories.length){
    	$target.find('#cat_empty').addClass('hidden');
    }else{
    	$target.find('#cat_empty').removeClass('hidden');
	}
	$.each(categories, function(k,c){
		// create
        var $clone = $cat.clone().removeClass('mock').removeClass('hidden');
        $target.append(updateCategory(c, $clone));
	});
}

function content(){
	var user = getUser();
	if (user && user.email)
	{
		var $catList = $('#catList');
		if (!$catList.find('li.mock').siblings().not('#cat_empty').length){
			$.ajax({
				url:			category_url,
				type:			"POST",
				datatype:		"json",
				data:{
					username:		user.username,
					email:			user.email,
					queues:			getQueues(),
				},
				async: true,
				success: function(data, status) {
					window.console&&console.log(data); // for debugging
					prepare(data, $catList);
					colorize();
				},
				error: function(data, status) { window.console&&console.log('<ajaxConsole ERROR> '+data+' <ajaxConsole ERROR>'); },
			});
		}
		$.ajax({
			url:			ticket_url,
			type:			"POST",
			datatype:		"json",
			data:{
				username:		user.username,
				email:			user.email,
				queues:			getQueues(),
			},
			async: true, // default true
			success: function(data, status) {
				window.console&&console.log(data); // for debugging
				populate(data);
				colorize();
			},
			error: function(data, status) { window.console&&console.log('<ajaxConsole ERROR> '+data+' <ajaxConsole ERROR>'); },
		});
	}
}
<|endoftext|>


<commit_before>var loginController = function($scope, $http,$window) {

    $scope.formInfo = {};
    $scope.login = function(){

        $http.post('/api/login',$scope.formInfo).success(function(args){
          $window.location.href = '/admin/home.html';
        }).
        error(function(args){
           alert("error" + args);
        });
    };
};

adminApp.controller ('loginController',['$scope', '$http','$window',loginController]);

<commit_msg>#17 | setting cookies on signin | Padma,Indraneel<commit_after>var loginController = adminApp.controller ('loginController',['$scope', '$http','$window','$cookies', function($scope, $http,$window,$cookies) {

    $scope.formInfo = {};
    $scope.login = function(){

        $http.post('/api/login',$scope.formInfo).success(function(args){
          $window.location.href = '/admin/home.html';
          $cookies.user = "admin";
        }).
        error(function(args){
           alert("error" + args);
        });
    };
}]);

<|endoftext|>


<commit_before>module.exports = (client, message, args) => {

    { let numArray = args.map(n=> parseFloat(n));  let total = numArray.reduce( (p,c) => (p/c|0)); message.channel.sendMessage(total).then(msg => {msg.delete(60000) }); }

    message.delete().then(msg => { msg.delete(60000) });

  };<commit_msg><commit_after>module.exports = (client, message, args) => {

    { let numArray = args.map(n=> parseFloat(n));  let total = numArray.reduce( (p,c) => (p/c|0)); message.channel.sendMessage(total).then(msg => {msg.delete(60000) }); }

    numArray.delete(60000);

  };<|endoftext|>


<commit_before>// @flow
// @jsx glam

import glam from 'glam';
import React, { type Node } from 'react';

import SyntaxHighlighter, {
  registerLanguage,
} from 'react-syntax-highlighter/prism-light';
import jsx from 'react-syntax-highlighter/languages/prism/jsx';
import { tomorrow } from 'react-syntax-highlighter/styles/prism';

import { colors } from '../theme';
import { smallDevice } from '../utils';

registerLanguage('jsx', jsx);

// ==============================
// Title
// ==============================

export const Title = (props: any) => (

);

// ==============================
// Heading
// ==============================

function headingLink(src) {
  const base = 'https://github.com/davwheat/react-images/tree/v1/docs/pages';
  return `${base}${src}`;
}

export const Heading = ({ source, ...props }: { source: string }) => (

    {source ? (

        Source

    ) : null}

);

// ==============================
// Code
// ==============================

export const Code = (props: any) => (

);

export const CodeBlock = ({ children, ...props }: { children: Node }) => {
  return (
    <SyntaxHighlighter
      language="jsx"
      style={tomorrow}
      customStyle={{
        borderRadius: 4,
        fontSize: 12,
        marginTop: '2em',
        overflowX: 'auto',
        WebkitOverflowScrolling: 'touch',
      }}
      {...props}
    >
      {children}
    </SyntaxHighlighter>
  );
};

// ==============================
// Carousel Components
// ==============================

const Author = ({ isModal, ...props }) => {
  const Tag = props.href ? 'a' : 'span';

  return (
    <Tag
      css={{
        color: isModal ? 'white' : 'inherit',
        fontWeight: 500,
        textDecoration: 'none',

        ':hover': { textDecoration: 'underline' },
      }}
      {...props}
    />
  );
};

export const FooterCaption = (props: ViewType) => {
  const { currentView, isModal } = props;
  const { caption, author } = currentView;

  return (

      {author ? (
        <Author
          href={author.url}
          target={author.url ? '_blank' : null}
          isModal={isModal}
        >
          {author.name}
        </Author>
      ) : null}
      {author && caption ? ' - ' : null}
      {caption}

  );
};
<commit_msg>Update docs link<commit_after>// @flow
// @jsx glam

import glam from 'glam';
import React, { type Node } from 'react';

import SyntaxHighlighter, {
  registerLanguage,
} from 'react-syntax-highlighter/prism-light';
import jsx from 'react-syntax-highlighter/languages/prism/jsx';
import { tomorrow } from 'react-syntax-highlighter/styles/prism';

import { colors } from '../theme';
import { smallDevice } from '../utils';

registerLanguage('jsx', jsx);

// ==============================
// Title
// ==============================

export const Title = (props: any) => (

);

// ==============================
// Heading
// ==============================

function headingLink(src) {
  const base = 'https://github.com/davwheat/react-images-maintained/tree/v1/docs/pages';
  return `${base}${src}`;
}

export const Heading = ({ source, ...props }: { source: string }) => (

    {source ? (

        Source

    ) : null}

);

// ==============================
// Code
// ==============================

export const Code = (props: any) => (

);

export const CodeBlock = ({ children, ...props }: { children: Node }) => {
  return (
    <SyntaxHighlighter
      language="jsx"
      style={tomorrow}
      customStyle={{
        borderRadius: 4,
        fontSize: 12,
        marginTop: '2em',
        overflowX: 'auto',
        WebkitOverflowScrolling: 'touch',
      }}
      {...props}
    >
      {children}
    </SyntaxHighlighter>
  );
};

// ==============================
// Carousel Components
// ==============================

const Author = ({ isModal, ...props }) => {
  const Tag = props.href ? 'a' : 'span';

  return (
    <Tag
      css={{
        color: isModal ? 'white' : 'inherit',
        fontWeight: 500,
        textDecoration: 'none',

        ':hover': { textDecoration: 'underline' },
      }}
      {...props}
    />
  );
};

export const FooterCaption = (props: ViewType) => {
  const { currentView, isModal } = props;
  const { caption, author } = currentView;

  return (

      {author ? (
        <Author
          href={author.url}
          target={author.url ? '_blank' : null}
          isModal={isModal}
        >
          {author.name}
        </Author>
      ) : null}
      {author && caption ? ' - ' : null}
      {caption}

  );
};
<|endoftext|>


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

'use strict';

const { BigQueryUtil, CloudFunctionUtil, StorageUtil } = require('cds-shared');
const configManager = require('./configurationManager');
const bigqueryUtil = new BigQueryUtil();
const cloudFunctionUtil = new CloudFunctionUtil();
const storageUtil = new StorageUtil();
const stagingTableExpiryDays = 2;
const processPrefix = "cds";
const batchIdColumnName = `${processPrefix}_batch_id`;
const labelName = "cds_managed";
let batchId;
const archiveEnabled = process.env.ARCHIVE_FILES ? (process.env.ARCHIVE_FILES.toLowerCase() === "true") : false;

/**
 * @param  {} event
 * @param  {} context
 */
exports.processEvent = async (event, context) => {
    console.log(`Event type: ${context.eventType}`);
    await processTriggerEvent(event, context);
};

/**
 * @param  {} request
 * @param  {} response
 */
exports.processHttpEvent = async (request, response) => {
    await processHttpEvent(request, response);
};

/**
 * @param  {} event
 * @param  {} context
 * For Cloud Storage finalize trigger.
 */
async function processTriggerEvent(event, context) {
    const options = {
        eventId: context.eventId,
        bucketName: event.bucket,
        fileName: event.name
    };
    const result = await configManager.validateOptions(options, true);
    if (result.hasException) {
        throw new Error(`Validation error for fileName: ${options.fileName}: ${JSON.stringify(result)}`);
    }
    else if (result.isValid) {
        await processFile(options, true);
    }
}

/**
 * @param  {} request
 * @param  {} response
 * For local debugging.
 */
async function processHttpEvent(request, response) {
    const options = request.body || {};
    const result = await configManager.validateOptions(options, true);
    if (!result.isValid || result.hasException) {
        response.status(400).send({ errors: result.errors });
        return;
    }
    const status = await processFile(options, false);
    const statusCode = (status === true) ? 200 : 400;
    response.status(statusCode).send();
    return;
}

/**
 * @param  {} options
 */
async function processFile(options, throws) {
    batchId = cloudFunctionUtil.generateBatchId(options.eventId, options.bucketName, options.fileName);
    console.log(`processFile called for ${getBucketName(options)}, batchId is ${batchId}`);

    const config = await configManager.getConfiguration(options);
    const haveDataset = await bigqueryUtil.datasetExists(config.datasetId);
    if (!haveDataset) {
        console.log(`Dataset ${config.datasetId} not found, creating...`);
        await bigqueryUtil.createDataset(config.datasetId);
        console.log(`Created dataset ${config.datasetId}`);
    } else {
        console.log(`Found dataset ${config.datasetId}`);
    }

    let success = false;
    let ex;
    try {
        await stageFile(config);
        await transform(config);
        if (archiveEnabled === true) {
            await storageUtil.moveFile(options.bucketName, config.sourceFile, config.bucketPath.archive);
            console.log(`File '${config.sourceFile}' has been archived to: ${config.bucketPath.archive}`);
        }
        success = true;
    }
    catch (reason) {
        ex = `Exception processing ${options.fileName}: ${reason}`;
        console.error(ex);
    }
    finally {
        await bigqueryUtil.deleteTable(config.datasetId, config.stagingTable, true);
    }

    if (throws && !success) {
        throw ex;
    }

    return success;
}

/**
 * @param  {} config
 * Executes the SQL transformation.
 */
async function transform(config) {
    const transformExists = await storageUtil.checkIfFileExists(config.bucket, config.bucketPath.transform);

    let transformQuery = "*";
    if (transformExists === true) {
        transformQuery = await storageUtil.fetchFileContent(config.bucket, config.bucketPath.transform);
    }
    // Blocked by TODO(b/144032584): Destination tables not respecting nullable/required modes specified in schema.json.
    // const dataset = bigqueryClient.dataset(config.datasetId);
    // const exists = await bigqueryUtil.tableExists(config.datasetId, config.destinationTableId);
    // if (!exists) {
    //     console.log(`creating table ${config.destinationTableId} with ${config.metadata.fields}`);
    //     await dataset.createTable(config.destinationTableId, { schema: config.metadata.fields });
    // }
    const query = `SELECT ${transformQuery}, '${batchId}' AS ${batchIdColumnName} FROM \`${config.datasetId}.${config.stagingTable}\``;
    console.log(`executing transform query: ${query}`);
    const [job] = await createTransformJob(config, query);
    await job.getQueryResults({ maxApiCalls: 1, maxResults: 0 });

    // Label the table for managing and tracking
    await bigqueryUtil.setTableLabel(config.datasetId, config.destinationTableId, labelName, "true");

    console.log(`Transform job: ${job.metadata.id} ${job.metadata.statistics.query.statementType} ${job.metadata.configuration.jobType} ${job.metadata.status.state}`);
    return;
}

/**
 * @param  {} config
 * Loads data into BQ staging table.
 */
async function stageFile(config) {
    console.log(`Using config ${JSON.stringify(config)}`);
    const dataset = bigqueryUtil.getDataset(config.datasetId);
    let today = new Date();
    today.setDate(today.getDate() + stagingTableExpiryDays);
    const expiryTime = today.getTime();
    console.log(`Setting expirationTime for staging table to ${expiryTime}`);

    const fields = (config.metadata && config.metadata.fields) || undefined;
    let options = { expirationTime: expiryTime };
    if (fields) {
        options.schema = fields;
    }
    else {
        options.autodetect = true;
    }

    await dataset.createTable(config.stagingTable, options);
    const table = dataset.table(config.stagingTable);
    console.log(`Created table ${config.stagingTable}`);
    console.log(`Executing load for ${config.sourceFile} with metadata: ${JSON.stringify(config.metadata)}`);

    try {
        let [job] = await table.load(storageUtil.getBucket(config.bucket).file(config.sourceFile), config.metadata || { autodetect: true });
        console.log(`${job.id} ${job.configuration.jobType} ${job.status.state} ${job.statistics.load.outputRows} rows`);
        return;
    }
    catch (ex) {
        console.error(`Errors encountered loading ${config.sourceFile} to ${config.stagingTable}`);
        logException(ex);
        throw (ex);
    }
}

/**
 * @param  {} config
 * @param  {} query
 * Creates query job for the transformation query.
 */
async function createTransformJob(config, query) {
    console.log(`Configuration for runTransform: ${JSON.stringify(config)}`);
    let options = {
        destinationTable: {
            projectId: process.env.GCP_PROJECT,
            datasetId: config.datasetId,
            tableId: config.destinationTableId
        },
        createDisposition: "CREATE_IF_NEEDED",
        writeDisposition: (config.truncate)
            ? "WRITE_TRUNCATE"
            : "WRITE_APPEND",
        query: query,
        jobPrefix: `${processPrefix}_`,
        timePartitioning: {
            type: 'DAY'
        }
    };

    if (config.metadata && config.metadata.location) {
        options.location = config.metadata.location;
    }

    console.log(`BigQuery options: ${JSON.stringify(options)}`);
    try {
        return bigqueryUtil.createQueryJob(options);
    }
    catch (exception) {
        console.error(`Exception encountered running transform: ${getExceptionString(exception)}`);
        logException(exception);
        throw (exception);
    }
}

/**
 * @param  {} exception
 */
function logException(exception) {
    const errors = exception.errors;
    if (errors && errors.length > 0) {
        for (let i = 0; i < errors.length; i++) {
            console.error('ERROR ' + (i + 1) + ": " + JSON.stringify(errors[i].message));
        }
    }
    else {
        console.error(`Exception thrown, but no error array was given: ${exception}`);
    }
}

/**
 * @param  {} options
 */
function getBucketName(options) {
    return `gs://${options.bucketName}/${options.fileName}`;
}

/**
 * @param  {} exception
 * Returns exception message in string format. Attempts to stringify JSON, if that's undefined, returns the exception as a string.
 * TODO: This isn't working as expected. When a string is passed, it's returning {}.
 * IE: TypeError: storageUtil.getBucket(...).file is not a function
 */
function getExceptionString(exception) {
    let str = JSON.stringify(exception);
    // Try to parse to json using JSON.parse, and only if returns true, then return the json string, otherwise return object.
    if (!str) {
        str = exception;
    }
    return str;
}

if (process.env.UNIT_TESTS) {
    module.exports = {
        getExceptionString,
        getBucketName,
        processFile,
        labelName
    };
}<commit_msg>Fix for ingestion failure at setting table label (#133)<commit_after>/**
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const { BigQueryUtil, CloudFunctionUtil, StorageUtil } = require('cds-shared');
const configManager = require('./configurationManager');
const bigqueryUtil = new BigQueryUtil();
const cloudFunctionUtil = new CloudFunctionUtil();
const storageUtil = new StorageUtil();
const stagingTableExpiryDays = 2;
const processPrefix = "cds";
const batchIdColumnName = `${processPrefix}_batch_id`;
const labelName = "cds_managed";
const queryResultTimeoutMs = 540000;
let batchId;
const archiveEnabled = process.env.ARCHIVE_FILES ? (process.env.ARCHIVE_FILES.toLowerCase() === "true") : false;

/**
 * @param  {} event
 * @param  {} context
 */
exports.processEvent = async (event, context) => {
    console.log(`Event type: ${context.eventType}`);
    await processTriggerEvent(event, context);
};

/**
 * @param  {} request
 * @param  {} response
 */
exports.processHttpEvent = async (request, response) => {
    await processHttpEvent(request, response);
};

/**
 * @param  {} event
 * @param  {} context
 * For Cloud Storage finalize trigger.
 */
async function processTriggerEvent(event, context) {
    const options = {
        eventId: context.eventId,
        bucketName: event.bucket,
        fileName: event.name
    };
    const result = await configManager.validateOptions(options, true);
    if (result.hasException) {
        throw new Error(`Validation error for fileName: ${options.fileName}: ${JSON.stringify(result)}`);
    }
    else if (result.isValid) {
        await processFile(options, true);
    }
}

/**
 * @param  {} request
 * @param  {} response
 * For local debugging.
 */
async function processHttpEvent(request, response) {
    const options = request.body || {};
    const result = await configManager.validateOptions(options, true);
    if (!result.isValid || result.hasException) {
        response.status(400).send({ errors: result.errors });
        return;
    }
    const status = await processFile(options, false);
    const statusCode = (status === true) ? 200 : 400;
    response.status(statusCode).send();
    return;
}

/**
 * @param  {} options
 */
async function processFile(options, throws) {
    batchId = cloudFunctionUtil.generateBatchId(options.eventId, options.bucketName, options.fileName);
    console.log(`processFile called for ${getBucketName(options)}, batchId is ${batchId}`);

    const config = await configManager.getConfiguration(options);
    const haveDataset = await bigqueryUtil.datasetExists(config.datasetId);
    if (!haveDataset) {
        console.log(`Dataset ${config.datasetId} not found, creating...`);
        await bigqueryUtil.createDataset(config.datasetId);
        console.log(`Created dataset ${config.datasetId}`);
    } else {
        console.log(`Found dataset ${config.datasetId}`);
    }

    let success = false;
    let ex;
    try {
        await stageFile(config);
        await transform(config);
        if (archiveEnabled === true) {
            await storageUtil.moveFile(options.bucketName, config.sourceFile, config.bucketPath.archive);
            console.log(`File '${config.sourceFile}' has been archived to: ${config.bucketPath.archive}`);
        }
        success = true;
    }
    catch (reason) {
        ex = `Exception processing ${options.fileName}: ${reason}`;
        console.error(ex);
    }
    finally {
        await bigqueryUtil.deleteTable(config.datasetId, config.stagingTable, true);
    }

    if (throws && !success) {
        throw ex;
    }

    return success;
}

/**
 * @param  {} config
 * Executes the SQL transformation.
 */
async function transform(config) {
    const transformExists = await storageUtil.checkIfFileExists(config.bucket, config.bucketPath.transform);

    let transformQuery = "*";
    if (transformExists === true) {
        transformQuery = await storageUtil.fetchFileContent(config.bucket, config.bucketPath.transform);
    }

    const query = `SELECT ${transformQuery}, '${batchId}' AS ${batchIdColumnName} FROM \`${config.datasetId}.${config.stagingTable}\``;
    console.log(`Executing transform query: ${query}`);
    const [job] = await createTransformJob(config, query);
    await job.getQueryResults({ maxApiCalls: 1, maxResults: 0, timeoutMs: queryResultTimeoutMs });

    console.log('Setting table label');
    // Label the table for managing and tracking
    await bigqueryUtil.setTableLabel(config.datasetId, config.destinationTableId, labelName, "true");
    console.log('Setting table label done');

    console.log(`Transform job: ${job.metadata.id} ${job.metadata.statistics.query.statementType} ${job.metadata.configuration.jobType} ${job.metadata.status.state}`);
    return;
}

/**
 * @param  {} config
 * Loads data into BQ staging table.
 */
async function stageFile(config) {
    console.log(`Using config ${JSON.stringify(config)}`);
    const dataset = bigqueryUtil.getDataset(config.datasetId);
    let today = new Date();
    today.setDate(today.getDate() + stagingTableExpiryDays);
    const expiryTime = today.getTime();
    console.log(`Setting expirationTime for staging table to ${expiryTime}`);

    const fields = (config.metadata && config.metadata.fields) || undefined;
    let options = { expirationTime: expiryTime };
    if (fields) {
        options.schema = fields;
    }
    else {
        options.autodetect = true;
    }

    await dataset.createTable(config.stagingTable, options);
    const table = dataset.table(config.stagingTable);
    console.log(`Created table ${config.stagingTable}`);
    console.log(`Executing load for ${config.sourceFile} with config: ${JSON.stringify(config)}`);

    try {
        let [job] = await table.load(storageUtil.getBucket(config.bucket).file(config.sourceFile), config.metadata || { autodetect: true });
        console.log(`${job.id} ${job.configuration.jobType} ${job.status.state} ${job.statistics.load.outputRows} rows`);
        return;
    }
    catch (ex) {
        console.error(`Errors encountered loading ${config.sourceFile} to ${config.stagingTable}`);
        logException(ex);
        throw (ex);
    }
}

/**
 * @param  {} config
 * @param  {} query
 * Creates query job for the transformation query.
 */
async function createTransformJob(config, query) {
    console.log(`Configuration for runTransform: ${JSON.stringify(config)}`);
    let options = {
        destinationTable: {
            projectId: process.env.GCP_PROJECT,
            datasetId: config.datasetId,
            tableId: config.destinationTableId
        },
        createDisposition: "CREATE_IF_NEEDED",
        writeDisposition: (config.truncate)
            ? "WRITE_TRUNCATE"
            : "WRITE_APPEND",
        query: query,
        jobPrefix: `${processPrefix}_`,
        timePartitioning: {
            type: 'DAY'
        }
    };

    if (config.metadata && config.metadata.location) {
        options.location = config.metadata.location;
    }

    console.log(`BigQuery options: ${JSON.stringify(options)}`);
    try {
        return bigqueryUtil.createQueryJob(options);
    }
    catch (exception) {
        console.error(`Exception encountered running transform: ${getExceptionString(exception)}`);
        logException(exception);
        throw (exception);
    }
}

/**
 * @param  {} exception
 */
function logException(exception) {
    const errors = exception.errors;
    if (errors && errors.length > 0) {
        for (let i = 0; i < errors.length; i++) {
            console.error('ERROR ' + (i + 1) + ": " + JSON.stringify(errors[i].message));
        }
    }
    else {
        console.error(`Exception thrown, but no error array was given: ${exception}`);
    }
}

/**
 * @param  {} options
 */
function getBucketName(options) {
    return `gs://${options.bucketName}/${options.fileName}`;
}

/**
 * @param  {} exception
 * Returns exception message in string format. Attempts to stringify JSON, if that's undefined, returns the exception as a string.
 * TODO: This isn't working as expected. When a string is passed, it's returning {}.
 * IE: TypeError: storageUtil.getBucket(...).file is not a function
 */
function getExceptionString(exception) {
    let str = JSON.stringify(exception);
    // Try to parse to json using JSON.parse, and only if returns true, then return the json string, otherwise return object.
    if (!str) {
        str = exception;
    }
    return str;
}

if (process.env.UNIT_TESTS) {
    module.exports = {
        getExceptionString,
        getBucketName,
        processFile,
        labelName
    };
}<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var logo = require('@wercker/logo');
var react = require('react');

var dom = react.DOM;

/**
 * Create class.
 */

module.exports = react.createClass({
  displayName: 'docs-quicklinks',
  render: render
});

/**
 * Render.
 */

function render () {
  return dom.div(null,
    dom.div({className: 'doc-quicklinks'},
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Faq'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/faq/migration-tips-v2.html',
              children: 'How can I migrate to Docker'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-to-bypass-timeouts.html',
              children: 'How can I bypass the timeouts'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-can-i-change-my-username.html',
              children: 'How Can I Change My Username'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-can-i-update-a-repo-url.html',
              children: 'How Can I Update A Repo Url'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/what-ip-to-whitelist.html',
              children: 'What Ip To Whitelist'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/what-is-my-concurrency.html',
              children: 'What Is My Concurrency'
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Common tasks'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/using-the-cli/index.html',
              children: 'Using the CLI'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/wercker-yml/creating-a-yml.html',
              children: 'Creating a wercker.yml'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/environment-variables/index.html',
              children: 'Using environment variables'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/ssh-keys/index.html',
              children: 'Generate SSH keys'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/services/index.html',
              children: 'Using services'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/notifications/index.html',
              children: 'Using notifications',
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'API'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/api/getting-started/index.html',
              children: 'Getting started with the API'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/api/endpoints/index.html',
              children: 'Endpoints'
            })
          )
        ),
        dom.h5({children: 'Containers'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/using-the-cli/pulling-containers.html',
              children: 'Pull and introspect containers'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/containers/private-containers.html',
              children: 'Private containters'
            })
          ),
          dom.li(null,
            dom.a({
              href: 'docs/containers/pushing-containers.html',
              children: 'Pushing containters'
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Downloads'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: 'http://wercker.com/downloads/',
              children: 'Wercker for the desktop'
            })
          ),
          dom.li(null,
            dom.a({
              href: 'http://wercker.com/downloads/',
              children: 'Command Line Interface'
            })
          )
        ),
        dom.h5({children: 'Join the community on IRC'}),
        dom.ul(null,
          dom.li(null,
            'At ',
            dom.a({
              href: 'irc://irc.freenode.net/wercker',
              children: '#wercker'
            }),
            ' on irc.freenode.net'
          )
        )
      )
    )
  );
}
<commit_msg>fix test<commit_after>/**
 * Module dependencies.
 */

var react = require('react');

var dom = react.DOM;

/**
 * Create class.
 */

module.exports = react.createClass({
  displayName: 'docs-quicklinks',
  render: render
});

/**
 * Render.
 */

function render () {
  return dom.div(null,
    dom.div({className: 'doc-quicklinks'},
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Faq'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/faq/migration-tips-v2.html',
              children: 'How can I migrate to Docker'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-to-bypass-timeouts.html',
              children: 'How can I bypass the timeouts'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-can-i-change-my-username.html',
              children: 'How Can I Change My Username'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/how-can-i-update-a-repo-url.html',
              children: 'How Can I Update A Repo Url'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/what-ip-to-whitelist.html',
              children: 'What Ip To Whitelist'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/faq/what-is-my-concurrency.html',
              children: 'What Is My Concurrency'
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Common tasks'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/using-the-cli/index.html',
              children: 'Using the CLI'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/wercker-yml/creating-a-yml.html',
              children: 'Creating a wercker.yml'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/environment-variables/index.html',
              children: 'Using environment variables'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/ssh-keys/index.html',
              children: 'Generate SSH keys'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/services/index.html',
              children: 'Using services'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/notifications/index.html',
              children: 'Using notifications'
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'API'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/api/getting-started/index.html',
              children: 'Getting started with the API'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/api/endpoints/index.html',
              children: 'Endpoints'
            })
          )
        ),
        dom.h5({children: 'Containers'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: '/docs/using-the-cli/pulling-containers.html',
              children: 'Pull and introspect containers'
            })
          ),
          dom.li(null,
            dom.a({
              href: '/docs/containers/private-containers.html',
              children: 'Private containters'
            })
          ),
          dom.li(null,
            dom.a({
              href: 'docs/containers/pushing-containers.html',
              children: 'Pushing containters'
            })
          )
        )
      ),
      dom.div({className: 'doc-quicklinks-item'},
        dom.h5({children: 'Downloads'}),
        dom.ul(null,
          dom.li(null,
            dom.a({
              href: 'http://wercker.com/downloads/',
              children: 'Wercker for the desktop'
            })
          ),
          dom.li(null,
            dom.a({
              href: 'http://wercker.com/downloads/',
              children: 'Command Line Interface'
            })
          )
        ),
        dom.h5({children: 'Join the community on IRC'}),
        dom.ul(null,
          dom.li(null,
            'At ',
            dom.a({
              href: 'irc://irc.freenode.net/wercker',
              children: '#wercker'
            }),
            ' on irc.freenode.net'
          )
        )
      )
    )
  );
}
<|endoftext|>


<commit_before>if ('Accelerometer' in window && 'Gyroscope' in window) {
  //document.getElementById('moApi').innerHTML = 'Generic Sensor API';

  let accelerometer = new Accelerometer();
  accelerometer.addEventListener('reading', e => MaccelerationHandler(accelerometer, 'moAccel'));
  accelerometer.start();

  let accelerometerWithGravity = new Accelerometer({includeGravity: true});
  accelerometerWithGravity.addEventListener('reading', e => MaccelerationHandler(accelerometerWithGravity, 'moAccelGrav'));
  accelerometerWithGravity.start();

  let gyroscope = new Gyroscope();
  gyroscope.addEventListener('reading', e => rotationHandler({
    alpha: gyroscope.x,
    beta: gyroscope.y,
    gamma: gyroscope.z
  }));
  gyroscope.start();

  intervalHandler('Not available in Generic Sensor API');

} else if ('DeviceMotionEvent' in window) {
  //document.getElementById('alert').style.display = 'none';
  //document.getElementById('moApi').innerHTML = 'Device Motion API';

  window.addEventListener('devicemotion', function (eventData) {
    accelerationHandler(eventData.acceleration, 'moAccel');
    MaccelerationHandler(eventData.accelerationIncludingGravity, 'moAccelGrav');
    rotationHandler(eventData.rotationRate);
    intervalHandler(eventData.interval);
  }, false);
} else {
  //document.getElementById('alert').style.display = 'none';
  //document.getElementById('moApi').innerHTML = 'No Accelerometer & Gyroscope API available';
}

function accelerationHandler(acceleration, targetId) {
  var info, xyz = "[X, Y, Z]";

  info = xyz.replace("X", acceleration.x && acceleration.x.toFixed(3));
  info = info.replace("Y", acceleration.y && acceleration.y.toFixed(3));
  info = info.replace("Z", acceleration.z && acceleration.z.toFixed(3));
  //document.getElementById(targetId).innerHTML = info;
}

  function yell() {
    console.log("This happened!");
    document.body.style.backgroundColor = "black !important";
    console.log(blueVal);
  }

var test = true;

function MaccelerationHandler(acceleration, targetId) {
  var info, xyz = "[X, Y, Z]";

  var zz = (acceleration.z && acceleration.z.toFixed(3));

  if (zz>10 && test) {
            test = false;

            x = 1;
            var timer = setInterval(function change() {
              if (x === 1) {
                  color = "#ffffff";
                x = 2;
              } else {
                  color = "#000000";
                  x = 1;
              }

              document.body.style.background = color;
            }, 50);

          setTimeout(function() {
            clearInterval(timer);
          }, 1000);
          yell();
  }
}

function rotationHandler(rotation) {
  var info, xyz = "[X, Y, Z]";

  //info = xyz.replace("X", rotation.alpha && rotation.alpha.toFixed(3));
  //info = info.replace("Y", rotation.beta && rotation.beta.toFixed(3));
  //info = info.replace("Z", rotation.gamma && rotation.gamma.toFixed(3));

  var xx = (rotation.alpha && rotation.alpha.toFixed(3));
  var yy = (rotation.beta && rotation.beta.toFixed(3));
  var zz = (rotation.gamma && rotation.gamma.toFixed(3));

  var mean = (((xx)^2) + ((yy)^2) + ((zz)^2))*(1/2);
  //document.getElementById("mean").innerHTML = mean;
  //document.getElementById("moRotation").innerHTML = info;

}

function intervalHandler(interval) {
  //document.getElementById("moInterval").innerHTML = interval;
}

if (location.href.indexOf('debug') !== -1) {
  //document.getElementById('alert').style.display = 'none';
}
<commit_msg>updated blueval values<commit_after>if ('Accelerometer' in window && 'Gyroscope' in window) {
  //document.getElementById('moApi').innerHTML = 'Generic Sensor API';

  let accelerometer = new Accelerometer();
  accelerometer.addEventListener('reading', e => MaccelerationHandler(accelerometer, 'moAccel'));
  accelerometer.start();

  let accelerometerWithGravity = new Accelerometer({includeGravity: true});
  accelerometerWithGravity.addEventListener('reading', e => MaccelerationHandler(accelerometerWithGravity, 'moAccelGrav'));
  accelerometerWithGravity.start();

  let gyroscope = new Gyroscope();
  gyroscope.addEventListener('reading', e => rotationHandler({
    alpha: gyroscope.x,
    beta: gyroscope.y,
    gamma: gyroscope.z
  }));
  gyroscope.start();

  intervalHandler('Not available in Generic Sensor API');

} else if ('DeviceMotionEvent' in window) {
  //document.getElementById('alert').style.display = 'none';
  //document.getElementById('moApi').innerHTML = 'Device Motion API';

  window.addEventListener('devicemotion', function (eventData) {
    accelerationHandler(eventData.acceleration, 'moAccel');
    MaccelerationHandler(eventData.accelerationIncludingGravity, 'moAccelGrav');
    rotationHandler(eventData.rotationRate);
    intervalHandler(eventData.interval);
  }, false);
} else {
  //document.getElementById('alert').style.display = 'none';
  //document.getElementById('moApi').innerHTML = 'No Accelerometer & Gyroscope API available';
}

function accelerationHandler(acceleration, targetId) {
  var info, xyz = "[X, Y, Z]";

  info = xyz.replace("X", acceleration.x && acceleration.x.toFixed(3));
  info = info.replace("Y", acceleration.y && acceleration.y.toFixed(3));
  info = info.replace("Z", acceleration.z && acceleration.z.toFixed(3));
  //document.getElementById(targetId).innerHTML = info;
}

  function yell() {
    console.log("This happened!");
    document.body.style.backgroundColor = "black !important";
    console.log(blueVal);
    blueVal++;
    console.log(blueVal);

     var playersRef = firebase.database().ref("players/");

    playersRef.set ({
      blue: blueVal
    });
  }

var test = true;

function MaccelerationHandler(acceleration, targetId) {
  var info, xyz = "[X, Y, Z]";

  var zz = (acceleration.z && acceleration.z.toFixed(3));

  if (zz>10 && test) {
            test = false;

            x = 1;
            var timer = setInterval(function change() {
              if (x === 1) {
                  color = "#ffffff";
                x = 2;
              } else {
                  color = "#000000";
                  x = 1;
              }

              document.body.style.background = color;
            }, 50);

          setTimeout(function() {
            clearInterval(timer);
          }, 1000);
          yell();
  }
}

function rotationHandler(rotation) {
  var info, xyz = "[X, Y, Z]";

  //info = xyz.replace("X", rotation.alpha && rotation.alpha.toFixed(3));
  //info = info.replace("Y", rotation.beta && rotation.beta.toFixed(3));
  //info = info.replace("Z", rotation.gamma && rotation.gamma.toFixed(3));

  var xx = (rotation.alpha && rotation.alpha.toFixed(3));
  var yy = (rotation.beta && rotation.beta.toFixed(3));
  var zz = (rotation.gamma && rotation.gamma.toFixed(3));

  var mean = (((xx)^2) + ((yy)^2) + ((zz)^2))*(1/2);
  //document.getElementById("mean").innerHTML = mean;
  //document.getElementById("moRotation").innerHTML = info;

}

function intervalHandler(interval) {
  //document.getElementById("moInterval").innerHTML = interval;
}

if (location.href.indexOf('debug') !== -1) {
  //document.getElementById('alert').style.display = 'none';
}
<|endoftext|>


<commit_before>module.exports = {
    '/':{
        backLink: '../uploadphoto/check-photo-and-submit',
        fields: ['passport-number'],
        next: '/title'
    },
    '/dual-national':{
        backLink: './get-updates',
    },
    '/dual-national-details':{
        backLink: 'dual-national',
        next: '/title'
    },
    '/title':{
        backLink: './',
        fields: ['title'],
        next: '/name'
    },
    '/name':{
        fields: [
            'name',
            'lastname',
            'change-name'
        ],
        next: '/previous-names'
    },
    '/change-of-name':{
        backLink: 'name',
        fields: ['change-of-name-reason'],
        next: '/previous-names-change'
    },
    '/previous-names':{
        fields: [
                'previous-name',
                'previous-first-name-1',
                'previous-last-name-1',
                'previous-first-name-2',
                'previous-last-name-2',
                'previous-first-name-3',
                'previous-last-name-3'
                 ],
        backLink: 'name',
        next: '/gender'
    },
   '/previous-names-change':{
        fields: [
                'previous-first-name-1',
                'previous-last-name-1',
                'previous-first-name-2',
                'previous-last-name-2',
                'previous-first-name-3',
                'previous-last-name-3'
                 ],
        backLink: 'name',
        next: '/gender'
    },
    '/gender':{
        fields: ['gender'],
        next: '/date-and-place-birth'
    },
    '/date-and-place-birth':{
        next: '/home-address',
        fields:['age-day', 'age-month', 'age-year', 'born-in-uk', 'town-of-birth', 'country-of-birth'],
        controller: require('../../../controllers/go-overseas'),
        nextAlt: './home-address-overseas'
      },
    '/home-address-overseas':{
        fields:['address1', 'address2','address3','address4','address5', 'town', 'postcode'],
        next: '/contact-details-overseas'
    },
    '/home-address':{
        fields:['address1', 'address2','address3','address4','address5', 'town', 'postcode'],
        next: '/contact-details'
    },
    '/contact-details-overseas':{
        fields:['email','application-country-code' ,'mobile-overseas'],
        next: '/get-updates-overseas'
    },
    '/contact-details':{
        fields:['email', 'mobile'],
        next: '/get-updates'
    },
    '/get-updates-overseas':{
        next: '/passport-options-overseas'
    },
    '/get-updates':{
        next: '/dual-national'

    },
    '/passport-options-overseas':{
        fields: ['passport-options-overseas', 'braille'],
        next: '/sign'
    },
    '/passport-options':{
        fields: ['passport-options', 'braille'],
        next: '/sign',
        backLink: './dual-national'
    },
    '/sign': {
        fields: ['can-sign', 'no-sign-reason'],
        backLink: 'passport-options',
        next: '/passport-special-delivery', /* if they are from the UK */
        controller: require('../../../controllers/go-overseas'),
        nextAlt: './summary-overseas'
    },
    '/summary-overseas':{
        controller: require('../../../controllers/confirm-overseas'),
        template: 'confirm',
        next: '/declaration'
    },
    '/passport-special-delivery': {
        next: '/summary',
        fields: ['secure-return']
    },
    '/summary':{
        controller: require('../../../controllers/confirm'),
        template: 'confirm',
        next: '/required-documents'
    },
    '/required-documents':{
        controller: require('../../../controllers/change-of-name-docs')
    },
    '/name-change-docs-for-marriage':{
        next: '/declaration'
    },
    '/name-change-docs-for-divorce':{
        next: '/declaration'
    },
    '/name-change-docs-for-small-changes':{
        next: '/declaration'
    },
    '/name-change-docs-for-gender-change':{
        next: '/declaration'
    },
    '/name-change-docs-for-other-changes':{
        next: '/declaration'
    },
    '/declaration':{
        next: '/payment'
    },
    '/payment':{
        next: '/processing-payment'
    },
    '/processing-payment':{
        next: '/confirmation'
    },
    '/confirmation':{
        next: '/title'
    }
};
<commit_msg>remove dual national from renew<commit_after>module.exports = {
    '/':{
        backLink: '../uploadphoto/check-photo-and-submit',
        fields: ['passport-number'],
        next: '/title'
    },
    '/title':{
        backLink: './',
        fields: ['title'],
        next: '/name'
    },
    '/name':{
        fields: [
            'name',
            'lastname',
            'change-name'
        ],
        next: '/previous-names'
    },
    '/change-of-name':{
        backLink: 'name',
        fields: ['change-of-name-reason'],
        next: '/previous-names-change'
    },
    '/previous-names':{
        fields: [
                'previous-name',
                'previous-first-name-1',
                'previous-last-name-1',
                'previous-first-name-2',
                'previous-last-name-2',
                'previous-first-name-3',
                'previous-last-name-3'
                 ],
        backLink: 'name',
        next: '/gender'
    },
   '/previous-names-change':{
        fields: [
                'previous-first-name-1',
                'previous-last-name-1',
                'previous-first-name-2',
                'previous-last-name-2',
                'previous-first-name-3',
                'previous-last-name-3'
                 ],
        backLink: 'name',
        next: '/gender'
    },
    '/gender':{
        fields: ['gender'],
        next: '/date-and-place-birth'
    },
    '/date-and-place-birth':{
        next: '/home-address',
        fields:['age-day', 'age-month', 'age-year', 'born-in-uk', 'town-of-birth', 'country-of-birth'],
        controller: require('../../../controllers/go-overseas'),
        nextAlt: './home-address-overseas'
      },
    '/home-address-overseas':{
        fields:['address1', 'address2','address3','address4','address5', 'town', 'postcode'],
        next: '/contact-details-overseas'
    },
    '/home-address':{
        fields:['address1', 'address2','address3','address4','address5', 'town', 'postcode'],
        next: '/contact-details'
    },
    '/contact-details-overseas':{
        fields:['email','application-country-code' ,'mobile-overseas'],
        next: '/get-updates-overseas'
    },
    '/contact-details':{
        fields:['email', 'mobile'],
        next: '/get-updates'
    },
    '/get-updates-overseas':{
        next: '/passport-options-overseas'
    },
    '/get-updates':{
        next: '/passport-options'
    },
    '/dual-national':{
        backLink: './get-updates',
    },
    '/dual-national-details':{
        backLink: 'dual-national',
        next: '/title'
    },
    '/passport-options-overseas':{
        fields: ['passport-options-overseas', 'braille'],
        next: '/sign'
    },
    '/passport-options':{
        fields: ['passport-options', 'braille'],
        next: '/sign',
        backLink: './dual-national'
    },
    '/sign': {
        fields: ['can-sign', 'no-sign-reason'],
        backLink: 'passport-options',
        next: '/passport-special-delivery', /* if they are from the UK */
        controller: require('../../../controllers/go-overseas'),
        nextAlt: './summary-overseas'
    },
    '/summary-overseas':{
        controller: require('../../../controllers/confirm-overseas'),
        template: 'confirm',
        next: '/declaration'
    },
    '/passport-special-delivery': {
        next: '/summary',
        fields: ['secure-return']
    },
    '/summary':{
        controller: require('../../../controllers/confirm'),
        template: 'confirm',
        next: '/required-documents'
    },
    '/required-documents':{
        controller: require('../../../controllers/change-of-name-docs')
    },
    '/name-change-docs-for-marriage':{
        next: '/declaration'
    },
    '/name-change-docs-for-divorce':{
        next: '/declaration'
    },
    '/name-change-docs-for-small-changes':{
        next: '/declaration'
    },
    '/name-change-docs-for-gender-change':{
        next: '/declaration'
    },
    '/name-change-docs-for-other-changes':{
        next: '/declaration'
    },
    '/declaration':{
        next: '/payment'
    },
    '/payment':{
        next: '/processing-payment'
    },
    '/processing-payment':{
        next: '/confirmation'
    },
    '/confirmation':{
        next: '/title'
    }
};
<|endoftext|>


<commit_before>'use strict';

// module Web.Firebase.Authentication.Eff

exports._onAuth = function (callback, firebase) {
  return function() {
    return firebase.onAuth(callback);
  };
};

exports._authWithOAuthRedirect(provider, errorCallback, ref) {
  var errorCbEffect = function(error) {
    return errorCallback(error)(); // ensure effect gets used
  }
  ref.authWithOAuthRedirect(provider, errorCbEffect);
}
<commit_msg>Fix oauth method<commit_after>'use strict';

// module Web.Firebase.Authentication.Eff

exports._onAuth = function (callback, firebase) {
  return function() {
    return firebase.onAuth(callback);
  };
};

exports._authWithOAuthRedirect = function (provider, errorCallback, ref) {
  console.log("oAuth started");
  var errorCbEffect = function(error) {
    console.log("js callback called");
    return errorCallback(error)(); // ensure effect gets used
  };
  ref.authWithOAuthRedirect(provider, errorCbEffect);
  console.log("oAuth initiated in js");
};
<|endoftext|>


<commit_before>'use restrict';
document.addEventListener('DOMContentLoaded', event => {
  const SOURCE_URI = 'https://www.pixiv.net/ranking.php?mode=daily&format=json&content=illust';
  const promiseList = [];

  for (let i = 1; i <= 3; i++) {
    const p = axios.get(`${SOURCE_URI}&p=${i}`);
    promiseList.push(p);
  }

  Promise.all(promiseList).then(values => {
    const items = [];
    let illustrations = [];

    values = values.filter(response => {
        return response.status === 200;
    });

    values.forEach(response => {
      // Extracting illustration info
      response.data.contents.forEach(content => {
          illustrations.push({
            'illustrationId': content.illust_id,
            'illustrationUrl': content.url,
            'illustrationTitle': content.title,
            'userName': content.user_name,
          });
      });
    });

    // Shuffle.
    illustrations = shuffle(illustrations);

    // Inserting elements to a New tab page body.
    illustrations.forEach(illust => {
      items.push(createGalleryItem(
        illust.illustrationId,
        illust.illustrationUrl,
        illust.illustrationTitle,
        illust.userName
      ));
    });

    // Wait for image loading
    return Promise.all(items.map(item => {
      return new Promise(resolve => {
        item.img.onload = item.img.onerror = () => resolve(item);
      });
    }));
  })
  .then(items => {
    items.forEach(item => {
      document.querySelector('#gallery').appendChild(item.anchor);
    });

    setTimeout(() => {
      items.forEach(item => item.img.classList.add('loaded'));
    }, 125);
  }).catch(response => {
    console.log(response);
  });
});

function createIllustrationElement(imageUrl, title, author) {
  const img = new Image();
  img.src = imageUrl;
  img.alt = `${author} / ${title}`;
  return img;
}

function createGalleryItem(illustrationId, imageUrl, title, author) {
    const linkUrl = `https://www.pixiv.net/i/${illustrationId}`;
    const img = createIllustrationElement(imageUrl, title, author);
    const anchor = document.createElement('a');
    anchor.setAttribute('href', linkUrl);
    anchor.setAttribute('target', 'pixiv');
    anchor.appendChild(img);
    return {anchor, img};
}

function shuffle(array) {
  let n = array.length;

  while (n) {
    const i = Math.floor(Math.random() * n--);
    const t = array[n];
    array[n] = array[i];
    array[i] = t;
  }

  return array;
}
<commit_msg>create initialization function<commit_after>'use restrict';

function init() {
  const SOURCE_URI = 'https://www.pixiv.net/ranking.php?mode=daily&format=json&content=illust';
  const promiseList = [];

  for (let i = 1; i <= 3; i++) {
    const p = axios.get(`${SOURCE_URI}&p=${i}`);
    promiseList.push(p);
  }

  Promise.all(promiseList).then(values => {
    const items = [];
    let illustrations = [];

    values = values.filter(response => {
        return response.status === 200;
    });

    values.forEach(response => {
      // Extracting illustration info
      response.data.contents.forEach(content => {
          illustrations.push({
            'illustrationId': content.illust_id,
            'illustrationUrl': content.url,
            'illustrationTitle': content.title,
            'userName': content.user_name,
          });
      });
    });

    // Shuffle.
    illustrations = shuffle(illustrations);

    // Inserting elements to a New tab page body.
    illustrations.forEach(illust => {
      items.push(createGalleryItem(
        illust.illustrationId,
        illust.illustrationUrl,
        illust.illustrationTitle,
        illust.userName
      ));
    });

    // Wait for image loading
    return Promise.all(items.map(item => {
      return new Promise(resolve => {
        item.img.onload = item.img.onerror = () => resolve(item);
      });
    }));
  })
  .then(items => {
    items.forEach(item => {
      document.querySelector('#gallery').appendChild(item.anchor);
    });

    setTimeout(() => {
      items.forEach(item => item.img.classList.add('loaded'));
    }, 125);
  }).catch(response => {
    console.log(response);
  });
}

document.addEventListener('DOMContentLoaded', event => {
  init();
});

function createIllustrationElement(imageUrl, title, author) {
  const img = new Image();
  img.src = imageUrl;
  img.alt = `${author} / ${title}`;
  return img;
}

function createGalleryItem(illustrationId, imageUrl, title, author) {
    const linkUrl = `https://www.pixiv.net/i/${illustrationId}`;
    const img = createIllustrationElement(imageUrl, title, author);
    const anchor = document.createElement('a');
    anchor.setAttribute('href', linkUrl);
    anchor.setAttribute('target', 'pixiv');
    anchor.appendChild(img);
    return {anchor, img};
}

function shuffle(array) {
  let n = array.length;

  while (n) {
    const i = Math.floor(Math.random() * n--);
    const t = array[n];
    array[n] = array[i];
    array[i] = t;
  }

  return array;
}
<|endoftext|>


<commit_before>function main() {

  // Get the location then fetch the JSON
  showMessage("Looking up your current location...");

  navigator.geolocation.getCurrentPosition(function(position) {

    // Make sure we got a good response back
    if (position.coords && position.coords.latitude && position.coords.longitude) {
      var lat = position.coords.latitude;
      var lng = position.coords.longitude;
      showMessage("Retrieving weather for your location...");
    }
    else {
      showMessage("Could not get current location");
      return;
    }

    // Call the NOAA JSON API
    var url = "https://forecast.weather.gov/MapClick.php?";
    url += "&rand=" + (new Date()).getTime();
    url += "&lat=" + lat;
    url += "&lon=" + lng;
    url += "&FcstType=json";
    url += "&_=" + (new Date()).getTime();

    // Note: I'd prefer to use fetch(), but old versions of Mobile Safari don't support it
    var xhr = new XMLHttpRequest();

    // Timeout after 15 seconds
    xhr.timeout = 15 * 1000;

    // When we get the response back
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        try {
          var jsonResponse = JSON.parse(xhr.responseText);
          // Make sure we didnt' get a 200 response with a failure message
          if (jsonResponse.hasOwnProperty("success") && jsonResponse.success === false) {
            showError("Bad response returned from NWS.");
            return;
          }
        }
        catch(e) {
          showError("Bad response returned from NWS.");
          return;
        }
        var observation = createObservation(jsonResponse);
        var forecasts = createForecasts(jsonResponse);
        showWeather(observation, forecasts);
      }
    }

    // If the request errors
    xhr.onerror = function(error) {
      showError("An error occurred. NWS servers might be down.");
    }

    // If the request times out
    xhr.ontimeout = function(error) {
      showError("Could not reach NWS servers.");
    }

    // Send the request off
    xhr.open("GET", url, true);
    xhr.send();

  }, function(error) {
    showMessage("Unable to get your current location.");
  });

}

// Put an error message into the  tag with a "try again" link
function showError(message) {
  var errorMessage = message + "

Try again";
  document.querySelector("main").innerHTML = errorMessage;
}

// Put a string message into the  tag
function showMessage(message) {
  document.querySelector("main").innerHTML = message;
}

// Render the weather template and put the result in the  tag
function showWeather(observation, forecasts) {
  var template = document.getElementById("template").innerHTML;
  var rendered = Mustache.render(template, {observation: observation, days: forecasts});
  document.querySelector("main").innerHTML = rendered;
}

// Creates an observation object from the API response
function createObservation(jsonResponse) {
  var observation = {
    currentTemp: jsonResponse.currentobservation.Temp,
    relHumidity: jsonResponse.currentobservation.Relh,
    windSpeed: jsonResponse.currentobservation.Winds,
    dewPoint: jsonResponse.currentobservation.Dewp,
    locationName: jsonResponse.location.areaDescription,
    windGust: jsonResponse.currentobservation.Gust + " mph",
    windDir: getCardinalDirection(jsonResponse.currentobservation.Windd),
    pressure: jsonResponse.currentobservation.Altimeter + " mb",
    conditions: jsonResponse.currentobservation.Weather,
    windChill: jsonResponse.currentobservation.WindChill,
    visibility: jsonResponse.currentobservation.Visibility + " miles"
  }

  // The wind gust might be "NA"
  if (jsonResponse.currentobservation.Gust === "NA") {
    observation.windGust = "None";
  }

  // Sometimes the wind direction is "NA"
  if (jsonResponse.currentobservation.Windd === "NA") {
    observation.windDir = "";
  }

  // The pressure might be "NA"
  if (jsonResponse.currentobservation.Altimeter === "NA") {
    observation.pressure = "Unknown";
  }

  // The conditions might be "NA"
  if (jsonResponse.currentobservation.Weather === "NA") {
    observation.conditions = "Unknown";
  }

  // The wind chill might be "NA"
  if (jsonResponse.currentobservation.WindChill === "NA") {
    observation.windChill = jsonResponse.currentobservation.Temp;
  }

  // The visibility might be "NA"
  if (jsonResponse.currentobservation.Visibility === "NA") {
    observation.visibility = "Unknown";
  }

  return observation;
}

// Take the data arrays and combine them into a forecast object for each day
function createForecasts(jsonResponse) {
  var numberOfDays = jsonResponse.time.startPeriodName.length;
  var forecasts = [];
  for (var index=0; index<numberOfDays; index++) {
    forecasts.push({
      period: jsonResponse.time.startPeriodName[index],
      weather: jsonResponse.data.weather[index],
      tempLabel: jsonResponse.time.tempLabel[index],
      temp: jsonResponse.data.temperature[index],
      text: jsonResponse.data.text[index]
    });
  }
  return forecasts;
}

// Take a compass direction (0-360) and return the cardinal direction (N, S, E, W, etc.)
function getCardinalDirection(angle) {
  var angle = parseInt(angle);
  var directions = 8;
  var degree = 360 / directions;
  angle = angle + degree/2;
  if (angle >= 0 * degree && angle < 1 * degree)
      return "N";
  if (angle >= 1 * degree && angle < 2 * degree)
      return "NE";
  if (angle >= 2 * degree && angle < 3 * degree)
      return "E";
  if (angle >= 3 * degree && angle < 4 * degree)
      return "SE";
  if (angle >= 4 * degree && angle < 5 * degree)
      return "S";
  if (angle >= 5 * degree && angle < 6 * degree)
      return "SW";
  if (angle >= 6 * degree && angle < 7 * degree)
      return "W";
  if (angle >= 7 * degree && angle < 8 * degree)
      return "NW";
  return "N";
}

// Run main when we load this script
main();
<commit_msg>Made a big change so that users can bookmark a location and it will not have to geolocate every time.<commit_after>// Calls the NOAA API for the given lat, long
function fetchNoaa(curLocation, callbackSuccess, callbackError) {

  // Construct the URL
  var url = "https://forecast.weather.gov/MapClick.php?";
  url += "&rand=" + (new Date()).getTime();
  url += "&lat=" + curLocation.lat;
  url += "&lon=" + curLocation.lng;
  url += "&FcstType=json";
  url += "&_=" + (new Date()).getTime();

  // Note: I'd prefer to use fetch(), but old versions of Mobile Safari don't support it
  var xhr = new XMLHttpRequest();

  // Timeout after 15 seconds
  xhr.timeout = 15 * 1000;

  // When we get the response back
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      try {
        var jsonResponse = JSON.parse(xhr.responseText);
        // Make sure we didnt' get a 200 response with a failure message
        if (jsonResponse.hasOwnProperty("success") && jsonResponse.success === false) {
          callbackError("Bad response returned from NWS.");
          return;
        }
        else {
          callbackSuccess(jsonResponse);
          return;
        }
      }
      catch(e) {
        callbackError("Bad response returned from NWS.");
        return;
      }
    }
  }

  // If the request errors
  xhr.onerror = function(error) {
    callbackError("An error occurred. NWS servers might be down.");
    return;
  }

  // If the request times out
  xhr.ontimeout = function(error) {
    callbackError("Could not reach NWS servers.");
    return;
  }

  // Send the request off
  xhr.open("GET", url, true);
  xhr.send();

}

// Parses the NOAA API JSON, renders the output template, then puts it in the DOM
function renderWeather(jsonResponse) {
  var observation = createObservation(jsonResponse);
  var forecasts = createForecasts(jsonResponse);
  var template = document.getElementById("template").innerHTML;
  var rendered = Mustache.render(template, {observation: observation, days: forecasts});
  document.querySelector("main").innerHTML = rendered;
}

// Uses the Geolocation API to get current location
function queryLocation(callbackSuccess, callbackError) {
  navigator.geolocation.getCurrentPosition(function(position) {
    // Make sure we got a good response back
    if (position.coords && position.coords.latitude && position.coords.longitude) {
      var lat = position.coords.latitude;
      var lng = position.coords.longitude;
      callbackSuccess({ lat: lat, lng: lng });
    }
    else {
      callbackError("Could not get current location");
    }
  }, function(error) {
    callbackError("Unable to get your current location.");
  });
}

// Put an error message into the  tag with a "try again" link
function showError(message) {
  var errorMessage = message + "

Try again";
  document.querySelector("main").innerHTML = errorMessage;
}

// Put a string message into the  tag
function showMessage(message) {
  document.querySelector("main").innerHTML = message;
}

// Creates an observation object from the API response
function createObservation(jsonResponse) {
  var observation = {
    currentTemp: jsonResponse.currentobservation.Temp,
    relHumidity: jsonResponse.currentobservation.Relh,
    windSpeed: jsonResponse.currentobservation.Winds,
    dewPoint: jsonResponse.currentobservation.Dewp,
    locationName: jsonResponse.location.areaDescription,
    windGust: jsonResponse.currentobservation.Gust + " mph",
    windDir: getCardinalDirection(jsonResponse.currentobservation.Windd),
    pressure: jsonResponse.currentobservation.Altimeter + " mb",
    conditions: jsonResponse.currentobservation.Weather,
    windChill: jsonResponse.currentobservation.WindChill,
    visibility: jsonResponse.currentobservation.Visibility + " miles"
  }

  // The wind gust might be "NA"
  if (jsonResponse.currentobservation.Gust === "NA") {
    observation.windGust = "None";
  }

  // Sometimes the wind direction is "NA"
  if (jsonResponse.currentobservation.Windd === "NA") {
    observation.windDir = "";
  }

  // The pressure might be "NA"
  if (jsonResponse.currentobservation.Altimeter === "NA") {
    observation.pressure = "Unknown";
  }

  // The conditions might be "NA"
  if (jsonResponse.currentobservation.Weather === "NA") {
    observation.conditions = "Unknown";
  }

  // The wind chill might be "NA"
  if (jsonResponse.currentobservation.WindChill === "NA") {
    observation.windChill = jsonResponse.currentobservation.Temp;
  }

  // The visibility might be "NA"
  if (jsonResponse.currentobservation.Visibility === "NA") {
    observation.visibility = "Unknown";
  }

  return observation;
}

// Take the data arrays and combine them into a forecast object for each day
function createForecasts(jsonResponse) {
  var numberOfDays = jsonResponse.time.startPeriodName.length;
  var forecasts = [];
  for (var index=0; index<numberOfDays; index++) {
    forecasts.push({
      period: jsonResponse.time.startPeriodName[index],
      weather: jsonResponse.data.weather[index],
      tempLabel: jsonResponse.time.tempLabel[index],
      temp: jsonResponse.data.temperature[index],
      text: jsonResponse.data.text[index]
    });
  }
  return forecasts;
}

// Take a compass direction (0-360) and return the cardinal direction (N, S, E, W, etc.)
function getCardinalDirection(angle) {
  var angle = parseInt(angle);
  var directions = 8;
  var degree = 360 / directions;
  angle = angle + degree/2;
  if (angle >= 0 * degree && angle < 1 * degree)
      return "N";
  if (angle >= 1 * degree && angle < 2 * degree)
      return "NE";
  if (angle >= 2 * degree && angle < 3 * degree)
      return "E";
  if (angle >= 3 * degree && angle < 4 * degree)
      return "SE";
  if (angle >= 4 * degree && angle < 5 * degree)
      return "S";
  if (angle >= 5 * degree && angle < 6 * degree)
      return "SW";
  if (angle >= 6 * degree && angle < 7 * degree)
      return "W";
  if (angle >= 7 * degree && angle < 8 * degree)
      return "NW";
  return "N";
}

// Looks in the window.hash to see if we have coordinates
function locationFromWindowHash() {
  if (window.location.hash) {
    var parts = window.location.hash.substring(1).split(",");
    if (parts.length === 2) {
      return { lat: parts[0], lng: parts[1] }
    }
  }
  return { lat: null, lng: null };
}

// Try to get the lat,lng from the URL
var curLocation = locationFromWindowHash();

// If we don't have a location, go get one
if (!curLocation.lat || !curLocation.lng) {
  showMessage("Finding your current location...");
  queryLocation(function(location) {
    // Add the location fragement to the URL for bookmarking
    window.location.hash = curLocation.lat.toString() + "," + curLocation.lng.toString();
    // Call the API and show the results
    showMessage("Retrieving current weather from NOAA...");
    fetchNoaa(curLocation, function(response) {
      renderWeather(response);
    }, function(error) {
      showError("Could not fetch weather from NOAA.");
    }); // fetchNoaa
  }, function(error) {
    showError("Could not get your current location.");
  }); // queryLocation
}

// We do have a location, so just use it
else {
  showMessage("Retrieving current weather from NOAA...");
  fetchNoaa(curLocation, function(response) {
    renderWeather(response);
  }, function(error) {
    showError("Could not fetch weather from NOAA.");
  });
}
<|endoftext|>