<commit_before>/*
Copyright (C) 2012, 2013 Alexander Murashkin, Neil Redman <http://gsd.uwaterloo.ca>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
function Input(host)
{
    this.id = "mdInput";
    this.title = "Input";

    this.requestTimeout = 60000; // what is the timeout for response after sending a file
    this.pollingTimeout = 60000;  // what is the timeout when polling
    this.pollingDelay = 2000;    // how often to send requests (poll) for updates

    this.width = 500;
    this.height = 30;
    this.posx = 0;
    this.posy = 0;

    this.pollingTimeoutObject = null;
    this.toCancel = false;

    this.host = host;
    this.serverAction = "/upload";
}

Input.method("onDataLoaded", function(data){
    this.processor = new ClaferProcessor(data.claferXML);
    this.goals = this.processor.getGoals();
});

Input.method("onInitRendered", function()
{
    this.optimizeFlag = 1;
    this.addInstancesFlag = 1;
    this.previousData = "";
    this.toCancel = false;

    $("#optimize").click(this.OptimizeCall.bind(this));
    $("#addInstances").click(this.addInstancesCall.bind(this));
    $("#myform [type='file']").change(this.inputChange.bind(this));

    $("#optimize").attr("disabled", "disabled");
    $("#addInstances").attr("disabled", "disabled");

    var options = new Object();
    options.beforeSubmit = this.beginQuery.bind(this);
    options.success = this.fileSent.bind(this);
    options.error = this.handleError.bind(this);
    options.timeout = this.requestTimeout;

    $('#myform').ajaxForm(options);
	$('#myform').submit();
});

/*
 * Cancel request
 */

Input.method("cancelCall", function()
{
    $("#cancel").hide();
    $("#status_label").html("Cancelling...");
    this.toCancel = true;
});

/*
 * Shows uploader and hides the form
*/
Input.method("beginQuery", function(formData, jqForm, options) {
	$("#load_area #myform").hide();
	$("#load_area").append('
Loading and processing...<button id="cancel">Cancel</button>
');
    $("#cancel").click(this.cancelCall.bind(this));
    return true;
});

// post-submit callback
Input.method("endQuery", function()  {
	$("#preloader").remove();
	$("#load_area #myform").show();

	return true;
});

/* Not used. We don't need it anymore
// pre-submit callback
Input.method("showRequest", function(formData, jqForm, options) {
    var queryString = $.param(formData);
    return true;
});
*/

Input.method("onPoll", function(response)
{
    if (response === "Working")
    {
        this.pollingTimeoutObject = setTimeout(this.poll.bind(this), this.pollingDelay);
    }
    else if (response === "Cancelled")
    {
        this.endQuery();
    }
    else
    {
        this.processToolResult(response);
        this.endQuery();
    }
});

Input.method("poll", function()
{
    var options = new Object();
    options.url = "/poll";
    options.type = "post";
    options.timeout = this.pollingTimeout;
    if (!this.toCancel)
        options.data = {windowKey: this.host.key, command: "ping"};
    else
        options.data = {windowKey: this.host.key, command: "cancel"};

    options.success = this.onPoll.bind(this);
    options.error = this.handleError.bind(this);

    $.ajax(options);
});

Input.method("fileSent", function(responseText, statusText, xhr, $form)  {
    this.toCancel = false;
    if (responseText.indexOf("no clafer file submitted") == -1)
        this.pollingTimeoutObject = setTimeout(this.poll.bind(this), this.pollingDelay);
    else
        this.endQuery();
});

Input.method("handleError", function(response, statusText, xhr)  {
	clearTimeout(this.pollingTimeoutObject);
	var er = document.getElementById("error_overlay");
	er.style.visibility = "visible";
    var caption;

    if (statusText == "timeout")
        caption = "Request Timeout.
Please check whether the server is available.";
    else if (statusText == "malformed_output")
        caption = "Malformed output received from ClaferMoo.
Please check whether you are using the correct version of ClaferMoo. Also, an unhandled exception is possible.";
    else if (statusText == "empty_instances")
        caption = "No instances returned. Possible reasons:

No optimal instances, all variants are non-optimal.

An unhandled exception occured during ClaferMoo execution. Please verify your input file: check syntax and integer ranges.

.";
    else if (statusText == "empty_argument")
        caption = "Empty argument given to processToolResult.
Please report this error.";
    else if (statusText == "error" && response.responseText == "")
        caption = "Request Error.
Please check whether the server is available.";
    else
        caption = xhr + '
' + response.responseText.replace("\n", "
");

	document.getElementById("error_report").innerHTML = ('<input id="close_error" type="image" src="images/no.png" alt="close" style="position: relative; left: -325px; top: 0px; width: 20px; height: 20px;">
' + caption + "
");
	document.getElementById("close_error").onclick = function(){
		document.getElementById("error_overlay").style.visibility = "hidden";
	};
	this.endQuery();

});

Input.method("convertHtmlTags", function(input) {
  var in_tag=false;
  var in_var=false;
  var output = new String("");

  var length = input.length;

  for (var i=0; i< length; i++)
    {
      ch = input.charAt(i);

      if (in_tag)
	  {
		if (in_var)
		{
			if (ch == '"')
			{
				in_var = false;
			}

			output += ch;
		}
		else
		{
			if (ch == '"')
			{
				in_var = true;
			}
			else if (ch == '>')
			{
				in_tag = false;
			}

			output += ch.toLowerCase();
		}
      }
      else
	  {
		if (ch == '<')
		{
			in_tag = true;
		}
		output += ch;
      }
    }

  return output;
});

Input.method("OptimizeCall", function(){
   	this.optimizeFlag = 1;
   	this.addInstancesFlag = 0;
   	this.previousData = "";
   	host.findModule("mdComparisonTable").permaHidden = {};
});

Input.method("addInstancesCall", function(){
   	this.optimizeFlag = 0;
   	this.addInstancesFlag = 1;
});

Input.method("inputChange", function(){
	var filename = $("#myform [type='file']").val()
	if (filename.substring(filename.length-4) == ".cfr"){
		$("#optimize").removeAttr("disabled")
		$("#addInstances").attr("disabled", "disabled");
	} else if (filename.substring(filename.length-5) == ".data"){
		$("#optimize").attr("disabled", "disabled");
		$("#addInstances").removeAttr("disabled")
	}
});

Input.method("processToolResult", function(result)
{
	if (!result)
    {
        this.handleError(null, "empty_argument", null);
        return;
    }

	var ar = [];

	if (this.optimizeFlag){
		ar = result.split("=====");
		this.optimizeFlag = 0;
    	this.addInstancesFlag = 0;
    	if (ar.length != 3)
		{
            this.handleError(null, "malformed_output", null);
       		return;
   		}
    } else if (this.addInstancesFlag) {
		ar = this.previousData.Unparsed;
		this.optimizeFlag = 0;
    	this.addInstancesFlag = 0;
		if (ar == null || ar.length != 3)
		{
            this.handleError(null, "malformed_output", null);
       		return;
   		}

		var parser = new InstanceConverter(result)
		ar[1] += parser.convertFromClaferIGOutputToClaferMoo(this.previousData.abstractXML);
	}

	var instancesXMLText = (new InstanceConverter(ar[1])).convertFromClaferMooOutputToXML();
	var abstractXMLText = ar[2];

	instancesXMLText = instancesXMLText.replaceAll('<?xml version="1.0"?>', '');

    if (instancesXMLText.length == 0 || instancesXMLText == "<instances></instances>")
    {
        this.handleError(null, "empty_instances", null);
        return;
    }

	abstractXMLText = abstractXMLText.replaceAll(""", "\"");
	abstractXMLText = abstractXMLText.replaceAll(">", ">");
	abstractXMLText = abstractXMLText.replaceAll("<", "<");
	abstractXMLText = abstractXMLText.replaceAll("&", "&");

	abstractXMLText = this.convertHtmlTags(abstractXMLText);

	// clean namespaces
	abstractXMLText = abstractXMLText.replaceAll('<?xml version="1.0"?>', '');
	abstractXMLText = abstractXMLText.replaceAll(' xmlns="http://clafer.org/ir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cl="http://clafer.org/ir" xsi:schemalocation="http://clafer.org/ir https://github.com/gsdlab/clafer/blob/master/src/ClaferIR.xsd"', '');
	abstractXMLText = abstractXMLText.replaceAll('cl:', '');
	abstractXMLText = abstractXMLText.replaceAll('xsi:', '');

    var data = new Object();
    data.error = false;
    data.output = ar[0];
    data.instancesXML = instancesXMLText;
    data.claferXML = abstractXMLText;
    if (this.previousData == ""){
    	var lines = ar[1].match(/^.*([\n\r]+|$)/gm);
    	lines = ar[1].split(lines[1]);
    	this.originalPoints = lines.length - 1;
    }
    data.originalPoints = this.originalPoints;
    console.log(data);
    this.previousData = { Unparsed: ar, abstractXML: data.claferXML };
    this.host.updateData(data);
});
Input.method("getInitContent", function()
{
	return '
<form id="myform" action="' + this.serverAction + '" method="post" enctype="multipart/form-data">' + '<input type="file" size="15" name="claferFile">' + '<input type="hidden" name="claferFileURL" value="' + window.location + '">' + '<input id="optimize" type="submit" value="Optimize">'+
    '<input type="hidden" id="windowKey" name="windowKey" value="' + this.host.key + '">' +
    '<input id="addInstances" type="submit" value="Add Instances">' + '</form>
';
});<commit_msg>Fixed an error with an empty instance.<commit_after>/*
Copyright (C) 2012, 2013 Alexander Murashkin, Neil Redman <http://gsd.uwaterloo.ca>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
function Input(host)
{
    this.id = "mdInput";
    this.title = "Input";

    this.requestTimeout = 60000; // what is the timeout for response after sending a file
    this.pollingTimeout = 60000;  // what is the timeout when polling
    this.pollingDelay = 2000;    // how often to send requests (poll) for updates

    this.width = 500;
    this.height = 30;
    this.posx = 0;
    this.posy = 0;

    this.pollingTimeoutObject = null;
    this.toCancel = false;

    this.host = host;
    this.serverAction = "/upload";
}

Input.method("onDataLoaded", function(data){
    this.processor = new ClaferProcessor(data.claferXML);
    this.goals = this.processor.getGoals();
});

Input.method("onInitRendered", function()
{
    this.optimizeFlag = 1;
    this.addInstancesFlag = 1;
    this.previousData = "";
    this.toCancel = false;

    $("#optimize").click(this.OptimizeCall.bind(this));
    $("#addInstances").click(this.addInstancesCall.bind(this));
    $("#myform [type='file']").change(this.inputChange.bind(this));

    $("#optimize").attr("disabled", "disabled");
    $("#addInstances").attr("disabled", "disabled");

    var options = new Object();
    options.beforeSubmit = this.beginQuery.bind(this);
    options.success = this.fileSent.bind(this);
    options.error = this.handleError.bind(this);
    options.timeout = this.requestTimeout;

    $('#myform').ajaxForm(options);
	$('#myform').submit();
});

/*
 * Cancel request
 */

Input.method("cancelCall", function()
{
    $("#cancel").hide();
    $("#status_label").html("Cancelling...");
    this.toCancel = true;
});

/*
 * Shows uploader and hides the form
*/
Input.method("beginQuery", function(formData, jqForm, options) {
	$("#load_area #myform").hide();
	$("#load_area").append('
Loading and processing...<button id="cancel">Cancel</button>
');
    $("#cancel").click(this.cancelCall.bind(this));
    return true;
});

// post-submit callback
Input.method("endQuery", function()  {
	$("#preloader").remove();
	$("#load_area #myform").show();

	return true;
});

/* Not used. We don't need it anymore
// pre-submit callback
Input.method("showRequest", function(formData, jqForm, options) {
    var queryString = $.param(formData);
    return true;
});
*/

Input.method("onPoll", function(response)
{
    if (response === "Working")
    {
        this.pollingTimeoutObject = setTimeout(this.poll.bind(this), this.pollingDelay);
    }
    else if (response === "Cancelled")
    {
        this.endQuery();
    }
    else
    {
        this.processToolResult(response);
        this.endQuery();
    }
});

Input.method("poll", function()
{
    var options = new Object();
    options.url = "/poll";
    options.type = "post";
    options.timeout = this.pollingTimeout;
    if (!this.toCancel)
        options.data = {windowKey: this.host.key, command: "ping"};
    else
        options.data = {windowKey: this.host.key, command: "cancel"};

    options.success = this.onPoll.bind(this);
    options.error = this.handleError.bind(this);

    $.ajax(options);
});

Input.method("fileSent", function(responseText, statusText, xhr, $form)  {
    this.toCancel = false;
    if (responseText.indexOf("no clafer file submitted") == -1)
        this.pollingTimeoutObject = setTimeout(this.poll.bind(this), this.pollingDelay);
    else
        this.endQuery();
});

Input.method("handleError", function(response, statusText, xhr)  {
	clearTimeout(this.pollingTimeoutObject);
	var er = document.getElementById("error_overlay");
	er.style.visibility = "visible";
    var caption;

    if (statusText == "timeout")
        caption = "Request Timeout.
Please check whether the server is available.";
    else if (statusText == "malformed_output")
        caption = "Malformed output received from ClaferMoo.
Please check whether you are using the correct version of ClaferMoo. Also, an unhandled exception is possible.  Please verify your input file: check syntax and integer ranges.";
    else if (statusText == "malformed_instance")
        caption = "Malformed instance data received from ClaferMoo.
An unhandled exception may have occured during ClaferMoo execution. Please verify your input file: check syntax and integer ranges.";
    else if (statusText == "empty_instances")
        caption = "No instances returned. Possible reasons:

No optimal instances, all variants are non-optimal.

An unhandled exception occured during ClaferMoo execution. Please verify your input file: check syntax and integer ranges.

.";
    else if (statusText == "empty_argument")
        caption = "Empty argument given to processToolResult.
Please report this error.";
    else if (statusText == "error" && response.responseText == "")
        caption = "Request Error.
Please check whether the server is available.";
    else
        caption = xhr + '
' + response.responseText.replace("\n", "
");

	document.getElementById("error_report").innerHTML = ('<input id="close_error" type="image" src="images/no.png" alt="close" style="position: relative; left: -325px; top: 0px; width: 20px; height: 20px;">
' + caption + "
");
	document.getElementById("close_error").onclick = function(){
		document.getElementById("error_overlay").style.visibility = "hidden";
	};
	this.endQuery();

});

Input.method("convertHtmlTags", function(input) {
  var in_tag=false;
  var in_var=false;
  var output = new String("");

  var length = input.length;

  for (var i=0; i< length; i++)
    {
      ch = input.charAt(i);

      if (in_tag)
	  {
		if (in_var)
		{
			if (ch == '"')
			{
				in_var = false;
			}

			output += ch;
		}
		else
		{
			if (ch == '"')
			{
				in_var = true;
			}
			else if (ch == '>')
			{
				in_tag = false;
			}

			output += ch.toLowerCase();
		}
      }
      else
	  {
		if (ch == '<')
		{
			in_tag = true;
		}
		output += ch;
      }
    }

  return output;
});

Input.method("OptimizeCall", function(){
   	this.optimizeFlag = 1;
   	this.addInstancesFlag = 0;
   	this.previousData = "";
   	host.findModule("mdComparisonTable").permaHidden = {};
});

Input.method("addInstancesCall", function(){
   	this.optimizeFlag = 0;
   	this.addInstancesFlag = 1;
});

Input.method("inputChange", function(){
	var filename = $("#myform [type='file']").val()
	if (filename.substring(filename.length-4) == ".cfr"){
		$("#optimize").removeAttr("disabled")
		$("#addInstances").attr("disabled", "disabled");
	} else if (filename.substring(filename.length-5) == ".data"){
		$("#optimize").attr("disabled", "disabled");
		$("#addInstances").removeAttr("disabled")
	}
});

Input.method("processToolResult", function(result)
{
	if (!result)
    {
        this.handleError(null, "empty_argument", null);
        return;
    }

	var ar = [];

	if (this.optimizeFlag){
		ar = result.split("=====");
		this.optimizeFlag = 0;
    	this.addInstancesFlag = 0;
    	if (ar.length != 3)
		{
            this.handleError(null, "malformed_output", null);
       		return;
   		}
    } else if (this.addInstancesFlag) {
		ar = this.previousData.Unparsed;
		this.optimizeFlag = 0;
    	this.addInstancesFlag = 0;
		if (ar == null || ar.length != 3)
		{
            this.handleError(null, "malformed_output", null);
       		return;
   		}

		var parser = new InstanceConverter(result)
		ar[1] += parser.convertFromClaferIGOutputToClaferMoo(this.previousData.abstractXML);
	}

	var instancesXMLText = (new InstanceConverter(ar[1])).convertFromClaferMooOutputToXML();
	var abstractXMLText = ar[2];

	instancesXMLText = instancesXMLText.replaceAll('<?xml version="1.0"?>', '');

    if (instancesXMLText.length == 0 || instancesXMLText == "<instances></instances>")
    {
        this.handleError(null, "empty_instances", null);
        return;
    }

    if (instancesXMLText.indexOf("<instance></instance>") >= 0)
	{
        this.handleError(null, "malformed_instance", null);
        return;
    }

	abstractXMLText = abstractXMLText.replaceAll(""", "\"");
	abstractXMLText = abstractXMLText.replaceAll(">", ">");
	abstractXMLText = abstractXMLText.replaceAll("<", "<");
	abstractXMLText = abstractXMLText.replaceAll("&", "&");

	abstractXMLText = this.convertHtmlTags(abstractXMLText);

	// clean namespaces
	abstractXMLText = abstractXMLText.replaceAll('<?xml version="1.0"?>', '');
	abstractXMLText = abstractXMLText.replaceAll(' xmlns="http://clafer.org/ir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cl="http://clafer.org/ir" xsi:schemalocation="http://clafer.org/ir https://github.com/gsdlab/clafer/blob/master/src/ClaferIR.xsd"', '');
	abstractXMLText = abstractXMLText.replaceAll('cl:', '');
	abstractXMLText = abstractXMLText.replaceAll('xsi:', '');

    var data = new Object();
    data.error = false;
    data.output = ar[0];
    data.instancesXML = instancesXMLText;
    data.claferXML = abstractXMLText;
    if (this.previousData == ""){
    	var lines = ar[1].match(/^.*([\n\r]+|$)/gm);
    	lines = ar[1].split(lines[1]);
    	this.originalPoints = lines.length - 1;
    }
    data.originalPoints = this.originalPoints;
    console.log(data);
    this.previousData = { Unparsed: ar, abstractXML: data.claferXML };
    this.host.updateData(data);
});
Input.method("getInitContent", function()
{
	return '
<form id="myform" action="' + this.serverAction + '" method="post" enctype="multipart/form-data">' + '<input type="file" size="15" name="claferFile">' + '<input type="hidden" name="claferFileURL" value="' + window.location + '">' + '<input id="optimize" type="submit" value="Optimize">'+
    '<input type="hidden" id="windowKey" name="windowKey" value="' + this.host.key + '">' +
    '<input id="addInstances" type="submit" value="Add Instances">' + '</form>
';
});<|endoftext|>


<commit_before>var v = require('skeemas')(),

    meta = require('./spec/meta_schema.json');

// console.log(v.validate({}, meta)); // Valid

// console.log(v.validate({ type:'array', items:{type:'object'} }, meta)); // Valid

console.log(v.validate({
        id: 'http://example.com/schema0b',
        $schema: 'http://json-schema.org/draft-04/schema#',
        type: 'object',
        properties: [
          { s: 'string' },
          { n: 'number' }
        ]
      }, meta, { breakOnError: true, schemas: {} })) // Invalid with 'Failed "anyOf" criteria' @ '#/items'<commit_msg>removed unused file<commit_after><|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

$(function () {

	let logicDocument = CreateLogicDocument();
	logicDocument.RemoveFromContent(0, logicDocument.GetElementsCount(), false);

	let formsManager = logicDocument.GetFormsManager();

	let p1 = new AscWord.CParagraph(editor.WordControl);
	let p2 = new AscWord.CParagraph(editor.WordControl);

	logicDocument.AddToContent(0, p1);
	logicDocument.AddToContent(1, p2);

	let r1 = new AscWord.CRun();
	p1.AddToContent(0, r1);
	r1.AddText("Hello Word!");

	let r2 = new AscWord.CRun();
	p2.AddToContent(0, r2);
	r2.AddText("Абракадабра");

	function AddFormPr(oCC)
	{
		oCC.SetFormPr(new AscWord.CSdtFormPr());
	}

	QUnit.module("Check forms");

	QUnit.test("Test: \"GetAllForms\"", function (assert)
	{
		let forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 0, "Check forms count (must be zero)");

		logicDocument.MoveCursorToStartPos();

		AddFormPr(logicDocument.AddContentControlCheckBox());
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 1, "Check forms count after adding checkbox form");

		AddFormPr(logicDocument.AddContentControlComboBox());
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 2, "Check forms count after adding combobox form");

		logicDocument.AddContentControlComboBox();
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 2, "Check forms count after adding combobox content control");
	});
});
<commit_msg>[de] Fix namespace issue<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

$(function () {

	let logicDocument = AscTest.CreateLogicDocument();
	logicDocument.RemoveFromContent(0, logicDocument.GetElementsCount(), false);

	let formsManager = logicDocument.GetFormsManager();

	let p1 = new AscWord.CParagraph(editor.WordControl);
	let p2 = new AscWord.CParagraph(editor.WordControl);

	logicDocument.AddToContent(0, p1);
	logicDocument.AddToContent(1, p2);

	let r1 = new AscWord.CRun();
	p1.AddToContent(0, r1);
	r1.AddText("Hello Word!");

	let r2 = new AscWord.CRun();
	p2.AddToContent(0, r2);
	r2.AddText("Абракадабра");

	function AddFormPr(oCC)
	{
		oCC.SetFormPr(new AscWord.CSdtFormPr());
	}

	QUnit.module("Check forms");

	QUnit.test("Test: \"GetAllForms\"", function (assert)
	{
		let forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 0, "Check forms count (must be zero)");

		logicDocument.MoveCursorToStartPos();

		AddFormPr(logicDocument.AddContentControlCheckBox());
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 1, "Check forms count after adding checkbox form");

		AddFormPr(logicDocument.AddContentControlComboBox());
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 2, "Check forms count after adding combobox form");

		logicDocument.AddContentControlComboBox();
		forms = formsManager.GetAllForms();
		assert.strictEqual(forms.length, 2, "Check forms count after adding combobox content control");
	});
});
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const { pick } = require('lodash');

const PROJECT_SETTINGS_FILE_INPUTS = ['menuLogo'];

const parseFilesData = async files => {
  const formatedFilesData = {};

  await Promise.all(
    PROJECT_SETTINGS_FILE_INPUTS.map(async inputName => {
      // Skip empty file inputs
      if (!files[inputName]) {
        return;
      }

      const getStream = () => fs.createReadStream(files[inputName].path);

      // Add formated data for the upload provider
      formatedFilesData[inputName] = strapi
        .plugin('upload')
        .service('upload')
        .formatFileInfo({
          filename: files[inputName].name,
          type: files[inputName].type,
          size: files[inputName].size,
        });

      // Add image dimensions
      Object.assign(
        formatedFilesData[inputName],
        await strapi
          .plugin('upload')
          .service('image-manipulation')
          .getDimensions({ getStream })
      );

      // Add file path, and stream
      Object.assign(formatedFilesData[inputName], {
        stream: getStream(),
        tmpPath: files[inputName].path,
        provider: strapi.config.get('plugin.upload').provider,
      });
    })
  );

  return formatedFilesData;
};

const getProjectSettings = async () => {
  const store = await strapi.store({ type: 'core', name: 'admin' });
  const projectSettings = await store.get({ key: 'project-settings' });

  // Filter file input fields
  PROJECT_SETTINGS_FILE_INPUTS.forEach(inputName => {
    if (projectSettings[inputName]) {
      projectSettings[inputName] = pick(projectSettings[inputName], [
        'name',
        'url',
        'width',
        'height',
        'ext',
        'size',
      ]);
    }
  });

  return projectSettings;
};

const uploadFiles = async files => {
  return Promise.all(Object.values(files).map(strapi.plugin('upload').provider.uploadStream));
};

const deleteOldFiles = async ({ previousSettings, newSettings }) => {
  return Promise.all(
    PROJECT_SETTINGS_FILE_INPUTS.map(async inputName => {
      // Skip if there was no previous file
      if (!previousSettings[inputName]) {
        return;
      }

      // Skip if the file was not changed
      if (
        newSettings[inputName] &&
        previousSettings[inputName].url === newSettings[inputName].url
      ) {
        return;
      }

      // Skip if the file was not uploaded with the current provider
      if (strapi.config.get('plugin.upload').provider !== previousSettings[inputName].provider) {
        return;
      }

      // There was a previous file and an new file was uploaded
      // Remove the previous file
      strapi.plugin('upload').provider.delete(previousSettings[inputName]);
    })
  );
};

const updateProjectSettings = async ({ body, files }) => {
  const store = await strapi.store({ type: 'core', name: 'admin' });
  const previousSettings = await store.get({ key: 'project-settings' });

  await uploadFiles(files);

  const newSettings = {
    ...body,
    ...files,
  };

  PROJECT_SETTINGS_FILE_INPUTS.forEach(inputName => {
    if (newSettings[inputName] !== undefined && !(typeof newSettings[inputName] === 'object')) {
      // If the user input exists but is not a formdata "file" remove the file
      newSettings[inputName] = null;
    } else if (!newSettings[inputName]) {
      // If the user input is undefined reuse previous setting (do not update field)
      newSettings[inputName] = previousSettings[inputName];
    } else {
      // Update the file
      newSettings[inputName] = {
        name: newSettings[inputName].name,
        hash: newSettings[inputName].hash,
        url: newSettings[inputName].url,
        width: newSettings[inputName].width,
        height: newSettings[inputName].height,
        ext: newSettings[inputName].ext,
        size: newSettings[inputName].size,
        provider: newSettings[inputName].provider,
      };
    }
  });

  // No await to proceed asynchronously
  deleteOldFiles({ previousSettings, newSettings });

  await store.set({
    key: 'project-settings',
    value: { ...previousSettings, ...newSettings },
  });

  return getProjectSettings();
};

module.exports = {
  deleteOldFiles,
  parseFilesData,
  getProjectSettings,
  updateProjectSettings,
};
<commit_msg>refactor(menu-logo): refactored project-settings service<commit_after>'use strict';

const fs = require('fs');
const { pick } = require('lodash');

const PROJECT_SETTINGS_FILE_INPUTS = ['menuLogo'];

const parseFilesData = async files => {
  const formatedFilesData = {};

  await Promise.all(
    PROJECT_SETTINGS_FILE_INPUTS.map(async inputName => {
      const file = files[inputName];

      // Skip empty file inputs
      if (!file) {
        return;
      }

      const getStream = () => fs.createReadStream(file.path);

      // Add formated data for the upload provider
      formatedFilesData[inputName] = strapi
        .plugin('upload')
        .service('upload')
        .formatFileInfo({
          filename: file.name,
          type: file.type,
          size: file.size,
        });

      // Add image dimensions
      Object.assign(
        formatedFilesData[inputName],
        await strapi
          .plugin('upload')
          .service('image-manipulation')
          .getDimensions({ getStream })
      );

      // Add file path, and stream
      Object.assign(formatedFilesData[inputName], {
        stream: getStream(),
        tmpPath: file.path,
        provider: strapi.config.get('plugin.upload').provider,
      });
    })
  );

  return formatedFilesData;
};

const getProjectSettings = async () => {
  const store = await strapi.store({ type: 'core', name: 'admin' });
  const projectSettings = await store.get({ key: 'project-settings' });

  // Filter file input fields
  PROJECT_SETTINGS_FILE_INPUTS.forEach(inputName => {
    if (!projectSettings[inputName]) {
      return;
    }

    projectSettings[inputName] = pick(projectSettings[inputName], [
      'name',
      'url',
      'width',
      'height',
      'ext',
      'size',
    ]);
  });

  return projectSettings;
};

const uploadFiles = async files => {
  // Call the provider upload function for each file
  return Promise.all(Object.values(files).map(strapi.plugin('upload').provider.uploadStream));
};

const deleteOldFiles = async ({ previousSettings, newSettings }) => {
  return Promise.all(
    PROJECT_SETTINGS_FILE_INPUTS.map(async inputName => {
      // Skip if there was no previous file
      if (!previousSettings[inputName]) {
        return;
      }

      // Skip if the file was not changed
      if (
        newSettings[inputName] &&
        previousSettings[inputName].url === newSettings[inputName].url
      ) {
        return;
      }

      // Skip if the file was not uploaded with the current provider
      if (strapi.config.get('plugin.upload').provider !== previousSettings[inputName].provider) {
        return;
      }

      // There was a previous file and an new file was uploaded
      // Remove the previous file
      strapi.plugin('upload').provider.delete(previousSettings[inputName]);
    })
  );
};

const updateProjectSettings = async ({ body, files }) => {
  const store = await strapi.store({ type: 'core', name: 'admin' });
  const previousSettings = await store.get({ key: 'project-settings' });

  await uploadFiles(files);

  const newSettings = {
    ...body,
    ...files,
  };

  PROJECT_SETTINGS_FILE_INPUTS.forEach(inputName => {
    // If the user input exists but is not a formdata "file" remove it
    if (newSettings[inputName] !== undefined && !(typeof newSettings[inputName] === 'object')) {
      newSettings[inputName] = null;
      return;
    }

    // If the user input is undefined reuse previous setting (do not update field)
    if (!newSettings[inputName]) {
      newSettings[inputName] = previousSettings[inputName];
      return;
    }

    // Update the file
    newSettings[inputName] = pick(newSettings[inputName], [
      'name',
      'hash',
      'url',
      'width',
      'height',
      'ext',
      'size',
      'provider',
    ]);
  });

  // No await to proceed asynchronously
  deleteOldFiles({ previousSettings, newSettings });

  await store.set({
    key: 'project-settings',
    value: { ...previousSettings, ...newSettings },
  });

  return getProjectSettings();
};

module.exports = {
  deleteOldFiles,
  parseFilesData,
  getProjectSettings,
  updateProjectSettings,
};
<|endoftext|>


<commit_before>(function(){
	var app = angular.module('domainApp', ['ngSanitize', 'ui.select']);
  	//controloller to perform the search to the S-CASE artefacts repo
  	app.controller('domainController',['$http',function($http){

  		var ProjectPage  = this;//we set this to a variable in order to use it in http
	  	ProjectPage.domains=[];//we are going to save the all the domains (all the domains from Google Verticals) here
	  	ProjectPage.subdomains=[];//we are going to save all subdomains (domains level 2 (with only one parent above)) here
	  	//ProjectPage.domains=parentDomains;//we are saving here the level 1 domains (the ones that do not have parent, (they have parent 0))
	  	$http.get('parentDomains.json').then(function(res){
        ProjectPage.domains=res.data;
        console.log(ProjectPage.domains)
      });
      ProjectPage.subdomainsTotal = [];
      $http.get('subDomains.json').then(function(res){
        ProjectPage.subdomainsTotal=res.data;
      });
	  	ProjectPage.projectDetails = {};//it will contain the information of the specific project we examine/edit
	  	//it will contain the following:
	  	//projectDetails.domainset: the domain of the project
	  	//projectDetails.subdomainset: the subdomain of project

	  	var subdomainsSelected = [];//it will contain all the subdomains that correspond to the domain selected
      //the function finds all the subdomains (domains level 2) for a provided parent domain
	  	this.subdomainJSON = function (domainSelected){
        ProjectPage.DomainSubdomainSelectSuccess=0//we set the flag for the alert message to zero in order not to display either success or danger message
	  		subdomainsSelected = [];//we initialize the subdomains selected
  			for(var i=0;i<ProjectPage.subdomainsTotal.length;i++){//we loop over all the subdomains
					var flag_parent_found=0;//flag for finding the domainSelected as parent domain in the parentDomains
					for(var j=0;j<ProjectPage.domains.length;j++){
						if(ProjectPage.subdomainsTotal[i].Parent==domainSelected.ID&&flag_parent_found==0){//if the parent ID of a subdomain equals to the ID of the domain selected then this subdomain should be pushed to the subdomains to be presented to the user
							subdomainsSelected.push(ProjectPage.subdomainsTotal[i]);
							flag_parent_found=1;
						}
					}
				}
        ProjectPage.subdomains = subdomainsSelected;
        ProjectPage.projectDetails.subdomainset = [];
        //console.log(ProjectPage.subdomains);
      };
      this.subdomainJSONifAlreadySubdomainSelected = function (domainSelected){
        ProjectPage.DomainSubdomainSelectSuccess=0//we set the flag for the alert message to zero in order not to display either success or danger message
        subdomainsSelected = [];
        var domainID;
        for(var j=0;j<ProjectPage.domains.length;j++){
          if(ProjectPage.domains[j].Category===domainSelected.Category){
            domainID=ProjectPage.domains[j].ID;
            //console.log(domainID)
          }
        }
        if(domainSelected.Category!="All"){
          for(var i=0;i<ProjectPage.subdomainsTotal.length;i++){
            var flag_parent_found=0;
            for(var j=0;j<ProjectPage.domains.length;j++){
                if(ProjectPage.subdomainsTotal[i].Parent==domainID&&flag_parent_found==0){
                  subdomainsSelected.push(ProjectPage.subdomainsTotal[i]);
                  flag_parent_found=1;
                }
            }
          }
        }
        ProjectPage.subdomains = subdomainsSelected;
        //console.log(ProjectPage.subdomains);
      };

      this.init = function(){
        var currentProjectName = window.projectCurrent;
        $http({
          url: 'http://scouter.ee.auth.gr:3000/getDomainSubdomain',
          method: "GET",
          params: {
            project_name: currentProjectName
          }
        })
        .success(function(data){
          console.log('Domain and Subdomain Got');
          ProjectPage.projectDetails.domainset=data[0];
          ProjectPage.projectDetails.subdomainset=data[1];
          ProjectPage.subdomainJSONifAlreadySubdomainSelected(ProjectPage.projectDetails.domainset);
        })
        .error(function(status){
          console.log(status);
        });
      };
      //function to set the new Domain and subdomain
      this.setDomainSubdomain = function(domain,subdomain){
        var currentDomain = domain;
        var currentSubdomain = subdomain;
        var currentProjectName = window.projectCurrent;
        ProjectPage.DomainSubdomainSelectSuccess=0; //flag to be used for the success or failure of the domain and subdomain set
        $http({
          url: 'http://scouter.ee.auth.gr:3000/changeDomainSubdomain',
          method: "GET",
          params: {
            domain: currentDomain,
            subdomain: currentSubdomain,
            project_name: currentProjectName
          }
        })
        .success(function(data){
          console.log('Domain and Subdomain Set');
          ProjectPage.DomainSubdomainSelectSuccess=1;
        })
        .error(function(status){
          console.log(status);
          ProjectPage.DomainSubdomainSelectSuccess=2;
        });
      };

      this.subdomainsDisabled = function (){
        if(!ProjectPage.subdomains.length&&!ProjectPage.projectDetails.subdomainset){
          return true;
        }
        else{
          return false;
        }

      };

  	}]);

})();
<commit_msg>Replaced obsolete urls<commit_after>(function(){
	var app = angular.module('domainApp', ['ngSanitize', 'ui.select']);
  	//controloller to perform the search to the S-CASE artefacts repo
  	app.controller('domainController',['$http',function($http){

  		var ProjectPage  = this;//we set this to a variable in order to use it in http
	  	ProjectPage.domains=[];//we are going to save the all the domains (all the domains from Google Verticals) here
	  	ProjectPage.subdomains=[];//we are going to save all subdomains (domains level 2 (with only one parent above)) here
	  	//ProjectPage.domains=parentDomains;//we are saving here the level 1 domains (the ones that do not have parent, (they have parent 0))
	  	$http.get('parentDomains.json').then(function(res){
        ProjectPage.domains=res.data;
        console.log(ProjectPage.domains)
      });
      ProjectPage.subdomainsTotal = [];
      $http.get('subDomains.json').then(function(res){
        ProjectPage.subdomainsTotal=res.data;
      });
	  	ProjectPage.projectDetails = {};//it will contain the information of the specific project we examine/edit
	  	//it will contain the following:
	  	//projectDetails.domainset: the domain of the project
	  	//projectDetails.subdomainset: the subdomain of project

	  	var subdomainsSelected = [];//it will contain all the subdomains that correspond to the domain selected
      //the function finds all the subdomains (domains level 2) for a provided parent domain
	  	this.subdomainJSON = function (domainSelected){
        ProjectPage.DomainSubdomainSelectSuccess=0//we set the flag for the alert message to zero in order not to display either success or danger message
	  		subdomainsSelected = [];//we initialize the subdomains selected
  			for(var i=0;i<ProjectPage.subdomainsTotal.length;i++){//we loop over all the subdomains
					var flag_parent_found=0;//flag for finding the domainSelected as parent domain in the parentDomains
					for(var j=0;j<ProjectPage.domains.length;j++){
						if(ProjectPage.subdomainsTotal[i].Parent==domainSelected.ID&&flag_parent_found==0){//if the parent ID of a subdomain equals to the ID of the domain selected then this subdomain should be pushed to the subdomains to be presented to the user
							subdomainsSelected.push(ProjectPage.subdomainsTotal[i]);
							flag_parent_found=1;
						}
					}
				}
        ProjectPage.subdomains = subdomainsSelected;
        ProjectPage.projectDetails.subdomainset = [];
        //console.log(ProjectPage.subdomains);
      };
      this.subdomainJSONifAlreadySubdomainSelected = function (domainSelected){
        ProjectPage.DomainSubdomainSelectSuccess=0//we set the flag for the alert message to zero in order not to display either success or danger message
        subdomainsSelected = [];
        var domainID;
        for(var j=0;j<ProjectPage.domains.length;j++){
          if(ProjectPage.domains[j].Category===domainSelected.Category){
            domainID=ProjectPage.domains[j].ID;
            //console.log(domainID)
          }
        }
        if(domainSelected.Category!="All"){
          for(var i=0;i<ProjectPage.subdomainsTotal.length;i++){
            var flag_parent_found=0;
            for(var j=0;j<ProjectPage.domains.length;j++){
                if(ProjectPage.subdomainsTotal[i].Parent==domainID&&flag_parent_found==0){
                  subdomainsSelected.push(ProjectPage.subdomainsTotal[i]);
                  flag_parent_found=1;
                }
            }
          }
        }
        ProjectPage.subdomains = subdomainsSelected;
        //console.log(ProjectPage.subdomains);
      };

      this.init = function(){
        var currentProjectName = window.projectCurrent;
        $http({
          url: 'http://109.231.126.133:3000/getDomainSubdomain',
          method: "GET",
          params: {
            project_name: currentProjectName
          }
        })
        .success(function(data){
          console.log('Domain and Subdomain Got');
          ProjectPage.projectDetails.domainset=data[0];
          ProjectPage.projectDetails.subdomainset=data[1];
          ProjectPage.subdomainJSONifAlreadySubdomainSelected(ProjectPage.projectDetails.domainset);
        })
        .error(function(status){
          console.log(status);
        });
      };
      //function to set the new Domain and subdomain
      this.setDomainSubdomain = function(domain,subdomain){
        var currentDomain = domain;
        var currentSubdomain = subdomain;
        var currentProjectName = window.projectCurrent;
        ProjectPage.DomainSubdomainSelectSuccess=0; //flag to be used for the success or failure of the domain and subdomain set
        $http({
          url: 'http://109.231.126.133:3000/changeDomainSubdomain',
          method: "GET",
          params: {
            domain: currentDomain,
            subdomain: currentSubdomain,
            project_name: currentProjectName
          }
        })
        .success(function(data){
          console.log('Domain and Subdomain Set');
          ProjectPage.DomainSubdomainSelectSuccess=1;
        })
        .error(function(status){
          console.log(status);
          ProjectPage.DomainSubdomainSelectSuccess=2;
        });
      };

      this.subdomainsDisabled = function (){
        if(!ProjectPage.subdomains.length&&!ProjectPage.projectDetails.subdomainset){
          return true;
        }
        else{
          return false;
        }

      };

  	}]);

})();
<|endoftext|>


<commit_before>function echo ( ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +   improved by: echo is bad
    // +   improved by: Nate
    // +    revised by: Der Simon (http://innerdom.sourceforge.net/)
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   bugfixed by: Eugene Bulkin (http://doubleaw.com/)
    // +   input by: JB
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // %        note 1: If browsers start to support DOM Level 3 Load and Save (parsing/serializing),
    // %        note 1: we wouldn't need any such long code (even most of the code below). See
    // %        note 1: link below for a cross-browser implementation in JavaScript. HTML5 might
    // %        note 1: possibly support DOMParser, but that is not presently a standard.
    // %        note 2: Although innerHTML is widely used and may become standard as of HTML5, it is also not ideal for
    // %        note 2: use with a temporary holder before appending to the DOM (as is our last resort below),
    // %        note 2: since it may not work in an XML context
    // %        note 3: Using innerHTML to directly add to the BODY is very dangerous because it will
    // %        note 3: break all pre-existing references to HTMLElements.
    // %        note 4: Must use well-formed XML/XHTML, including use of the XHTML namespace.
    // *     example 1: echo('

abc

abc

');
    // *     returns 1: undefined

    var arg = '', argc = arguments.length, argv = arguments, i = 0;
	var d = this.window.document;

    var stringToDOM = function (q) {
        if (window.DOMImplementationLS &&
            window.DOMImplementationLS.createLSInput &&
            window.DOMImplementationLS.createLSParser) { // Follows the DOM 3 Load and Save standard, but not
            // implemented in browsers at present; HTML5 is to standardize on innerHTML, but not for XML (though
            // possibly will also standardize with DOMParser); in the meantime, to ensure fullest browser support, could
            // attach http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.js (see http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.xhtml for a simple test file)
            var lsInput = DOMImplementationLS.createLSInput();
            lsInput.stringData = q;
            var lsParser = DOMImplementationLS.createLSParser(1, null); // synchronous, no schema type
            return lsParser.parse(lsInput);
        }
        else if (window.DOMParser) {
            return new DOMParser().parseFromString(q, 'text/xml').documentElement;
        }
        else if (window.ActiveXObject) {
            var d = new ActiveXObject('MSXML2.DOMDocument');
             d.loadXML(q);
             return d;
        }
        /*else if (window.XMLHttpRequest) { // Supposed to work in older Safari
            var req = new window.XMLHttpRequest;
            req.open('GET', 'data:application/xml;charset=utf-8,'+encodeURIComponent(q), false);
            if (req.overrideMimeType) {
                req.overrideMimeType('application/xml');
            }
            req.send(null);
            return req.responseXML;
        }*/
        else if (document.createDocumentFragment) { // Document fragment did not work with innerHTML, so we create a temporary element holder
            var holder;
            if (document.createElementNS) {
                holder = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
            }
            else {
                holder = document.createElement('div'); // Document fragment did not work with innerHTML
            }
            holder.innerHTML = q;
            var df = document.createDocumentFragment();
            while (holder.firstChild) {
                df.appendChild(holder.firstChild);
            }
            return df;
        }
        throw 'Your browser does not support DOM parsing as required by echo()';
    };

    for (i = 0; i < argc; i++ ) {
        arg = argv[i];
        if (d.createDocumentFragment && d.createTextNode && d.appendChild) {
            if (d.body) {
                d.body.appendChild(stringToDOM(arg));
            } else {
                d.documentElement.appendChild(stringToDOM(arg));
            }
        } else if (d.write) {
            d.write(arg);
        }/* else { // This could recurse if we ever add print!
            print(arg);
        }*/
    }
}<commit_msg>Further echo() improvements<commit_after>function echo ( ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philip Peterson
    // +   improved by: echo is bad
    // +   improved by: Nate
    // +    revised by: Der Simon (http://innerdom.sourceforge.net/)
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // +   bugfixed by: Eugene Bulkin (http://doubleaw.com/)
    // +   input by: JB
    // +   improved by: Brett Zamir (http://brettz9.blogspot.com)
    // %        note 1: If browsers start to support DOM Level 3 Load and Save (parsing/serializing),
    // %        note 1: we wouldn't need any such long code (even most of the code below). See
    // %        note 1: link below for a cross-browser implementation in JavaScript. HTML5 might
    // %        note 1: possibly support DOMParser, but that is not presently a standard.
    // %        note 2: Although innerHTML is widely used and may become standard as of HTML5, it is also not ideal for
    // %        note 2: use with a temporary holder before appending to the DOM (as is our last resort below),
    // %        note 2: since it may not work in an XML context
    // %        note 3: Using innerHTML to directly add to the BODY is very dangerous because it will
    // %        note 3: break all pre-existing references to HTMLElements.
    // %        note 4: Must use well-formed XML/XHTML, including use of the XHTML namespace.
    // *     example 1: echo('

abc

abc

');
    // *     returns 1: undefined

    var arg = '', argc = arguments.length, argv = arguments, i = 0;
    var win = this.window;
	var d = win.document;

    var stringToDOM = function (q, parent) {
        if (win.DOMImplementationLS &&
            win.DOMImplementationLS.createLSInput &&
            win.DOMImplementationLS.createLSParser) { // Follows the DOM 3 Load and Save standard, but not
            // implemented in browsers at present; HTML5 is to standardize on innerHTML, but not for XML (though
            // possibly will also standardize with DOMParser); in the meantime, to ensure fullest browser support, could
            // attach http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.js (see http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.xhtml for a simple test file)
            var lsInput = DOMImplementationLS.createLSInput();
            lsInput.stringData = q;
            var lsParser = DOMImplementationLS.createLSParser(1, null); // synchronous, no schema type
            return lsParser.parse(lsInput);
        }
        else if (win.DOMParser) {
            return new DOMParser().parseFromString(q, 'text/xml').documentElement;
        }
        else if (win.ActiveXObject) {
            var d = new ActiveXObject('MSXML2.DOMDocument');
             d.loadXML(q);
             return d;
        }
        /*else if (win.XMLHttpRequest) { // Supposed to work in older Safari
            var req = new win.XMLHttpRequest;
            req.open('GET', 'data:application/xml;charset=utf-8,'+encodeURIComponent(q), false);
            if (req.overrideMimeType) {
                req.overrideMimeType('application/xml');
            }
            req.send(null);
            return req.responseXML;
        }*/
        else { // Document fragment did not work with innerHTML, so we create a temporary element holder
            var holder;
            if (d.createElementNS) {
                holder = d.createElementNS('http://www.w3.org/1999/xhtml', 'div');
            }
            else {
                holder = d.createElement('div'); // Document fragment did not work with innerHTML
            }
            holder.innerHTML = q;

            while (holder.firstChild) {
                parent.appendChild(holder.firstChild);
            }
        }
        // throw 'Your browser does not support DOM parsing as required by echo()';
    };

    for (i = 0; i < argc; i++ ) {
        arg = argv[i];
        if (d.appendChild) {
            if (d.body) {
                d.body.appendChild(stringToDOM(arg, d.body));
            } else {
                d.documentElement.appendChild(stringToDOM(arg, d.documentElement));
            }
        } else if (d.write) {
            d.write(arg);
        }/* else { // This could recurse if we ever add print!
            print(arg);
        }*/
    }
}<|endoftext|>


<commit_before>import dedent from 'dedent';
import moment from 'moment-timezone';
import { Observable } from 'rx';
import debugFactory from 'debug';

import {
  frontEndChallengeId,
  dataVisChallengeId,
  backEndChallengeId
} from '../utils/constantStrings.json';

import certTypes from '../utils/certTypes.json';

import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware';
import { observeQuery } from '../utils/rx';
import {
  prepUniqueDays,
  calcCurrentStreak,
  calcLongestStreak
} from '../utils/user-stats';

const debug = debugFactory('fcc:boot:user');
const sendNonUserToMap = ifNoUserRedirectTo('/map');
const certIds = {
  [certTypes.frontEnd]: frontEndChallengeId,
  [certTypes.dataVis]: dataVisChallengeId,
  [certTypes.backEnd]: backEndChallengeId
};

const certViews = {
  [certTypes.frontEnd]: 'certificate/front-end.jade',
  [certTypes.dataVis]: 'certificate/data-vis.jade',
  [certTypes.backEnd]: 'certificate/back-end.jade',
  [certTypes.fullStack]: 'certificate/full-stack.jade'
};

const certText = {
  [certTypes.fronEnd]: 'Front End certified',
  [certTypes.dataVis]: 'Data Vis Certified',
  [certTypes.backEnd]: 'Back End Certified',
  [certTypes.fullStack]: 'Full Stack Certified'
};

const dateFormat = 'MMM DD, YYYY';

function replaceScriptTags(value) {
  return value
    .replace(/<script>/gi, 'fccss')
    .replace(/<\/script>/gi, 'fcces');
}

function replaceFormAction(value) {
  return value.replace(/<form[^>]*>/, function(val) {
    return val.replace(/action(\s*?)=/, 'fccfaa$1=');
  });
}

function encodeFcc(value = '') {
  return replaceScriptTags(replaceFormAction(value));
}

function isAlgorithm(challenge) {
  // test if name starts with hike/waypoint/basejump/zipline
  // fix for bug that saved different challenges with incorrect
  // challenge types
  return !(/^(waypoint|hike|zipline|basejump)/i).test(challenge.name) &&
    +challenge.challengeType === 5;
}

function isProject(challenge) {
  return +challenge.challengeType === 3 ||
    +challenge.challengeType === 4;
}

function getChallengeGroup(challenge) {
  if (isProject(challenge)) {
    return 'projects';
  } else if (isAlgorithm(challenge)) {
    return 'algorithms';
  }
  return 'challenges';
}

// buildDisplayChallenges(challengeMap: Object, tz: String) => Observable[{
//   algorithms: Array,
//   projects: Array,
//   challenges: Array
// }]
function buildDisplayChallenges(challengeMap = {}, timezone) {
  return Observable.from(Object.keys(challengeMap))
    .map(challengeId => challengeMap[challengeId])
    .map(challenge => {
      let finalChallenge = { ...challenge };
      if (challenge.completedDate) {
        finalChallenge.completedDate = moment
          .tz(challenge.completedDate, timezone)
          .format(dateFormat);
      }

      if (challenge.lastUpdated) {
        finalChallenge.lastUpdated = moment
          .tz(challenge.lastUpdated, timezone)
          .format(dateFormat);
      }

      return finalChallenge;
    })
    .filter(({ challengeType }) => challengeType !== 6)
    .groupBy(getChallengeGroup)
    .flatMap(group$ => {
      return group$.toArray().map(challenges => ({
        [getChallengeGroup(challenges[0])]: challenges
      }));
    })
    .reduce((output, group) => ({ ...output, ...group}), {})
    .map(groups => ({
      algorithms: groups.algorithms || [],
      projects: groups.projects || [],
      challenges: groups.challenges || []
    }));
}

module.exports = function(app) {
  var router = app.loopback.Router();
  var User = app.models.User;
  function findUserByUsername$(username, fields) {
    return observeQuery(
      User,
      'findOne',
      {
        where: { username },
        fields
      }
    );
  }

  router.get('/login', function(req, res) {
    res.redirect(301, '/signin');
  });
  router.get('/logout', function(req, res) {
    res.redirect(301, '/signout');
  });
  router.get('/signin', getSignin);
  router.get('/signout', signout);
  router.get('/forgot', getForgot);
  router.post('/forgot', postForgot);
  router.get('/reset-password', getReset);
  router.post('/reset-password', postReset);
  router.get('/email-signup', getEmailSignup);
  router.get('/email-signin', getEmailSignin);
  router.get(
    '/toggle-lockdown-mode',
    sendNonUserToMap,
    toggleLockdownMode
  );
  router.get(
    '/toggle-announcement-email-mode',
    sendNonUserToMap,
    toggleReceivesAnnouncementEmails
  );
  router.get(
    '/toggle-notification-email-mode',
    sendNonUserToMap,
    toggleReceivesNotificationEmails
  );
  router.get(
    '/toggle-quincy-email-mode',
    sendNonUserToMap,
    toggleReceivesQuincyEmails
  );
  router.post(
    '/account/delete',
    ifNoUser401,
    postDeleteAccount
  );
  router.get(
    '/account',
    sendNonUserToMap,
    getAccount
  );
  router.get(
    '/settings',
    sendNonUserToMap,
    getSettings
  );
  router.get('/vote1', vote1);
  router.get('/vote2', vote2);

  // Ensure these are the last routes!
  router.get(
    '/:username/front-end-certification',
    showCert.bind(null, certTypes.frontEnd)
  );

  router.get(
    '/:username/data-visualization-certification',
    showCert.bind(null, certTypes.dataVis)
  );

  router.get(
    '/:username/back-end-certification',
    showCert.bind(null, certTypes.backEnd)
  );

  router.get(
    '/:username/full-stack-certification',
    (req, res) => res.redirect(req.url.replace('full-stack', 'back-end'))
  );

  router.get('/:username', returnUser);

  app.use(router);

  function getSignin(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/signin', {
      title: 'Sign in to Free Code Camp using a Social Media Account'
    });
  }

  function signout(req, res) {
    req.logout();
    res.redirect('/');
  }

  function getEmailSignin(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/email-signin', {
      title: 'Sign in to Free Code Camp using your Email Address'
    });
  }

  function getEmailSignup(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/email-signup', {
      title: 'Sign up for Free Code Camp using your Email Address'
    });
  }

  function getAccount(req, res) {
    const { username } = req.user;
    return res.redirect('/' + username);
  }

  function getSettings(req, res) {
    res.render('account/settings');
  }

  function returnUser(req, res, next) {
    const username = req.params.username.toLowerCase();
    const { user, path } = req;

    // timezone of signed-in account
    // to show all date related components
    // using signed-in account's timezone
    // not of the profile she is viewing
    const timezone = user && user.timezone ?
      user.timezone :
      'UTC';

    const query = {
      where: { username },
      include: 'pledge'
    };

    return User.findOne$(query)
      .filter(userPortfolio => {
        if (!userPortfolio) {
          req.flash('errors', {
            msg: `We couldn't find a page for ${ path }`
          });
          res.redirect('/');
        }
        return !!userPortfolio;
      })
      .flatMap(userPortfolio => {
        userPortfolio = userPortfolio.toJSON();

        const timestamps = userPortfolio
          .progressTimestamps
          .map(objOrNum => {
            return typeof objOrNum === 'number' ?
              objOrNum :
              objOrNum.timestamp;
          });

        const uniqueDays = prepUniqueDays(timestamps, timezone);

        userPortfolio.currentStreak = calcCurrentStreak(uniqueDays, timezone);
        userPortfolio.longestStreak = calcLongestStreak(uniqueDays, timezone);

        const calender = userPortfolio
          .progressTimestamps
          .map((objOrNum) => {
            return typeof objOrNum === 'number' ?
              objOrNum :
              objOrNum.timestamp;
          })
          .filter((timestamp) => {
            return !!timestamp;
          })
          .reduce((data, timeStamp) => {
            data[(timeStamp / 1000)] = 1;
            return data;
          }, {});

        return buildDisplayChallenges(userPortfolio.challengeMap, timezone)
          .map(displayChallenges => ({
            ...userPortfolio,
            ...displayChallenges,
            title: 'Camper ' + userPortfolio.username + '\'s Code Portfolio',
            calender,
            github: userPortfolio.githubURL,
            moment,
            encodeFcc
          }));
      })
      .doOnNext(data => {
        return res.render('account/show', data);
      })
      .subscribe(
        () => {},
        next
      );
  }

  function showCert(certType, req, res, next) {
    const username = req.params.username.toLowerCase();
    const certId = certIds[certType];
    return findUserByUsername$(username, {
          isGithubCool: true,
          isCheater: true,
          isLocked: true,
          isFrontEndCert: true,
          isDataVisCert: true,
          isBackEndCert: true,
          isFullStackCert: true,
          isHonest: true,
          username: true,
          name: true,
          challengeMap: true
      })
      .subscribe(
        user => {
          if (!user) {
            req.flash('errors', {
              msg: `We couldn't find a user with the username ${username}`
            });
            return res.redirect('/');
          }
          if (!user.isGithubCool) {
            req.flash('errors', {
              msg: dedent`
                This user needs to link GitHub with their account
                in order for others to be able to view their certificate.
              `
            });
            return res.redirect('back');
          }

          if (user.isCheater) {
            req.flash('errors', {
              msg: dedent`
                Upon review, this account has been flagged for academic
                dishonesty. If you’re the owner of this account contact
                team@freecodecamp.com for details.
              `
            });
            return res.redirect(`/${user.username}`);
          }

          if (user.isLocked) {
            req.flash('errors', {
              msg: dedent`
                ${username} has chosen to make their profile
                  private. They will need to make their profile public
                  in order for others to be able to view their certificate.
              `
            });
            return res.redirect('back');
          }
          if (!user.isHonest) {
            req.flash('errors', {
              msg: dedent`
                ${username} has not yet agreed to our Academic Honesty Pledge.
              `
            });
            return res.redirect('back');
          }

          if (user[certType]) {

            const { challengeMap = {} } = user;
            const { completedDate = new Date() } = challengeMap[certId] || {};

            return res.render(
              certViews[certType],
              {
                username: user.username,
                date: moment(new Date(completedDate)).format('MMMM, Do YYYY'),
                name: user.name
              }
            );
          }
          req.flash('errors', {
            msg: `Looks like user ${username} is not ${certText[certType]}`
          });
          return res.redirect('back');
        },
        next
      );
  }

  function toggleLockdownMode(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('isLocked', !user.isLocked, function(err) {
        if (err) { return next(err); }
        req.flash('info', {
          msg: 'We\'ve successfully updated your Privacy preferences.'
        });
        return res.redirect('/settings');
      });
    });
  }

  function toggleReceivesAnnouncementEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute(
        'sendMonthlyEmail',
        !user.sendMonthlyEmail,
        (err) => {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
        });
    });
  }

  function toggleReceivesQuincyEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('sendQuincyEmail', !user.sendQuincyEmail,
        (err) => {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
        }
      );
    });
  }

  function toggleReceivesNotificationEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute(
        'sendNotificationEmail',
        !user.sendNotificationEmail,
        function(err) {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
      });
    });
  }

  function postDeleteAccount(req, res, next) {
    User.destroyById(req.user.id, function(err) {
      if (err) { return next(err); }
      req.logout();
      req.flash('info', { msg: 'You\'ve successfully deleted your account.' });
      return res.redirect('/');
    });
  }

  function getReset(req, res) {
    if (!req.accessToken) {
      req.flash('errors', { msg: 'access token invalid' });
      return res.render('account/forgot');
    }
    return res.render('account/reset', {
      title: 'Reset your Password',
      accessToken: req.accessToken.id
    });
  }

  function postReset(req, res, next) {
    const errors = req.validationErrors();
    const { password } = req.body;

    if (errors) {
      req.flash('errors', errors);
      return res.redirect('back');
    }

    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('password', password, function(err) {
        if (err) { return next(err); }

        debug('password reset processed successfully');
        req.flash('info', { msg: 'You\'ve successfully reset your password.' });
        return res.redirect('/');
      });
    });
  }

  function getForgot(req, res) {
    if (req.isAuthenticated()) {
      return res.redirect('/');
    }
    return res.render('account/forgot', {
      title: 'Forgot Password'
    });
  }

  function postForgot(req, res) {
    const errors = req.validationErrors();
    const email = req.body.email.toLowerCase();

    if (errors) {
      req.flash('errors', errors);
      return res.redirect('/forgot');
    }

    return User.resetPassword({
      email: email
    }, function(err) {
      if (err) {
        req.flash('errors', err.message);
        return res.redirect('/forgot');
      }

      req.flash('info', {
        msg: 'An e-mail has been sent to ' +
        email +
        ' with further instructions.'
      });
      return res.render('account/forgot');
    });
  }

  function vote1(req, res, next) {
    if (req.user) {
      req.user.tshirtVote = 1;
      req.user.save(function(err) {
        if (err) { return next(err); }

        req.flash('success', { msg: 'Thanks for voting!' });
        return res.redirect('/map');
      });
    } else {
      req.flash('error', { msg: 'You must be signed in to vote.' });
      res.redirect('/map');
    }
  }

  function vote2(req, res, next) {
    if (req.user) {
      req.user.tshirtVote = 2;
      req.user.save(function(err) {
        if (err) { return next(err); }

        req.flash('success', { msg: 'Thanks for voting!' });
        return res.redirect('/map');
      });
    } else {
      req.flash('error', {msg: 'You must be signed in to vote.'});
      res.redirect('/map');
    }
  }
};
<commit_msg>added title to settings page<commit_after>import dedent from 'dedent';
import moment from 'moment-timezone';
import { Observable } from 'rx';
import debugFactory from 'debug';

import {
  frontEndChallengeId,
  dataVisChallengeId,
  backEndChallengeId
} from '../utils/constantStrings.json';

import certTypes from '../utils/certTypes.json';

import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware';
import { observeQuery } from '../utils/rx';
import {
  prepUniqueDays,
  calcCurrentStreak,
  calcLongestStreak
} from '../utils/user-stats';

const debug = debugFactory('fcc:boot:user');
const sendNonUserToMap = ifNoUserRedirectTo('/map');
const certIds = {
  [certTypes.frontEnd]: frontEndChallengeId,
  [certTypes.dataVis]: dataVisChallengeId,
  [certTypes.backEnd]: backEndChallengeId
};

const certViews = {
  [certTypes.frontEnd]: 'certificate/front-end.jade',
  [certTypes.dataVis]: 'certificate/data-vis.jade',
  [certTypes.backEnd]: 'certificate/back-end.jade',
  [certTypes.fullStack]: 'certificate/full-stack.jade'
};

const certText = {
  [certTypes.fronEnd]: 'Front End certified',
  [certTypes.dataVis]: 'Data Vis Certified',
  [certTypes.backEnd]: 'Back End Certified',
  [certTypes.fullStack]: 'Full Stack Certified'
};

const dateFormat = 'MMM DD, YYYY';

function replaceScriptTags(value) {
  return value
    .replace(/<script>/gi, 'fccss')
    .replace(/<\/script>/gi, 'fcces');
}

function replaceFormAction(value) {
  return value.replace(/<form[^>]*>/, function(val) {
    return val.replace(/action(\s*?)=/, 'fccfaa$1=');
  });
}

function encodeFcc(value = '') {
  return replaceScriptTags(replaceFormAction(value));
}

function isAlgorithm(challenge) {
  // test if name starts with hike/waypoint/basejump/zipline
  // fix for bug that saved different challenges with incorrect
  // challenge types
  return !(/^(waypoint|hike|zipline|basejump)/i).test(challenge.name) &&
    +challenge.challengeType === 5;
}

function isProject(challenge) {
  return +challenge.challengeType === 3 ||
    +challenge.challengeType === 4;
}

function getChallengeGroup(challenge) {
  if (isProject(challenge)) {
    return 'projects';
  } else if (isAlgorithm(challenge)) {
    return 'algorithms';
  }
  return 'challenges';
}

// buildDisplayChallenges(challengeMap: Object, tz: String) => Observable[{
//   algorithms: Array,
//   projects: Array,
//   challenges: Array
// }]
function buildDisplayChallenges(challengeMap = {}, timezone) {
  return Observable.from(Object.keys(challengeMap))
    .map(challengeId => challengeMap[challengeId])
    .map(challenge => {
      let finalChallenge = { ...challenge };
      if (challenge.completedDate) {
        finalChallenge.completedDate = moment
          .tz(challenge.completedDate, timezone)
          .format(dateFormat);
      }

      if (challenge.lastUpdated) {
        finalChallenge.lastUpdated = moment
          .tz(challenge.lastUpdated, timezone)
          .format(dateFormat);
      }

      return finalChallenge;
    })
    .filter(({ challengeType }) => challengeType !== 6)
    .groupBy(getChallengeGroup)
    .flatMap(group$ => {
      return group$.toArray().map(challenges => ({
        [getChallengeGroup(challenges[0])]: challenges
      }));
    })
    .reduce((output, group) => ({ ...output, ...group}), {})
    .map(groups => ({
      algorithms: groups.algorithms || [],
      projects: groups.projects || [],
      challenges: groups.challenges || []
    }));
}

module.exports = function(app) {
  var router = app.loopback.Router();
  var User = app.models.User;
  function findUserByUsername$(username, fields) {
    return observeQuery(
      User,
      'findOne',
      {
        where: { username },
        fields
      }
    );
  }

  router.get('/login', function(req, res) {
    res.redirect(301, '/signin');
  });
  router.get('/logout', function(req, res) {
    res.redirect(301, '/signout');
  });
  router.get('/signin', getSignin);
  router.get('/signout', signout);
  router.get('/forgot', getForgot);
  router.post('/forgot', postForgot);
  router.get('/reset-password', getReset);
  router.post('/reset-password', postReset);
  router.get('/email-signup', getEmailSignup);
  router.get('/email-signin', getEmailSignin);
  router.get(
    '/toggle-lockdown-mode',
    sendNonUserToMap,
    toggleLockdownMode
  );
  router.get(
    '/toggle-announcement-email-mode',
    sendNonUserToMap,
    toggleReceivesAnnouncementEmails
  );
  router.get(
    '/toggle-notification-email-mode',
    sendNonUserToMap,
    toggleReceivesNotificationEmails
  );
  router.get(
    '/toggle-quincy-email-mode',
    sendNonUserToMap,
    toggleReceivesQuincyEmails
  );
  router.post(
    '/account/delete',
    ifNoUser401,
    postDeleteAccount
  );
  router.get(
    '/account',
    sendNonUserToMap,
    getAccount
  );
  router.get(
    '/settings',
    sendNonUserToMap,
    getSettings
  );
  router.get('/vote1', vote1);
  router.get('/vote2', vote2);

  // Ensure these are the last routes!
  router.get(
    '/:username/front-end-certification',
    showCert.bind(null, certTypes.frontEnd)
  );

  router.get(
    '/:username/data-visualization-certification',
    showCert.bind(null, certTypes.dataVis)
  );

  router.get(
    '/:username/back-end-certification',
    showCert.bind(null, certTypes.backEnd)
  );

  router.get(
    '/:username/full-stack-certification',
    (req, res) => res.redirect(req.url.replace('full-stack', 'back-end'))
  );

  router.get('/:username', returnUser);

  app.use(router);

  function getSignin(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/signin', {
      title: 'Sign in to Free Code Camp using a Social Media Account'
    });
  }

  function signout(req, res) {
    req.logout();
    res.redirect('/');
  }

  function getEmailSignin(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/email-signin', {
      title: 'Sign in to Free Code Camp using your Email Address'
    });
  }

  function getEmailSignup(req, res) {
    if (req.user) {
      return res.redirect('/');
    }
    return res.render('account/email-signup', {
      title: 'Sign up for Free Code Camp using your Email Address'
    });
  }

  function getAccount(req, res) {
    const { username } = req.user;
    return res.redirect('/' + username);
  }

  function getSettings(req, res) {
    res.render('account/settings', {
        title: 'Settings'
    });
  }

  function returnUser(req, res, next) {
    const username = req.params.username.toLowerCase();
    const { user, path } = req;

    // timezone of signed-in account
    // to show all date related components
    // using signed-in account's timezone
    // not of the profile she is viewing
    const timezone = user && user.timezone ?
      user.timezone :
      'UTC';

    const query = {
      where: { username },
      include: 'pledge'
    };

    return User.findOne$(query)
      .filter(userPortfolio => {
        if (!userPortfolio) {
          req.flash('errors', {
            msg: `We couldn't find a page for ${ path }`
          });
          res.redirect('/');
        }
        return !!userPortfolio;
      })
      .flatMap(userPortfolio => {
        userPortfolio = userPortfolio.toJSON();

        const timestamps = userPortfolio
          .progressTimestamps
          .map(objOrNum => {
            return typeof objOrNum === 'number' ?
              objOrNum :
              objOrNum.timestamp;
          });

        const uniqueDays = prepUniqueDays(timestamps, timezone);

        userPortfolio.currentStreak = calcCurrentStreak(uniqueDays, timezone);
        userPortfolio.longestStreak = calcLongestStreak(uniqueDays, timezone);

        const calender = userPortfolio
          .progressTimestamps
          .map((objOrNum) => {
            return typeof objOrNum === 'number' ?
              objOrNum :
              objOrNum.timestamp;
          })
          .filter((timestamp) => {
            return !!timestamp;
          })
          .reduce((data, timeStamp) => {
            data[(timeStamp / 1000)] = 1;
            return data;
          }, {});

        return buildDisplayChallenges(userPortfolio.challengeMap, timezone)
          .map(displayChallenges => ({
            ...userPortfolio,
            ...displayChallenges,
            title: 'Camper ' + userPortfolio.username + '\'s Code Portfolio',
            calender,
            github: userPortfolio.githubURL,
            moment,
            encodeFcc
          }));
      })
      .doOnNext(data => {
        return res.render('account/show', data);
      })
      .subscribe(
        () => {},
        next
      );
  }

  function showCert(certType, req, res, next) {
    const username = req.params.username.toLowerCase();
    const certId = certIds[certType];
    return findUserByUsername$(username, {
          isGithubCool: true,
          isCheater: true,
          isLocked: true,
          isFrontEndCert: true,
          isDataVisCert: true,
          isBackEndCert: true,
          isFullStackCert: true,
          isHonest: true,
          username: true,
          name: true,
          challengeMap: true
      })
      .subscribe(
        user => {
          if (!user) {
            req.flash('errors', {
              msg: `We couldn't find a user with the username ${username}`
            });
            return res.redirect('/');
          }
          if (!user.isGithubCool) {
            req.flash('errors', {
              msg: dedent`
                This user needs to link GitHub with their account
                in order for others to be able to view their certificate.
              `
            });
            return res.redirect('back');
          }

          if (user.isCheater) {
            req.flash('errors', {
              msg: dedent`
                Upon review, this account has been flagged for academic
                dishonesty. If you’re the owner of this account contact
                team@freecodecamp.com for details.
              `
            });
            return res.redirect(`/${user.username}`);
          }

          if (user.isLocked) {
            req.flash('errors', {
              msg: dedent`
                ${username} has chosen to make their profile
                  private. They will need to make their profile public
                  in order for others to be able to view their certificate.
              `
            });
            return res.redirect('back');
          }
          if (!user.isHonest) {
            req.flash('errors', {
              msg: dedent`
                ${username} has not yet agreed to our Academic Honesty Pledge.
              `
            });
            return res.redirect('back');
          }

          if (user[certType]) {

            const { challengeMap = {} } = user;
            const { completedDate = new Date() } = challengeMap[certId] || {};

            return res.render(
              certViews[certType],
              {
                username: user.username,
                date: moment(new Date(completedDate)).format('MMMM, Do YYYY'),
                name: user.name
              }
            );
          }
          req.flash('errors', {
            msg: `Looks like user ${username} is not ${certText[certType]}`
          });
          return res.redirect('back');
        },
        next
      );
  }

  function toggleLockdownMode(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('isLocked', !user.isLocked, function(err) {
        if (err) { return next(err); }
        req.flash('info', {
          msg: 'We\'ve successfully updated your Privacy preferences.'
        });
        return res.redirect('/settings');
      });
    });
  }

  function toggleReceivesAnnouncementEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute(
        'sendMonthlyEmail',
        !user.sendMonthlyEmail,
        (err) => {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
        });
    });
  }

  function toggleReceivesQuincyEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('sendQuincyEmail', !user.sendQuincyEmail,
        (err) => {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
        }
      );
    });
  }

  function toggleReceivesNotificationEmails(req, res, next) {
    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute(
        'sendNotificationEmail',
        !user.sendNotificationEmail,
        function(err) {
          if (err) { return next(err); }
          req.flash('info', {
            msg: 'We\'ve successfully updated your Email preferences.'
          });
          return res.redirect('/settings');
      });
    });
  }

  function postDeleteAccount(req, res, next) {
    User.destroyById(req.user.id, function(err) {
      if (err) { return next(err); }
      req.logout();
      req.flash('info', { msg: 'You\'ve successfully deleted your account.' });
      return res.redirect('/');
    });
  }

  function getReset(req, res) {
    if (!req.accessToken) {
      req.flash('errors', { msg: 'access token invalid' });
      return res.render('account/forgot');
    }
    return res.render('account/reset', {
      title: 'Reset your Password',
      accessToken: req.accessToken.id
    });
  }

  function postReset(req, res, next) {
    const errors = req.validationErrors();
    const { password } = req.body;

    if (errors) {
      req.flash('errors', errors);
      return res.redirect('back');
    }

    return User.findById(req.accessToken.userId, function(err, user) {
      if (err) { return next(err); }
      return user.updateAttribute('password', password, function(err) {
        if (err) { return next(err); }

        debug('password reset processed successfully');
        req.flash('info', { msg: 'You\'ve successfully reset your password.' });
        return res.redirect('/');
      });
    });
  }

  function getForgot(req, res) {
    if (req.isAuthenticated()) {
      return res.redirect('/');
    }
    return res.render('account/forgot', {
      title: 'Forgot Password'
    });
  }

  function postForgot(req, res) {
    const errors = req.validationErrors();
    const email = req.body.email.toLowerCase();

    if (errors) {
      req.flash('errors', errors);
      return res.redirect('/forgot');
    }

    return User.resetPassword({
      email: email
    }, function(err) {
      if (err) {
        req.flash('errors', err.message);
        return res.redirect('/forgot');
      }

      req.flash('info', {
        msg: 'An e-mail has been sent to ' +
        email +
        ' with further instructions.'
      });
      return res.render('account/forgot');
    });
  }

  function vote1(req, res, next) {
    if (req.user) {
      req.user.tshirtVote = 1;
      req.user.save(function(err) {
        if (err) { return next(err); }

        req.flash('success', { msg: 'Thanks for voting!' });
        return res.redirect('/map');
      });
    } else {
      req.flash('error', { msg: 'You must be signed in to vote.' });
      res.redirect('/map');
    }
  }

  function vote2(req, res, next) {
    if (req.user) {
      req.user.tshirtVote = 2;
      req.user.save(function(err) {
        if (err) { return next(err); }

        req.flash('success', { msg: 'Thanks for voting!' });
        return res.redirect('/map');
      });
    } else {
      req.flash('error', {msg: 'You must be signed in to vote.'});
      res.redirect('/map');
    }
  }
};
<|endoftext|>


<commit_before>var Header = React.createClass({
  render: function() {
    var Navbar = ReactBootstrap.Navbar;
    var NavBrand = ReactBootstrap.NavBrand;
    var Nav = ReactBootstrap.Nav;
    var NavItem = ReactBootstrap.NavItem;

    return (
      <Navbar>
        <NavBrand>iRonhead</NavBrand>

          <NavItem eventKey={1} href="#">Link</NavItem>
          <NavItem eventKey={2} href="#">Link</NavItem>

      </Navbar>
    );
  }
});

var DummyDocument = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>

          Document type {
            this.props.doc.document_type
          } is not implemented!

    )
  }
});

var Image = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var BImage = ReactBootstrap.Image;

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>
        <BImage src={ this.props.doc.url } responsive />

    );
  }
});

var Shelf = React.createClass({
  handleClick: function(doc) {
    this.props.container.loadDocument(doc.url);
  },

  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var Table = ReactBootstrap.Table;

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>

Title	Type

{
            this.props.doc.documents.map(function(doc, index) {
              return (

                  { doc.name }
                  { doc.document_type }

              );
            }.bind(this))
          }

    );
  }
});

var Youtube = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var ResponsiveEmbed = ReactBootstrap.ResponsiveEmbed;

    // FIXME: iframe bug, check console.

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>
        <ResponsiveEmbed a16by9>

        </ResponsiveEmbed>

    );
  }
});

var Container = React.createClass({
  loadDocument: function(url) {
    $.ajax({
      url: url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({ doc: data });
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  getInitialState: function() {
    return { doc: { document_type: "unknown" } };
  },

  componentDidMount: function() {
    this.loadDocument(this.props.url);
  },

  render: function() {
    switch (this.state.doc.document_type) {
      case "image":
        return (<Image doc={ this.state.doc } />);
      case "shelf":
        return (<Shelf doc={ this.state.doc } container={ this } />);
      case "youtube":
        return (<Youtube doc={ this.state.doc } />);
      default:
        return (<DummyDocument doc={ this.state.doc } />);
    }
  }
});

ReactDOM.render(, document.getElementById('navbar'));
ReactDOM.render(<Container url="/target/shelves/shelves_0.json" />, document.getElementById('shelf'));
<commit_msg>- add description to image document (on index page).<commit_after>var Header = React.createClass({
  render: function() {
    var Navbar = ReactBootstrap.Navbar;
    var NavBrand = ReactBootstrap.NavBrand;
    var Nav = ReactBootstrap.Nav;
    var NavItem = ReactBootstrap.NavItem;

    return (
      <Navbar>
        <NavBrand>iRonhead</NavBrand>

          <NavItem eventKey={1} href="#">Link</NavItem>
          <NavItem eventKey={2} href="#">Link</NavItem>

      </Navbar>
    );
  }
});

var DummyDocument = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>

          Document type {
            this.props.doc.document_type
          } is not implemented!

    )
  }
});

var Image = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var BImage = ReactBootstrap.Image;

    return (

        <PageHeader>{ this.props.doc.name }</PageHeader>
        <BImage src={ this.props.doc.url } responsive />

{ this.props.doc.description }

    );
  }
});

var Shelf = React.createClass({
  handleClick: function(doc) {
    this.props.container.loadDocument(doc.url);
  },

  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var Table = ReactBootstrap.Table;

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>

Title	Type

{
            this.props.doc.documents.map(function(doc, index) {
              return (

                  { doc.name }
                  { doc.document_type }

              );
            }.bind(this))
          }

    );
  }
});

var Youtube = React.createClass({
  render: function() {
    var PageHeader = ReactBootstrap.PageHeader;
    var ResponsiveEmbed = ReactBootstrap.ResponsiveEmbed;

    // FIXME: iframe bug, check console.

    return (

        <PageHeader>{this.props.doc.name}</PageHeader>
        <ResponsiveEmbed a16by9>

        </ResponsiveEmbed>

    );
  }
});

var Container = React.createClass({
  loadDocument: function(url) {
    $.ajax({
      url: url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({ doc: data });
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  getInitialState: function() {
    return { doc: { document_type: "unknown" } };
  },

  componentDidMount: function() {
    this.loadDocument(this.props.url);
  },

  render: function() {
    switch (this.state.doc.document_type) {
      case "image":
        return (<Image doc={ this.state.doc } />);
      case "shelf":
        return (<Shelf doc={ this.state.doc } container={ this } />);
      case "youtube":
        return (<Youtube doc={ this.state.doc } />);
      default:
        return (<DummyDocument doc={ this.state.doc } />);
    }
  }
});

ReactDOM.render(, document.getElementById('navbar'));
ReactDOM.render(<Container url="/target/shelves/shelves_0.json" />, document.getElementById('shelf'));
<|endoftext|>