<commit_before>/**
 * XadillaX created at 2016-03-23 14:52:05 With ♥
 *
 * Copyright (c) 2016 akyuu.moe, all rights
 * reserved.
 */
"use strict";

var path = require("path");
var util = require("util");

require("sugar");

var Model = require("./loader/model.js");
var Connection = require("./loader/connection");
var Controller = require("./loader/controller");
var Express = require("./_express/application");
var Logger = require("./logger");
var Service = require("./loader/service");

var logRequest = require("./middware/request_logger");

/**
 * Akyuu
 * @constructor
 * @param {String} [projectRoot] the project root path
 */
var Akyuu = function(projectRoot) {
    Express.call(this);

    this.projectRoot = projectRoot || path.resolve(__dirname, "../../../src");
    this.requirePaths = require("./require");
    this.requirePaths.addRequirePath(this.projectRoot);

    this.config = require("./config");
    this.logger = new Logger(this);

    this.Errors = require("./error/predefinition");

    this.connection = new Connection(this);
    this.model = new Model(this);
    this.controller = new Controller(this);
    this.service = new Service(this);
};

util.inherits(Akyuu, Express);

/**
 * init
 * @param {Function} callback the callback function
 */
Akyuu.prototype.init = function(callback) {
    Express.prototype.init.call(this);

    // load controllers...
    this.logger.load();
    this.use(logRequest);

    this.service.load("");
    this.connection.load();
    this.model.load("");
    this.controller.load("");

    process.nextTick(callback);
};

module.exports = Akyuu;
<commit_msg>load plugins in akyuu<commit_after>/**
 * XadillaX created at 2016-03-23 14:52:05 With ♥
 *
 * Copyright (c) 2016 akyuu.moe, all rights
 * reserved.
 */
"use strict";

var path = require("path");
var util = require("util");

require("sugar");

var Model = require("./loader/model.js");
var Connection = require("./loader/connection");
var Controller = require("./loader/controller");
var Express = require("./_express/application");
var Logger = require("./logger");
var Plugin = require("./loader/plugin");
var Service = require("./loader/service");

var logRequest = require("./middware/request_logger");

/**
 * Akyuu
 * @constructor
 * @param {String} [projectRoot] the project root path
 */
var Akyuu = function(projectRoot) {
    Express.call(this);

    this.projectRoot = projectRoot || path.resolve(__dirname, "../../../src");
    this.requirePaths = require("./require");
    this.requirePaths.addRequirePath(this.projectRoot);

    this.config = require("./config");
    this.logger = new Logger(this);

    this.Errors = require("./error/predefinition");

    this.PLUGIN_POS = Plugin.POS;

    this.plugin = new Plugin(this);
    this.connection = new Connection(this);
    this.model = new Model(this);
    this.controller = new Controller(this);
    this.service = new Service(this);
};

util.inherits(Akyuu, Express);

/**
 * init
 * @param {Function} callback the callback function
 */
Akyuu.prototype.init = function(callback) {
    Express.prototype.init.call(this);

    this.logger.load();
    this.use(logRequest);

    this.plugin.load();

    this.plugin.plug(this.PLUGIN_POS.BEFORE_SERVICE);
    this.service.load("");
    this.plugin.plug(this.PLUGIN_POS.AFTER_SERVICE);

    this.plugin.plug(this.PLUGIN_POS.BEFORE_CONNECTION);
    this.connection.load();
    this.plugin.plug(this.PLUGIN_POS.AFTER_CONNECTION);

    this.plugin.plug(this.PLUGIN_POS.BEFORE_MODEL);
    this.model.load("");
    this.plugin.plug(this.PLUGIN_POS.AFTER_MODEL);

    this.plugin.plug(this.PLUGIN_POS.BEFORE_CONTROLLER);
    this.controller.load("");
    this.plugin.plug(this.PLUGIN_POS.AFTER_CONTROLLER);

    process.nextTick(callback);
};

module.exports = Akyuu;
<|endoftext|>


<commit_before>var gulp         = require( 'gulp' );
var watch        = require( 'gulp-watch' );
var sass         = require( 'gulp-sass' );
var cssmin       = require( 'gulp-minify-css' );
var rename       = require( 'gulp-rename' );
var browser_sync = require( 'browser-sync' );
var autoprefixer = require( 'gulp-autoprefixer' );

gulp.task( 'sass', function() {
	return gulp.src( './assets/src/scss/*.scss' )
		.pipe( sass( {
			outputStyle: 'expanded'
		} ) )
		.pipe( autoprefixer( {
			browsers: ['last 2 versions'],
			cascade: false
		} ) )
		.pipe( gulp.dest( './assets/dist/css/' ) );
} );

gulp.task( 'sass:build', ['sass'], function() {
	return gulp.src( ['./assets/dist/css/*.css', '!./assets/dist/css/*.min.css'] )
		.pipe( cssmin() )
		.pipe( rename( { suffix: '.min' } ) )
		.pipe( gulp.dest( './assets/dist/css/' ) );
} );

gulp.task( 'browsersync', function() {
	browser_sync.init( {
		server: {
			baseDir: "./"
		}
	} );
} );

gulp.task( 'watch', function() {
	gulp.watch( ['assets/*.scss', 'assets/**/*.scss'], ['sass'] );
	gulp.watch( ['**/*.html', 'assets/dist/css/*.css'], function() {
		browser_sync.reload();
	} );
} );

gulp.task( 'build', ['sass:build'] );

gulp.task( 'release', ['build'], function() {
	return gulp.src(
			[
				'./**/*.html',
				'./assets/dist/**',
				"!./release/**",
				"!./node_modules/**/*.*"
			],
			{ base: './' }
		)
		.pipe( gulp.dest( 'release' ) );
} );

gulp.task( 'default', ['sass', 'browsersync', 'watch'] );
<commit_msg>fixed gulpfile.js bug<commit_after>var gulp         = require( 'gulp' );
var watch        = require( 'gulp-watch' );
var sass         = require( 'gulp-sass' );
var cssmin       = require( 'gulp-minify-css' );
var rename       = require( 'gulp-rename' );
var browser_sync = require( 'browser-sync' );
var autoprefixer = require( 'gulp-autoprefixer' );

gulp.task( 'sass', function() {
	return gulp.src( './assets/src/scss/*.scss' )
		.pipe( sass( {
			outputStyle: 'expanded'
		} ) )
		.pipe( autoprefixer( {
			browsers: ['last 2 versions'],
			cascade: false
		} ) )
		.pipe( gulp.dest( './assets/dist/css/' ) );
} );

gulp.task( 'sass:build', ['sass'], function() {
	return gulp.src( ['./assets/dist/css/*.css', '!./assets/dist/css/*.min.css'] )
		.pipe( cssmin() )
		.pipe( rename( { suffix: '.min' } ) )
		.pipe( gulp.dest( './assets/dist/css/' ) );
} );

gulp.task( 'browsersync', function() {
	browser_sync.init( {
		server: {
			baseDir: "./"
		}
	} );
} );

gulp.task( 'watch', function() {
	gulp.watch( ['assets/**/*.scss'], ['sass:build'] );
	gulp.watch( ['**/*.html', 'assets/dist/css/*.css'], function() {
		browser_sync.reload();
	} );
} );

gulp.task( 'build', ['sass:build'] );

gulp.task( 'release', ['build'], function() {
	return gulp.src(
			[
				'./**/*.html',
				'./assets/dist/**',
				"!./release/**",
				"!./node_modules/**/*.*"
			],
			{ base: './' }
		)
		.pipe( gulp.dest( 'release' ) );
} );

gulp.task( 'default', ['build', 'browsersync', 'watch'] );
<|endoftext|>


<commit_before>/**
 *
 */

function showmessage(selector, message, option){
	var msgdiv = $("
");
	if (option=='error') {
		msgdiv.addClass("ui-state-error ui-corner-all");
		msgdiv.html(message);
		msgdiv.prepend('');
	} else {
		msgdiv.addClass("ui-state-highlight ui-corner-all");
		msgdiv.html(message);
		msgdiv.prepend('');
	}
	msgdiv.appendTo($(selector)).show();
	setTimeout(function(){msgdiv.remove();}, 5000);
}

var selected_group="";
var selected_user="";
var selected_user_in_group="";
var user_realname=new Object;

function refresh() {
	if (selected_group!="") {
		$('#allgroups [name="'+selected_group+'"]').click();
	}
	if (selected_user!="") {
		$('#allusers [name="'+selected_user+'"]').click();
	}
	if (selected_user_in_group!="") {
		$('#groupmemberdiv [name="'+selected_user_in_group+'"]').click();
	}
}

function getusergroupmap() {
	$.ajax({
		'url':'manage_server.php',
		'data':{
			'action': 'listusergroup'
		},
		'success':function(data) {
			if (data.result==0) {
				showmessage('#usergroupdiv', "Cannot get user group map. "+
						"Error message: $data.message", 'error');
			} else {
				$('#userlist').empty();
				$('#grouplist').empty();
				$.each(data.users, function(i, v) {
					if (v.active==0) {
						return;
					}
					var user = $("
");
					user.html(v.realname);

						user_realname[i]=v.realname;

						user.click(function(){
							$(".user").removeClass('ui-state-highlight');
							user.addClass('ui-state-highlight');
							selected_user = i;
							$('.group').each(function(){
								$(this).css({'font-weight':'normal'});
								for (var gindex=0; gindex<v.groups.length; gindex++) {
									if ($(this).attr('name') == v.groups[gindex]) {
										$(this).css({'font-weight':'bold'});
										break;
									}
								}
							});

						});

					$('#userlist').append(user);
				});
				$.each(data.groups, function(i, v){
					var group = $("
");

					group.html(i+" ("+ v.length + (v.length>1?" members)":" member)"));
					group.click(function(){
						$(".group").removeClass('ui-state-highlight');
						group.addClass('ui-state-highlight');
						$("#groupmember").empty();
						for (index=0; index<v.length; index++) {
							var member = $("
");
							if (v[index].isadmin==1) {
								member.html(""+user_realname[v[index].user]+"");
							} else {
								member.html(user_realname[v[index].user]);
							}
							member.click(function(){
								$(".user").removeClass('ui-state-highlight');
								$(this).addClass('ui-state-highlight');
								selected_user_in_group= $(this).attr('name');
							});
							$("#groupmember").append(member);
						}
						selected_group=i;
					});
					$('#grouplist').append(group);
				});
				$('#groupmember').empty();
				refresh();
			}
		},
		'dataType': 'json'
	});
}

function initCreateGroupDialog() {
	$('#creategroupdialog').dialog({
		modal: true,
		buttons: {
			"Create Group": function() {
				var groupname =
					$('#newgroupname').attr('value');
				$.ajax({
					'url':'manage_server.php',
					'data': {
						'action': 'creategroup',
						'groupname': groupname
					},
					'success':function(data) {

						if (data.result==1) {
							showmessage("#message",
									"Successfully created group '"+
									groupname+"'.",
									"info");
							getusergroupmap();
							selected_group=groupname;
							refresh();
						} else {
							showmessage("#message",
									"Failed to create group '"+
									groupname+"'. Message from server: " +
									data.message, "error");
						}
					},
					'dataType': 'json'
				});
				$( this ).dialog( "close" );
			},
			Cancel: function() {
				$( this ).dialog( "close" );
			}
		},
		autoOpen: false
	});
}

function deleteUser(username) {
	var allusers = $("
");
	var explain = $('
');
	explain.html('Please choose a user to take over all items.');
	explain.appendTo(allusers);
	var selusers = $("<select/>");
	selusers.appendTo(allusers);
	$.each(user_realname, function(i,v){
		if (username!=i) {
			var opt = $("<option value='"+i+"'/>");
			opt.html(v);
			opt.appendTo(selusers);
		}
	});
	allusers.dialog({
		modal: true,
		buttons: {
			"Delete User": function() {
				var transferusername =
					$('option:selected', selusers).attr('value');
				$.ajax({
					'url':'manage_server.php',
					'data': {
						'action': 'deleteuser',
						'username': username,
						'transferusername': transferusername
					},
					'success':function(data) {

						if (data.result==1) {
							showmessage("#message",
									"Successfully deleted user",
									"info");
							selected_user = "";
							delete user_realname[username];
							getusergroupmap();
						} else {
							showmessage("#message",
									data.message, "error");
						}
					},
					'dataType': 'json'
				});

				$( this ).dialog( "close" );
				$( this ).remove();

			},
			Cancel: function() {
				$( this ).dialog( "close" );
				$( this ).remove();
				return;
			}
		}
	});

}

function deleteGroup(groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'deletegroup',
			'groupname': groupname
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully deleted group '"+groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to delete group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
			selected_group = "";
		},
		'dataType': 'json'
	});
}

function addUserToGroup(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'addusertogroup',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully added "+username+" to group '"+groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to add user "+username+" to group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}

function deleteUserFromGroup(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'deleteuserfromgroup',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully deleted "+username+" from group '"+
						groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to delete user "+username+" from group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}

function toggleUserGroupAdmin(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'toggleusergroupadmin',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						data.message,
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}
function setupmanagepage() {
	initCreateGroupDialog();

	$('#creategroupbtn').click(function(){
		$('#creategroupdialog').dialog('open');
	});

	$('#deleteuserbtn').click(function(){
		if (selected_user=="") {
			return;
		}
		deleteUser(selected_user);
	});
	$('#deletegroupbtn').click(function(){
		if (selected_group=="") {
			return;
		}
		deleteGroup(selected_group);
	});
	$('#addusertogroupbtn').click(function(){
		if (selected_user=="" || selected_group=="") {
			return;
		}
		addUserToGroup(selected_user, selected_group);
	});
	$('#deleteuserfromgroupbtn').click(function(){
		if (selected_user_in_group=="" || selected_group=="") {
			return;
		}
		deleteUserFromGroup(selected_user_in_group, selected_group);
	});

	$('#toggleuseradminbtn').click(function(){
		if (selected_user_in_group=="" || selected_group=="") {
			return;
		}
		toggleUserGroupAdmin(selected_user_in_group, selected_group);
	});

	getusergroupmap();
}

$('document').ready(function(){
	/*
	 * for manage.php
	 */
	setupmanagepage();
	decobutton();
	decomenu();
	decopanel();
});

<commit_msg>Update manage.js<commit_after>/**
 *
 */

function showmessage(selector, message, option){
	var msgdiv = $("
");
	if (option=='error') {
		msgdiv.addClass("ui-state-error ui-corner-all");
		msgdiv.html(message);
		msgdiv.prepend('');
	} else {
		msgdiv.addClass("ui-state-highlight ui-corner-all");
		msgdiv.html(message);
		msgdiv.prepend('');
	}
	msgdiv.appendTo($(selector)).show();
	setTimeout(function(){msgdiv.remove();}, 5000);
}

var selected_group="";
var selected_user="";
var selected_user_in_group="";
var user_realname=new Object;

function refresh() {
	if (selected_group!="") {
		$('#allgroups [name="'+selected_group+'"]').click();
	}
	if (selected_user!="") {
		$('#allusers [name="'+selected_user+'"]').click();
	}
	if (selected_user_in_group!="") {
		$('#groupmemberdiv [name="'+selected_user_in_group+'"]').click();
	}
}

function getusergroupmap() {
	$.ajax({
		'url':'manage_server.php',
		'data':{
			'action': 'listusergroup'
		},
		'success':function(data) {
			if (data.result==0) {
				showmessage('#usergroupdiv', "Cannot get user group map. "+
						"Error message: $data.message", 'error');
			} else {
				$('#userlist').empty();
				$('#grouplist').empty();
				$.each(data.users, function(i, v) {
					if (v.active==0) {
						return;
					}
					var user = $("
");
					user.html(v.realname);

						user_realname[i]=v.realname;

						user.click(function(){
							$(".user").removeClass('ui-state-highlight');
							user.addClass('ui-state-highlight');
							selected_user = i;
							$('.group').each(function(){
								$(this).css({'font-weight':'normal'});
								for (var gindex=0; gindex<v.groups.length; gindex++) {
									if ($(this).attr('name') == v.groups[gindex]) {
										$(this).css({'font-weight':'bold'});
										break;
									}
								}
							});

						});

					$('#userlist').append(user);
				});
				$.each(data.groups, function(i, v){
					var group = $("
");

					group.html(i+" ("+ v.length + (v.length>1?" members)":" member)"));
					group.click(function(){
						$(".group").removeClass('ui-state-highlight');
						group.addClass('ui-state-highlight');
						$("#groupmember").empty();
						for (index=0; index<v.length; index++) {
							var member = $("
");
							if (v[index].isadmin==1) {
								member.html(""+user_realname[v[index].user]+"");
							} else {
								member.html(user_realname[v[index].user]);
							}
							member.click(function(){
								$(".user").removeClass('ui-state-highlight');
								$(this).addClass('ui-state-highlight');
								selected_user_in_group= $(this).attr('name');
							});
							$("#groupmember").append(member);
						}
						selected_group=i;
					});
					$('#grouplist').append(group);
				});
				$('#groupmember').empty();
				refresh();
			}
		},
		'dataType': 'json'
	});
}

function initCreateGroupDialog() {
	$('#creategroupdialog').dialog({
		modal: true,
		buttons: {
			"Create Group": function() {
				var groupname =
					$('#newgroupname').val();
				$.ajax({
					'url':'manage_server.php',
					'data': {
						'action': 'creategroup',
						'groupname': groupname
					},
					'success':function(data) {

						if (data.result==1) {
							showmessage("#message",
									"Successfully created group '"+
									groupname+"'.",
									"info");
							getusergroupmap();
							selected_group=groupname;
							refresh();
						} else {
							showmessage("#message",
									"Failed to create group '"+
									groupname+"'. Message from server: " +
									data.message, "error");
						}
					},
					'dataType': 'json'
				});
				$( this ).dialog( "close" );
			},
			Cancel: function() {
				$( this ).dialog( "close" );
			}
		},
		autoOpen: false
	});
}

function deleteUser(username) {
	var allusers = $("
");
	var explain = $('
');
	explain.html('Please choose a user to take over all items.');
	explain.appendTo(allusers);
	var selusers = $("<select/>");
	selusers.appendTo(allusers);
	$.each(user_realname, function(i,v){
		if (username!=i) {
			var opt = $("<option value='"+i+"'/>");
			opt.html(v);
			opt.appendTo(selusers);
		}
	});
	allusers.dialog({
		modal: true,
		buttons: {
			"Delete User": function() {
				var transferusername =
					$('option:selected', selusers).attr('value');
				$.ajax({
					'url':'manage_server.php',
					'data': {
						'action': 'deleteuser',
						'username': username,
						'transferusername': transferusername
					},
					'success':function(data) {

						if (data.result==1) {
							showmessage("#message",
									"Successfully deleted user",
									"info");
							selected_user = "";
							delete user_realname[username];
							getusergroupmap();
						} else {
							showmessage("#message",
									data.message, "error");
						}
					},
					'dataType': 'json'
				});

				$( this ).dialog( "close" );
				$( this ).remove();

			},
			Cancel: function() {
				$( this ).dialog( "close" );
				$( this ).remove();
				return;
			}
		}
	});

}

function deleteGroup(groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'deletegroup',
			'groupname': groupname
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully deleted group '"+groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to delete group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
			selected_group = "";
		},
		'dataType': 'json'
	});
}

function addUserToGroup(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'addusertogroup',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully added "+username+" to group '"+groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to add user "+username+" to group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}

function deleteUserFromGroup(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'deleteuserfromgroup',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						"Successfully deleted "+username+" from group '"+
						groupname+"'.",
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						"Failed to delete user "+username+" from group '"+
						groupname+"'. Message from server: " +
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}

function toggleUserGroupAdmin(username, groupname) {
	$.ajax({
		'url':'manage_server.php',
		'data': {
			'action': 'toggleusergroupadmin',
			'groupname': groupname,
			'username': username
		},
		'success':function(data) {

			if (data.result==1) {
				showmessage("#message",
						data.message,
						"info");
				getusergroupmap();
			} else {
				showmessage("#message",
						data.message, "error");
			}
		},
		'dataType': 'json'
	});
}
function setupmanagepage() {
	initCreateGroupDialog();

	$('#creategroupbtn').click(function(){
		$('#creategroupdialog').dialog('open');
	});

	$('#deleteuserbtn').click(function(){
		if (selected_user=="") {
			return;
		}
		deleteUser(selected_user);
	});
	$('#deletegroupbtn').click(function(){
		if (selected_group=="") {
			return;
		}
		deleteGroup(selected_group);
	});
	$('#addusertogroupbtn').click(function(){
		if (selected_user=="" || selected_group=="") {
			return;
		}
		addUserToGroup(selected_user, selected_group);
	});
	$('#deleteuserfromgroupbtn').click(function(){
		if (selected_user_in_group=="" || selected_group=="") {
			return;
		}
		deleteUserFromGroup(selected_user_in_group, selected_group);
	});

	$('#toggleuseradminbtn').click(function(){
		if (selected_user_in_group=="" || selected_group=="") {
			return;
		}
		toggleUserGroupAdmin(selected_user_in_group, selected_group);
	});

	getusergroupmap();
}

$('document').ready(function(){
	/*
	 * for manage.php
	 */
	setupmanagepage();
	decobutton();
	decomenu();
	decopanel();
});

<|endoftext|>


<commit_before>// eslint-disable-next-line
import { onDestroy } from 'svelte';
import { f7 } from './f7';

export const useStore = (...args) => {
  // (store, getter, callback)
  let store = args[0];
  let getter = args[1];
  let callback = args[2];
  if (args.length === 1) {
    // (getter)
    store = f7.store;
    getter = args[0];
  } else if (args.length === 2 && typeof args[0] === 'string') {
    // (getter, callback)
    store = f7.store;
    getter = args[0];
    callback = args[1];
  }
  const obj = store.getters[getter];
  const value = obj.value;
  if (callback) {
    obj.onUpdated(callback);
  }

  onDestroy(() => {
    if (callback) {
      // eslint-disable-next-line
      store.__removeCallback(callback);
    }
    // eslint-disable-next-line
    store.__removeCallback(obj.__callback);
  });
  return value;
};
<commit_msg>chore(vue): use plain getters in Svelte useStore<commit_after>// eslint-disable-next-line
import { onDestroy } from 'svelte';
import { f7 } from './f7';

export const useStore = (...args) => {
  // (store, getter, callback)
  let store = args[0];
  let getter = args[1];
  let callback = args[2];
  if (args.length === 1) {
    // (getter)
    store = f7.store;
    getter = args[0];
  } else if (args.length === 2 && typeof args[0] === 'string') {
    // (getter, callback)
    store = f7.store;
    getter = args[0];
    callback = args[1];
  }
  // eslint-disable-next-line
  const obj = store._gettersPlain[getter];
  const value = obj.value;
  if (callback) {
    obj.onUpdated(callback);
  }

  onDestroy(() => {
    if (callback) {
      // eslint-disable-next-line
      store.__removeCallback(callback);
    }
  });
  return value;
};
<|endoftext|>


<commit_before>frappe.ui.form.ControlMarkdownEditor = frappe.ui.form.ControlCode.extend({
	editor_class: 'markdown',
	make_ace_editor() {
		this._super();

		this.ace_editor_target.wrap(`<div class="${this.editor_class}-container">`);
		this.markdown_container = this.$input_wrapper.find(`.${this.editor_class}-container`);

		this.showing_preview = false;
		this.preview_toggle_btn = $(`<button class="btn btn-default btn-xs ${this.editor_class}-toggle">${__('Preview')}</button>`)
			.click(e => {
				if (!this.showing_preview) {
					this.update_preview();
				}

				const $btn = $(e.target);
				this.markdown_preview.toggle(!this.showing_preview);
				this.ace_editor_target.toggle(this.showing_preview);

				this.showing_preview = !this.showing_preview;

				$btn.text(this.showing_preview ? __('Edit') : __('Preview'));
			});
		this.markdown_container.prepend(this.preview_toggle_btn);

		this.markdown_preview = $(`<div class="${this.editor_class}-preview border rounded">`).hide();
		this.markdown_container.append(this.markdown_preview);
	},

	set_language() {
		this.df.options = 'Markdown';
		this._super();
	},

	update_preview() {
		const value = this.get_value() || "";
		this.markdown_preview.html(frappe.markdown(value));
	},

	set_formatted_input(value) {
		this._super(value)
			.then(() => {
				this.update_preview();
			});
	}
});
<commit_msg>fix(minor): wrap text in markdown editor<commit_after>frappe.ui.form.ControlMarkdownEditor = frappe.ui.form.ControlCode.extend({
	editor_class: 'markdown',
	make_ace_editor() {
		this._super();

		this.ace_editor_target.wrap(`<div class="${this.editor_class}-container">`);
		this.markdown_container = this.$input_wrapper.find(`.${this.editor_class}-container`);

		this.editor.getSession().setUseWrapMode(true);

		this.showing_preview = false;
		this.preview_toggle_btn = $(`<button class="btn btn-default btn-xs ${this.editor_class}-toggle">${__('Preview')}</button>`)
			.click(e => {
				if (!this.showing_preview) {
					this.update_preview();
				}

				const $btn = $(e.target);
				this.markdown_preview.toggle(!this.showing_preview);
				this.ace_editor_target.toggle(this.showing_preview);

				this.showing_preview = !this.showing_preview;

				$btn.text(this.showing_preview ? __('Edit') : __('Preview'));
			});
		this.markdown_container.prepend(this.preview_toggle_btn);

		this.markdown_preview = $(`<div class="${this.editor_class}-preview border rounded">`).hide();
		this.markdown_container.append(this.markdown_preview);
	},

	set_language() {
		this.df.options = 'Markdown';
		this._super();
	},

	update_preview() {
		const value = this.get_value() || "";
		this.markdown_preview.html(frappe.markdown(value));
	},

	set_formatted_input(value) {
		this._super(value)
			.then(() => {
				this.update_preview();
			});
	}
});
<|endoftext|>


<commit_before>var dns = {}
dns.google = new Array("8.8.8.8", "8.8.4.4", "Google Public DNS Server");
dns.opendns = new Array("208.67.222.222", "208.67.220.220", "OpenDNS");
dns.nortondns = new Array("198.153.192.50", "198.153.194.50", "Norton DNS Server");
dns.advantage = new Array("156.154.70.1", "156.154.71.1", "DNS Advantage");
dns.comodo = new Array("8.26.56.26", "8.20.247.20", "Comodo Secure DNS Server");

var main_dns = "google";

$(document).ready(function(){
  if($("dns")){
    for(var key in dns){
      if(key != main_dns){
        $("dns").append("
" + dns[key][0] + ", " + dns[key][1] + " - " + dns[key][2] + "
");
      }
    }

    $("#mdns").html("" + dns[main_dns][0] + ", " + dns[main_dns][1] + "");
    $("#name").html("" + dns[main_dns][2]);
  }
});
<commit_msg>Update index.js<commit_after>$(document).ready(function(){
  if($("dns")){
    for(var key in dns){
      if(key != main_dns){
        $("dns").append("
" + dns[key][0] + ", " + dns[key][1] + " - " + dns[key][2] + "
");
      }
    }

    $("#mdns").html("" + dns[main_dns][0] + ", " + dns[main_dns][1] + "");
    $("#name").html("" + dns[main_dns][2]);
  }
});
<|endoftext|>


<commit_before>import * as React from 'react';
import { createEvent, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import DismissibleTextForm from 'amo/components/DismissibleTextForm';
import {
  createFakeDebounce,
  createFakeLocalState,
  dispatchClientMetadata,
  render as defaultRender,
  screen,
  within,
} from 'tests/unit/helpers';

describe(__filename, () => {
  let store;

  const renderProps = (customProps = {}) => {
    return {
      _createLocalState: createFakeLocalState,
      _debounce: createFakeDebounce(),
      id: 'any-form-id',
      onDelete: null,
      onDismiss: jest.fn(),
      onSubmit: jest.fn(),
      ...customProps,
    };
  };

  const render = (customProps = {}) => {
    const props = renderProps(customProps);
    return defaultRender(<DismissibleTextForm {...props} />, { store });
  };

  const getTextBox = () => screen.getByRole('textbox');

  beforeEach(() => {
    store = dispatchClientMetadata().store;
  });

  it('can be configured with a custom class', () => {
    render({ className: 'some-class' });

    expect(screen.getByTagName('form')).toHaveClass('some-class');
  });

  it('lets you configure the submit button class', () => {
    render({ submitButtonClassName: 'my-class' });

    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'my-class',
    );
  });

  it('renders a default cancel button', () => {
    render({ dismissButtonText: undefined });

    expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
  });

  it('lets you configure the cancel button text', () => {
    const dismissButtonText = 'Nevermind, cancel it';
    render({ dismissButtonText });

    expect(
      screen.getByRole('button', { name: dismissButtonText }),
    ).toBeInTheDocument();
  });

  it('renders a placeholder', () => {
    render({ placeholder: 'Enter some text' });

    expect(screen.getByPlaceholderText('Enter some text')).toBeInTheDocument();
  });

  it('lets you render text', () => {
    render({ text: 'Some text to edit' });

    expect(getTextBox()).toHaveValue('Some text to edit');
  });

  it('calls back when dismissing the textarea', () => {
    const onDismiss = jest.fn();
    render({ onDismiss });

    userEvent.click(screen.getByRole('button', { name: 'Cancel' }));

    expect(onDismiss).toHaveBeenCalled();
  });

  it('clears the form onDismiss', () => {
    render({ onDismiss: jest.fn() });

    userEvent.type(getTextBox(), 'Example text');
    userEvent.click(screen.getByRole('button', { name: 'Cancel' }));

    expect(getTextBox()).toHaveValue('');
  });

  it('calls back when submitting the form', () => {
    const onSubmit = jest.fn();
    render({ onSubmit });
    const enteredText = 'Some review text';

    userEvent.type(getTextBox(), enteredText);
    userEvent.click(screen.getByRole('button', { name: 'Submit' }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        text: enteredText,
      }),
    );
  });

  it('lets you configure the submit button text', () => {
    render({
      submitButtonText: 'Submit the form',
    });

    expect(
      screen.getByRole('button', { name: 'Submit the form' }),
    ).toBeInTheDocument();
  });

  it('lets you configure the in-progress submit button text', () => {
    render({
      submitButtonInProgressText: 'Submitting the form',
      isSubmitting: true,
    });

    expect(
      screen.getByRole('button', { name: 'Submitting the form' }),
    ).toBeInTheDocument();
  });

  it('disables the submit button while submitting the form', () => {
    render({ isSubmitting: true, text: 'Some text' });

    expect(screen.getByRole('button', { name: 'Submitting' })).toBeDisabled();
  });

  it('disables the submit button before text has been entered', () => {
    render({ text: '' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables submit button before non-empty text has been entered', () => {
    // Enter only white space:
    render({ text: '    ' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables submit button before the text has changed', () => {
    render({ text: 'Some text' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables the dismiss button while submitting the form', () => {
    render({ isSubmitting: true });

    expect(screen.getByRole('button', { name: 'Cancel' })).toBeDisabled();
  });

  it('enables the dismiss button while not submitting the form', () => {
    render({ isSubmitting: false });

    expect(screen.getByRole('button', { name: 'Cancel' })).not.toBeDisabled();
  });

  it('enables the submit button after text has been entered', () => {
    render({ text: '' });

    userEvent.type(getTextBox(), 'Typing some text...');

    expect(screen.getByRole('button', { name: 'Submit' })).not.toBeDisabled();
  });

  it('disables the submit button when updating with whitespaces', () => {
    render({ text: 'Some Text' });

    userEvent.type(getTextBox(), '   ');

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables the textarea when submitting the form', () => {
    render({ isSubmitting: true });

    expect(getTextBox()).toBeDisabled();
  });

  it('enables the textarea when not submitting the form', () => {
    render({ isSubmitting: false });

    expect(getTextBox()).not.toBeDisabled();
  });

  it('hides the delete button when onDelete is empty', () => {
    render({ onDelete: null });

    expect(
      screen.queryByRole('button', { name: 'Delete' }),
    ).not.toBeInTheDocument();
  });

  it('displays the delete button when onDelete is provided', () => {
    render({ onDelete: jest.fn() });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--alert',
    );
  });

  it('creates micro buttons when requested', () => {
    render({
      microButtons: true,
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
    });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).toHaveClass(
      'Button--micro',
    );
  });

  it('creates puffy buttons when requested', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
      puffyButtons: true,
    });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).toHaveClass(
      'Button--puffy',
    );
  });

  it('creates non-micro, non-puffy buttons by default', () => {
    render({
      onDismiss: jest.fn(),
      onDelete: jest.fn(),
    });

    expect(screen.getByRole('button', { name: 'Delete' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Delete' })).not.toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).not.toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).not.toHaveClass(
      'Button--puffy',
    );
  });

  it('cannot create conflicting button types', () => {
    expect(() => {
      render({ puffyButtons: true, microButtons: true });
    }).toThrow(/microButtons and puffyButtons cannot both be true/);
  });

  it('disables the delete button when there is no text', () => {
    render({ onDelete: jest.fn(), text: '' });

    expect(screen.getByRole('button', { name: 'Delete' })).toBeDisabled();
  });

  it('enables the delete button after text has been entered', () => {
    render({ onDelete: jest.fn(), text: '' });

    userEvent.type(getTextBox(), 'Typing some text...');

    expect(screen.getByRole('button', { name: 'Delete' })).not.toBeDisabled();
  });

  it('calls back when clicking the delete button', () => {
    const onDelete = jest.fn();
    render({ onDelete });

    userEvent.type(getTextBox(), 'Some review text');

    // Submit the form.
    const button = screen.getByRole('button', { name: 'Delete' });
    const clickEvent = createEvent.click(button);
    const preventDefaultWatcher = jest.spyOn(clickEvent, 'preventDefault');

    fireEvent(button, clickEvent);

    expect(preventDefaultWatcher).toHaveBeenCalled();
    expect(onDelete).toHaveBeenCalled();
  });

  it('can hide the cancel/dismiss button', () => {
    render({ onDismiss: undefined });

    expect(
      screen.queryByRole('button', { name: 'Cancel' }),
    ).not.toBeInTheDocument();
  });

  it('hides a formFooter by default', () => {
    render();

    expect(
      screen.queryByClassName('DismissibleTextForm-formFooter'),
    ).not.toBeInTheDocument();
  });

  it('renders a formFooter', () => {
    const footerText = 'Some footer text';
    render({ formFooter: <div>{footerText}</div> });

    expect(
      within(screen.getByClassName('DismissibleTextForm-formFooter')).getByText(
        footerText,
      ),
    ).toBeInTheDocument();
  });

  it('renders all buttons in a default order', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
    });

    const allButtons = screen.getAllByRole('button');
    expect(allButtons[0]).toHaveTextContent('Cancel');
    expect(allButtons[1]).toHaveTextContent('Delete');
    expect(allButtons[2]).toHaveTextContent('Submit');
  });

  it('can reverse the button order', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
      reverseButtonOrder: true,
    });

    const allButtons = screen.getAllByRole('button');
    expect(allButtons[0]).toHaveTextContent('Submit');
    expect(allButtons[1]).toHaveTextContent('Delete');
    expect(allButtons[2]).toHaveTextContent('Cancel');
  });

  describe('LocalState', () => {
    // TODO: I don't think we want to be testing the internals of LocalState,
    // but rather just if it works as expected.
    // We might be able to do that by typing something and then unmounting and
    // then rendering again.
    it('configures LocalState', () => {
      const _createLocalState = jest.fn(createFakeLocalState);
      const id = 'some-form-id';

      render({ id, _createLocalState });

      expect(_createLocalState).toHaveBeenCalledWith(id);
    });

    it('loads LocalState on mount', () => {
      const loadSpy = jest.fn(() => Promise.resolve(null));
      render({
        _createLocalState: () => createFakeLocalState({ load: loadSpy }),
      });

      expect(loadSpy).toHaveBeenCalled();
    });

    it('populates the form with text from LocalState', async () => {
      const text = 'Some text that was saved to LocalState';
      render({
        _createLocalState: () =>
          createFakeLocalState({ load: () => Promise.resolve({ text }) }),
      });

      await waitFor(() => expect(getTextBox()).toHaveValue(text));
    });

    it('does not populate the form with null data', async () => {
      const text = 'Some initial text';
      render({
        _createLocalState: () =>
          // Set up LocalState to load null data.
          createFakeLocalState({ load: () => Promise.resolve(null) }),
        text,
      });

      expect(getTextBox()).toHaveValue(text);

      // The text box is focussed after checkForStoredState has been called.
      await waitFor(() => expect(getTextBox()).toHaveClass('focus-visible'));

      // Make sure the text was not erased.
      expect(getTextBox()).toHaveValue(text);
    });

    it('saves to LocalState when typing', () => {
      const saveSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ save: saveSpy }),
      });

      const text = 'Example text';
      userEvent.type(getTextBox(), text);

      expect(saveSpy).toHaveBeenCalledWith({ text });
    });

    it('clears LocalState onDismiss', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onDismiss: jest.fn(),
      });

      userEvent.click(screen.getByRole('button', { name: 'Cancel' }));

      expect(clearSpy).toHaveBeenCalled();
    });

    it('clears LocalState onDelete', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onDelete: jest.fn(),
      });

      userEvent.type(getTextBox(), 'something');
      userEvent.click(screen.getByRole('button', { name: 'Delete' }));

      expect(clearSpy).toHaveBeenCalled();
    });

    it('clears LocalState onSubmit', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onSubmit: jest.fn(),
      });

      userEvent.type(getTextBox(), 'something');
      userEvent.click(screen.getByRole('button', { name: 'Submit' }));

      expect(clearSpy).toHaveBeenCalled();
    });
  });
});
<commit_msg>Make TestDismissibleTextForm forward compatible with future dependencies (#11720)<commit_after>import * as React from 'react';
import { createEvent, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import DismissibleTextForm from 'amo/components/DismissibleTextForm';
import {
  createFakeDebounce,
  createFakeLocalState,
  dispatchClientMetadata,
  render as defaultRender,
  screen,
  within,
} from 'tests/unit/helpers';

describe(__filename, () => {
  let store;

  const renderProps = (customProps = {}) => {
    return {
      _createLocalState: createFakeLocalState,
      _debounce: createFakeDebounce(),
      id: 'any-form-id',
      onDelete: null,
      onDismiss: jest.fn(),
      onSubmit: jest.fn(),
      ...customProps,
    };
  };

  const render = (customProps = {}) => {
    const props = renderProps(customProps);
    return defaultRender(<DismissibleTextForm {...props} />, { store });
  };

  const getTextBox = () => screen.getByRole('textbox');

  beforeEach(() => {
    store = dispatchClientMetadata().store;
  });

  it('can be configured with a custom class', () => {
    render({ className: 'some-class' });

    expect(screen.getByTagName('form')).toHaveClass('some-class');
  });

  it('lets you configure the submit button class', () => {
    render({ submitButtonClassName: 'my-class' });

    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'my-class',
    );
  });

  it('renders a default cancel button', () => {
    render({ dismissButtonText: undefined });

    expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
  });

  it('lets you configure the cancel button text', () => {
    const dismissButtonText = 'Nevermind, cancel it';
    render({ dismissButtonText });

    expect(
      screen.getByRole('button', { name: dismissButtonText }),
    ).toBeInTheDocument();
  });

  it('renders a placeholder', () => {
    render({ placeholder: 'Enter some text' });

    expect(screen.getByPlaceholderText('Enter some text')).toBeInTheDocument();
  });

  it('lets you render text', () => {
    render({ text: 'Some text to edit' });

    expect(getTextBox()).toHaveValue('Some text to edit');
  });

  it('calls back when dismissing the textarea', () => {
    const onDismiss = jest.fn();
    render({ onDismiss });

    userEvent.click(screen.getByRole('button', { name: 'Cancel' }));

    expect(onDismiss).toHaveBeenCalled();
  });

  it('clears the form onDismiss', async () => {
    render({ onDismiss: jest.fn() });

    userEvent.type(getTextBox(), 'Example text');
    userEvent.click(screen.getByRole('button', { name: 'Cancel' }));
    await waitFor(() => expect(getTextBox()).toHaveValue(''));
  });

  it('calls back when submitting the form', () => {
    const onSubmit = jest.fn();
    render({ onSubmit });
    const enteredText = 'Some review text';

    userEvent.type(getTextBox(), enteredText);
    userEvent.click(screen.getByRole('button', { name: 'Submit' }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        text: enteredText,
      }),
    );
  });

  it('lets you configure the submit button text', () => {
    render({
      submitButtonText: 'Submit the form',
    });

    expect(
      screen.getByRole('button', { name: 'Submit the form' }),
    ).toBeInTheDocument();
  });

  it('lets you configure the in-progress submit button text', () => {
    render({
      submitButtonInProgressText: 'Submitting the form',
      isSubmitting: true,
    });

    expect(
      screen.getByRole('button', { name: 'Submitting the form' }),
    ).toBeInTheDocument();
  });

  it('disables the submit button while submitting the form', () => {
    render({ isSubmitting: true, text: 'Some text' });

    expect(screen.getByRole('button', { name: 'Submitting' })).toBeDisabled();
  });

  it('disables the submit button before text has been entered', () => {
    render({ text: '' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables submit button before non-empty text has been entered', () => {
    // Enter only white space:
    render({ text: '    ' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables submit button before the text has changed', () => {
    render({ text: 'Some text' });

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables the dismiss button while submitting the form', () => {
    render({ isSubmitting: true });

    expect(screen.getByRole('button', { name: 'Cancel' })).toBeDisabled();
  });

  it('enables the dismiss button while not submitting the form', () => {
    render({ isSubmitting: false });

    expect(screen.getByRole('button', { name: 'Cancel' })).not.toBeDisabled();
  });

  it('enables the submit button after text has been entered', () => {
    render({ text: '' });

    userEvent.type(getTextBox(), 'Typing some text...');

    expect(screen.getByRole('button', { name: 'Submit' })).not.toBeDisabled();
  });

  it('disables the submit button when updating with whitespaces', () => {
    render({ text: 'Some Text' });

    userEvent.type(getTextBox(), '   ');

    expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
  });

  it('disables the textarea when submitting the form', () => {
    render({ isSubmitting: true });

    expect(getTextBox()).toBeDisabled();
  });

  it('enables the textarea when not submitting the form', () => {
    render({ isSubmitting: false });

    expect(getTextBox()).not.toBeDisabled();
  });

  it('hides the delete button when onDelete is empty', () => {
    render({ onDelete: null });

    expect(
      screen.queryByRole('button', { name: 'Delete' }),
    ).not.toBeInTheDocument();
  });

  it('displays the delete button when onDelete is provided', () => {
    render({ onDelete: jest.fn() });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--alert',
    );
  });

  it('creates micro buttons when requested', () => {
    render({
      microButtons: true,
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
    });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).toHaveClass(
      'Button--micro',
    );
  });

  it('creates puffy buttons when requested', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
      puffyButtons: true,
    });

    expect(screen.getByRole('button', { name: 'Delete' })).toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).toHaveClass(
      'Button--puffy',
    );
  });

  it('creates non-micro, non-puffy buttons by default', () => {
    render({
      onDismiss: jest.fn(),
      onDelete: jest.fn(),
    });

    expect(screen.getByRole('button', { name: 'Delete' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).not.toHaveClass(
      'Button--micro',
    );
    expect(screen.getByRole('button', { name: 'Delete' })).not.toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Submit' })).not.toHaveClass(
      'Button--puffy',
    );
    expect(screen.getByRole('button', { name: 'Cancel' })).not.toHaveClass(
      'Button--puffy',
    );
  });

  it('cannot create conflicting button types', () => {
    expect(() => {
      render({ puffyButtons: true, microButtons: true });
    }).toThrow(/microButtons and puffyButtons cannot both be true/);
  });

  it('disables the delete button when there is no text', () => {
    render({ onDelete: jest.fn(), text: '' });

    expect(screen.getByRole('button', { name: 'Delete' })).toBeDisabled();
  });

  it('enables the delete button after text has been entered', () => {
    render({ onDelete: jest.fn(), text: '' });

    userEvent.type(getTextBox(), 'Typing some text...');

    expect(screen.getByRole('button', { name: 'Delete' })).not.toBeDisabled();
  });

  it('calls back when clicking the delete button', () => {
    const onDelete = jest.fn();
    render({ onDelete });

    userEvent.type(getTextBox(), 'Some review text');

    // Submit the form.
    const button = screen.getByRole('button', { name: 'Delete' });
    const clickEvent = createEvent.click(button);
    const preventDefaultWatcher = jest.spyOn(clickEvent, 'preventDefault');

    fireEvent(button, clickEvent);

    expect(preventDefaultWatcher).toHaveBeenCalled();
    expect(onDelete).toHaveBeenCalled();
  });

  it('can hide the cancel/dismiss button', () => {
    render({ onDismiss: undefined });

    expect(
      screen.queryByRole('button', { name: 'Cancel' }),
    ).not.toBeInTheDocument();
  });

  it('hides a formFooter by default', () => {
    render();

    expect(
      screen.queryByClassName('DismissibleTextForm-formFooter'),
    ).not.toBeInTheDocument();
  });

  it('renders a formFooter', () => {
    const footerText = 'Some footer text';
    render({ formFooter: <div>{footerText}</div> });

    expect(
      within(screen.getByClassName('DismissibleTextForm-formFooter')).getByText(
        footerText,
      ),
    ).toBeInTheDocument();
  });

  it('renders all buttons in a default order', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
    });

    const allButtons = screen.getAllByRole('button');
    expect(allButtons[0]).toHaveTextContent('Cancel');
    expect(allButtons[1]).toHaveTextContent('Delete');
    expect(allButtons[2]).toHaveTextContent('Submit');
  });

  it('can reverse the button order', () => {
    render({
      onDelete: jest.fn(),
      onDismiss: jest.fn(),
      reverseButtonOrder: true,
    });

    const allButtons = screen.getAllByRole('button');
    expect(allButtons[0]).toHaveTextContent('Submit');
    expect(allButtons[1]).toHaveTextContent('Delete');
    expect(allButtons[2]).toHaveTextContent('Cancel');
  });

  describe('LocalState', () => {
    // TODO: I don't think we want to be testing the internals of LocalState,
    // but rather just if it works as expected.
    // We might be able to do that by typing something and then unmounting and
    // then rendering again.
    it('configures LocalState', () => {
      const _createLocalState = jest.fn(createFakeLocalState);
      const id = 'some-form-id';

      render({ id, _createLocalState });

      expect(_createLocalState).toHaveBeenCalledWith(id);
    });

    it('loads LocalState on mount', () => {
      const loadSpy = jest.fn(() => Promise.resolve(null));
      render({
        _createLocalState: () => createFakeLocalState({ load: loadSpy }),
      });

      expect(loadSpy).toHaveBeenCalled();
    });

    it('populates the form with text from LocalState', async () => {
      const text = 'Some text that was saved to LocalState';
      render({
        _createLocalState: () =>
          createFakeLocalState({ load: () => Promise.resolve({ text }) }),
      });

      await waitFor(() => expect(getTextBox()).toHaveValue(text));
    });

    it('does not populate the form with null data', async () => {
      const text = 'Some initial text';
      render({
        _createLocalState: () =>
          // Set up LocalState to load null data.
          createFakeLocalState({ load: () => Promise.resolve(null) }),
        text,
      });

      expect(getTextBox()).toHaveValue(text);

      // The text box is focussed after checkForStoredState has been called.
      await waitFor(() => expect(getTextBox()).toHaveClass('focus-visible'));

      // Make sure the text was not erased.
      expect(getTextBox()).toHaveValue(text);
    });

    it('saves to LocalState when typing', () => {
      const saveSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ save: saveSpy }),
      });

      const text = 'Example text';
      userEvent.type(getTextBox(), text);

      expect(saveSpy).toHaveBeenCalledWith({ text });
    });

    it('clears LocalState onDismiss', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onDismiss: jest.fn(),
      });

      userEvent.click(screen.getByRole('button', { name: 'Cancel' }));

      expect(clearSpy).toHaveBeenCalled();
    });

    it('clears LocalState onDelete', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onDelete: jest.fn(),
      });

      userEvent.type(getTextBox(), 'something');
      userEvent.click(screen.getByRole('button', { name: 'Delete' }));

      expect(clearSpy).toHaveBeenCalled();
    });

    it('clears LocalState onSubmit', () => {
      const clearSpy = jest.fn(() => Promise.resolve());
      render({
        _createLocalState: () => createFakeLocalState({ clear: clearSpy }),
        onSubmit: jest.fn(),
      });

      userEvent.type(getTextBox(), 'something');
      userEvent.click(screen.getByRole('button', { name: 'Submit' }));

      expect(clearSpy).toHaveBeenCalled();
    });
  });
});
<|endoftext|>


<commit_before>'use strict'

/**
 * plugin.js
 *
 * Released under LGPL License.
 * Copyright (c) 2016 SIRAP Group All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * plugin.js Tinymce plugin headersfooters
 * @file plugin.js
 * @module
 * @name tinycmce-plugin-headersfooters
 * @description
 * A plugin for tinymce WYSIWYG HTML editor that allow to insert headers and footers
 * It will may be used with requires tinymce-plugin-paginate the a near future, but not for now.
 * @link https://github.com/sirap-group/tinymce-plugin-headersfooters
 * @author Rémi Becheras
 * @author Groupe SIRAP
 * @license GNU GPL-v2 http://www.tinymce.com/license
 * @version 1.0.0
 */

/**
 * Tinymce library - injected by the plugin loader.
 * @external tinymce
 * @see {@link https://www.tinymce.com/docs/api/class/tinymce/|Tinymce API Reference}
 */
var tinymce = window.tinymce

/**
 * The jQuery plugin namespace - plugin dependency.
 * @external "jQuery.fn"
 * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins}
 */
var $ = window.jQuery

var ui = require('./utils/ui')
var HeaderFooterFactory = require('./classes/HeaderFooterFactory')

// Add the plugin to the tinymce PluginManager
tinymce.PluginManager.add('headersfooters', tinymcePluginHeadersFooters)

/**
 * Tinymce plugin headers/footers
 * @function
 * @global
 * @param {tinymce.Editor} editor - The injected tinymce editor.
 * @returns void
 */
function tinymcePluginHeadersFooters (editor, url) {
  var headerFooterFactory

  var menuItems = {
    insertHeader: ui.createInsertHeaderMenuItem(),
    insertFooter: ui.createInsertFooterMenuItem(),
    removeHeader: ui.createRemoveHeaderMenuItem(),
    removeFooter: ui.createRemoveFooterMenuItem()
  }

  // add menu items
  editor.addMenuItem('insertHeader', menuItems.insertHeader)
  editor.addMenuItem('removeHeader', menuItems.removeHeader)
  editor.addMenuItem('insertFooter', menuItems.insertFooter)
  editor.addMenuItem('removeFooter', menuItems.removeFooter)

  editor.on('init', onInitHandler)
  editor.on('SetContent', onSetContent)
  editor.on('NodeChange', onNodeChange)
  editor.on('NodeChange', function (evt) {
    // if (!editor.selection.isCollapsed()) {
    //   if (editor.selection.getNode() === editor.getBody()) {
    //     console.info('Select ALL')
    //     editor.selection.select(headerFooterFactory.getActiveSection())
    //   }
    // }
  })

  /**
   * On init event handler. Instanciate the factory and initialize menu items states
   * @function
   * @inner
   * @returns void
   */
  function onInitHandler () {
    headerFooterFactory = new HeaderFooterFactory(editor)
    initMenuItems(headerFooterFactory, menuItems)
  }

  /**
   * On SetContent event handler. Load or reload headers and footers from existing elements if it should do.
   * @function
   * @inner
   * @returns void
   */
  function onSetContent (evt) {
    // var $bodyElmt = $('body', editor.getDoc())
    var content = $(editor.getBody()).html()
    var emptyContent = '

'
    if (content && content !== emptyContent) {
      if (headerFooterFactory) {
        reloadHeadFoots(menuItems)
      } else {
        setTimeout(reloadHeadFoots.bind(null, menuItems), 100)
      }
    } else {
      // evt.content = '
' + evt.content + '
'
    }
  }

  function onNodeChange (evt) {
    headerFooterFactory.forceCursorToAllowedLocation(evt.element)
  }

  /**
   * Helper function. Do the reload of headers and footers
   * @function
   * @inner
   * @returns void
   */
  function reloadHeadFoots (menuItems) {
    var $headFootElmts = $('*[data-headfoot]', editor.getDoc())
    var $bodyElmt = $('*[data-headfoot-body]', editor.getDoc())
    var hasBody = !!$bodyElmt.length
    var $allElmts = null

    // init starting states
    menuItems.insertHeader.show()
    menuItems.insertFooter.show()
    menuItems.removeHeader.hide()
    menuItems.removeFooter.hide()

    // set another state and load elements if a header or a footer exists
    $headFootElmts.each(function (i, el) {
      var $el = $(el)
      if ($el.attr('data-headfoot-header')) {
        menuItems.insertHeader.hide()
        menuItems.removeHeader.show()
      } else if ($el.attr('data-headfoot-body')) {
        // @TODO something ?
      } else if ($el.attr('data-headfoot-footer')) {
        menuItems.insertFooter.hide()
        menuItems.removeFooter.show()
      }
      headerFooterFactory.loadElement(el)
    })

    if (!hasBody) {
      $allElmts = $(editor.getBody()).children()
      headerFooterFactory.insertBody()
      var $body = $(headerFooterFactory.body.node)
      $body.empty()
      $allElmts.each(function (i, el) {
        var $el = $(el)
        if (!$el.attr('data-headfoot')) {
          $body.append($el)
        }
      })
    }
  }
}

/**
 * Initialize menu items states (show, hide, ...) and implements onclick handlers
 * @function
 * @inner
 * @param {HeaderFooterFactory} factory The header and footer factory
 * @param {object} menuItems The set of plugin's menu items
 * @returns undefined
 */
function initMenuItems (factory, menuItems) {
  // on startup, hide remove buttons
  menuItems.removeHeader.hide()
  menuItems.removeFooter.hide()

  // override insertHeader, insertFooter, removeHeader and removeFooter onclick handlers
  menuItems.insertHeader.onclick = function () {
    factory.insertHeader()
    menuItems.insertHeader.hide()
    menuItems.removeHeader.show()
  }
  menuItems.insertFooter.onclick = function () {
    factory.insertFooter()
    menuItems.insertFooter.hide()
    menuItems.removeFooter.show()
  }
  menuItems.removeHeader.onclick = function () {
    factory.removeHeader()
    menuItems.insertHeader.show()
    menuItems.removeHeader.hide()
  }
  menuItems.removeFooter.onclick = function () {
    factory.removeFooter()
    menuItems.insertFooter.show()
    menuItems.removeFooter.hide()
  }
}
<commit_msg>add unselectable class on init editor<commit_after>'use strict'

/**
 * plugin.js
 *
 * Released under LGPL License.
 * Copyright (c) 2016 SIRAP Group All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * plugin.js Tinymce plugin headersfooters
 * @file plugin.js
 * @module
 * @name tinycmce-plugin-headersfooters
 * @description
 * A plugin for tinymce WYSIWYG HTML editor that allow to insert headers and footers
 * It will may be used with requires tinymce-plugin-paginate the a near future, but not for now.
 * @link https://github.com/sirap-group/tinymce-plugin-headersfooters
 * @author Rémi Becheras
 * @author Groupe SIRAP
 * @license GNU GPL-v2 http://www.tinymce.com/license
 * @version 1.0.0
 */

/**
 * Tinymce library - injected by the plugin loader.
 * @external tinymce
 * @see {@link https://www.tinymce.com/docs/api/class/tinymce/|Tinymce API Reference}
 */
var tinymce = window.tinymce

/**
 * The jQuery plugin namespace - plugin dependency.
 * @external "jQuery.fn"
 * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins}
 */
var $ = window.jQuery

var ui = require('./utils/ui')
var HeaderFooterFactory = require('./classes/HeaderFooterFactory')

// Add the plugin to the tinymce PluginManager
tinymce.PluginManager.add('headersfooters', tinymcePluginHeadersFooters)

/**
 * Tinymce plugin headers/footers
 * @function
 * @global
 * @param {tinymce.Editor} editor - The injected tinymce editor.
 * @returns void
 */
function tinymcePluginHeadersFooters (editor, url) {
  var headerFooterFactory

  var menuItems = {
    insertHeader: ui.createInsertHeaderMenuItem(),
    insertFooter: ui.createInsertFooterMenuItem(),
    removeHeader: ui.createRemoveHeaderMenuItem(),
    removeFooter: ui.createRemoveFooterMenuItem()
  }

  // add menu items
  editor.addMenuItem('insertHeader', menuItems.insertHeader)
  editor.addMenuItem('removeHeader', menuItems.removeHeader)
  editor.addMenuItem('insertFooter', menuItems.insertFooter)
  editor.addMenuItem('removeFooter', menuItems.removeFooter)

  editor.on('init', onInitHandler)
  editor.on('SetContent', onSetContent)
  editor.on('NodeChange', onNodeChange)
  editor.on('NodeChange', function (evt) {
    // if (!editor.selection.isCollapsed()) {
    //   if (editor.selection.getNode() === editor.getBody()) {
    //     console.info('Select ALL')
    //     editor.selection.select(headerFooterFactory.getActiveSection())
    //   }
    // }
  })

  /**
   * On init event handler. Instanciate the factory and initialize menu items states
   * @function
   * @inner
   * @returns void
   */
  function onInitHandler () {
    headerFooterFactory = new HeaderFooterFactory(editor)
    initMenuItems(headerFooterFactory, menuItems)
    ui.addUnselectableCSSClass(editor)
  }

  /**
   * On SetContent event handler. Load or reload headers and footers from existing elements if it should do.
   * @function
   * @inner
   * @returns void
   */
  function onSetContent (evt) {
    // var $bodyElmt = $('body', editor.getDoc())
    var content = $(editor.getBody()).html()
    var emptyContent = '

'
    if (content && content !== emptyContent) {
      if (headerFooterFactory) {
        reloadHeadFoots(menuItems)
      } else {
        setTimeout(reloadHeadFoots.bind(null, menuItems), 100)
      }
    } else {
      // evt.content = '
' + evt.content + '
'
    }
  }

  function onNodeChange (evt) {
    headerFooterFactory.forceCursorToAllowedLocation(evt.element)
  }

  /**
   * Helper function. Do the reload of headers and footers
   * @function
   * @inner
   * @returns void
   */
  function reloadHeadFoots (menuItems) {
    var $headFootElmts = $('*[data-headfoot]', editor.getDoc())
    var $bodyElmt = $('*[data-headfoot-body]', editor.getDoc())
    var hasBody = !!$bodyElmt.length
    var $allElmts = null

    // init starting states
    menuItems.insertHeader.show()
    menuItems.insertFooter.show()
    menuItems.removeHeader.hide()
    menuItems.removeFooter.hide()

    // set another state and load elements if a header or a footer exists
    $headFootElmts.each(function (i, el) {
      var $el = $(el)
      if ($el.attr('data-headfoot-header')) {
        menuItems.insertHeader.hide()
        menuItems.removeHeader.show()
      } else if ($el.attr('data-headfoot-body')) {
        // @TODO something ?
      } else if ($el.attr('data-headfoot-footer')) {
        menuItems.insertFooter.hide()
        menuItems.removeFooter.show()
      }
      headerFooterFactory.loadElement(el)
    })

    if (!hasBody) {
      $allElmts = $(editor.getBody()).children()
      headerFooterFactory.insertBody()
      var $body = $(headerFooterFactory.body.node)
      $body.empty()
      $allElmts.each(function (i, el) {
        var $el = $(el)
        if (!$el.attr('data-headfoot')) {
          $body.append($el)
        }
      })
    }
  }
}

/**
 * Initialize menu items states (show, hide, ...) and implements onclick handlers
 * @function
 * @inner
 * @param {HeaderFooterFactory} factory The header and footer factory
 * @param {object} menuItems The set of plugin's menu items
 * @returns undefined
 */
function initMenuItems (factory, menuItems) {
  // on startup, hide remove buttons
  menuItems.removeHeader.hide()
  menuItems.removeFooter.hide()

  // override insertHeader, insertFooter, removeHeader and removeFooter onclick handlers
  menuItems.insertHeader.onclick = function () {
    factory.insertHeader()
    menuItems.insertHeader.hide()
    menuItems.removeHeader.show()
  }
  menuItems.insertFooter.onclick = function () {
    factory.insertFooter()
    menuItems.insertFooter.hide()
    menuItems.removeFooter.show()
  }
  menuItems.removeHeader.onclick = function () {
    factory.removeHeader()
    menuItems.insertHeader.show()
    menuItems.removeHeader.hide()
  }
  menuItems.removeFooter.onclick = function () {
    factory.removeFooter()
    menuItems.insertFooter.show()
    menuItems.removeFooter.hide()
  }
}
<|endoftext|>


<commit_before>/* eslint-disable */
/* bender-tags: editor,unit */
/* bender-ckeditor-plugins: wysiwygarea,structuredheadings,toolbar,basicstyles,dialog,richcombo,undo */
/* eslint-enable */

// Clean up all instances been created on the page.
(function () {
  var comboName = "NumFormats";

  bender.editor = {
    allowedForTests: "h1; h2; p"
  };

  bender.test({
    setUp: function () {
      //Anything to be run before each test if needed
    },

    tearDown: function () {
      var editor = this.editorBot.editor;
      editor.plugins.structuredheadings.currentScheme = "1. a. i. a. i.";
    },

    "applies headings correctly when paragraph is followed by another paragraph, and triple clicked": function () {
      var bot = this.editorBot;
      bot.setHtmlWithSelection("
[foo

]bar
");

      bot.combo(comboName, function (combo) {
        // click h2
        combo.onClick("h2");
        // the new h2 has autonumbering set, since no prior heading exists
        assert.areSame(
          "
foo
" +
          "
bar
",
          bot.getData(),
          "applied h2 and remains autonumbered"
        );
      });
    }
  });
})();
<commit_msg>after scratching my head and debugging non problems, I realized i was setting the precondition in the wrong place.<commit_after>/* eslint-disable */
/* bender-tags: editor,unit */
/* bender-ckeditor-plugins: wysiwygarea,structuredheadings,toolbar,basicstyles,dialog,richcombo,undo */
/* eslint-enable */

// Clean up all instances been created on the page.
(function () {
  var comboName = "NumFormats";

  bender.editor = {
    allowedForTests: "h1; h2; p"
  };

  bender.test({
    setUp: function () {
      //Anything to be run before each test if needed
    },

    tearDown: function () {
      var editor = this.editorBot.editor;
      editor.plugins.structuredheadings.currentScheme = "1.1.1.1.1.";
    },

    "applies headings correctly when paragraph is followed by another paragraph, and triple clicked": function () {
      var bot = this.editorBot;
      bot.editor.plugins.structuredheadings.currentScheme = "1. a. i. a. i.";
      bot.setHtmlWithSelection("
[foo

]bar
");

      bot.combo(comboName, function (combo) {
        // click h2
        combo.onClick("h2");
        // the new h2 has autonumbering set, since no prior heading exists
        assert.areSame(
          "
foo
" +
          "
bar
",
          bot.getData(),
          "applied h2 and remains autonumbered"
        );
      });
    }
  });
})();
<|endoftext|>


<commit_before>'use strict';

var serialize = require('./utils').serialize;

module.exports = function apply(target, patch) {
  patch = serialize(patch);
  if (patch === null || typeof patch !== 'object' || Array.isArray(patch)) {
    return patch;
  }

  target = serialize(target);
  if (target === null || typeof target !== 'object' || Array.isArray(target)) {
    target = {};
  }
  var keys = Object.keys(patch);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    if (patch[key] === null) {
      if (target.hasOwnProperty(key)) {
        delete target[key];
      }
    } else {
      target[key] = apply(target[key], patch[key]);
    }
  }
  return target;
};
<commit_msg>Fix Prototype Pollution<commit_after>'use strict';

var serialize = require('./utils').serialize;

module.exports = function apply(target, patch) {
  patch = serialize(patch);
  if (patch === null || typeof patch !== 'object' || Array.isArray(patch)) {
    return patch;
  }

  target = serialize(target);
  if (target === null || typeof target !== 'object' || Array.isArray(target)) {
    target = {};
  }
  var keys = Object.keys(patch);
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
      return target;
    }
    if (patch[key] === null) {
      if (target.hasOwnProperty(key)) {
        delete target[key];
      }
    } else {
      target[key] = apply(target[key], patch[key]);
    }
  }
  return target;
};
<|endoftext|>


<commit_before>var MongoClient = require('mongodb').MongoClient,
    assert = require('assert'),
    ObjectID = require('mongodb').ObjectID;
var config = require(".././util/config");

module.exports.list = function(req, res) {
  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).find().toArray(function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured when query", null)
      }

      db.close();

      if (result.length == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "No data", null)
      }

      return jsonResponse(res, config.HttpResponseStatus.Success, "Fetch data success", { result })
    });
  });
}

module.exports.insert = function(req, res) {
  if (req.body == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Bad request", null)
  }

  if (req.body.app_name == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "app name must be declared", null)
  }

  if (req.body.android_ver == null || req.body.android_force == null || req.body.android_link == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Android properties must be declared", null)
  }

  if (req.body.ios_ver == null || req.body.ios_force == null || req.body.ios_link == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "iOS properties must be declared", null)
  }

  var verData = {
    "app_name" : req.body.app_name,
    "app_description" : req.body.app_description,
    "data" : {
      "android" : {
        "version" : req.body.android_ver,
        "force_update" : req.body.android_force,
        "link_update" : req.body.android_link
      },
      "ios" : {
        "version" : req.body.ios_ver,
        "force_update" : req.body.ios_force,
        "link_update" : req.body.ios_link
      }
    }
  }

  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).insertOne(verData, function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured", null)
      }

      db.close();

      return jsonResponse(res, config.HttpResponseStatus.Success, "Success insert data", null)
    });
  });
}

module.exports.update = function(req, res) {
  if (req.body.app_id == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "App Id must be declared", null)
  }

  var objString = (req.body.app_id).toString()

  if (!ObjectID.isValid(objString)) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Not valid app ID", null)
  }

  var objectID = new ObjectID(objString)
  var objectUpdate = {}

  if (req.body.app_name != null) {
    objectUpdate["app_name"] = req.body.app_name
  }

  if (req.body.app_description != null) {
    objectUpdate["app_description"] = req.body.app_description
  }

  if (req.body.android_ver != null) {
    objectUpdate["data.android.version"] = req.body.android_ver
  }

  if (req.body.android_force != null) {
    var isForce = (req.body.android_force == 'true')
    objectUpdate["data.android.force_update"] = isForce
  }

  if (req.body.android_link != null) {
    objectUpdate["data.android.link_update"] = req.body.android_link
  }

  if (req.body.ios_ver != null) {
    objectUpdate["data.ios.version"] = req.body.ios_ver
  }

  if (req.body.ios_force != null) {
    var isForce = (req.body.ios_force == 'true')
    objectUpdate["data.ios.force_update"] = isForce
  }

  if (req.body.ios_link != null) {
    objectUpdate["data.ios.link_update"] = req.body.ios_link
  }

  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).updateOne({"_id" : objectID}, {$set : objectUpdate}, function(err, result){
      if (err != null) {
        throw err
        db.close()
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "An error occured", null)
      }

      db.close()
      if (result.result.n == 0) {
        return jsonResponse(res, config.HttpResponseStatus.BadRequest, "User is not found", null)
      } else if (result.result.nModified == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "Success with no modified data", null)
      } else {
        return jsonResponse(res, config.HttpResponseStatus.Success, "Success update data", result)
      }
    })
  })
}

module.exports.listSpesific = function(req, res) {
  if(req.query.appid == "") {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "App Id must be declared", null)
  }

  var objString = (req.query.appid).toString()

  if (!ObjectID.isValid(objString)) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Not valid app ID", null)
  }

  var objectID = new ObjectID(objString)
  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).find({"_id" : objectID}).toArray(function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured when query", null)
      }

      db.close();

      if (result == null || result.length == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "No data", null)
      }

      return jsonResponse(res, config.HttpResponseStatus.Success, "Fetch data success", result)
    });
  });
}

function jsonResponse(response, status, message, metadata) {
  return response.json({
    status: status,
    message: message,
    metadata: metadata
  })
}
<commit_msg>Updated version controller<commit_after>var MongoClient = require('mongodb').MongoClient,
    assert = require('assert'),
    ObjectID = require('mongodb').ObjectID;
var config = require(".././util/config");

module.exports.list = function(req, res) {
  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).find().toArray(function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured when query", null)
      }

      db.close();

      if (result.length == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "No data", null)
      }

      return jsonResponse(res, config.HttpResponseStatus.Success, "Fetch data success", { result })
    });
  });
}

module.exports.insert = function(req, res) {
  if (req.body == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Bad request", null)
  }

  if (req.body.app_name == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "app name must be declared", null)
  }

  if (req.body.android_ver == null || req.body.android_force == null || req.body.android_link == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Android properties must be declared", null)
  }

  if (req.body.ios_ver == null || req.body.ios_force == null || req.body.ios_link == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "iOS properties must be declared", null)
  }

  var verData = {
    "app_name" : req.body.app_name,
    "app_description" : req.body.app_description,
    "data" : {
      "android" : {
        "version" : req.body.android_ver,
        "force_update" : (req.body.android_force == 'true'),
        "link_update" : req.body.android_link
      },
      "ios" : {
        "version" : req.body.ios_ver,
        "force_update" : (req.body.ios_force == 'true'),
        "link_update" : req.body.ios_link
      }
    },
    "credential" : ["admin"],
    "time_created" : new Date(),
    "last_updated" : new Date()
  }

  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).insertOne(verData, function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured", null)
      }

      db.close();

      return jsonResponse(res, config.HttpResponseStatus.Success, "Success insert data", null)
    });
  });
}

module.exports.update = function(req, res) {
  if (req.body.app_id == null) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "App Id must be declared", null)
  }

  var objString = (req.body.app_id).toString()

  if (!ObjectID.isValid(objString)) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Not valid app ID", null)
  }

  var objectID = new ObjectID(objString)
  var objectUpdate = {}

  if (req.body.app_name != null) {
    objectUpdate["app_name"] = req.body.app_name
  }

  if (req.body.app_description != null) {
    objectUpdate["app_description"] = req.body.app_description
  }

  if (req.body.android_ver != null) {
    objectUpdate["data.android.version"] = req.body.android_ver
  }

  if (req.body.android_force != null) {
    var isForce = (req.body.android_force == 'true')
    objectUpdate["data.android.force_update"] = isForce
  }

  if (req.body.android_link != null) {
    objectUpdate["data.android.link_update"] = req.body.android_link
  }

  if (req.body.ios_ver != null) {
    objectUpdate["data.ios.version"] = req.body.ios_ver
  }

  if (req.body.ios_force != null) {
    var isForce = (req.body.ios_force == 'true')
    objectUpdate["data.ios.force_update"] = isForce
  }

  if (req.body.ios_link != null) {
    objectUpdate["data.ios.link_update"] = req.body.ios_link
  }

  objectUpdate["last_updated"] = new Date()

  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).updateOne({"_id" : objectID}, {$set : objectUpdate}, function(err, result){
      if (err != null) {
        throw err
        db.close()
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "An error occured", null)
      }

      db.close()
      if (result.result.n == 0) {
        return jsonResponse(res, config.HttpResponseStatus.BadRequest, "User is not found", null)
      } else if (result.result.nModified == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "Success with no modified data", null)
      } else {
        return jsonResponse(res, config.HttpResponseStatus.Success, "Success update data", result)
      }
    })
  })
}

module.exports.listSpesific = function(req, res) {
  if(req.query.appid == "") {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "App Id must be declared", null)
  }

  var objString = (req.query.appid).toString()

  if (!ObjectID.isValid(objString)) {
    return jsonResponse(res, config.HttpResponseStatus.BadRequest, "Not valid app ID", null)
  }

  var objectID = new ObjectID(objString)
  MongoClient.connect(config.db, function(err, db) {
    db.collection(config.collection).find({"_id" : objectID}).toArray(function(err, result){
      if (err != null) {
        throw err;
        db.close();
        return jsonResponse(res, config.HttpResponseStatus.InternalServerError, "an error occured when query", null)
      }

      db.close();

      if (result == null || result.length == 0) {
        return jsonResponse(res, config.HttpResponseStatus.SuccessNoContent, "No data", null)
      }

      return jsonResponse(res, config.HttpResponseStatus.Success, "Fetch data success", result)
    });
  });
}

function jsonResponse(response, status, message, metadata) {
  return response.json({
    status: status,
    message: message,
    metadata: metadata
  })
}
<|endoftext|>


<commit_before>/* =========================================================================
 * Dependencies
 * ========================================================================= */
var appConfig = require('src/config/appConfig');

var packageJson = require('./package.json');

var gulp = require('gulp');
var inject = require('gulp-inject'); // jshint ignore:line
var jshint = require('gulp-jshint');
var less = require('gulp-less');
var replace = require('gulp-replace');
var sh = require('shelljs');
var wrap = require('gulp-wrap');
var electronConnect = require('electron-connect');

require('gulp-task-list')(gulp);

/* =========================================================================
 * Constants
 * ========================================================================= */
const APP_NAME = packageJson.name;

const BUILD_DIR = 'build';
const RELEASE_DIR = 'release';

const VENDOR_JS = [
  BUILD_DIR + '/browser/vendor/bootstrap/dist/js/bootstrap.js',
  BUILD_DIR + '/browser/vendor/console-polyfill/index.js',
  BUILD_DIR + '/browser/vendor/angular/angular.js',
  BUILD_DIR + '/browser/vendor/angular-resource/angular-resource.js',
  BUILD_DIR + '/browser/vendor/angular-ui-router/release/angular-ui-router.js',
  BUILD_DIR + '/browser/vendor/angular-bootstrap/ui-bootstrap-tpls.js',
  BUILD_DIR + '/browser/vendor/underscore/underscore.js',
  BUILD_DIR + '/browser/vendor/angular-animate/angular-animate.js',
  BUILD_DIR + '/browser/vendor/angular-sanitize/angular-sanitize.js',
  BUILD_DIR + '/browser/vendor/angular-scroll/angular-scroll.js',
  BUILD_DIR + '/browser/vendor/jquery.splitter/js/jquery.splitter-0.15.0.js',
  BUILD_DIR + '/browser/vendor/toastr/toastr.js',
  BUILD_DIR + '/browser/vendor/moment/moment.js',
  BUILD_DIR + '/browser/vendor/codemirror/lib/codemirror.js',
  BUILD_DIR + '/browser/vendor/angular/angular.js',
  BUILD_DIR + '/browser/vendor/angular-ui-codemirror/ui-codemirror.js',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson.js',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson-tmpl.js',
  BUILD_DIR + '/browser/vendor/Keypress/keypress.js'
];

const LESSOPTIONS = {
  compress: false
};

const VENDOR_CSS = [
  BUILD_DIR + '/browser/vendor/jquery.splitter/css/jquery.splitter.css',
  BUILD_DIR + '/browser/vendor/toastr/toastr.css',
  BUILD_DIR + '/browser/vendor/codemirror/lib/codemirror.css',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson.css'
];

/* =========================================================================
 * Tasks
 * ========================================================================= */
/**
 * List gulp tasks
 */
gulp.task('?', function(next) {
  sh.exec('gulp task-list');
  next();
});

gulp.task('clean', function(next) {
  sh.rm('-rf', BUILD_DIR);
  sh.rm('-rf', RELEASE_DIR);
  next();
});

gulp.task('copy', ['clean', 'copy-bower'], function() {
  return _init(gulp.src(['package.json', 'src/**/*.*']))
    .pipe(gulp.dest(BUILD_DIR));
});

gulp.task('copy-bower', ['clean'], function() {
  return _init(gulp.src('src/broswer/vendor/**/**/*.js'))
    .pipe(wrap('(function(){<%= contents %>\n})();'))
    .pipe(gulp.dest(BUILD_DIR + '/browser/vendor'));
});

gulp.task('replace', ['copy'], function() {
  return _replace(gulp.src(['build/**/**/*', '!build/browser/vendor/**/*.js']))
    .pipe(gulp.dest(BUILD_DIR));
});

gulp.task('css', ['js', 'css-vendor'], function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(BUILD_DIR + '/browser/less/main.less')
    .pipe(less(LESSOPTIONS))
    .pipe(gulp.dest(BUILD_DIR + '/browser/css'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectSrcCss:css -->',
      endtag: '<!-- endinjectSrcCss -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<link rel="stylesheet" href="' + path + '"/>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('css-vendor', ['js', 'copy', 'replace'], function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(VENDOR_CSS)
    .pipe(less(LESSOPTIONS))
    .pipe(gulp.dest(BUILD_DIR + '/css'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectVendorCss:css -->',
      endtag: '<!-- endinjectVendorCss -->',
      transform: function(filepath) {
        var path = filepath.replace('/build', '');
        return '<link rel="stylesheet" href="..' + path + '"/>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('js', ['js-vendor', 'copy', 'replace'], function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src([BUILD_DIR + '/browser/**/*.js', '!' + BUILD_DIR + '/browser/vendor/**/*.js'])
    .pipe(gulp.dest(BUILD_DIR + '/browser'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectSrcJs:js -->',
      endtag: '<!-- endinjectSrcJs -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<script src="' + path + '"></script>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('js-vendor', ['copy', 'replace'], function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(VENDOR_JS)
    .pipe(gulp.dest(BUILD_DIR + '/browser/vendor'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectVendorJs:js -->',
      endtag: '<!-- endinjectVendorJs -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<script src="' + path + '"></script>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('html', ['css', 'js'], function() {
  return gulp.src(BUILD_DIR + '/**/**/*.html')
    .pipe(gulp.dest(BUILD_DIR));
});

gulp.task('jshint', ['replace'], function() {
  return _init(gulp.src(['src/**/*.js', '!src/browser/vendor/**/*.js']))
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

gulp.task('release', ['build'], function(done) {
  sh.exec('electron-packager ' + BUILD_DIR + ' ' + APP_NAME + ' --out=' + RELEASE_DIR + ' --platform=darwin  --arch=x64 --version=0.30.2', done);
});

gulp.task('build', ['clean', 'copy', 'replace', 'css', 'js', 'html']);

gulp.task('serve', ['build'], function() {
  var electron = electronConnect.server.create({
    path: './' + BUILD_DIR
  });

  // Start browser process
  electron.start();

  // Restart browser process
  gulp.watch('src/main.js', ['default', electron.restart]);

  // Reload renderer process
  gulp.watch(['src/browser/app.js', 'src/browser/index.html'], ['default', electron.reload]);
});

gulp.task('default', ['serve']);

gulp.task('test', ['jshint'], function() {});

/* =========================================================================
 * Helper Functions
 * ========================================================================= */
function _init(stream) {
  stream.setMaxListeners(0);
  return stream;
}

function _replace(stream) {
  _init(stream);

  for (var key in appConfig) {
    stream.pipe(replace('@@' + key, appConfig[key], {
      skipBinary: true
    }));
  }

  return stream;
}
<commit_msg>simplify gulp file more, use run-sequence to run gulp build tasks in order<commit_after>/* =========================================================================
 * Dependencies
 * ========================================================================= */
var appConfig = require('src/config/appConfig');

var packageJson = require('./package.json');

var gulp = require('gulp');
var inject = require('gulp-inject'); // jshint ignore:line
var jshint = require('gulp-jshint');
var less = require('gulp-less');
var replace = require('gulp-replace');
var sh = require('shelljs');
var wrap = require('gulp-wrap');
var electronConnect = require('electron-connect');
var runSequence = require('run-sequence');

require('gulp-task-list')(gulp);

/* =========================================================================
 * Constants
 * ========================================================================= */
const APP_NAME = packageJson.name;

const BUILD_DIR = 'build';
const RELEASE_DIR = 'release';

const VENDOR_JS = [
  BUILD_DIR + '/browser/vendor/bootstrap/dist/js/bootstrap.js',
  BUILD_DIR + '/browser/vendor/console-polyfill/index.js',
  BUILD_DIR + '/browser/vendor/angular/angular.js',
  BUILD_DIR + '/browser/vendor/angular-resource/angular-resource.js',
  BUILD_DIR + '/browser/vendor/angular-ui-router/release/angular-ui-router.js',
  BUILD_DIR + '/browser/vendor/angular-bootstrap/ui-bootstrap-tpls.js',
  BUILD_DIR + '/browser/vendor/underscore/underscore.js',
  BUILD_DIR + '/browser/vendor/angular-animate/angular-animate.js',
  BUILD_DIR + '/browser/vendor/angular-sanitize/angular-sanitize.js',
  BUILD_DIR + '/browser/vendor/angular-scroll/angular-scroll.js',
  BUILD_DIR + '/browser/vendor/jquery.splitter/js/jquery.splitter-0.15.0.js',
  // BUILD_DIR + '/browser/vendor/toastr/toastr.js',
  BUILD_DIR + '/browser/vendor/moment/moment.js',
  BUILD_DIR + '/browser/vendor/codemirror/lib/codemirror.js',
  BUILD_DIR + '/browser/vendor/angular/angular.js',
  BUILD_DIR + '/browser/vendor/angular-ui-codemirror/ui-codemirror.js',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson.js',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson-tmpl.js',
  BUILD_DIR + '/browser/vendor/Keypress/keypress.js'
];

const LESSOPTIONS = {
  compress: false
};

const VENDOR_CSS = [
  BUILD_DIR + '/browser/vendor/jquery.splitter/css/jquery.splitter.css',
  BUILD_DIR + '/browser/vendor/toastr/toastr.css',
  BUILD_DIR + '/browser/vendor/codemirror/lib/codemirror.css',
  BUILD_DIR + '/browser/vendor/ng-prettyjson/src/ng-prettyjson.css'
];

/* =========================================================================
 * Tasks
 * ========================================================================= */
/**
 * List gulp tasks
 */
gulp.task('?', function(next) {
  sh.exec('gulp task-list');
  next();
});

gulp.task('clean', function(next) {
  sh.rm('-rf', BUILD_DIR);
  sh.rm('-rf', RELEASE_DIR);
  next();
});

gulp.task('copy', ['clean', 'copy-vendor'], function() {
  return _init(gulp.src(['package.json', 'src/**/*.*']))
    .pipe(gulp.dest(BUILD_DIR));
});

gulp.task('copy-vendor', ['clean'], function() {
  return _init(gulp.src('src/broswer/vendor/**/**/*.js'))
    .pipe(wrap('(function(){<%= contents %>\n})();'))
    .pipe(gulp.dest(BUILD_DIR + '/browser/vendor'));
});

gulp.task('replace', ['copy'], function() {
  return _replace(gulp.src(['build/**/**/*', '!build/browser/vendor/**/*.js']))
    .pipe(gulp.dest(BUILD_DIR));
});

gulp.task('css', function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(BUILD_DIR + '/browser/less/main.less')
    .pipe(less(LESSOPTIONS))
    .pipe(gulp.dest(BUILD_DIR + '/browser/css'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectSrcCss:css -->',
      endtag: '<!-- endinjectSrcCss -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<link rel="stylesheet" href="' + path + '"/>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('css-vendor', function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(VENDOR_CSS)
    .pipe(less(LESSOPTIONS))
    .pipe(gulp.dest(BUILD_DIR + '/css'));

  return target.pipe(inject(sources, {
      starttag: '<!-- injectVendorCss:css -->',
      endtag: '<!-- endinjectVendorCss -->',
      transform: function(filepath) {
        var path = filepath.replace('/build', '');
        return '<link rel="stylesheet" href="..' + path + '"/>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('js', function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src([BUILD_DIR + '/browser/**/*.js', '!' + BUILD_DIR + '/browser/vendor/**/*.js']);

  return target.pipe(inject(sources, {
      starttag: '<!-- injectSrcJs:js -->',
      endtag: '<!-- endinjectSrcJs -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<script src="' + path + '"></script>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('js-vendor', function() {
  var target = gulp.src(BUILD_DIR + '/browser/index.html');

  var sources = gulp.src(VENDOR_JS);

  return target.pipe(inject(sources, {
      starttag: '<!-- injectVendorJs:js -->',
      endtag: '<!-- endinjectVendorJs -->',
      transform: function(filepath) {
        var path = filepath.replace('/build/browser/', '');
        return '<script src="' + path + '"></script>';
      }
    }))
    .pipe(gulp.dest(BUILD_DIR + '/browser'));
});

gulp.task('jshint', ['replace'], function() {
  return _init(gulp.src(['src/**/*.js', '!src/browser/vendor/**/*.js']))
    .pipe(jshint())
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'));
});

gulp.task('release', ['build'], function(done) {
  sh.exec('electron-packager ' + BUILD_DIR + ' ' + APP_NAME + ' --out=' + RELEASE_DIR + ' --platform=darwin  --arch=x64 --version=0.30.2', done);
});

gulp.task('build', ['clean', 'copy', 'replace'], function(next) {
  runSequence('css', 'css-vendor', 'js', 'js-vendor', next);
});

gulp.task('serve', ['build'], function() {
  var electron = electronConnect.server.create({
    path: './' + BUILD_DIR
  });

  // Start browser process
  electron.start();

  // Restart browser process
  gulp.watch('src/main.js', ['default', electron.restart]);

  // Reload renderer process
  gulp.watch(['src/browser/app.js', 'src/browser/index.html'], ['default', electron.reload]);
});

gulp.task('default', ['serve']);

gulp.task('test', ['jshint'], function() {});

/* =========================================================================
 * Helper Functions
 * ========================================================================= */
function _init(stream) {
  stream.setMaxListeners(0);
  return stream;
}

function _replace(stream) {
  _init(stream);

  for (var key in appConfig) {
    stream.pipe(replace('@@' + key, appConfig[key], {
      skipBinary: true
    }));
  }

  return stream;
}
<|endoftext|>