<commit_before>/*

Jappix - An open social platform
These are the welcome tool functions for Jappix

-------------------------------------------------

License: AGPL
Author: Valérian Saliou
Last revision: 11/06/11

*/

// Opens the welcome tools
function openWelcome() {
	// Share message
	var share_msg = printf(_e("Using Jappix, an open social platform. I am %s!"), getXID());

	// Popup HTML content
	var html =
	'
' + _e("Welcome!") + '
' +

	'
' +
		'' + _e("Options") + '' +
		'' + _e("Friends") + '' +
		'' + _e("Share") + '' +
	'
' +

	'
' +
		'
' +
			'
' +
				'
' + _e("Welcome on Jappix, your own social cloud!") + '
' +
				'
' + _e("Before you start using it, you will have to change some settings, search for friends and complete your profile.") + '
' +
			'
' +

			'' +
				'' + _e("Sounds") + '' +
				'' + _e("Enable notification sounds") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Geolocation") + '' +
				'' + _e("Share your position on the globe") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("XMPP links") + '' +
				'' + _e("Open XMPP links with Jappix") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Message archiving") + '' +
				'' + _e("Store a history of your chats") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Offline friends") + '' +
				'' + _e("Don\'t hide offline friends") + '' +
				'' +
				'' +
			'' +
		'
' +

		'
' +
			'
' +
				'
' + _e("Friends") + '
' +
				'
' + _e("Use this tool to find your friends on the server you are using right now, or add them later.") + '
' +
			'
' +

			'

' +
		'
' +

		'
' +
			'
' +
				'
' + _e("Share") + '
' +
				'
' + _e("Great work! Now, you can share Jappix with your friends!") + '
' +
				'
' + _e("When you will press the save button, the profile editor will be opened. Happy socializing!") + '
' +
			'
' +

			'' +
				'' +
				'Facebook' +
				'' + printf(_e("Share Jappix on %s"), 'Facebook') + '' +
				'' +
			'' +

			'' +
				'' +
				'Twitter' +
				'' + printf(_e("Share Jappix on %s"), 'Twitter') + '' +
				'' +
			'' +

			'' +
				'' +
				'Google Buzz' +
				'' + printf(_e("Share Jappix on %s"), 'Google Buzz') + '' +
				'' +
			'' +

			'' +
				'' +
				'Identi.ca' +
				'' + printf(_e("Share Jappix on %s"), 'Identi.ca') + '' +
				'' +
			'' +
		'
' +
	'
' +

	'
' +
		'

' +

		'' + _e("Next") + ' »' +
		'' + _e("Save") + '' +
	'
';

	// Create the popup
	createPopup('welcome', html);

	// Apply the features
	applyFeatures('welcome');

	// Associate the events
	launchWelcome();

	logThis('Welcome assistant opened.');
}

// Closes the welcome tools
function closeWelcome() {
	// Destroy the popup
	destroyPopup('welcome');

	return false;
}

// Switches the welcome tabs
function switchWelcome(id) {
	// Path to
	var welcome = '#welcome ';
	var content = welcome + '.content .';
	var tab = welcome + '.tab ';
	var wait = $(welcome + '.wait');

	$(content + 'one-lap').hide();
	$(content + 'welcome' + id).show();
	$(tab + 'a').removeClass('tab-active');
	$(tab + 'a[data-step=' + id + ']').addClass('tab-active').removeClass('tab-missing');

	// Update the "save" button if all is okay
	if(!exists(tab + '.tab-missing')) {
		var finish = welcome + '.finish.';
		$(finish + 'save').show();
		$(finish + 'next').hide();
	}

	// If this is ID 2: vJUD search
	if(id == 2) {
		wait.show();
		dataForm(HOST_VJUD, 'search', '', '', 'welcome');
	}

	else
		wait.hide();

	return false;
}

// Sends the welcome options
function sendWelcome(array) {
	// Sends the options
	var iq = new JSJaCIQ();
	iq.setType('set');

	var query = iq.setQuery(NS_PRIVATE);
	var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));

	// Value array
	var tags = new Array('sounds', 'geolocation', '', '', 'roster-showall');

	// Build the XML with the array
	for(i in array) {
		var value = array[i];
		var tag = tags[i];

		if((i != 2) && (i != 3) && tag && value) {
			storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value));
			setDB('options', tag, value);
		}
	}

	con.send(iq);

	// If geolocation is enabled
	if(array[1] == '1')
		geolocate();
}

// Saves the welcome options
function saveWelcome() {
	// Get the new options
	var array = new Array();

	$('#welcome a.box').each(function() {
		var current = '0';

		if($(this).hasClass('enabled'))
			current = '1';

		array.push(current);
	});

	// If XMPP links is enabled
	if(array[2] == '1')
		xmppLinksHandler();

	// If offline buddies showing is enabled
	if(array[4] == '1')
		showAllBuddies('welcome');

	// If archiving is supported by the server
	if(enabledArchives('pref')) {
		var aEnabled = false;

		// If archiving is enabled
		if(array[3] == '1')
			aEnabled = true;

		// Send the archives configuration
		configArchives(aEnabled);
	}

	// Send the new options
	sendWelcome(array);

	// Close the welcome tool
	closeWelcome();

	// Open the profile editor
	openVCard();

	return false;
}

// Goes to the next welcome step
function nextWelcome() {
	// Check the next step to go to
	var next = 1;
	var missing = '#welcome .tab a.tab-missing';

	if(exists(missing))
		next = parseInt($(missing + ':first').attr('data-step'));

	// Switch to the next step
	switchWelcome(next);

	return false;
}

// Plugin launcher
function launchWelcome() {
	// Click events
	$('#welcome .tab a').click(function() {
		// Switch to the good tab
		var key = parseInt($(this).attr('data-step'));

		return switchWelcome(key);
	});

	$('#welcome a.box:not(.share)').click(function() {
		if($(this).hasClass('enabled'))
			$(this).removeClass('enabled').attr('title', _e("Click to enable"));
		else
			$(this).addClass('enabled').attr('title', _e("Click to disable"));

		return false;
	});

	$('#welcome .bottom .finish').click(function() {
		if($(this).is('.next'))
			return nextWelcome();
		if($(this).is('.save'))
			return saveWelcome();

		return false;
	});
}
<commit_msg>Facebook share link updated to new one.<commit_after>/*

Jappix - An open social platform
These are the welcome tool functions for Jappix

-------------------------------------------------

License: AGPL
Author: Valérian Saliou
Last revision: 24/07/11

*/

// Opens the welcome tools
function openWelcome() {
	// Share message
	var share_msg = printf(_e("Using Jappix, an open social platform. I am %s!"), getXID());

	// Popup HTML content
	var html =
	'
' + _e("Welcome!") + '
' +

	'
' +
		'' + _e("Options") + '' +
		'' + _e("Friends") + '' +
		'' + _e("Share") + '' +
	'
' +

	'
' +
		'
' +
			'
' +
				'
' + _e("Welcome on Jappix, your own social cloud!") + '
' +
				'
' + _e("Before you start using it, you will have to change some settings, search for friends and complete your profile.") + '
' +
			'
' +

			'' +
				'' + _e("Sounds") + '' +
				'' + _e("Enable notification sounds") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Geolocation") + '' +
				'' + _e("Share your position on the globe") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("XMPP links") + '' +
				'' + _e("Open XMPP links with Jappix") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Message archiving") + '' +
				'' + _e("Store a history of your chats") + '' +
				'' +
				'' +
			'' +

			'' +
				'' + _e("Offline friends") + '' +
				'' + _e("Don\'t hide offline friends") + '' +
				'' +
				'' +
			'' +
		'
' +

		'
' +
			'
' +
				'
' + _e("Friends") + '
' +
				'
' + _e("Use this tool to find your friends on the server you are using right now, or add them later.") + '
' +
			'
' +

			'

' +
		'
' +

		'
' +
			'
' +
				'
' + _e("Share") + '
' +
				'
' + _e("Great work! Now, you can share Jappix with your friends!") + '
' +
				'
' + _e("When you will press the save button, the profile editor will be opened. Happy socializing!") + '
' +
			'
' +

			'' +
				'' +
				'Facebook' +
				'' + printf(_e("Share Jappix on %s"), 'Facebook') + '' +
				'' +
			'' +

			'' +
				'' +
				'Twitter' +
				'' + printf(_e("Share Jappix on %s"), 'Twitter') + '' +
				'' +
			'' +

			'' +
				'' +
				'Google Buzz' +
				'' + printf(_e("Share Jappix on %s"), 'Google Buzz') + '' +
				'' +
			'' +

			'' +
				'' +
				'Identi.ca' +
				'' + printf(_e("Share Jappix on %s"), 'Identi.ca') + '' +
				'' +
			'' +
		'
' +
	'
' +

	'
' +
		'

' +

		'' + _e("Next") + ' »' +
		'' + _e("Save") + '' +
	'
';

	// Create the popup
	createPopup('welcome', html);

	// Apply the features
	applyFeatures('welcome');

	// Associate the events
	launchWelcome();

	logThis('Welcome assistant opened.');
}

// Closes the welcome tools
function closeWelcome() {
	// Destroy the popup
	destroyPopup('welcome');

	return false;
}

// Switches the welcome tabs
function switchWelcome(id) {
	// Path to
	var welcome = '#welcome ';
	var content = welcome + '.content .';
	var tab = welcome + '.tab ';
	var wait = $(welcome + '.wait');

	$(content + 'one-lap').hide();
	$(content + 'welcome' + id).show();
	$(tab + 'a').removeClass('tab-active');
	$(tab + 'a[data-step=' + id + ']').addClass('tab-active').removeClass('tab-missing');

	// Update the "save" button if all is okay
	if(!exists(tab + '.tab-missing')) {
		var finish = welcome + '.finish.';
		$(finish + 'save').show();
		$(finish + 'next').hide();
	}

	// If this is ID 2: vJUD search
	if(id == 2) {
		wait.show();
		dataForm(HOST_VJUD, 'search', '', '', 'welcome');
	}

	else
		wait.hide();

	return false;
}

// Sends the welcome options
function sendWelcome(array) {
	// Sends the options
	var iq = new JSJaCIQ();
	iq.setType('set');

	var query = iq.setQuery(NS_PRIVATE);
	var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));

	// Value array
	var tags = new Array('sounds', 'geolocation', '', '', 'roster-showall');

	// Build the XML with the array
	for(i in array) {
		var value = array[i];
		var tag = tags[i];

		if((i != 2) && (i != 3) && tag && value) {
			storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value));
			setDB('options', tag, value);
		}
	}

	con.send(iq);

	// If geolocation is enabled
	if(array[1] == '1')
		geolocate();
}

// Saves the welcome options
function saveWelcome() {
	// Get the new options
	var array = new Array();

	$('#welcome a.box').each(function() {
		var current = '0';

		if($(this).hasClass('enabled'))
			current = '1';

		array.push(current);
	});

	// If XMPP links is enabled
	if(array[2] == '1')
		xmppLinksHandler();

	// If offline buddies showing is enabled
	if(array[4] == '1')
		showAllBuddies('welcome');

	// If archiving is supported by the server
	if(enabledArchives('pref')) {
		var aEnabled = false;

		// If archiving is enabled
		if(array[3] == '1')
			aEnabled = true;

		// Send the archives configuration
		configArchives(aEnabled);
	}

	// Send the new options
	sendWelcome(array);

	// Close the welcome tool
	closeWelcome();

	// Open the profile editor
	openVCard();

	return false;
}

// Goes to the next welcome step
function nextWelcome() {
	// Check the next step to go to
	var next = 1;
	var missing = '#welcome .tab a.tab-missing';

	if(exists(missing))
		next = parseInt($(missing + ':first').attr('data-step'));

	// Switch to the next step
	switchWelcome(next);

	return false;
}

// Plugin launcher
function launchWelcome() {
	// Click events
	$('#welcome .tab a').click(function() {
		// Switch to the good tab
		var key = parseInt($(this).attr('data-step'));

		return switchWelcome(key);
	});

	$('#welcome a.box:not(.share)').click(function() {
		if($(this).hasClass('enabled'))
			$(this).removeClass('enabled').attr('title', _e("Click to enable"));
		else
			$(this).addClass('enabled').attr('title', _e("Click to disable"));

		return false;
	});

	$('#welcome .bottom .finish').click(function() {
		if($(this).is('.next'))
			return nextWelcome();
		if($(this).is('.save'))
			return saveWelcome();

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


<commit_before>'use strict';

const BlogCategory = use('App/Models/BlogCategory');
const BlogPost = use('App/Models/BlogPost');
const User = use('App/Models/User');

class BlogController {

  async index({ view }) {
    const categories = await BlogCategory.all();

    // Eagerloading to avoid n+1 requests.
    const posts = await BlogPost
      .query()
      .with('user')
      .orderBy('updated_at', 'desc')
      .fetch();

    return view.render('frontend.blog.home', {
      categories: categories.toJSON(),
      posts: posts.toJSON(),
    });
  }

  async show({ view, params, request, response }) {
    const categories = await BlogCategory.all();
    const postPromise = await BlogPost.query().where('slug', params.slug).first();
    const postJSON = postPromise.toJSON();
    const author = await User.find(postJSON.user_id);

    return view.render('frontend.blog.show', {
      post: postJSON,
      author: author.toJSON(),
      categories: categories.toJSON(),
    });
  }

  async showTag({ view, params }) {
    const categories = await BlogCategory.all();
    const tag = await BlogCategory.query().where('slug', params.slug).first();

    // Eagerloading to avoid n+1 requests.
    const posts = await BlogPost
      .query()
      .with('user')
      .where('category_id', tag.id)
      .orderBy('updated_at', 'desc')
      .fetch();

    return view.render('frontend.blog.home', {
      categories: categories.toJSON(),
      posts: posts.toJSON(),
    });
  }
}

module.exports = BlogController;
<commit_msg>Little fix until I find why Lucid.with() method returns null...<commit_after>'use strict';

const BlogCategory = use('App/Models/BlogCategory');
const BlogPost = use('App/Models/BlogPost');
const User = use('App/Models/User');

class BlogController {

  async index({ view }) {
    const categories = await BlogCategory.all();

    // Eagerloading to avoid n+1 requests.
    const posts = await BlogPost
      .query()
      .orderBy('updated_at', 'desc')
      .fetch();

    return view.render('frontend.blog.home', {
      categories: categories.toJSON(),
      posts: posts.toJSON(),
    });
  }

  async show({ view, params, request, response }) {
    const categories = await BlogCategory.all();
    const postPromise = await BlogPost.query().where('slug', params.slug).first();
    const postJSON = postPromise.toJSON();
    const author = await User.find(postJSON.user_id);

    return view.render('frontend.blog.show', {
      post: postJSON,
      author: author.toJSON(),
      categories: categories.toJSON(),
    });
  }

  async showTag({ view, params }) {
    const categories = await BlogCategory.all();
    const tag = await BlogCategory.query().where('slug', params.slug).first();

    // Eagerloading to avoid n+1 requests.
    const posts = await BlogPost
      .query()
      .with('user')
      .where('category_id', tag.id)
      .orderBy('updated_at', 'desc')
      .fetch();

    return view.render('frontend.blog.home', {
      categories: categories.toJSON(),
      posts: posts.toJSON(),
    });
  }
}

module.exports = BlogController;
<|endoftext|>


<commit_before><commit_msg>remove css js optimization from dexecure<commit_after><|endoftext|>


<commit_before>$(document).ready(function() {

  // TOOD: limit headings to h3 .... hx
  var CkEditor = {
    toolbar: [
      { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
      { name: 'tools', items: [ 'Maximize' ] },
      { name: 'document', items: [ 'Source' ] },
	    '/',
      { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', '-', 'RemoveFormat' ] },
      { name: 'paragraph', groups: [ 'list', 'indent' ], items: [ 'NumberedList', 'BulletedList', 'CreateDiv' ] },
      { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
	    { name: 'styles', items: ['Format'] },
    ]
  };

  var opts = {
    toolbar: CkEditor.toolbar,
    format_tags: 'p;h1;h2;h3;h4'
  };

  // do not use the class name .ckeditor for richtext textareas.
  // some magic initialization will take place by default.
  CkEditor.init = function(scope) {
    $('.richtext', scope).each(function(idx, textarea) {
      $(textarea).ckeditor(opts);
    });
  };

  CkEditor.destroy = function(scope) {
    $('.richtext', scope).each(function(idx, textarea){
      var id = $(textarea).attr('id'),
          editor = CKEDITOR.instances[id];
      if (typeof editor !== 'undefined') {
        editor.destroy();
        CKEDITOR.remove(id);
      }
    });
  };

  window.CmsCkEditor = {
    init: CkEditor.init,
    destroy: CkEditor.destroy
  };

});
<commit_msg>add iframe to ckeditro extra allowed content #20149<commit_after>$(document).ready(function() {
  CKEDITOR.config.extraAllowedContent = 'iframe[*]';

  // TOOD: limit headings to h3 .... hx
  var CkEditor = {
    toolbar: [
      { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
      { name: 'tools', items: [ 'Maximize' ] },
      { name: 'document', items: [ 'Source' ] },
	    '/',
      { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', '-', 'RemoveFormat' ] },
      { name: 'paragraph', groups: [ 'list', 'indent' ], items: [ 'NumberedList', 'BulletedList', 'CreateDiv' ] },
      { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
	    { name: 'styles', items: ['Format'] },
    ]
  };

  var opts = {
    toolbar: CkEditor.toolbar,
    format_tags: 'p;h1;h2;h3;h4'
  };

  // do not use the class name .ckeditor for richtext textareas.
  // some magic initialization will take place by default.
  CkEditor.init = function(scope) {
    $('.richtext', scope).each(function(idx, textarea) {
      $(textarea).ckeditor(opts);
    });
  };

  CkEditor.destroy = function(scope) {
    $('.richtext', scope).each(function(idx, textarea){
      var id = $(textarea).attr('id'),
          editor = CKEDITOR.instances[id];
      if (typeof editor !== 'undefined') {
        editor.destroy();
        CKEDITOR.remove(id);
      }
    });
  };

  window.CmsCkEditor = {
    init: CkEditor.init,
    destroy: CkEditor.destroy
  };

});
<|endoftext|>


<commit_before>// Noty
window.displayNoty = function(text, timeout, type) {
  noty({
    text: text,
    timeout: timeout,
    type: type,
    layout: 'topRight',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated bounceInRight',
      close: 'animated bounceOutRight',
      easing: 'swing',
      speed: 500
    }
  });
};

window.confirm = function(message, okCallback, cancelCallback) {
  var okButton = {
    addClass: 'btn btn-primary',
    text: I18n.t('actions.ok'),
    onClick: function($noty) {
      $noty.close();
      if (okCallback !== undefined && _.isFunction(okCallback)) {
        okCallback();
      }
      return false;
    }
  };

  var cancelButton = {
    addClass: 'btn btn-danger',
    text: I18n.t('actions.cancel'),
    onClick: function($noty) {
      $noty.close();
      if (cancelCallback !== undefined && _.isFunction(cancelCallback)) {
        cancelCallBack();
      }
      return false;
    }
  };

  noty({
    text: message,
    buttons: [okButton, cancelButton],
    type: 'warning',
    layout: 'bottom',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated fadeInUp',
      close: 'animated fadeOutDown',
      easing: 'swing',
      speed: 500
    }
  });
};

window.displayConfirm = function(ev, $element) {
  var okButton = {
    addClass: 'btn btn-primary',
    text: I18n.t('actions.ok'),
    onClick: function($noty) {
      $noty.close();
      if ($element.data('method') === undefined) {
        window.location = $element.attr('href');
      } else {
        console.log($element.data('method'));
        $.ajax({
          url: $element.attr('href'),
          method: $element.data('method'),
          complete: function(result) {
            if ($element.data('redirect') === undefined) {
              window.location.reload();
            } else {
              window.location = $element.data('redirect');
            }
          }
        });
      }
      return false;
    }
  };

  var cancelButton = {
    addClass: 'btn btn-danger',
    text: I18n.t('actions.cancel'),
    onClick: function($noty) {
      $noty.close();
      return false;
    }
  };

  noty({
    text: $element.data('notyconfirm'),
    buttons: [okButton, cancelButton],
    type: 'warning',
    layout: 'bottom',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated fadeInUp',
      close: 'animated fadeOutDown',
      easing: 'swing',
      speed: 500
    }
  });
};

window.displaySuccess = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'success');
};

window.displayAlert = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'warning');
};

window.displayInfo = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'alert');
};

window.displayError = function(text, timeout) {
  if (timeout === undefined) {
    timeout = false;
  }
  displayNoty(text, timeout, 'error');
};

$(function() {

  $("[data-notyConfirm]").click(function(ev) {
    displayConfirm(ev, $(this));
    return false;
  });

  var success = $('body').data('success');
  if (success) {
    displaySuccess(success);
  }

  var info = $('body').data('info');
  if (info) {
    displayAlert(info);
  }

  var error = $('body').data('error');
  if (error) {
    displayError(error);
  }
});
<commit_msg>fix(noty): noty needs to be initialized on turbolinks page load<commit_after>// Noty
window.displayNoty = function(text, timeout, type) {
  noty({
    text: text,
    timeout: timeout,
    type: type,
    layout: 'topRight',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated bounceInRight',
      close: 'animated bounceOutRight',
      easing: 'swing',
      speed: 500
    }
  });
};

window.confirm = function(message, okCallback, cancelCallback) {
  var okButton = {
    addClass: 'btn btn-primary',
    text: I18n.t('actions.ok'),
    onClick: function($noty) {
      $noty.close();
      if (okCallback !== undefined && _.isFunction(okCallback)) {
        okCallback();
      }
      return false;
    }
  };

  var cancelButton = {
    addClass: 'btn btn-danger',
    text: I18n.t('actions.cancel'),
    onClick: function($noty) {
      $noty.close();
      if (cancelCallback !== undefined && _.isFunction(cancelCallback)) {
        cancelCallBack();
      }
      return false;
    }
  };

  noty({
    text: message,
    buttons: [okButton, cancelButton],
    type: 'warning',
    layout: 'bottom',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated fadeInUp',
      close: 'animated fadeOutDown',
      easing: 'swing',
      speed: 500
    }
  });
};

window.displayConfirm = function(ev, $element) {
  var okButton = {
    addClass: 'btn btn-primary',
    text: I18n.t('actions.ok'),
    onClick: function($noty) {
      $noty.close();
      if ($element.data('method') === undefined) {
        window.location = $element.attr('href');
      } else {
        console.log($element.data('method'));
        $.ajax({
          url: $element.attr('href'),
          method: $element.data('method'),
          complete: function(result) {
            if ($element.data('redirect') === undefined) {
              window.location.reload();
            } else {
              window.location = $element.data('redirect');
            }
          }
        });
      }
      return false;
    }
  };

  var cancelButton = {
    addClass: 'btn btn-danger',
    text: I18n.t('actions.cancel'),
    onClick: function($noty) {
      $noty.close();
      return false;
    }
  };

  noty({
    text: $element.data('notyconfirm'),
    buttons: [okButton, cancelButton],
    type: 'warning',
    layout: 'bottom',
    theme: 'bootstrapTheme',
    animation: {
      open: 'animated fadeInUp',
      close: 'animated fadeOutDown',
      easing: 'swing',
      speed: 500
    }
  });
};

window.displaySuccess = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'success');
};

window.displayAlert = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'warning');
};

window.displayInfo = function(text, timeout) {
  if (timeout === undefined) {
    timeout = 3000;
  }
  displayNoty(text, timeout, 'alert');
};

window.displayError = function(text, timeout) {
  if (timeout === undefined) {
    timeout = false;
  }
  displayNoty(text, timeout, 'error');
};

document.addEventListener("turbolinks:load", function() {
  $("[data-notyConfirm]").click(function(ev) {
    displayConfirm(ev, $(this));
    return false;
  });

  var success = $('body').data('success');
  if (success) {
    displaySuccess(success);
  }

  var info = $('body').data('info');
  if (info) {
    displayAlert(info);
  }

  var error = $('body').data('error');
  if (error) {
    displayError(error);
  }
});
<|endoftext|>


<commit_before>Teikei.module('Places', function(Places, App, Backbone, Marionette, $, _) {

  // Map Model
  // ----------

  Places.Model = Backbone.Model.extend({

    urlRoot: function(){
      var type = this.get("type").toLowerCase();
      var query = "/api/v1/{type}s/";
      return query.replace("{type}", type);
    },

    parse: function (data) {
      if (data && _.isObject(data.place)) {
        return data.place;
      } else {
        return data;
      }
    },

    destroy: function(callback) {
      callback.error(
        new Places.Model({
          name: "Zombie Place"
        })
      );
      return false;
    },

    defaults: {
      name: "",
      type: "",
      accepts_new_members: "yes",
      address: "",
      city: "",
      contact_email: "",
      contact_funtion: "",
      contact_name: "",
      contact_phone: "",
      contact_url: "",
      description: "",
      is_established: true,
      latitude: "",
      longitude: "",
      places: [],
      founded_at_year: "",
      founded_at_month: "",
      maximum_members: null,
      participation: "",
      acts_ecological: false,
      economical_behavior: "",
      vegetable_products: "",
      animal_products: "",
      beverages: "",
      additional_product_information: "",
      related_places_count: 0,
      delivery_days: "",
      user_id: null,
      updated_at: null,
      image: {
       url: "",
       thumbnail_url: "",
       description: null
      }
    },

    toString: function(){
      string = [];
      string.push(this.get("name"));
      string.push(this.get("type"));
      return string.join(", ");
    }
  });
});
<commit_msg>Remove debugging code from place model.<commit_after>Teikei.module('Places', function(Places, App, Backbone, Marionette, $, _) {

  // Map Model
  // ----------

  Places.Model = Backbone.Model.extend({

    urlRoot: function(){
      var type = this.get("type").toLowerCase();
      var query = "/api/v1/{type}s/";
      return query.replace("{type}", type);
    },

    parse: function (data) {
      if (data && _.isObject(data.place)) {
        return data.place;
      } else {
        return data;
      }
    },

    defaults: {
      name: "",
      type: "",
      accepts_new_members: "yes",
      address: "",
      city: "",
      contact_email: "",
      contact_funtion: "",
      contact_name: "",
      contact_phone: "",
      contact_url: "",
      description: "",
      is_established: true,
      latitude: "",
      longitude: "",
      places: [],
      founded_at_year: "",
      founded_at_month: "",
      maximum_members: null,
      participation: "",
      acts_ecological: false,
      economical_behavior: "",
      vegetable_products: "",
      animal_products: "",
      beverages: "",
      additional_product_information: "",
      related_places_count: 0,
      delivery_days: "",
      user_id: null,
      updated_at: null,
      image: {
       url: "",
       thumbnail_url: "",
       description: null
      }
    },

    toString: function(){
      string = [];
      string.push(this.get("name"));
      string.push(this.get("type"));
      return string.join(", ");
    }
  });
});
<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require best_in_place

//= require jquery-ui
//= require jquery-ui/datepicker-fi
//= require best_in_place.jquery-ui

//= require bootstrap
//= require_self

$.datepicker.setDefaults( $.datepicker.regional[ 'fi' ] );

$(function() {
   $( ".datepicker" ).datepicker( );
 });

function initPage(){
  // Add Error Form style with bootstrap
  $("div.form-group>div.field_with_errors").parent().addClass("error");
  $("#error_explanation").addClass("text-error");

}
$(window).bind('page:change', function() {
    initPage();
});

$(document).ready(function() {
  /* Activating Best In Place */
  jQuery(".best_in_place").best_in_place();
  /* and fading alerts */
  jQuery(".alert").delay(5000).fadeOut("slow");
});
<commit_msg>use minified jss<commit_after>//= require jquery.min
//= require jquery_ujs
//= require best_in_place

//= require jquery-ui/datepicker
//= require jquery-ui/datepicker-fi
//= require best_in_place.jquery-ui

//= require bootstrap.min
//= require_self

$.datepicker.setDefaults( $.datepicker.regional[ 'fi' ] );

$(function() {
   $( ".datepicker" ).datepicker( );
 });

function initPage(){
  // Add Error Form style with bootstrap
  $("div.form-group>div.field_with_errors").parent().addClass("error");
  $("#error_explanation").addClass("text-error");

}
$(window).bind('page:change', function() {
    initPage();
});

$(document).ready(function() {
  /* Activating Best In Place */
  jQuery(".best_in_place").best_in_place();
  /* and fading alerts */
  jQuery(".alert").delay(5000).fadeOut("slow");
});
<|endoftext|>


<commit_before>(function () {

  Meteor.accounts.weibo.setSecret = function (secret) {
    Meteor.accounts.weibo._secret = secret;
  };

  Meteor.accounts.oauth2.registerService('weibo', function(query) {
    if (query.error) {
      // The user didn't authorize access
      return null;
    }

    if (!Meteor.accounts.weibo._clientId || !Meteor.accounts.weibo._appUrl)
      throw new Meteor.accounts.ConfigError("Need to call Meteor.accounts.weibo.config first");
    if (!Meteor.accounts.weibo._secret)
      throw new Meteor.accounts.ConfigError("Need to call Meteor.accounts.weibo.setSecret first");

    var result = getAccessToken(query);
    var identity = getIdentity(result.access_token, parseInt(result.uid, 10));

    return {
      options: {
        services: {
          weibo: {
            id: result.uid,
            accessToken: result.accessToken,
            screenName: identity.screen_name
          }
        }
      }
    };
  });

  var getAccessToken = function (query) {
    var result = Meteor.http.post(
      "https://api.weibo.com/oauth2/access_token", {params: {
        code: query.code,
        client_id: Meteor.accounts.weibo._clientId,
        client_secret: Meteor.accounts.weibo._secret,
        redirect_uri: Meteor.accounts.weibo._appUrl + "/_oauth/weibo?close",
        grant_type: 'authorization_code'
      }});

    if (result.error) // if the http response was an error
      throw result.error;
    if (typeof result.content === "string")
      result.content = JSON.parse(result.content);
    if (result.content.error) // if the http response was a json object with an error attribute
      throw result.content;
    return result.content;
  };

  var getIdentity = function (accessToken, userId) {
    var result = Meteor.http.get(
      "https://api.weibo.com/2/users/show.json",
      {params: {access_token: accessToken, uid: userId}});

    if (result.error)
      throw result.error;
    return result.data;
  };
})();
<commit_msg>Update accounts-weibo according to latest changes in the branch<commit_after>(function () {

  Meteor.accounts.weibo.setSecret = function (secret) {
    Meteor.accounts.weibo._secret = secret;
  };

  Meteor.accounts.oauth2.registerService('weibo', function(query) {
    if (query.error) {
      // The user didn't authorize access
      return null;
    }

    if (!Meteor.accounts.weibo._clientId || !Meteor.accounts.weibo._appUrl)
      throw new Meteor.accounts.ConfigError("Need to call Meteor.accounts.weibo.config first");
    if (!Meteor.accounts.weibo._secret)
      throw new Meteor.accounts.ConfigError("Need to call Meteor.accounts.weibo.setSecret first");

    var result = getAccessToken(query);
    var identity = getIdentity(result.access_token, parseInt(result.uid, 10));

    return {
      options: {
        services: {
          weibo: {
            id: result.uid,
            accessToken: result.accessToken
          }
        }
      },
      extra: {name: identity.screen_name}
    };
  });

  var getAccessToken = function (query) {
    var result = Meteor.http.post(
      "https://api.weibo.com/oauth2/access_token", {params: {
        code: query.code,
        client_id: Meteor.accounts.weibo._clientId,
        client_secret: Meteor.accounts.weibo._secret,
        redirect_uri: Meteor.accounts.weibo._appUrl + "/_oauth/weibo?close",
        grant_type: 'authorization_code'
      }});

    if (result.error) // if the http response was an error
      throw result.error;
    if (typeof result.content === "string")
      result.content = JSON.parse(result.content);
    if (result.content.error) // if the http response was a json object with an error attribute
      throw result.content;
    return result.content;
  };

  var getIdentity = function (accessToken, userId) {
    var result = Meteor.http.get(
      "https://api.weibo.com/2/users/show.json",
      {params: {access_token: accessToken, uid: userId}});

    if (result.error)
      throw result.error;
    return result.data;
  };
})();
<|endoftext|>


<commit_before>'use strict';

module.exports = function(UserBadge) {
  /**
   * If invoked from List User Badges,
   * This method is used to find x badges to be shown for the user.
   * The x is the sum of user badges + default badges if required.
   *
   * If invoked from List SystemBadges,
   * This method just returns all the user badges without any limit.
   *getBadgesForUser
   * @param {*} ctx
   * @param {*} resolve
   */
  var getBadgesForUser = function(ctx, resolve, limit) {
    if (limit) {
      UserBadge.find({
        where: {
          userId: ctx.req.accessToken.userId,
        },
        include: [{
          user: ['scores'],
        }, {
          badge: {
            level: ['category'],
          },
        }],
        limit: ctx.req.configs[0].value,
      }, function(err, userBadges) {
        resolve(userBadges);
      });
    } else {
      UserBadge.find({
        where: {
          userId: ctx.req.accessToken.userId,
        },
        include: [{
          user: ['scores'],
        }, {
          badge: {
            level: ['category'],
          },
        }],
      }, function(err, userBadges) {
        resolve(userBadges);
      });
    }
  };

  /**
  * This remote method is used to list the x badges.
  * The x is the configurable no of user badges to be returned.
  */
  UserBadge.listUserBadges = function(ctx, cb) {
    // Find the list of user badges with the user, score, level and category details.
    // Limit the result set to the configured x
    Promise.resolve(new Promise(function(resolve) {
      getBadgesForUser(ctx, resolve, true);
    })).then((userBadges) => {
      cb(null, userBadges);
    });
  };

  /**
   * This method is used to get the configuration value no_of_badges_in_widget.
   * This happens before the remote method executes.
   */
  UserBadge.beforeRemote('listUserBadges', function(context, unused, next) {
    UserBadge.app.models.config.find({
      where: {name: 'no_of_badges_in_widget'},
    },
      function(err, configs) {
        context.req.configs = configs;
        next();
      });
  });

  /**
  *  This remote method is used to list the x badges.
  */
  UserBadge.remoteMethod('listUserBadges', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-user-badges',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });

  /**
  * This remote method is used to list all the system badges.
  * It also contains the details about the user obtained badges info in it.
  */
  UserBadge.listSystemBadges = function(ctx, cb) {
    let userIdValue = ctx.req.accessToken.userId;

    // Find the list of user badges with the user, score, level and category details.
    // Limit the result set to the configured x
    Promise.resolve(new Promise(function(resolve) {
      getBadgesForUser(ctx, resolve, false);
    })).then((userBadges) => {
      // Process the user badges returned
      let usBadges = [];
      let defaultPromises = [];

      // Get the list of all system badges for all categories and levels
      defaultPromises.push(new Promise(function(resolve) {
        getAllBadges(resolve);
      })
      );
      Promise.all(defaultPromises)
        .then((defaultResponse) => {
          defaultResponse[0].forEach(function(resp) {
            resp = resp.toJSON();
            userBadges.forEach(function(uBadge) {
              uBadge = uBadge.toJSON();

              // Check if the user allready has this badge in the system badge list
              if ((uBadge.badge.id + '') === (resp.id + '')) {
                resp.userId = uBadge.userId;
                resp.user = uBadge.user;
              }
            });
            let tempBadges = {
              'badge': resp,
            };

            // Push the user details into the system badge if user has obtained it.
            if (resp.userId !== undefined && resp.userId !== '') {
              tempBadges.userId = resp.userId;
              tempBadges.user = resp.user;
              delete resp.userId;
              delete resp.user;
            } else {
              /* tempBadges.pointsForNextLevel =
                tempBadges.badge.level.pointsEndRange; */
            }
            usBadges = usBadges.concat(tempBadges);
          });

          // Group the badges by category before returning
          let categoryGroup = groupByCategory(usBadges);

          // Return the group
          cb(null, categoryGroup);
        });
    });
  };

  /**
  * This method is used to group the badges by category Ids.
  */
  var groupByCategory = function(usBadges) {
    let categoryGroup = {};
    usBadges.forEach(function(resp) {
      if (categoryGroup[resp.badge.level.categoryId] != undefined) {
        let catArr = categoryGroup[resp.badge.level.categoryId];
        catArr.push(resp);
        categoryGroup[resp.badge.level.categoryId] = catArr;
      } else {
        let catArr = [];
        catArr.push(resp);
        categoryGroup[resp.badge.level.categoryId] = catArr;
      }
    });

    return categoryGroup;
  };

  /**
  * This method returns the list of all system badges for all the categories.
  */
  var getAllBadges = function(resolve) {
    UserBadge.app.models['Badge'].find({
      include: {
        level: ['category'],
      },
    }, function(err, badges) {
      resolve(badges);
    });
  };

  /**
  * This remote method returns the list of all default system badges for all the categories.
  */
  UserBadge.remoteMethod('listSystemBadges', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-system-badges',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });

  /**
  * This method returns the list of all next levels for the categoryId passed.
  * The result which is the next levels is appended to the score object.
  * This is to access the current score  and the next level easily.
  */
  var getNextLevelsInCategories = function(score, categoryId, resolve) {
    UserBadge.app.models['Level'].find({
      where: {
        categoryId: categoryId,
      },
    }, function(err, nextLevels) {
      score.levels = nextLevels;
      resolve(score);
    });
  };

  /**
  * This remote method returns the list of all categories where the user has scored points.
  */
  UserBadge.listUserCategories = function(ctx, cb) {
    let userIdValue = ctx.req.accessToken.userId;
    // Get the list of all score objects for the user in each category
    let configs = ctx.req.configs;
    UserBadge.app.models.score.find({
      where: {
        userId: userIdValue,
      },
      include: ['category'],
    }, function(err, userScores) {
      const promises = [];
      const categoryIdArr = [];
      if (userScores != undefined) {
        userScores.forEach(function(score) {
          categoryIdArr.push(score.categoryId);
          // Get the next levels for each of the categories where the user has participated
          promises.push(new Promise(function(resolve) {
            getNextLevelsInCategories(score, score.categoryId, resolve);
          }));
        });

        Promise.all(promises).then((response) => {
          Promise.resolve(new Promise(function(resolve) {
            getBadgesForUser(ctx, resolve, false);
          })).then((userBadges) => {
                          // Group the badges by category before returning
            console.log(userBadges);
            let tempBadges = [];
            userBadges.forEach(function(uBadge) {
              uBadge = uBadge.toJSON();
              tempBadges = tempBadges.concat(uBadge);
            });
            let categoryGroup = groupByCategory(tempBadges);
            let respp = {};
            respp.userCategories = response;
            respp.userBadges = categoryGroup;

            cb(null, respp);
          });

            // cb(null, response);
        });
      } else {
        cb(null);
      }
    });
  };
  /**
  * This happens before the remote method executes.
  */
  UserBadge.beforeRemote('listUserCategories', function(context, unused, next) {
    UserBadge.app.models.config.find({
      where: {name: 'no_of_categories_in_widget'},
    },
      function(err, configs) {
        context.req.configs = configs;
        next();
      });
  });

  /**
  * This remote method is used to get the list of all categories for the user.
  * This list includes the sum of user scored categories + default categories.
  */
  UserBadge.remoteMethod('listUserCategories', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-user-categories',
      verb: 'get',
    },
    returns: {
      arg: 'userProgressInfo',
      type: 'object',
    },
  });

  /**
    * This remote method returns the list of all badges that can be claimed by the user.
    */
  UserBadge.listBadgesToBeClaimed = function(ctx, cb) {
    UserBadge.find({
      where: {
        userId: ctx.req.accessToken.userId,
        claimed: false,
      },
      include: [{
        user: ['scores'],
      }, {
        badge: {
          level: ['category'],
        },
      }],
    }, function(err, userBadges) {
      cb(null, userBadges);
    });
  };

  /**
  * This remote method is used to get the list of all categories for the user.
  * This list includes the sum of user scored categories + default categories.
  */
  UserBadge.remoteMethod('listBadgesToBeClaimed', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-badges-to-be-claimed',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });
};
<commit_msg>view all system badges fix<commit_after>'use strict';

module.exports = function(UserBadge) {
  /**
   * If invoked from List User Badges,
   * This method is used to find x badges to be shown for the user.
   * The x is the sum of user badges + default badges if required.
   *
   * If invoked from List SystemBadges,
   * This method just returns all the user badges without any limit.
   *getBadgesForUser
   * @param {*} ctx
   * @param {*} resolve
   */
  var getBadgesForUser = function(ctx, resolve, limit) {
    if (limit) {
      UserBadge.find({
        where: {
          userId: ctx.req.accessToken.userId,
        },
        include: [{
          user: ['scores'],
        }, {
          badge: {
            level: ['category'],
          },
        }],
        limit: ctx.req.configs[0].value,
      }, function(err, userBadges) {
        resolve(userBadges);
      });
    } else {
      UserBadge.find({
        where: {
          userId: ctx.req.accessToken.userId,
        },
        include: [{
          user: ['scores'],
        }, {
          badge: {
            level: ['category'],
          },
        }],
      }, function(err, userBadges) {
        resolve(userBadges);
      });
    }
  };

  /**
  * This remote method is used to list the x badges.
  * The x is the configurable no of user badges to be returned.
  */
  UserBadge.listUserBadges = function(ctx, cb) {
    // Find the list of user badges with the user, score, level and category details.
    // Limit the result set to the configured x
    Promise.resolve(new Promise(function(resolve) {
      getBadgesForUser(ctx, resolve, true);
    })).then((userBadges) => {
      cb(null, userBadges);
    });
  };

  /**
   * This method is used to get the configuration value no_of_badges_in_widget.
   * This happens before the remote method executes.
   */
  UserBadge.beforeRemote('listUserBadges', function(context, unused, next) {
    UserBadge.app.models.config.find({
      where: {name: 'no_of_badges_in_widget'},
    },
      function(err, configs) {
        context.req.configs = configs;
        next();
      });
  });

  /**
  *  This remote method is used to list the x badges.
  */
  UserBadge.remoteMethod('listUserBadges', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-user-badges',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });

  /**
  * This remote method is used to list all the system badges.
  * It also contains the details about the user obtained badges info in it.
  */
  UserBadge.listSystemBadges = function(ctx, cb) {
    let userIdValue = ctx.req.accessToken.userId;

    // Find the list of user badges with the user, score, level and category details.
    // Limit the result set to the configured x
    Promise.resolve(new Promise(function(resolve) {
      getBadgesForUser(ctx, resolve, false);
    })).then((userBadges) => {
      // Process the user badges returned
      let usBadges = [];
      let defaultPromises = [];

      // Get the list of all system badges for all categories and levels
      defaultPromises.push(new Promise(function(resolve) {
        getAllBadges(resolve);
      })
      );
      Promise.all(defaultPromises)
        .then((defaultResponse) => {
          defaultResponse[0].forEach(function(resp) {
            resp = resp.toJSON();
            // To return only main categories
            if (resp.level.category.type === '') {
              userBadges.forEach(function(uBadge) {
                uBadge = uBadge.toJSON();

                // Check if the user allready has this badge in the system badge list
                if ((uBadge.badge.id + '') === (resp.id + '')) {
                  resp.userId = uBadge.userId;
                  resp.user = uBadge.user;
                }
              });
              let tempBadges = {
                'badge': resp,
              };

              // Push the user details into the system badge if user has obtained it.
              if (resp.userId !== undefined && resp.userId !== '') {
                tempBadges.userId = resp.userId;
                tempBadges.user = resp.user;
                delete resp.userId;
                delete resp.user;
              } else {
                /* tempBadges.pointsForNextLevel =
                  tempBadges.badge.level.pointsEndRange; */
              }
              usBadges = usBadges.concat(tempBadges);
            }
          });

          // Group the badges by category before returning
          let categoryGroup = groupByCategory(usBadges);

          // Return the group
          cb(null, categoryGroup);
        });
    });
  };

  /**
  * This method is used to group the badges by category Ids.
  */
  var groupByCategory = function(usBadges) {
    let categoryGroup = {};
    usBadges.forEach(function(resp) {
      if (categoryGroup[resp.badge.level.categoryId] != undefined) {
        let catArr = categoryGroup[resp.badge.level.categoryId];
        catArr.push(resp);
        categoryGroup[resp.badge.level.categoryId] = catArr;
      } else {
        let catArr = [];
        catArr.push(resp);
        categoryGroup[resp.badge.level.categoryId] = catArr;
      }
    });

    return categoryGroup;
  };

  /**
  * This method returns the list of all system badges for all the categories.
  */
  var getAllBadges = function(resolve) {
    UserBadge.app.models['Badge'].find({
      include: {
        level: ['category'],
      },
    }, function(err, badges) {
      resolve(badges);
    });
  };

  /**
  * This remote method returns the list of all default system badges for all the categories.
  */
  UserBadge.remoteMethod('listSystemBadges', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-system-badges',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });

  /**
  * This method returns the list of all next levels for the categoryId passed.
  * The result which is the next levels is appended to the score object.
  * This is to access the current score  and the next level easily.
  */
  var getNextLevelsInCategories = function(score, categoryId, resolve) {
    UserBadge.app.models['Level'].find({
      where: {
        categoryId: categoryId,
      },
    }, function(err, nextLevels) {
      score.levels = nextLevels;
      resolve(score);
    });
  };

  /**
  * This remote method returns the list of all categories where the user has scored points.
  */
  UserBadge.listUserCategories = function(ctx, cb) {
    let userIdValue = ctx.req.accessToken.userId;
    // Get the list of all score objects for the user in each category
    let configs = ctx.req.configs;
    UserBadge.app.models.score.find({
      where: {
        userId: userIdValue,
      },
      include: ['category'],
    }, function(err, userScores) {
      const promises = [];
      const categoryIdArr = [];
      if (userScores != undefined) {
        userScores.forEach(function(score) {
          categoryIdArr.push(score.categoryId);
          // Get the next levels for each of the categories where the user has participated
          promises.push(new Promise(function(resolve) {
            getNextLevelsInCategories(score, score.categoryId, resolve);
          }));
        });

        Promise.all(promises).then((response) => {
          Promise.resolve(new Promise(function(resolve) {
            getBadgesForUser(ctx, resolve, false);
          })).then((userBadges) => {
            // Group the badges by category before returning
            console.log(userBadges);
            let tempBadges = [];
            userBadges.forEach(function(uBadge) {
              uBadge = uBadge.toJSON();
              tempBadges = tempBadges.concat(uBadge);
            });
            let categoryGroup = groupByCategory(tempBadges);
            let respp = {};
            respp.userCategories = response;
            respp.userBadges = categoryGroup;

            cb(null, respp);
          });

          // cb(null, response);
        });
      } else {
        cb(null);
      }
    });
  };
  /**
  * This happens before the remote method executes.
  */
  UserBadge.beforeRemote('listUserCategories', function(context, unused, next) {
    UserBadge.app.models.config.find({
      where: {name: 'no_of_categories_in_widget'},
    },
      function(err, configs) {
        context.req.configs = configs;
        next();
      });
  });

  /**
  * This remote method is used to get the list of all categories for the user.
  * This list includes the sum of user scored categories + default categories.
  */
  UserBadge.remoteMethod('listUserCategories', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-user-categories',
      verb: 'get',
    },
    returns: {
      arg: 'userProgressInfo',
      type: 'object',
    },
  });

  /**
    * This remote method returns the list of all badges that can be claimed by the user.
    */
  UserBadge.listBadgesToBeClaimed = function(ctx, cb) {
    UserBadge.find({
      where: {
        userId: ctx.req.accessToken.userId,
        claimed: false,
      },
      include: [{
        user: ['scores'],
      }, {
        badge: {
          level: ['category'],
        },
      }],
    }, function(err, userBadges) {
      cb(null, userBadges);
    });
  };

  /**
  * This remote method is used to get the list of all categories for the user.
  * This list includes the sum of user scored categories + default categories.
  */
  UserBadge.remoteMethod('listBadgesToBeClaimed', {
    accepts: [
      {arg: 'ctx', type: 'object', http: {source: 'context'}},
    ],
    http: {
      path: '/list-badges-to-be-claimed',
      verb: 'get',
    },
    returns: {
      arg: 'badges',
      type: 'array',
    },
  });
};
<|endoftext|>


<commit_before>/**
 * This file contains some re-usable parts for websocket audio communication.
 *
 * @module api/utils/audio-over-socket
 */

import autobahn from 'autobahn';
import {
  getWebsocketConnection,
  makeWebsocketCall,
} from '../communication/websocket';
import broadcaster from '../broadcaster';
import { dataToBase64, asyncBlobToArrayBuffer } from './index';

/**
 * This class allows us to stream audio from the recorder to the backend.
 * @private
 */
class StreamRecorderAudio {
  /**
   * @param {MediaRecorder} recorder - Recorder to use to capture data from.
   * @param {string} rpcName - Name of the registered RPC function.
   */
  constructor(recorder, rpcName, websocketConnection) {
    /**
     * MediaRecorder to process the stream from.
     * @type {MediaRecorder}
     */
    this.recorder = recorder;

    /**
     * Name of the RPC registered.
     * This name will be prepended with 'nl.itslanguage' for better consistency.
     * @type {string}
     */
    this.rpcName = `nl.itslanguage.${rpcName}`;

    /**
     * Store a reference to the websocket connection.
     * @type {autobahn.Connection}
     */
    this.websocketConnection = websocketConnection;

    /**
     * The autobahn.Registration object. This is returned when you register
     * a function through Session.register.
     * @type {null|autobahn.Registration}
     */
    this.registration = null;

    this.sendAudioChunks = this.sendAudioChunks.bind(this);
    this.register = this.register.bind(this);
    this.unregister = this.unregister.bind(this);
  }

  /**
   * This is the function that will be registered to the autobahn realm that the backend will call
   * to receive audio on.
   *
   * Once called, it will prepare the recorder to allow data transmission trough the progressive
   * results meganism.
   *
   * @see https://github.com/crossbario/autobahn-js/blob/master/doc/reference.md#register
   * @see https://github.com/crossbario/autobahn-js/blob/master/doc/reference.md#progressive-results
   *
   * @private
   * @param {Array} args - Argument list.
   * @param {Object} kwargs - Key-valued argument list.
   * @param {Object} details - Details, just as the progress function.
   * @returns {Promise} - A promise that can be resolved to end the asynchronous behaviour of this
   * registered RCP.
   */
  sendAudioChunks(args, kwargs, details) {
    const defer = new autobahn.when.defer(); // eslint-disable-line new-cap
    let lastChunk = false;

    const processData = ({ data }) => {
      asyncBlobToArrayBuffer(data).then(audioData => {
        if (details.progress) {
          const dataToSend = Array.from(new Uint8Array(audioData));
          details.progress([dataToSend]);

          // If the last one ends, closing time!
          if (lastChunk) {
            defer.resolve();
            this.unregister();
          }
        } else {
          defer.reject('no progress function registered');
        }
      });
    };

    const recorderStopped = () => {
      // When stopped, the dataavailableevent will be triggered
      // one final time, so make sure it will cleanup afterwards
      lastChunk = true;
    };

    // Before adding the events, let's make sure they have not been added
    // on a previous session;
    this.recorder.removeEventListener('dataavailable', processData);
    this.recorder.removeEventListener('stop', recorderStopped);

    // Now add the event listeners!
    this.recorder.addEventListener('dataavailable', processData);
    this.recorder.addEventListener('stop', recorderStopped);

    // Notify listeners that we are ready to process audio;
    this.recorder.dispatchEvent(new Event('recorderready'));

    return defer.promise;
  }

  /**
   * register the RPC to the autobahn realm.
   * @returns {Promise}
   */
  register() {
    return new Promise((resolve, reject) => {
      const { session } = this.websocketConnection;
      // First cleanup previously created registrations on this session;
      Promise.all(
        session.registrations.map(reg => session.unregister(reg)),
      ).then(() => {
        session
          .register(this.rpcName, this.sendAudioChunks)
          .then(registration => {
            this.registration = registration;
            resolve(registration);
          })
          .catch(reject);
      });
    });
  }

  /**
   * unregister the RPC from the autobahn realm.
   */
  unregister() {
    return new Promise((resolve, reject) => {
      this.websocketConnection.session
        .unregister(this.registration)
        .then(() => {
          this.registration = null;
          resolve();
        })
        .catch(reject);
    });
  }
}

/**
 * Register a RPC call to the current websocket connection. The backend will call this registered
 * function once, an then we can send progressive results (the details.progress call) to send audio
 * chunks to the backend. We will send those chunks as soon as we got audio from the recorder.
 *
 * When the recording ends we un-register the rpc.
 *
 * @param {MediaRecorder} recorder - Audio recorder instance.
 * @param {string} rpcName - Name of the RPC to register. This name will be prepended with
 * nl.itslanguage for better consistency.
 * @fires broadcaster#websocketserverreadyforaudio
 * @returns {Promise} - It returns a promise with the service registration as result.
 */
export function registerStreamForRecorder(recorder, rpcName) {
  // Start registering a RPC call. As a result, this function will return a promise with the
  // registration of the RPC as result.
  return new Promise((resolve, reject) => {
    getWebsocketConnection().then(websocketConnection => {
      const streamingSession = new StreamRecorderAudio(
        recorder,
        rpcName,
        websocketConnection,
      );
      streamingSession
        .register()
        .then(registration => {
          /**
           * Notify that we are ready to process audio.
           * @event broadcaster#websocketserverreadyforaudio
           * @deprecated will be removed in a future version
           */
          broadcaster.emit('websocketserverreadyforaudio');
          recorder.dispatchEvent(new Event('websocketserverreadyforaudio'));
          resolve(registration);
        })
        .catch(reject);
    });
  });
}

/**
 * Encode the audio as base64 and send it to the websocket server.
 *
 * @param {string} id - The reserved ID for the audio.
 * @param {MediaRecorder} recorder - The recorder to use to get the recording.
 * @param {string} rpc - The RPC to use to store the data.
 *
 * @returns {Promise<*>} - The response of the given RPC.
 */
export function encodeAndSendAudioOnDataAvailable(id, recorder, rpc) {
  return new Promise((resolve, reject) => {
    let lastChunk = false;

    // When data is received from the recorder, it will be in Blob format.
    // When we read the data from the Blob element, base64 it and send it to
    // the websocket server and continue with the chain.
    const processData = ({ data }) => {
      asyncBlobToArrayBuffer(data).then(audioData => {
        const encoded = dataToBase64(audioData);
        // Send the audio
        makeWebsocketCall(rpc, { args: [id, encoded, 'base64'] })
          .then(result => {
            /* istanbul ignore else */
            if (lastChunk) {
              resolve(result);
            }
          })
          .catch(error => {
            reject(error);
          });
      });
    };

    const recorderStopped = () => {
      // When stopped, the dataavailable event will be triggered
      // one final time, so make sure it will cleanup afterwards
      lastChunk = true;
    };

    // Before adding the events, let's make sure they have not been added
    // on a previous session;
    recorder.removeEventListener('dataavailable', processData);
    recorder.removeEventListener('stop', recorderStopped);

    // Now add the event listeners!
    recorder.addEventListener('dataavailable', processData);
    recorder.addEventListener('stop', recorderStopped);

    // Notify listeners that we are ready to process audio;
    recorder.dispatchEvent(new Event('recorderready'));
  });
}

/**
 * Send the recorder settings to the websocket server to initialize it.
 *
 * The reserved ID (passed in the parameters) is returned once the promise is resolved.
 *
 * @param {string} id - The reserved ID for the audio.
 * @param {MediaRecorder} recorder - The recorder which has been set up to record.
 * @param {string} rpc - The RPC to use to initialize the websocket server.
 *
 * @emits {websocketserverreadyforaudio} - When the websocket server has been prepared for and is
 * ready to receive the audio.
 *
 * @returns {Promise} - The promise which resolves when the websocket server is ready for the audio.
 */
export function prepareServerForAudio(id, recorder, rpc) {
  const { audioFormat, audioParameters } = recorder.getAudioSpecs();
  return makeWebsocketCall(rpc, {
    args: [id, audioFormat],
    kwargs: audioParameters,
  }).then(() => {
    // We've prepped the websocket server, now it can receive audio. Broadcast
    // that it is allowed to record.
    // This call is deprecated and will be removed in a future version, the
    // event on the recorder will stay.
    broadcaster.emit('websocketserverreadyforaudio');
    recorder.dispatchEvent(new Event('websocketserverreadyforaudio'));
    return id;
  });
}
<commit_msg>fix: reuse of recorder<commit_after>/**
 * This file contains some re-usable parts for websocket audio communication.
 *
 * @module api/utils/audio-over-socket
 */

import autobahn from 'autobahn';
import {
  getWebsocketConnection,
  makeWebsocketCall,
} from '../communication/websocket';
import broadcaster from '../broadcaster';
import { dataToBase64, asyncBlobToArrayBuffer } from './index';

/**
 * This class allows us to stream audio from the recorder to the backend.
 * @private
 */
class StreamRecorderAudio {
  /**
   * @param {MediaRecorder} recorder - Recorder to use to capture data from.
   * @param {string} rpcName - Name of the registered RPC function.
   */
  constructor(recorder, rpcName, websocketConnection) {
    /**
     * MediaRecorder to process the stream from.
     * @type {MediaRecorder}
     */
    this.recorder = recorder;

    /**
     * Name of the RPC registered.
     * This name will be prepended with 'nl.itslanguage' for better consistency.
     * @type {string}
     */
    this.rpcName = `nl.itslanguage.${rpcName}`;

    /**
     * Store a reference to the websocket connection.
     * @type {autobahn.Connection}
     */
    this.websocketConnection = websocketConnection;

    /**
     * The autobahn.Registration object. This is returned when you register
     * a function through Session.register.
     * @type {null|autobahn.Registration}
     */
    this.registration = null;

    this.sendAudioChunks = this.sendAudioChunks.bind(this);
    this.register = this.register.bind(this);
    this.unregister = this.unregister.bind(this);
  }

  /**
   * This is the function that will be registered to the autobahn realm that the backend will call
   * to receive audio on.
   *
   * Once called, it will prepare the recorder to allow data transmission trough the progressive
   * results meganism.
   *
   * @see https://github.com/crossbario/autobahn-js/blob/master/doc/reference.md#register
   * @see https://github.com/crossbario/autobahn-js/blob/master/doc/reference.md#progressive-results
   *
   * @private
   * @param {Array} args - Argument list.
   * @param {Object} kwargs - Key-valued argument list.
   * @param {Object} details - Details, just as the progress function.
   * @returns {Promise} - A promise that can be resolved to end the asynchronous behaviour of this
   * registered RCP.
   */
  sendAudioChunks(args, kwargs, details) {
    const defer = new autobahn.when.defer(); // eslint-disable-line new-cap
    let lastChunk = false;

    const processData = ({ data }) => {
      asyncBlobToArrayBuffer(data).then(audioData => {
        if (details.progress) {
          const dataToSend = Array.from(new Uint8Array(audioData));
          details.progress([dataToSend]);

          // If the last one ends, closing time!
          if (lastChunk) {
            defer.resolve();
            this.unregister();
            lastChunk = false;
          }
        } else {
          defer.reject('no progress function registered');
        }
      });
    };

    const recorderStopped = () => {
      // When stopped, the dataavailableevent will be triggered
      // one final time, so make sure it will cleanup afterwards
      lastChunk = true;
    };

    // Before adding the events, let's make sure they have not been added
    // on a previous session;
    this.recorder.removeEventListener('dataavailable', processData);
    this.recorder.removeEventListener('stop', recorderStopped);

    // Now add the event listeners!
    this.recorder.addEventListener('dataavailable', processData);
    this.recorder.addEventListener('stop', recorderStopped);

    // Notify listeners that we are ready to process audio;
    this.recorder.dispatchEvent(new Event('recorderready'));

    return defer.promise;
  }

  /**
   * register the RPC to the autobahn realm.
   * @returns {Promise}
   */
  register() {
    return new Promise((resolve, reject) => {
      const { session } = this.websocketConnection;
      // First cleanup previously created registrations on this session;
      Promise.all(
        session.registrations.map(reg => session.unregister(reg)),
      ).then(() => {
        session
          .register(this.rpcName, this.sendAudioChunks)
          .then(registration => {
            this.registration = registration;
            resolve(registration);
          })
          .catch(reject);
      });
    });
  }

  /**
   * unregister the RPC from the autobahn realm.
   */
  unregister() {
    return new Promise((resolve, reject) => {
      this.websocketConnection.session
        .unregister(this.registration)
        .then(() => {
          this.registration = null;
          resolve();
        })
        .catch(reject);
    });
  }
}

/**
 * Register a RPC call to the current websocket connection. The backend will call this registered
 * function once, an then we can send progressive results (the details.progress call) to send audio
 * chunks to the backend. We will send those chunks as soon as we got audio from the recorder.
 *
 * When the recording ends we un-register the rpc.
 *
 * @param {MediaRecorder} recorder - Audio recorder instance.
 * @param {string} rpcName - Name of the RPC to register. This name will be prepended with
 * nl.itslanguage for better consistency.
 * @fires broadcaster#websocketserverreadyforaudio
 * @returns {Promise} - It returns a promise with the service registration as result.
 */
export function registerStreamForRecorder(recorder, rpcName) {
  // Start registering a RPC call. As a result, this function will return a promise with the
  // registration of the RPC as result.
  return new Promise((resolve, reject) => {
    getWebsocketConnection().then(websocketConnection => {
      const streamingSession = new StreamRecorderAudio(
        recorder,
        rpcName,
        websocketConnection,
      );
      streamingSession
        .register()
        .then(registration => {
          /**
           * Notify that we are ready to process audio.
           * @event broadcaster#websocketserverreadyforaudio
           * @deprecated will be removed in a future version
           */
          broadcaster.emit('websocketserverreadyforaudio');
          recorder.dispatchEvent(new Event('websocketserverreadyforaudio'));
          resolve(registration);
        })
        .catch(reject);
    });
  });
}

/**
 * Encode the audio as base64 and send it to the websocket server.
 *
 * @param {string} id - The reserved ID for the audio.
 * @param {MediaRecorder} recorder - The recorder to use to get the recording.
 * @param {string} rpc - The RPC to use to store the data.
 *
 * @returns {Promise<*>} - The response of the given RPC.
 */
export function encodeAndSendAudioOnDataAvailable(id, recorder, rpc) {
  return new Promise((resolve, reject) => {
    let lastChunk = false;

    // When data is received from the recorder, it will be in Blob format.
    // When we read the data from the Blob element, base64 it and send it to
    // the websocket server and continue with the chain.
    const processData = ({ data }) => {
      asyncBlobToArrayBuffer(data).then(audioData => {
        const encoded = dataToBase64(audioData);
        // Send the audio
        makeWebsocketCall(rpc, { args: [id, encoded, 'base64'] })
          .then(result => {
            /* istanbul ignore else */
            if (lastChunk) {
              resolve(result);
            }
          })
          .catch(error => {
            reject(error);
          });
      });
    };

    const recorderStopped = () => {
      // When stopped, the dataavailable event will be triggered
      // one final time, so make sure it will cleanup afterwards
      lastChunk = true;
    };

    // Before adding the events, let's make sure they have not been added
    // on a previous session;
    recorder.removeEventListener('dataavailable', processData);
    recorder.removeEventListener('stop', recorderStopped);

    // Now add the event listeners!
    recorder.addEventListener('dataavailable', processData);
    recorder.addEventListener('stop', recorderStopped);

    // Notify listeners that we are ready to process audio;
    recorder.dispatchEvent(new Event('recorderready'));
  });
}

/**
 * Send the recorder settings to the websocket server to initialize it.
 *
 * The reserved ID (passed in the parameters) is returned once the promise is resolved.
 *
 * @param {string} id - The reserved ID for the audio.
 * @param {MediaRecorder} recorder - The recorder which has been set up to record.
 * @param {string} rpc - The RPC to use to initialize the websocket server.
 *
 * @emits {websocketserverreadyforaudio} - When the websocket server has been prepared for and is
 * ready to receive the audio.
 *
 * @returns {Promise} - The promise which resolves when the websocket server is ready for the audio.
 */
export function prepareServerForAudio(id, recorder, rpc) {
  const { audioFormat, audioParameters } = recorder.getAudioSpecs();
  return makeWebsocketCall(rpc, {
    args: [id, audioFormat],
    kwargs: audioParameters,
  }).then(() => {
    // We've prepped the websocket server, now it can receive audio. Broadcast
    // that it is allowed to record.
    // This call is deprecated and will be removed in a future version, the
    // event on the recorder will stay.
    broadcaster.emit('websocketserverreadyforaudio');
    recorder.dispatchEvent(new Event('websocketserverreadyforaudio'));
    return id;
  });
}
<|endoftext|>


<commit_before>import File from "../libs/file";
import {FOLDER_ADD,
        FOLDER_DELETE,
        FOLDER_ITEM_ADD,
        FOLDER_ITEM_DELETE,
        FOLDER_ITEM_EDIT,
        FOLDER_FETCH} from '../actions/index';

export default function(state = [],action) {
    const file = new File();
    var folders = [];
    switch (action.type){
        case FOLDER_FETCH:
            return action.payload;

        case FOLDER_ADD:
            folders = [...state,action.payload]
            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });
            return folders;

        case FOLDER_DELETE:
            folders = state.slice();
            folders.splice(action.payload.folder,1);
            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });
            return folders;

        case FOLDER_ITEM_ADD:
            folders = state.map(function(folder){
                if (folder.id == action.payload.folder){
                    folder.items.push({
                        name: action.payload.item.name,
                        description: action.payload.item.description,
                        type: action.payload.item.type,
                        url: action.payload.item.url
                    })
                }
                return folder;
            });

            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });

            alert("Request successfully saved!");

            return folders;

        case FOLDER_ITEM_DELETE:
            folders = state.map(function(folder,index){
                if (index == action.payload.folder){
                    folder.items.splice(action.payload.item,1);
                }
                return folder;
            });

            file.loadStorageFile(function (data){
                data.folders = state
                file.updateStorageFile(data);
            });

            console.log(folders);

            return folders;
        case FOLDER_ITEM_EDIT:
            folders = state.map(function(folder){
                folder.items.forEach(function(item,index){
                    if (item.id === action.payload.item.id){
                        console.log("find id:",item.id," with url: ",action.payload.item.url);
                        folder.items[index] = action.payload.item;
                    }
                })
                return folder;
            });

            console.log(folders);

            file.loadStorageFile(function (data){
                data.folders = state
                file.updateStorageFile(data);
            });

            alert("Request successfully updated!");

            return folders;
    }
    return state;
}
<commit_msg>remove alerts<commit_after>import File from "../libs/file";
import {FOLDER_ADD,
        FOLDER_DELETE,
        FOLDER_ITEM_ADD,
        FOLDER_ITEM_DELETE,
        FOLDER_ITEM_EDIT,
        FOLDER_FETCH} from '../actions/index';

export default function(state = [],action) {
    const file = new File();
    var folders = [];
    switch (action.type){
        case FOLDER_FETCH:
            return action.payload;

        case FOLDER_ADD:
            folders = [...state,action.payload]
            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });
            return folders;

        case FOLDER_DELETE:
            folders = state.slice();
            folders.splice(action.payload.folder,1);
            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });
            return folders;

        case FOLDER_ITEM_ADD:
            folders = state.map(function(folder){
                if (folder.id == action.payload.folder){
                    folder.items.push({
                        name: action.payload.item.name,
                        description: action.payload.item.description,
                        type: action.payload.item.type,
                        url: action.payload.item.url
                    })
                }
                return folder;
            });

            file.loadStorageFile(function (data){
                data.folders = folders
                file.updateStorageFile(data);
            });
            return folders;

        case FOLDER_ITEM_DELETE:
            folders = state.map(function(folder,index){
                if (index == action.payload.folder){
                    folder.items.splice(action.payload.item,1);
                }
                return folder;
            });

            file.loadStorageFile(function (data){
                data.folders = state
                file.updateStorageFile(data);
            });

            console.log(folders);

            return folders;
        case FOLDER_ITEM_EDIT:
            folders = state.map(function(folder){
                folder.items.forEach(function(item,index){
                    if (item.id === action.payload.item.id){
                        console.log("find id:",item.id," with url: ",action.payload.item.url);
                        folder.items[index] = action.payload.item;
                    }
                })
                return folder;
            });

            console.log(folders);

            file.loadStorageFile(function (data){
                data.folders = state
                file.updateStorageFile(data);
            });
            return folders;
    }
    return state;
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { withRouter, Link } from 'olymp';
import { Menu, Icon } from 'antd';
import { ContentLoader, createComponent } from 'olymp-fela';
import { upperFirst } from 'lodash';
import { Gateway } from 'react-gateway';
import { withItem } from '../decorators';
import { DetailForm } from '../components';

const getFormSchema = ({ fields }) =>
  fields.reduce((result, field) => {
    if (field.type.name === 'Blocks') {
      // if slate => own group
      result[upperFirst(field.name)] = [field];
    } else if (field.type.name === 'Image') {
      // if image => own group
      result[upperFirst(field.name)] = [field];
    } else {
      // Group
      const group = field['@'].detail ? field['@'].detail.arg0 : 'Allgemein';

      if (!result[group]) {
        result[group] = [];
      }
      result[group].push(field);
    }
    return result;
  }, {});

const Flex = createComponent(
  ({ theme }) => ({
    display: 'flex',
    flexDirection: 'column',
    paddingTop: theme.space3,
    '> ul': {
      zIndex: 1,
    },
    '> form': {
      overflow: 'auto',
    },
  }),
  'div',
  []
);

const RightSubMenu = createComponent(
  () => ({
    float: 'right!important',
  }),
  p => <Menu.SubMenu {...p} />,
  p => Object.keys(p)
);
const RightMenuItem = createComponent(
  () => ({
    float: 'right!important',
  }),
  p => <Menu.Item {...p} />,
  p => Object.keys(p)
);

@withRouter
@withItem
export default class CollectionDetail extends Component {
  render() {
    const { id, item, collection, onSave, pathname, query } = this.props;
    const schema = getFormSchema(collection);
    const keys = Object.keys(schema);
    const currentTab = query.tab || Object.keys(schema)[0];
    return (
      <ContentLoader isLoading={id && !item}>
        <Flex>
          <Gateway into="navigation">
            <RightSubMenu>
              <RightMenuItem key="save">

                  <Icon type="save" /> Speichern

              </RightMenuItem>
              {keys.map(tab =>
                (<RightMenuItem key={tab}>
                  <Link to={{ pathname, query: { ...query, tab } }}>
                    {tab}
                  </Link>
                </RightMenuItem>)
              )}
            </RightSubMenu>
          </Gateway>

          <DetailForm
            {...this.props}
            item={item || {}}
            fields={schema[currentTab]}
            onCreate={onSave}
          />
        </Flex>
      </ContentLoader>
    );
  }
}
<commit_msg>fix tabs<commit_after>import React, { Component } from 'react';
import { withRouter, Link } from 'olymp';
import { Menu, Icon } from 'antd';
import { ContentLoader, createComponent } from 'olymp-fela';
import { upperFirst } from 'lodash';
import { Gateway } from 'react-gateway';
import { withItem } from '../decorators';
import { DetailForm } from '../components';

const getFormSchema = ({ fields }) =>
  fields.reduce((result, field) => {
    if (field.type.name === 'Blocks') {
      // if slate => own group
      result[upperFirst(field.name)] = [field];
    } else if (field.type.name === 'Image') {
      // if image => own group
      result[upperFirst(field.name)] = [field];
    } else {
      // Group
      const group = field['@'].detail ? field['@'].detail.arg0 : 'Allgemein';

      if (!result[group]) {
        result[group] = [];
      }
      result[group].push(field);
    }
    return result;
  }, {});

const Flex = createComponent(
  ({ theme }) => ({
    display: 'flex',
    flexDirection: 'column',
    paddingTop: theme.space3,
    '> ul': {
      zIndex: 1,
    },
    '> form': {
      overflow: 'auto',
    },
  }),
  'div',
  []
);

const RightMenu = createComponent(
  () => ({
    float: 'right!important',
  }),
  p => <Menu {...p} />,
  p => Object.keys(p)
);

@withRouter
@withItem
export default class CollectionDetail extends Component {
  render() {
    const { id, item, collection, onSave, pathname, query } = this.props;
    const schema = getFormSchema(collection);
    const keys = Object.keys(schema);
    const currentTab = query.tab || Object.keys(schema)[0];
    return (
      <ContentLoader isLoading={id && !item}>
        <Flex>
          <Gateway into="navigation">
            <RightMenu>
              <Menu.Item key="save">

                  <Icon type="save" /> Speichern

              </Menu.Item>
              {keys.map(tab =>
                (<Menu.Item key={tab}>
                  <Link to={{ pathname, query: { ...query, tab } }}>
                    {tab}
                  </Link>
                </Menu.Item>)
              )}
            </RightMenu>
          </Gateway>

          <DetailForm
            {...this.props}
            item={item || {}}
            fields={schema[currentTab]}
            onCreate={onSave}
          />
        </Flex>
      </ContentLoader>
    );
  }
}
<|endoftext|>


<commit_before>const { createInterfaceAdapter } = require("@truffle/interface-adapter");
const web3Utils = require("web3-utils");
const Config = require("@truffle/config");
const Migrate = require("@truffle/migrate");
const TestResolver = require("./testresolver");
const TestSource = require("./testsource");
const expect = require("@truffle/expect");
const contract = require("@truffle/contract");
const path = require("path");
const fs = require("fs-extra");
const util = require("util");
const debug = require("debug")("lib:testing:testrunner");
const Decoder = require("@truffle/decoder");
const Codec = require("@truffle/codec");

function TestRunner(options = {}) {
  expect.options(options, [
    "resolver",
    "provider",
    "contracts_build_directory"
  ]);

  this.config = Config.default().merge(options);

  this.logger = options.logger || console;
  this.initial_resolver = options.resolver;
  this.provider = options.provider;

  this.can_snapshot = false;
  this.first_snapshot = true;
  this.initial_snapshot = null;
  this.interfaceAdapter = createInterfaceAdapter({
    provider: options.provider,
    networkType: options.networks[options.network].type
  });
  this.decoder = null;

  // For each test
  this.currentTestStartBlock = null;

  this.BEFORE_TIMEOUT =
    (options.mocha && options.mocha.before_timeout) || 120000;
  this.TEST_TIMEOUT = (options.mocha && options.mocha.timeout) || 300000;
}

TestRunner.prototype.initialize = async function() {
  debug("initializing");
  let test_source = new TestSource(this.config);
  this.config.resolver = new TestResolver(
    this.initial_resolver,
    test_source,
    this.config.contracts_build_directory
  );

  if (this.first_snapshot) {
    try {
      let initial_snapshot = await this.snapshot();
      this.can_snapshot = true;
      this.initial_snapshot = initial_snapshot;
    } catch (_) {}
    this.first_snapshot = false;
  } else {
    await this.resetState();
  }

  let files = fs
    .readdirSync(this.config.contracts_build_directory)
    .filter(file => path.extname(file) === ".json");

  let data = files.map(file =>
    fs.readFileSync(
      path.join(this.config.contracts_build_directory, file),
      "utf8"
    )
  );

  let contracts = data.map(JSON.parse).map(json => contract(json));

  //NOTE: in future should get rid of contracts argument
  this.decoder = await Decoder.forProject(this.provider, contracts);
};

TestRunner.prototype.deploy = async function() {
  await Migrate.run(
    this.config.with({
      reset: true,
      quiet: true
    })
  );
};

TestRunner.prototype.resetState = async function() {
  if (this.can_snapshot) {
    await this.revert(this.initial_snapshot);
    this.initial_snapshot = await this.snapshot();
  } else {
    await this.deploy();
  }
};

TestRunner.prototype.startTest = async function() {
  let blockNumber = await this.interfaceAdapter.getBlockNumber();
  let one = web3Utils.toBN(1);
  blockNumber = web3Utils.toBN(blockNumber);

  // Add one in base 10
  this.currentTestStartBlock = blockNumber.add(one);
};

TestRunner.prototype.endTest = async function(mocha) {
  // Skip logging if test passes and `show-events` option is not true
  if (mocha.currentTest.state !== "failed" && !this.config["show-events"]) {
    return;
  }

  function indent(unindented, indentation, initialPrefix = "") {
    return unindented
      .split("\n")
      .map(
        (line, index) =>
          index === 0
            ? initialPrefix + " ".repeat(indentation - initialPrefix) + line
            : " ".repeat(indentation) + line
      )
      .join("\n");
  }

  function printEvent(decoding, indentation = 0, initialPrefix = "") {
    const anonymousPrefix = decoding.kind === "anonymous" ? "<anonymous> " : "";
    const className = decoding.definedIn
      ? decoding.definedIn.typeName
      : decoding.class.typeName;
    const eventName = decoding.abi.name;
    const fullEventName = anonymousPrefix + `${className}.${eventName}`;
    const eventArgs = decoding.arguments
      .map(({ name, indexed, value }) => {
        let namePrefix = name ? `${name}: ` : "";
        let indexedPrefix = indexed ? "<indexed> " : "";
        let displayValue = util.inspect(
          new Codec.Format.Utils.Inspect.ResultInspector(value),
          {
            depth: null,
            colors: true,
            maxArrayLength: null,
            breakLength: 80
          }
        );
        let typeString = ` (type: ${Codec.Format.Types.typeStringWithoutLocation(
          value.type
        )})`;
        return namePrefix + indexedPrefix + displayValue + typeString;
      })
      .join(",\n");
    return indent(
      `${fullEventName}(\n${indent(eventArgs, 2)}\n)`,
      indentation,
      initialPrefix
    );
  }

  const logs = await this.decoder.events({
    //NOTE: block numbers shouldn't be over 2^53 so this
    //should be fine, but should change this once decoder
    //accepts more general types for blocks
    fromBlock: this.currentTestStartBlock.toNumber()
  });

  if (logs.length === 0) {
    this.logger.log("    > No events were emitted");
    return;
  }

  this.logger.log("\n    Events emitted during test:");
  this.logger.log("    ---------------------------");
  this.logger.log("");

  for (const log of logs) {
    switch (log.decodings.length) {
      case 0:
        this.logger.log(`    Warning: Could not decode event!`);
        this.logger.log("");
        break;
      case 1:
        this.logger.log(printEvent(log.decodings[0], 4));
        this.logger.log("");
        break;
      default:
        this.logger.log(`    Ambiguous event, possible interpretations:`);
        for (const decoding of log.decodings) {
          this.logger.log(printEvent(decoding, 6, "    * "));
        }
        this.logger.log("");
        break;
    }
  }
  this.logger.log("\n    ---------------------------");
};

TestRunner.prototype.snapshot = async function() {
  return (await this.rpc("evm_snapshot")).result;
};

TestRunner.prototype.revert = async function(snapshot_id) {
  await this.rpc("evm_revert", [snapshot_id]);
};

TestRunner.prototype.rpc = async function(method, arg) {
  let request = {
    jsonrpc: "2.0",
    method: method,
    id: Date.now(),
    params: arg
  };

  let result = await util.promisify(this.provider.send)(request);

  if (result.error != null) {
    throw new Error("RPC Error: " + (result.error.message || result.error));
  }
};

module.exports = TestRunner;
<commit_msg>Display no-argument events on one line<commit_after>const { createInterfaceAdapter } = require("@truffle/interface-adapter");
const web3Utils = require("web3-utils");
const Config = require("@truffle/config");
const Migrate = require("@truffle/migrate");
const TestResolver = require("./testresolver");
const TestSource = require("./testsource");
const expect = require("@truffle/expect");
const contract = require("@truffle/contract");
const path = require("path");
const fs = require("fs-extra");
const util = require("util");
const debug = require("debug")("lib:testing:testrunner");
const Decoder = require("@truffle/decoder");
const Codec = require("@truffle/codec");

function TestRunner(options = {}) {
  expect.options(options, [
    "resolver",
    "provider",
    "contracts_build_directory"
  ]);

  this.config = Config.default().merge(options);

  this.logger = options.logger || console;
  this.initial_resolver = options.resolver;
  this.provider = options.provider;

  this.can_snapshot = false;
  this.first_snapshot = true;
  this.initial_snapshot = null;
  this.interfaceAdapter = createInterfaceAdapter({
    provider: options.provider,
    networkType: options.networks[options.network].type
  });
  this.decoder = null;

  // For each test
  this.currentTestStartBlock = null;

  this.BEFORE_TIMEOUT =
    (options.mocha && options.mocha.before_timeout) || 120000;
  this.TEST_TIMEOUT = (options.mocha && options.mocha.timeout) || 300000;
}

TestRunner.prototype.initialize = async function() {
  debug("initializing");
  let test_source = new TestSource(this.config);
  this.config.resolver = new TestResolver(
    this.initial_resolver,
    test_source,
    this.config.contracts_build_directory
  );

  if (this.first_snapshot) {
    try {
      let initial_snapshot = await this.snapshot();
      this.can_snapshot = true;
      this.initial_snapshot = initial_snapshot;
    } catch (_) {}
    this.first_snapshot = false;
  } else {
    await this.resetState();
  }

  let files = fs
    .readdirSync(this.config.contracts_build_directory)
    .filter(file => path.extname(file) === ".json");

  let data = files.map(file =>
    fs.readFileSync(
      path.join(this.config.contracts_build_directory, file),
      "utf8"
    )
  );

  let contracts = data.map(JSON.parse).map(json => contract(json));

  //NOTE: in future should get rid of contracts argument
  this.decoder = await Decoder.forProject(this.provider, contracts);
};

TestRunner.prototype.deploy = async function() {
  await Migrate.run(
    this.config.with({
      reset: true,
      quiet: true
    })
  );
};

TestRunner.prototype.resetState = async function() {
  if (this.can_snapshot) {
    await this.revert(this.initial_snapshot);
    this.initial_snapshot = await this.snapshot();
  } else {
    await this.deploy();
  }
};

TestRunner.prototype.startTest = async function() {
  let blockNumber = await this.interfaceAdapter.getBlockNumber();
  let one = web3Utils.toBN(1);
  blockNumber = web3Utils.toBN(blockNumber);

  // Add one in base 10
  this.currentTestStartBlock = blockNumber.add(one);
};

TestRunner.prototype.endTest = async function(mocha) {
  // Skip logging if test passes and `show-events` option is not true
  if (mocha.currentTest.state !== "failed" && !this.config["show-events"]) {
    return;
  }

  function indent(unindented, indentation, initialPrefix = "") {
    return unindented
      .split("\n")
      .map(
        (line, index) =>
          index === 0
            ? initialPrefix + " ".repeat(indentation - initialPrefix) + line
            : " ".repeat(indentation) + line
      )
      .join("\n");
  }

  function printEvent(decoding, indentation = 0, initialPrefix = "") {
    const anonymousPrefix = decoding.kind === "anonymous" ? "<anonymous> " : "";
    const className = decoding.definedIn
      ? decoding.definedIn.typeName
      : decoding.class.typeName;
    const eventName = decoding.abi.name;
    const fullEventName = anonymousPrefix + `${className}.${eventName}`;
    const eventArgs = decoding.arguments
      .map(({ name, indexed, value }) => {
        let namePrefix = name ? `${name}: ` : "";
        let indexedPrefix = indexed ? "<indexed> " : "";
        let displayValue = util.inspect(
          new Codec.Format.Utils.Inspect.ResultInspector(value),
          {
            depth: null,
            colors: true,
            maxArrayLength: null,
            breakLength: 80
          }
        );
        let typeString = ` (type: ${Codec.Format.Types.typeStringWithoutLocation(
          value.type
        )})`;
        return namePrefix + indexedPrefix + displayValue + typeString;
      })
      .join(",\n");
    if (decoding.arguments.length > 0) {
      return indent(
        `${fullEventName}(\n${indent(eventArgs, 2)}\n)`,
        indentation,
        initialPrefix
      );
    } else {
      return indent(`${fullEventName}()`, indentation, initialPrefix);
    }
  }

  const logs = await this.decoder.events({
    //NOTE: block numbers shouldn't be over 2^53 so this
    //should be fine, but should change this once decoder
    //accepts more general types for blocks
    fromBlock: this.currentTestStartBlock.toNumber()
  });

  if (logs.length === 0) {
    this.logger.log("    > No events were emitted");
    return;
  }

  this.logger.log("\n    Events emitted during test:");
  this.logger.log("    ---------------------------");
  this.logger.log("");

  for (const log of logs) {
    switch (log.decodings.length) {
      case 0:
        this.logger.log(`    Warning: Could not decode event!`);
        this.logger.log("");
        break;
      case 1:
        this.logger.log(printEvent(log.decodings[0], 4));
        this.logger.log("");
        break;
      default:
        this.logger.log(`    Ambiguous event, possible interpretations:`);
        for (const decoding of log.decodings) {
          this.logger.log(printEvent(decoding, 6, "    * "));
        }
        this.logger.log("");
        break;
    }
  }
  this.logger.log("\n    ---------------------------");
};

TestRunner.prototype.snapshot = async function() {
  return (await this.rpc("evm_snapshot")).result;
};

TestRunner.prototype.revert = async function(snapshot_id) {
  await this.rpc("evm_revert", [snapshot_id]);
};

TestRunner.prototype.rpc = async function(method, arg) {
  let request = {
    jsonrpc: "2.0",
    method: method,
    id: Date.now(),
    params: arg
  };

  let result = await util.promisify(this.provider.send)(request);

  if (result.error != null) {
    throw new Error("RPC Error: " + (result.error.message || result.error));
  }
};

module.exports = TestRunner;
<|endoftext|>


<commit_before>APP.directive('miloMatchEntity', function() {
	return {
		scope: {
			entityEndpoint: '=miloMatchEntity',
			entityName: '=?miloEntityName',
			entityId: '=?miloEntityId',
			ngModel: '='
		}, controller: ['$scope', '$element', '$attrs', 'GlobalService', function($scope, $element, $attrs, GlobalService) {
			var matchEntity = function (instances) {
				for (var i = 0; instances && i < instances.length; i ++) {
					if ($scope.ngModel && instances[i][$scope.entityId] === $scope.ngModel[$scope.entityId]) {
						$scope.ngModel = instances[i];
					}
				}
			};
			var scope = $element.scope();
			if (! scope.miloSelectData) {
				scope.miloSelectData = {};
			}
			if (! $scope.entityName) {
				$scope.entityName = 'name';
			}
			if (! $scope.entityId) {
				$scope.entityId = 'id';
			}
			if (! scope.miloSelectData[$scope.entityEndpoint]) {
				GlobalService.getEntityInstances($scope.entityEndpoint).$promise.then(function (data) {
					scope.miloSelectData[$scope.entityEndpoint] = data;
					scope.miloSelectData[$scope.entityEndpoint].unshift({});
					matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
				});
			} else {
				matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
			}
			$attrs['ngOptions'] = 'value.' + $scope.entityName + ' for value in miloSelectData["' + $scope.entityEndpoint + '"]';

			$scope.$watch('ngModel', function () {
					matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
			});
    	}]
	};
});
<commit_msg>fix match entity directive empty line<commit_after>APP.directive('miloMatchEntity', function() {
	return {
		scope: {
			entityEndpoint: '=miloMatchEntity',
			entityName: '=?miloEntityName',
			entityId: '=?miloEntityId',
			ngModel: '='
		}, controller: ['$scope', '$element', '$attrs', 'GlobalService', function($scope, $element, $attrs, GlobalService) {
			var matchEntity = function (instances) {
				for (var i = 0; instances && i < instances.length; i ++) {
					if ($scope.ngModel && instances[i][$scope.entityId] === $scope.ngModel[$scope.entityId]) {
						$scope.ngModel = instances[i];
					}
				}
			};
			var scope = $element.scope();
			if (! scope.miloSelectData) {
				scope.miloSelectData = {};
			}
			if (! $scope.entityName) {
				$scope.entityName = 'name';
			}
			if (! $scope.entityId) {
				$scope.entityId = 'id';
			}
			if (! scope.miloSelectData[$scope.entityEndpoint]) {
				GlobalService.getEntityInstances($scope.entityEndpoint).$promise.then(function (data) {
					if (data && data.length) { // add empty line at the beginning
						delete data[0]['$$hashKey'];
						if (JSON.stringify(data[0]) != '{"name":""}') {
							data.unshift({"name":""});
						}
					}
					scope.miloSelectData[$scope.entityEndpoint] = data;
					matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
				});
			} else {
				matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
			}
			$attrs['ngOptions'] = 'value.' + $scope.entityName + ' for value in miloSelectData["' + $scope.entityEndpoint + '"]';

			$scope.$watch('ngModel', function () {
					matchEntity(scope.miloSelectData[$scope.entityEndpoint]);
			});
    	}]
	};
});
<|endoftext|>