<commit_before>VISH.Editor.IMSQTI = (function(V,$,undefined){

	var init = function(){
	};

	var isCompliantXMLFile = function(fileXML){
		var contains;
		var schema;

		var xmlDoc = $.parseXML( fileXML );
		var xml = $(xmlDoc);

		if($(xml).find('assessmentItem').length != 0){
			$(xml).find('assessmentItem').each(function(){
				$(this.attributes).each(function(index,attribute){
					if(attribute.name == "xsi:schemaLocation"){
						if((((attribute.textContent).indexOf("http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_v2p1.xsd")) != -1) ||(((attribute.textContent).indexOf("http://www.imsglobal.org/xsd/imsqti_v2p1.xsd")) != -1)) {
							schema = true;
						} else {
							schema = false;
						}
					}
				});
			});
		} else {
			schema = false;
		}

		if(checkQuizType(fileXML) == "multipleCA"){
		var itemBody = $(xml).find("itemBody");
		var simpleChoice = $(xml).find("simpleChoice");
		var correctResponse = $(xml).find("correctResponse value");

		if((itemBody.length == 0)||(simpleChoice.length == 0)||(correctResponse.length == 0)|| (schema == false)){
			contains = false;
		} else {
			contains= true;
		}
	}else{
		alert("no es un tipo válido!");
		contains = false;
	}

		return contains;
 	};

	var checkAnswer = function(answer, correctArray){
		var answerBoolean;

		if((jQuery.inArray(answer,correctArray)) == -1){
			answerBoolean = false;
		} else {
			answerBoolean = true;
		}

		return answerBoolean;
	};

	var checkQuizType = function(fileXML){

		var quizType;

		var xmlDoc = $.parseXML( fileXML );
		var xml = $(xmlDoc);

		var multipleCA = $(xml).find("simpleChoice");
		var fillInTheBlankText = $(xml).find("textEntryInteraction");
		var hotSpotClick = $(xml).find("selectPointInteraction");
		var openshortAnswer = $(xml).find("extendTextInteraction");
		var order = $(xml).find("orderInteraction");
		var fillInTheBlankGap = $(xml).find("gapMatchInteraction");
		var matching = $(xml).find("matchInteraction");

		if(fillInTheBlankText.length != 0){
			quizType = "fillInTheBlankText";
		}else if(hotSpotClick.length != 0){
			quizType = "hotSpotClick";
		}else if(openshortAnswer.length != 0){
			quizType = "openshortAnswer";
		}else if(order.length != 0){
			quizType = "order";
		}else if(fillInTheBlankGap.length != 0){
			quizType = "fillInTheBlankGap";
		}else if(matching.length != 0){
			quizType = "matching";
		}else if (multipleCA.length != 0){
			quizType = "multipleCA"
		}

	return quizType;
	}

	var getJSONFromXMLFile = function(fileXML){
		var elements = [];
		var question;
		var answerArray = [];
		var correctanswerArray = [];
		var nAnswers;
		var answerIds = [];

		var xmlDoc = $.parseXML(fileXML);
		var xml = $(xmlDoc);

		/*To get the question */
		if($(xml).find('prompt').length != 0){
		$(xml).find('prompt').each(function(){
			question = $(this).text();
		});
		}else{
			$(xml).find('itemBody').children().first().each(function(){
				question = $(this).text();
			});
		}

		/*To get array of answers */
		$(xml).find('simpleChoice').each(function(){
			var answer = $(this).text();
			answerArray.push(answer);
		});

		/* To get array of corrrect answers */
		$(xml).find('correctResponse value').each(function(){
			var cAnswer = $(this).text();
			correctanswerArray.push(cAnswer);
		});

		/* To get identifiers */
		$(xml).find('simpleChoice').each(function(){
			$(this.attributes).each(function(index,attribute){
				if(attribute.name == "identifier"){
					answerIds.push(attribute.textContent);
		    	}
		   	})
		});

		if(correctanswerArray.length > 1){
			nAnswers = true;
		} else {
			nAnswers = false;
		}

		var choices = [];
		for (var i = 1; i <= answerArray.length; i++ ){
			var iChoice;
			iChoice = {
				'id': i.toString(),
				'value': (answerArray[i-1]).toString() ,
				'wysiwygValue' :  "
\n\t" + (answerArray[i-1]).toString() + '
\n',
				'answer': checkAnswer(answerIds[i-1], correctanswerArray)
			};
			choices.push(iChoice);
		}

		elements.push({
			"id":"article2_zone1",
			"type":"quiz",
			"areaid":"left",
			"quiztype":"multiplechoice",
			"selfA":true,
			"question":{
				"value": question,
				"wysiwygValue":"
\n\t" + question + "
\n"
			},
			"choices": $.extend([{}], choices),
			"extras":{
				"multipleAnswer": nAnswers
			}
		});

		var options = {
			template : "t2"
		}

		return V.Editor.Presentation.generatePresentationScaffold(elements,options);
	};

	return {
		init 						: init,
		isCompliantXMLFile			: isCompliantXMLFile,
		getJSONFromXMLFile			: getJSONFromXMLFile
	};

}) (VISH, jQuery);
<commit_msg>First version of import IMS QTI Sorting Quizzes done. Now importing sorting quizzes: http://www.imsglobal.org/question/qtiv2p1/examples/items/order.xml<commit_after>VISH.Editor.IMSQTI = (function(V,$,undefined){

	var init = function(){
	};

	var isCompliantXMLFile = function(fileXML){
		var contains;
		var schema;

		var xmlDoc = $.parseXML( fileXML );
		var xml = $(xmlDoc);

		var itemBody = $(xml).find("itemBody");
		var simpleChoice = $(xml).find("simpleChoice");
		var orderInteraction = $(xml).find("orderInteraction");
		var correctResponse = $(xml).find("correctResponse value");

		if($(xml).find('assessmentItem').length != 0){
			$(xml).find('assessmentItem').each(function(){
				$(this.attributes).each(function(index,attribute){
					if(attribute.name == "xsi:schemaLocation"){
						if((((attribute.textContent).indexOf("http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_v2p1.xsd")) != -1) ||(((attribute.textContent).indexOf("http://www.imsglobal.org/xsd/imsqti_v2p1.xsd")) != -1)) {
							schema = true;
						} else {
							schema = false;
						}
					}
				});
			});
		} else {
			schema = false;
		}

		if(checkQuizType(fileXML) == "multipleCA"){
			if((itemBody.length == 0)||(simpleChoice.length == 0)||(correctResponse.length == 0)|| (schema == false)){
				contains = false;
			}else{
				contains= true;
			}
		}else if(checkQuizType(fileXML) == "order"){
			if((itemBody.length == 0)||(orderInteraction.length == 0)||(correctResponse.length == 0)|| (schema == false)){
				contains = false;
			}else{
				contains = true;
			}
		}else{
			contains = false;
		}

		return contains;
 	};

	var checkAnswer = function(answer, correctArray){
		var answerBoolean;

		if((jQuery.inArray(answer,correctArray)) == -1){
			answerBoolean = false;
		} else {
			answerBoolean = true;
		}

		return answerBoolean;
	};

	var checkQuizType = function(fileXML){

		var quizType;

		var xmlDoc = $.parseXML( fileXML );
		var xml = $(xmlDoc);

		var multipleCA = $(xml).find("simpleChoice");
		var fillInTheBlankText = $(xml).find("textEntryInteraction");
		var hotSpotClick = $(xml).find("selectPointInteraction");
		var openshortAnswer = $(xml).find("extendTextInteraction");
		var order = $(xml).find("orderInteraction");
		var fillInTheBlankGap = $(xml).find("gapMatchInteraction");
		var matching = $(xml).find("matchInteraction");

		if(fillInTheBlankText.length != 0){
			quizType = "fillInTheBlankText";
		}else if(hotSpotClick.length != 0){
			quizType = "hotSpotClick";
		}else if(openshortAnswer.length != 0){
			quizType = "openshortAnswer";
		}else if(order.length != 0){
			quizType = "order";
		}else if(fillInTheBlankGap.length != 0){
			quizType = "fillInTheBlankGap";
		}else if(matching.length != 0){
			quizType = "matching";
		}else if (multipleCA.length != 0){
			quizType = "multipleCA"
		}

	return quizType;
	}

	var getJSONFromXMLFile = function(fileXML){
		if(checkQuizType(fileXML) == "multipleCA"){
			return getJSONFromXMLFileMC(fileXML);
		}else if(checkQuizType(fileXML) == "order"){
			console.log("hola, order");
			return getJSONFromXMLFileSorting(fileXML);
		}

	}

	var getJSONFromXMLFileMC = function(fileXML){
		var elements = [];
		var question;
		var answerArray = [];
		var correctanswerArray = [];
		var nAnswers;
		var answerIds = [];

		var xmlDoc = $.parseXML(fileXML);
		var xml = $(xmlDoc);

		/*To get the question */
		if($(xml).find('prompt').length != 0){
		$(xml).find('prompt').each(function(){
			question = $(this).text();
		});
		}else{
			$(xml).find('itemBody').children().first().each(function(){
				question = $(this).text();
			});
		}

		/*To get array of answers */
		$(xml).find('simpleChoice').each(function(){
			var answer = $(this).text();
			answerArray.push(answer);
		});

		/* To get array of corrrect answers */
		$(xml).find('correctResponse value').each(function(){
			var cAnswer = $(this).text();
			correctanswerArray.push(cAnswer);
		});

		/* To get identifiers */
		$(xml).find('simpleChoice').each(function(){
			$(this.attributes).each(function(index,attribute){
				if(attribute.name == "identifier"){
					answerIds.push(attribute.textContent);
		    	}
		   	})
		});

		if(correctanswerArray.length > 1){
			nAnswers = true;
		} else {
			nAnswers = false;
		}

		var choices = [];
		for (var i = 1; i <= answerArray.length; i++ ){
			var iChoice;
			iChoice = {
				'id': i.toString(),
				'value': (answerArray[i-1]).toString() ,
				'wysiwygValue' :  "
\n\t" + (answerArray[i-1]).toString() + '
\n',
				'answer': checkAnswer(answerIds[i-1], correctanswerArray)
			};
			choices.push(iChoice);
		}

		elements.push({
			"id":"article2_zone1",
			"type":"quiz",
			"areaid":"left",
			"quiztype":"multiplechoice",
			"selfA":true,
			"question":{
				"value": question,
				"wysiwygValue":"
\n\t" + question + "
\n"
			},
			"choices": $.extend([{}], choices),
			"extras":{
				"multipleAnswer": nAnswers
			}
		});

		var options = {
			template : "t2"
		}

		return V.Editor.Presentation.generatePresentationScaffold(elements,options);
	};

	var getJSONFromXMLFileSorting = function(fileXML){
		var elements = [];
		var question;
		var answerArray = [];
		var correctanswerArray = [];
		var answerIds = [];

		var xmlDoc = $.parseXML(fileXML);
		var xml = $(xmlDoc);

		/*To get the question */
		if($(xml).find('prompt').length != 0){
		$(xml).find('prompt').each(function(){
			question = $(this).text();
		});
		}else{
			$(xml).find('itemBody').children().first().each(function(){
				question = $(this).text();
			});
		}

		/*To get array of answers */
		$(xml).find('simpleChoice').each(function(){
			var answer = $(this).text();
			answerArray.push(answer);
		});

		/* To get array of corrrect answers */
		$(xml).find('correctResponse value').each(function(){
			var cAnswer = $(this).text();
			correctanswerArray.push(cAnswer);
		});

		/* To get identifiers */
		$(xml).find('simpleChoice').each(function(){
			$(this.attributes).each(function(index,attribute){
				if(attribute.name == "identifier"){
					answerIds.push(attribute.textContent);
		    	}
		   	})
		});

		//we get the IDs
		//now we have to get the choices according to that ID
		$(xml).find('simpleChoice').each(function(){
			$(this.attributes).each(function(index,attribute){
				if(attribute.name == "identifier"){
					answerIds.push(attribute.textContent);
		    	}
		   	})
		});

		var myHash = [];
		for (var i = 1; i <= answerArray.length; i++ ){
			myHash[answerIds[i-1]] = answerArray[i-1];
		}

		var choices = [];
		for (var i = 1; i <= answerArray.length; i++ ){
			var iChoice;
			iChoice = {
				'id': i.toString(),
				'value': myHash[correctanswerArray[i-1]] ,
				'wysiwygValue' :  "
\n\t" + myHash[correctanswerArray[i-1]] + '
\n',
				'answer': i.toString()
			};
			choices.push(iChoice);

		}

		elements.push({
			"id":"article2_zone1",
			"type":"quiz",
			"areaid":"left",
			"quiztype":"sorting",
			"selfA":true,
			"question":{
				"value": question,
				"wysiwygValue":"
\n\t" + question + "
\n"
			},
			"choices": $.extend([{}], choices),
		});

		var options = {
			template : "t2"
		}

		console.log("elements");
		console.log(elements);

		return V.Editor.Presentation.generatePresentationScaffold(elements,options);
	};

	return {
		init 						: init,
		isCompliantXMLFile			: isCompliantXMLFile,
		getJSONFromXMLFile			: getJSONFromXMLFile
	};

}) (VISH, jQuery);
<|endoftext|>


<commit_before>function(args) {
/*
is_app(true)
control_type("VB")
display_name("Shapes control")
description("This will return the shapes control")
base_component_id("shapes_control")
load_once_from_file(true)
visibility("PRIVATE")
read_only(true)
properties(
    [
        {
            id:     "text",
            name:   "Text",
            type:   "String"
        }
        ,
        {
            id:     "background_color",
            name:   "Background color",
            type:   "String"
        }
    ]
)//properties
logo_url("/driver_icons/shapes.png")
*/

    Vue.component("shapes_control",{
      props: ["args"]
      ,
      template: `<div v-bind:style='"height:100%;width:100%; border: 0px;" +
                                    "background-color: "+    args["background_color"]  +  ";"'>

                                                {{args.text}}
                 </div>`
      ,
      data: function() {
       return {
         msg: "..."
     }
      },
    })
}
<commit_msg>Create a circle or square<commit_after>function(args) {
/*
is_app(true)
control_type("VB")
display_name("Shapes control")
description("This will return the shapes control")
base_component_id("shapes_control")
load_once_from_file(true)
visibility("PRIVATE")
read_only(true)
properties(
    [
        {
            id:     "text",
            name:   "Text",
            type:   "String"
        }
        ,
        {
            id:     "background_color",
            name:   "Background color",
            default:    "blue",
            type:   "String"
        }
        ,
        {
            id:         "shape",
            name:       "Shape",
            type:       "Select",
            default:    "square",
            values:     [
                            {display: "Square",   square: ""},
                            {display: "Circle",  value: "circle"}
                        ]
        }
    ]
)//properties
logo_url("/driver_icons/shapes.png")
*/

    Vue.component("shapes_control",{
      props: ["args"]
      ,
      template: `<div v-bind:style='"height:100%;width:100%; border: 0px;" +
                                    "background-color: "+    args["background_color"]  +  ";"'>

                 </div>`
      ,
      data: function() {
       return {
         msg: "..."
     }
      },
    })
}
<|endoftext|>


<commit_before>/*
glUtils v0.1.0

The MIT License (MIT)

Copyright (c) 2014 Tarek Sherif

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(){"use strict";window.glUtils={getGL:function(a){var b=a.getContext("experimental-webgl");return b.viewport(0,0,a.width,a.height),b},getProgram:function(a,b,c){var d=a.createShader(a.VERTEX_SHADER);a.shaderSource(d,document.getElementById(b).text),a.compileShader(d),a.getShaderParameter(d,a.COMPILE_STATUS)||console.error(a.getShaderInfoLog(d));var e=a.createShader(a.FRAGMENT_SHADER);a.shaderSource(e,document.getElementById(c).text),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)||console.error(a.getShaderInfoLog(e));var f=a.createProgram();return a.attachShader(f,d),a.attachShader(f,e),a.linkProgram(f),a.getProgramParameter(f,a.LINK_STATUS)||console.error(a.getProgramInfoLog(f)),a.useProgram(f),f},getGLVars:function(a,b,c){var d={},e=c.attributes||[],f=c.uniforms||[];return e.forEach(function(c){d[c]=a.getAttribLocation(b,c)}),f.forEach(function(c){d[c]=a.getUniformLocation(b,c)}),d},setBuffer:function(a,b,c,d,e){e=e||a.FLOAT;var f=a.createBuffer();a.bindBuffer(a.ARRAY_BUFFER,f),a.bufferData(a.ARRAY_BUFFER,c,a.STATIC_DRAW),a.vertexAttribPointer(b,d,e,!1,0,0),a.enableVertexAttribArray(b)},createBox:function(a){var b,c,d,e,f=a.position||[0,0,0],g=a.dimensions||[1,1,1],h=f[0],i=f[1],j=f[2],k=g[0],l=g[1],m=g[2],n={x:h,y:i,z:j+m},o={x:h+k,y:i,z:j+m},p={x:h,y:i+l,z:j+m},q={x:h+k,y:i+l,z:j+m},r={x:h,y:i,z:j},s={x:h+k,y:i,z:j},t={x:h,y:i+l,z:j},u={x:h+k,y:i+l,z:j},v=new Float32Array([n.x,n.y,n.z,o.x,o.y,o.z,p.x,p.y,p.z,p.x,p.y,p.z,o.x,o.y,o.z,q.x,q.y,q.z,o.x,o.y,o.z,s.x,s.y,s.z,q.x,q.y,q.z,q.x,q.y,q.z,s.x,s.y,s.z,u.x,u.y,u.z,o.x,s.y,s.z,r.x,r.y,r.z,u.x,u.y,u.z,u.x,u.y,u.z,r.x,r.y,r.z,t.x,t.y,t.z,r.x,r.y,r.z,n.x,n.y,n.z,t.x,t.y,t.z,t.x,t.y,t.z,n.x,n.y,n.z,p.x,p.y,p.z,p.x,p.y,p.z,q.x,q.y,q.z,t.x,t.y,t.z,t.x,t.y,t.z,q.x,q.y,q.z,u.x,u.y,u.z,r.x,r.y,r.z,s.x,s.y,s.z,n.x,n.y,n.z,n.x,n.y,n.z,s.x,s.y,s.z,o.x,o.y,o.z]),w=new Float32Array(v.length);for(b=0,c=v.length/3;c>b;b++)d=4*b,e=3*b,w[e]=1===parseInt(b/6,10)?1:3===parseInt(b/6,10)?-1:0,w[e+1]=4===parseInt(b/6,10)?1:5===parseInt(b/6,10)?-1:0,w[e+2]=0===parseInt(b/6,10)?1:2===parseInt(b/6,10)?-1:0;return{vertices:v,normals:w}},createSphere:function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=a.position||[0,0,0],s=a.long_bands||10,t=a.lat_bands||10,u=a.radius||5,v=Math.PI/t,w=2*Math.PI/s,x=s*t*6,y=new Float32Array(3*x),z=new Float32Array(3*x),A=r[0],B=r[1],C=r[2],D=0;for(n=0;t>n;n++)for(b=n*v,h=Math.cos(b),i=Math.cos(b+v),o=0;s>o;o++)c=o*w,d=Math.sin(b)*Math.cos(c),e=Math.sin(b)*Math.cos(c+w),f=Math.sin(b+v)*Math.cos(c),g=Math.sin(b+v)*Math.cos(c+w),j=Math.sin(b)*Math.sin(c),k=Math.sin(b)*Math.sin(c+w),l=Math.sin(b+v)*Math.sin(c),m=Math.sin(b+v)*Math.sin(c+w),p=3*D,q=4*D,y[p]=d*u+A,y[p+1]=h*u+B,y[p+2]=j*u+C,y[p+3]=f*u+A,y[p+4]=i*u+B,y[p+5]=l*u+C,y[p+6]=e*u+A,y[p+7]=h*u+B,y[p+8]=k*u+C,y[p+9]=f*u+A,y[p+10]=i*u+B,y[p+11]=l*u+C,y[p+12]=g*u+A,y[p+13]=i*u+B,y[p+14]=m*u+C,y[p+15]=e*u+A,y[p+16]=h*u+B,y[p+17]=k*u+C,z[p]=d,z[p+1]=h,z[p+2]=j,z[p+3]=f,z[p+4]=i,z[p+5]=l,z[p+6]=e,z[p+7]=h,z[p+8]=k,z[p+9]=f,z[p+10]=i,z[p+11]=l,z[p+12]=g,z[p+13]=i,z[p+14]=m,z[p+15]=e,z[p+16]=h,z[p+17]=k,D+=6;return{vertices:y,normals:z}}}}();<commit_msg>Update gl-utils.<commit_after>/*
glUtils v0.2.1

The MIT License (MIT)

Copyright (c) 2014 Tarek Sherif

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(){"use strict";window.glUtils={getGL:function(a){var b=a.getContext("webgl")||a.getContext("experimental-webgl");return b.viewport(0,0,a.width,a.height),b},getProgram:function(a,b,c){var d=a.createShader(a.VERTEX_SHADER);a.shaderSource(d,document.getElementById(b).text),a.compileShader(d),a.getShaderParameter(d,a.COMPILE_STATUS)||console.error(a.getShaderInfoLog(d));var e=a.createShader(a.FRAGMENT_SHADER);a.shaderSource(e,document.getElementById(c).text),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)||console.error(a.getShaderInfoLog(e));var f=a.createProgram();return a.attachShader(f,d),a.attachShader(f,e),a.linkProgram(f),a.getProgramParameter(f,a.LINK_STATUS)||console.error(a.getProgramInfoLog(f)),a.useProgram(f),f},getGLVars:function(a,b,c){var d={},e=c.attributes||[],f=c.uniforms||[];return e.forEach(function(c){d[c]=a.getAttribLocation(b,c)}),f.forEach(function(c){d[c]=a.getUniformLocation(b,c)}),d},setBuffer:function(a,b,c,d,e){e=e||a.FLOAT;var f=a.createBuffer();return a.bindBuffer(a.ARRAY_BUFFER,f),a.bufferData(a.ARRAY_BUFFER,c,a.STATIC_DRAW),a.vertexAttribPointer(b,d,e,!1,0,0),a.enableVertexAttribArray(b),f},enableBuffer:function(a,b,c,d){return a.bindBuffer(a.ARRAY_BUFFER,c),a.vertexAttribPointer(b,d,a.FLOAT,!1,0,0),a.enableVertexAttribArray(b),c},createBox:function(a){a=a||{};var b,c,d,e=a.dimensions||[1,1,1],f=a.position||[-e[0]/2,-e[1]/2,-e[2]/2],g=f[0],h=f[1],i=f[2],j=e[0],k=e[1],l=e[2],m={x:g,y:h,z:i+l},n={x:g+j,y:h,z:i+l},o={x:g,y:h+k,z:i+l},p={x:g+j,y:h+k,z:i+l},q={x:g,y:h,z:i},r={x:g+j,y:h,z:i},s={x:g,y:h+k,z:i},t={x:g+j,y:h+k,z:i},u=new Float32Array([m.x,m.y,m.z,n.x,n.y,n.z,o.x,o.y,o.z,o.x,o.y,o.z,n.x,n.y,n.z,p.x,p.y,p.z,n.x,n.y,n.z,r.x,r.y,r.z,p.x,p.y,p.z,p.x,p.y,p.z,r.x,r.y,r.z,t.x,t.y,t.z,n.x,r.y,r.z,q.x,q.y,q.z,t.x,t.y,t.z,t.x,t.y,t.z,q.x,q.y,q.z,s.x,s.y,s.z,q.x,q.y,q.z,m.x,m.y,m.z,s.x,s.y,s.z,s.x,s.y,s.z,m.x,m.y,m.z,o.x,o.y,o.z,o.x,o.y,o.z,p.x,p.y,p.z,s.x,s.y,s.z,s.x,s.y,s.z,p.x,p.y,p.z,t.x,t.y,t.z,q.x,q.y,q.z,r.x,r.y,r.z,m.x,m.y,m.z,m.x,m.y,m.z,r.x,r.y,r.z,n.x,n.y,n.z]),v=new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,1,1]),w=new Float32Array(u.length);for(b=0,c=u.length/3;c>b;b++)d=3*b,w[d]=1===parseInt(b/6,10)?1:3===parseInt(b/6,10)?-1:0,w[d+1]=4===parseInt(b/6,10)?1:5===parseInt(b/6,10)?-1:0,w[d+2]=0===parseInt(b/6,10)?1:2===parseInt(b/6,10)?-1:0;return{vertices:u,normals:w,texture_coords:v}},createSphere:function(a){a=a||{};var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=a.position||[0,0,0],w=a.long_bands||10,x=a.lat_bands||10,y=a.radius||5,z=Math.PI/x,A=2*Math.PI/w,B=w*x*6,C=new Float32Array(3*B),D=new Float32Array(3*B),E=new Float32Array(2*B),F=v[0],G=v[1],H=v[2],I=0;for(r=0;x>r;r++)for(b=r*z,h=Math.cos(b),i=Math.cos(b+z),s=0;w>s;s++)c=s*A,d=Math.sin(b)*Math.cos(c),e=Math.sin(b)*Math.cos(c+A),f=Math.sin(b+z)*Math.cos(c),g=Math.sin(b+z)*Math.cos(c+A),j=Math.sin(b)*Math.sin(c),k=Math.sin(b)*Math.sin(c+A),l=Math.sin(b+z)*Math.sin(c),m=Math.sin(b+z)*Math.sin(c+A),n=1-s/w,o=1-(s+1)/w,p=1-r/x,q=1-(r+1)/x,t=3*I,u=2*I,C[t]=d*y+F,C[t+1]=h*y+G,C[t+2]=j*y+H,C[t+3]=f*y+F,C[t+4]=i*y+G,C[t+5]=l*y+H,C[t+6]=e*y+F,C[t+7]=h*y+G,C[t+8]=k*y+H,C[t+9]=f*y+F,C[t+10]=i*y+G,C[t+11]=l*y+H,C[t+12]=g*y+F,C[t+13]=i*y+G,C[t+14]=m*y+H,C[t+15]=e*y+F,C[t+16]=h*y+G,C[t+17]=k*y+H,D[t]=d,D[t+1]=h,D[t+2]=j,D[t+3]=f,D[t+4]=i,D[t+5]=l,D[t+6]=e,D[t+7]=h,D[t+8]=k,D[t+9]=f,D[t+10]=i,D[t+11]=l,D[t+12]=g,D[t+13]=i,D[t+14]=m,D[t+15]=e,D[t+16]=h,D[t+17]=k,E[u]=n,E[u+1]=p,E[u+2]=n,E[u+3]=q,E[u+4]=o,E[u+5]=p,E[u+6]=n,E[u+7]=q,E[u+8]=o,E[u+9]=q,E[u+10]=o,E[u+11]=p,I+=6;return{vertices:C,normals:D,texture_coords:E}}}}();<|endoftext|>


<commit_before>	//---------------------------------------------------------------------
	// Created by General Wrex
	// My Patreons have made creating this script possible @ https://www.patreon.com/generalwrex
	// At the time of editing this script, they are:
	// - MitchDaGamer
	//
	// Thanks so much guys, you allow me to continue to do what i love!
	// Add URL to json object,
	// add path to the object you want from the json
	// set your variable type and name
	// example URL: https://api.github.com/repos/HellionCommunity/HellionExtendedServer/releases/latest
	// example Path: name
	// will return object.name
	// in this example the variable would contain "[DEV] Version 1.2.2.3"
	//---------------------------------------------------------------------

module.exports = {

	//---------------------------------------------------------------------
	// DBM Mods Manager Variables (Optional but nice to have!)
	//
	// These are variables that DBM Mods Manager uses to show information
	// about the mods for people to see in the list.
	//---------------------------------------------------------------------

	// Who made the mod (If not set, defaults to "DBM Mods")
	author: "General Wrex",

	// The version of the mod (Defaults to 1.0.0)
	version: "1.0.0",

    // A short description to show on the mod line for this mod (Must be on a single line)
	short_description: "Stores JSON from a webapi into a variable.",

	// If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods
	depends_on_mods: ["WrexMODS"],

	//---------------------------------------------------------------------

	//---------------------------------------------------------------------
	// Action Name
	//
	// This is the name of the action displayed in the editor.
	//---------------------------------------------------------------------

	name: "Store Json From WebAPI",

	//---------------------------------------------------------------------
	// Action Section
	//
	// This is the section the action will fall into.
	//---------------------------------------------------------------------

	section: "JSON Things",

	//---------------------------------------------------------------------
	// Action Subtitle
	//
	// This function generates the subtitle displayed next to the name.
	//---------------------------------------------------------------------

	subtitle: function(data) {
		return `${data.varName}`;
	},

	//---------------------------------------------------------------------
	// Action Storage Function
	//
	// Stores the relevant variable info for the editor.
	//---------------------------------------------------------------------

	variableStorage: function(data, varType) {
		const type = parseInt(data.storage);
		if(type !== varType) return;
		return ([data.varName, 'JSON Object']);
	},

	//---------------------------------------------------------------------
	// Action Fields
	//
	// These are the fields for the action. These fields are customized
	// by creating elements with corresponding IDs in the HTML. These
	// are also the names of the fields stored in the action's JSON data.
	//---------------------------------------------------------------------

	fields: ["behavior", "token", "user", "pass" ,"url", "path", "storage", "varName"],

	//---------------------------------------------------------------------
	// Command HTML
	//
	// This function returns a string containing the HTML used for
	// editing actions.
	//
	// The "isEvent" parameter will be true if this action is being used
	// for an event. Due to their nature, events lack certain information,
	// so edit the HTML to reflect this.
	//
	// The "data" parameter stores constants for select elements to use.
	// Each is an array: index 0 for commands, index 1 for events.
	// The names are: sendTargets, members, roles, channels,
	//                messages, servers, variables
	//---------------------------------------------------------------------

	html: function(isEvent, data) {
		return `

				Mod Info:

				Created by General Wrex!

		End Behavior:

		<select id="behavior" class="round">
			<option value="0" selected>Call Next Action Automatically</option>
			<option value="1">Do Not Call Next Action</option>
		</select>

    WebAPI URL:

		<textarea id="url" class="round" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Bearer Token ( If a bearer token is required, put it here!)

		<textarea id="token" class="round" placeholder="blank if none"   style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Username( If a password is required, put it here!)

		<input id="user" class="round"  placeholder="blank if none" style="width: 99%; resize: none;" >

		Password ( If a password is required, put it here!)

		<input id="pass" class="round"  placeholder="blank if none"  style="width: 99%; resize: none;" >

		Initial JSON Path: (Leave blank to store everything, supports the usage of JSON Path (Regex))

		<input id="path" class="round"; style="width: 75%;" type="text">

		Store In:

		<select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer')">
			${data.variables[0]}
		</select>

		JSON Storage Variable Name:

		<input id="varName" class="round" type="text">

`
	},

	//---------------------------------------------------------------------
	// Action Editor Init Code
	//
	// When the HTML is first applied to the action editor, this code
	// is also run. This helps add modifications or setup reactionary
	// functions for the DOM elements.
	//---------------------------------------------------------------------

	init: function() {
		const {glob, document} = this;
		glob.variableChange(document.getElementById('storage'), 'varNameContainer');
	},

	//---------------------------------------------------------------------
	// Action Bot Function
	//
	// This is the function for the action within the Bot's Action class.
	// Keep in mind event calls won't have access to the "msg" parameter,
	// so be sure to provide checks for variable existance.
	//---------------------------------------------------------------------

	action: function(cache) {
		var _this = this;

		var WrexMODS = this.getWrexMods();

		const data = cache.actions[cache.index];
		const varName = this.evalMessage(data.varName, cache);

		const token = this.evalMessage(data.token, cache);
		const user = this.evalMessage(data.user, cache);
		const pass = this.evalMessage(data.pass, cache);

		const storage = parseInt(data.storage);
		var url = this.evalMessage(data.url, cache);
		const path = this.evalMessage(data.path, cache);

		if(!WrexMODS.checkURL(url)){
			url = encodeURI(url);
		};

		if(WrexMODS.checkURL(url)){

			WrexMODS.runPublicRequest(url, true, function(error, statusCode, jsonData){

				try {

					if(error){
						var errorJson = JSON.stringify({error, statusCode})
						_this.storeValue(errorJson, storage, varName, cache);

						console.error("WebAPI: Error: " + errorJson + " stored to: ["+ varName+"]");
					}
					else{
						if(path){
							var outData = WrexMODS.jsonPath(jsonData, path);

							console.log(outData);

							try {
								var test = JSON.parse(JSON.stringify(outData));
							} catch (error) {
								var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
								_this.storeValue(errorJson, storage, varName, cache);
								console.error(error.stack ? error.stack : error);
							}

							var outValue = eval(JSON.stringify(outData), cache);

							if(outData.success != null){
								var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
								_this.storeValue(errorJson, storage, varName, cache);
								console.log("WebAPI: Error Invalid JSON, is the Path set correctly? [" + path + "]");
							}else{
								if(outValue.success != null || !outValue){
									var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
									_this.storeValue(errorJson, storage, varName, cache);
									console.log("WebAPI: Error Invalid JSON, is the Path set correctly? [" + path + "]");
								}else{
									_this.storeValue(outValue, storage, varName, cache);
									console.log("WebAPI: JSON Data values starting from ["+ path +"] stored to: ["+ varName+"]");
								}

							}

						}else{
							_this.storeValue(jsonData, storage, varName, cache);
							console.log("WebAPI: JSON Data Object stored to: ["+ varName+"]");
						}
					}

					if(data.behavior === "0") {
						_this.callNextAction(cache);
					}
				} catch (err) {
					console.error(err.stack ? err.stack : err);
				}

			}, token, user, pass);
		}
		else{
			console.error('URL ['+url+'] Is Not Valid');
		}
	},

	//---------------------------------------------------------------------
	// Action Bot Mod
	//
	// Upon initialization of the bot, this code is run. Using the bot's
	// DBM namespace, one can add/modify existing functions if necessary.
	// In order to reduce conflictions between mods, be sure to alias
	// functions you wish to overwrite.
	//---------------------------------------------------------------------

	mod: function(DBM) {

	}

	}; // End of module
<commit_msg>Minor change - Backward compatibility for Store Variable from WebAPI<commit_after>	//---------------------------------------------------------------------
	// Created by General Wrex
	// My Patreons have made creating this script possible @ https://www.patreon.com/generalwrex
	// At the time of editing this script, they are:
	// - MitchDaGamer
	//
	// Thanks so much guys, you allow me to continue to do what i love!
	// Add URL to json object,
	// add path to the object you want from the json
	// set your variable type and name
	// example URL: https://api.github.com/repos/HellionCommunity/HellionExtendedServer/releases/latest
	// example Path: name
	// will return object.name
	// in this example the variable would contain "[DEV] Version 1.2.2.3"
	//---------------------------------------------------------------------

module.exports = {

	//---------------------------------------------------------------------
	// DBM Mods Manager Variables (Optional but nice to have!)
	//
	// These are variables that DBM Mods Manager uses to show information
	// about the mods for people to see in the list.
	//---------------------------------------------------------------------

	// Who made the mod (If not set, defaults to "DBM Mods")
	author: "General Wrex",

	// The version of the mod (Defaults to 1.0.0)
	version: "1.0.1",

    // A short description to show on the mod line for this mod (Must be on a single line)
	short_description: "Stores JSON from a webapi into a variable.",

	// If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods
	depends_on_mods: ["WrexMODS"],

	//---------------------------------------------------------------------

	//---------------------------------------------------------------------
	// Action Name
	//
	// This is the name of the action displayed in the editor.
	//---------------------------------------------------------------------

	name: "Store Json From WebAPI",

	//---------------------------------------------------------------------
	// Action Section
	//
	// This is the section the action will fall into.
	//---------------------------------------------------------------------

	section: "JSON Things",

	//---------------------------------------------------------------------
	// Action Subtitle
	//
	// This function generates the subtitle displayed next to the name.
	//---------------------------------------------------------------------

	subtitle: function(data) {
		return `${data.varName}`;
	},

	//---------------------------------------------------------------------
	// Action Storage Function
	//
	// Stores the relevant variable info for the editor.
	//---------------------------------------------------------------------

	variableStorage: function(data, varType) {
		const type = parseInt(data.storage);
		if(type !== varType) return;
		return ([data.varName, 'JSON Object']);
	},

	//---------------------------------------------------------------------
	// Action Fields
	//
	// These are the fields for the action. These fields are customized
	// by creating elements with corresponding IDs in the HTML. These
	// are also the names of the fields stored in the action's JSON data.
	//---------------------------------------------------------------------

	fields: ["behavior", "token", "user", "pass" ,"url", "path", "storage", "varName"],

	//---------------------------------------------------------------------
	// Command HTML
	//
	// This function returns a string containing the HTML used for
	// editing actions.
	//
	// The "isEvent" parameter will be true if this action is being used
	// for an event. Due to their nature, events lack certain information,
	// so edit the HTML to reflect this.
	//
	// The "data" parameter stores constants for select elements to use.
	// Each is an array: index 0 for commands, index 1 for events.
	// The names are: sendTargets, members, roles, channels,
	//                messages, servers, variables
	//---------------------------------------------------------------------

	html: function(isEvent, data) {
		return `

				Mod Info:

				Created by General Wrex!

		End Behavior:

		<select id="behavior" class="round">
			<option value="0" selected>Call Next Action Automatically</option>
			<option value="1">Do Not Call Next Action</option>
		</select>

    WebAPI URL:

		<textarea id="url" class="round" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Bearer Token ( If a bearer token is required, put it here!)

		<textarea id="token" class="round" placeholder="blank if none"   style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Username( If a password is required, put it here!)

		<input id="user" class="round"  placeholder="blank if none" style="width: 99%; resize: none;" >

		Password ( If a password is required, put it here!)

		<input id="pass" class="round"  placeholder="blank if none"  style="width: 99%; resize: none;" >

		Initial JSON Path: (Leave blank to store everything, supports the usage of JSON Path (Regex))

		<input id="path" class="round"; style="width: 75%;" type="text">

		Store In:

		<select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer')">
			${data.variables[0]}
		</select>

		JSON Storage Variable Name:

		<input id="varName" class="round" type="text">

`
	},

	//---------------------------------------------------------------------
	// Action Editor Init Code
	//
	// When the HTML is first applied to the action editor, this code
	// is also run. This helps add modifications or setup reactionary
	// functions for the DOM elements.
	//---------------------------------------------------------------------

	init: function() {
		const {glob, document} = this;
		glob.variableChange(document.getElementById('storage'), 'varNameContainer');
	},

	//---------------------------------------------------------------------
	// Action Bot Function
	//
	// This is the function for the action within the Bot's Action class.
	// Keep in mind event calls won't have access to the "msg" parameter,
	// so be sure to provide checks for variable existance.
	//---------------------------------------------------------------------

	action: function(cache) {
		var _this = this;

		var WrexMODS = this.getWrexMods();

		const data = cache.actions[cache.index];
		const varName = this.evalMessage(data.varName, cache);

		const token = this.evalMessage(data.token, cache);
		const user = this.evalMessage(data.user, cache);
		const pass = this.evalMessage(data.pass, cache);

		const storage = parseInt(data.storage);
		var url = this.evalMessage(data.url, cache);
		const path = this.evalMessage(data.path, cache);

		if(!WrexMODS.checkURL(url)){
			url = encodeURI(url);
		};

		if(WrexMODS.checkURL(url)){

			WrexMODS.runPublicRequest(url, true, function(error, statusCode, jsonData){

				try {

					if(error){
						var errorJson = JSON.stringify({error, statusCode})
						_this.storeValue(errorJson, storage, varName, cache);

						console.error("WebAPI: Error: " + errorJson + " stored to: ["+ varName+"]");
					}
					else{
						if(path){
							var outData = WrexMODS.jsonPath(jsonData, path);

							console.log(outData);

							try {
								var test = JSON.parse(JSON.stringify(outData));
							} catch (error) {
								var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
								_this.storeValue(errorJson, storage, varName, cache);
								console.error(error.stack ? error.stack : error);
							}

							var outValue = eval(JSON.stringify(outData), cache);

							if(outData.success != null){
								var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
								_this.storeValue(errorJson, storage, varName, cache);
								console.log("WebAPI: Error Invalid JSON, is the Path set correctly? [" + path + "]");
							}else{
								if(outValue.success != null || !outValue){
									var errorJson = JSON.stringify({error: error, statusCode: statusCode, success: false})
									_this.storeValue(errorJson, storage, varName, cache);
									console.log("WebAPI: Error Invalid JSON, is the Path set correctly? [" + path + "]");
								}else{
									_this.storeValue(outValue, storage, varName, cache);
									console.log("WebAPI: JSON Data values starting from ["+ path +"] stored to: ["+ varName+"]");
								}

							}

						}else{
							_this.storeValue(jsonData, storage, varName, cache);
							console.log("WebAPI: JSON Data Object stored to: ["+ varName+"]");
						}
					}

					if(data.behavior === "0") {
						_this.callNextAction(cache);
					}
				} catch (err) {
					console.error(err.stack ? err.stack : err);
				}

			}, token, user, pass);
		}
		else{
			console.error('URL ['+url+'] Is Not Valid');
		}
	},

	//---------------------------------------------------------------------
	// Action Bot Mod
	//
	// Upon initialization of the bot, this code is run. Using the bot's
	// DBM namespace, one can add/modify existing functions if necessary.
	// In order to reduce conflictions between mods, be sure to alias
	// functions you wish to overwrite.
	//---------------------------------------------------------------------

	mod: function(DBM) {
			 // aliases for backwards compatibility, in the bot only, DBM will still say the action is missing.
			 DBM.Actions["Store Variable From WebAPI"] = DBM.Actions["Store Json From WebAPI"];
	 }

	}; // End of module
<|endoftext|>


<commit_before>module.exports = {
  name: 'Store Json From WebAPI',
  section: 'JSON Things',

  subtitle (data) {
    return `${data.varName}`
  },

  variableStorage (data, varType) {
    const type = parseInt(data.storage)
    if (type !== varType) return
    return ([data.varName, 'JSON Object'])
  },

  fields: ['token', 'user', 'pass', 'url', 'path', 'storage', 'varName', 'debugMode', 'headers', 'reUse'],

  html (isEvent, data) {
    return `

    WebAPI URL:

    <textarea id="url" class="round" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>
      <text style="font-size: 60%;">If the url is the same, json data will be used from the initial store json within the command</text>

      Headers (By default 'User-Agent: Other' is applied, It's 1 per line, (key:value))

      <textarea id="headers" class="round" placeholder="User-Agent: Other" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    <input type="checkbox" name="public" id="toggleAuth" onclick="glob.checkBox(this, 'auth');">
    Show Authentication Options
    <text style="font-size: 60%;">Show/Hide Auth Options</text>

    Bearer Token

    <textarea id="token" class="round" placeholder="blank if none" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Username

    <input id="user" class="round" placeholder="blank if none" style="width: 99%; resize: none;" >

    Password

    <input id="pass" class="round" placeholder="blank if none"  style="width: 99%; resize: none;" >

  JSON Path: (Leave blank to store everything)

  Supports the usage of JSON Path (Regex)

  You don't need to add the x. of JSON Path

  More info here

  http://goessner.net/articles/JsonPath/index.html#e2

  <input id="path" class="round"; style="width: 75%;" type="text">

      Store In:

      <select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer')">
        ${data.variables[0]}
      </select>

      JSON Storage Variable Name:

      <input id="varName" class="round" type="text">

      Re-Use Previously Stored
      <select id="reUse" class="round" onchange="glob.disallowAlert(this)">
        <option value="1" selected>Allow</option>
        <option value="0">Disallow</option>
      </select>
      <text style="font-size: 60%;">Toggles re-use of previously stored JSON from same URL.</text>

    Debug Mode
    <select id="debugMode" class="round">
      <option value="1" selected>Enabled</option>
      <option value="0">Disabled</option>
    </select>
    <text style="font-size: 60%;">Enables printing to console, disable to remove all messages. Turn on to see errors.</text>

`
  },

  init () {
    const { glob, document } = this
    glob.variableChange(document.getElementById('storage'), 'varNameContainer')

    glob.checkBox = function (element, type) {
      if (type === 'auth') {
        document.getElementById('authSection').style.display = element.checked ? '' : 'none'
        document.getElementById('showAuth').value = element.checked ? '1' : '0'
      }
    }

    glob.disallowAlert = function (element) {
      if (element.value === '0') {
        alert('Disabling this could lead to you being banned or rate limited by APIs, please be careful.')
      }
    }

    glob.checkBox(document.getElementById('toggleAuth'), 'auth')
  },

  action (cache) {
    const _this = this
    const data = cache.actions[cache.index]
    const Mods = this.getMods()
    const request = Mods.require('request')
    const debugMode = parseInt(data.debugMode)
    const storage = parseInt(data.storage)
    const varName = this.evalMessage(data.varName, cache)
    let url = this.evalMessage(data.url, cache)
    const path = this.evalMessage(data.path, cache)
    const token = this.evalMessage(data.token, cache)
    const user = this.evalMessage(data.user, cache)
    const reUse = parseInt(data.reUse)
    const pass = this.evalMessage(data.pass, cache)
    const headers = this.evalMessage(data.headers, cache)

    // if it fails the check, try to re-encode the url
    if (!Mods.checkURL(url)) { url = encodeURI(url) }

    if (Mods.checkURL(url)) {
      try {
        // eslint-disable-next-line no-inner-declarations
        function storeData (error, res, jsonData) {
          const statusCode = res ? res.statusCode : 200
          let errorJson
          if (error) {
            errorJson = JSON.stringify({ error, statusCode })
            _this.storeValue(errorJson, storage, varName, cache)

            if (debugMode) console.error(`WebAPI: Error: ${errorJson} stored to: [${varName}]`)
          } else if (path) {
            const outData = Mods.jsonPath(jsonData, path)

            if (debugMode) console.dir(outData)

            try {
              JSON.parse(JSON.stringify(outData))
            } catch (error) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              _this.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.error(error.stack ? error.stack : error)
            }

            // eslint-disable-next-line no-eval
            const outValue = eval(JSON.stringify(outData), cache)

            if (!outData) {
              errorJson = JSON.stringify({ error: 'No JSON Data Returned', statusCode: 0 })
              _this.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.error(`WebAPI: Error: ${errorJson} NO JSON data returned. Check the URL: ${url}`)
            } else if (outData.success != null) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              _this.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.log(`WebAPI: Error Invalid JSON, is the Path and/or URL set correctly? [${path}]`)
            } else if (outValue.success != null || !outValue) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              _this.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.log(`WebAPI: Error Invalid JSON, is the Path and/or URL set correctly? [${path}]`)
            } else {
              _this.storeValue(outValue, storage, varName, cache)
              _this.storeValue(jsonData, 1, url, cache)
              _this.storeValue(url, 1, `${url}_URL`, cache)
              if (debugMode) console.log(`WebAPI: JSON Data values starting from [${path}] stored to: [${varName}]`)
            }
          } else {
            if (debugMode) console.dir(jsonData)
            _this.storeValue(jsonData, storage, varName, cache)
            _this.storeValue(jsonData, 1, url, cache)
            _this.storeValue(url, 1, `${url}_URL`, cache)
            if (debugMode) console.log(`WebAPI: JSON Data Object stored to: [${varName}]`)
          }
          _this.callNextAction(cache)
        }

        const oldUrl = this.getVariable(1, `${url}_URL`, cache)

        if (url === oldUrl && reUse === 1) {
          let jsonData
          let error
          const res = { statusCode: 200 }

          try {
            jsonData = this.getVariable(1, url, cache)
          } catch (err) {
            error = err
          }

          if (debugMode) console.log('WebAPI: Using previously stored json data from the initial store json action within this command.')

          storeData(error, res, jsonData)
        } else {
          const setHeaders = {}

          // set default required header
          setHeaders['User-Agent'] = 'Other'

          // Because headers are a dictionary ;)
          if (headers) {
            const lines = String(headers).split('\n')
            for (let i = 0; i < lines.length; i++) {
              const header = lines[i].split(':')

              if (lines[i].includes(':') && header.length > 0) {
                const key = header[0] || 'Unknown'
                const value = header[1] || 'Unknown'
                setHeaders[key] = value

                if (debugMode) console.log(`Applied Header: ${lines[i]}`)
              } else {
                if (debugMode) console.error(`WebAPI: Error: Custom Header line ${lines[i]} is wrongly formatted. You must split the key from the value with a colon (:)`)
              }
            }
          }

          request.get({
            url,
            json: true,
            headers: setHeaders,
            auth: {
              bearer: token,
              user,
              pass,
              sendImmediately: false
            }
          }, (error, res, jsonData) => storeData(error, res, jsonData))
        }
      } catch (err) {
        if (debugMode) console.error(err.stack ? err.stack : err)
      }
    } else {
      if (debugMode) console.error(`URL [${url}] Is Not Valid`)
    }
  },

  mod (DBM) {
    DBM.Actions['Store Variable From WebAPI'] = DBM.Actions['Store Json From WebAPI']
  }
}
<commit_msg>Change from request to node-fetch (#701)<commit_after>module.exports = {
  name: 'Store Json From WebAPI',
  section: 'JSON Things',

  subtitle (data) {
    return `${data.varName}`
  },

  variableStorage (data, varType) {
    const type = parseInt(data.storage)
    if (type !== varType) return
    return ([data.varName, 'JSON Object'])
  },

  fields: ['token', 'user', 'pass', 'url', 'path', 'storage', 'varName', 'debugMode', 'headers', 'reUse'],

  html (isEvent, data) {
    return `

    WebAPI URL:

    <textarea id="url" class="round" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>
      <text style="font-size: 60%;">If the url is the same, json data will be used from the initial store json within the command</text>

      Headers (By default 'User-Agent: Other' is applied, It's 1 per line, (key:value))

      <textarea id="headers" class="round" placeholder="User-Agent: Other" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    <input type="checkbox" name="public" id="toggleAuth" onclick="glob.checkBox(this, 'auth');">
    Show Authentication Options
    <text style="font-size: 60%;">Show/Hide Auth Options</text>

    Bearer Token

    <textarea id="token" class="round" placeholder="blank if none" style="width: 99%; resize: none;" type="textarea" rows="4" cols="20"></textarea>

    Username

    <input id="user" class="round" placeholder="blank if none" style="width: 99%; resize: none;" >

    Password

    <input id="pass" class="round" placeholder="blank if none"  style="width: 99%; resize: none;" >

  JSON Path: (Leave blank to store everything)

  Supports the usage of JSON Path (Regex)

  You don't need to add the x. of JSON Path

  More info here

  http://goessner.net/articles/JsonPath/index.html#e2

  <input id="path" class="round"; style="width: 75%;" type="text">

      Store In:

      <select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer')">
        ${data.variables[0]}
      </select>

      JSON Storage Variable Name:

      <input id="varName" class="round" type="text">

      Re-Use Previously Stored
      <select id="reUse" class="round" onchange="glob.disallowAlert(this)">
        <option value="1" selected>Allow</option>
        <option value="0">Disallow</option>
      </select>
      <text style="font-size: 60%;">Toggles re-use of previously stored JSON from same URL.</text>

    Debug Mode
    <select id="debugMode" class="round">
      <option value="1" selected>Enabled</option>
      <option value="0">Disabled</option>
    </select>
    <text style="font-size: 60%;">Enables printing to console, disable to remove all messages. Turn on to see errors.</text>

`
  },

  init () {
    const { glob, document } = this
    glob.variableChange(document.getElementById('storage'), 'varNameContainer')

    glob.checkBox = function (element, type) {
      if (type === 'auth') {
        document.getElementById('authSection').style.display = element.checked ? '' : 'none'
        document.getElementById('showAuth').value = element.checked ? '1' : '0'
      }
    }

    glob.disallowAlert = function (element) {
      if (element.value === '0') {
        alert('Disabling this could lead to you being banned or rate limited by APIs, please be careful.')
      }
    }

    glob.checkBox(document.getElementById('toggleAuth'), 'auth')
  },

  async action (cache) {
    const data = cache.actions[cache.index]
    const Actions = this.getDBM().Actions
    const Mods = this.getMods()
    const fetch = Mods.require('node-fetch')
    const debugMode = parseInt(data.debugMode)
    const storage = parseInt(data.storage)
    const varName = this.evalMessage(data.varName, cache)
    let url = this.evalMessage(data.url, cache)
    const path = this.evalMessage(data.path, cache)
    const token = this.evalMessage(data.token, cache)
    const user = this.evalMessage(data.user, cache)
    const reUse = parseInt(data.reUse)
    const pass = this.evalMessage(data.pass, cache)
    const headers = this.evalMessage(data.headers, cache)

    // if it fails the check, try to re-encode the url
    if (!Mods.checkURL(url)) { url = encodeURI(url) }

    if (Mods.checkURL(url)) {
      try {
        // eslint-disable-next-line no-inner-declarations
        function storeData (error, res, jsonData) {
          const statusCode = res ? res.statusCode : 200
          let errorJson
          if (error) {
            errorJson = JSON.stringify({ error, statusCode })
            Actions.storeValue(errorJson, storage, varName, cache)

            if (debugMode) console.error(`WebAPI: Error: ${errorJson} stored to: [${varName}]`)
          } else if (path) {
            const outData = Mods.jsonPath(jsonData, path)

            if (debugMode) console.dir(outData)

            try {
              JSON.parse(JSON.stringify(outData))
            } catch (error) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              Actions.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.error(error.stack ? error.stack : error)
            }

            // eslint-disable-next-line no-eval
            const outValue = eval(JSON.stringify(outData), cache)

            if (!outData) {
              errorJson = JSON.stringify({ error: 'No JSON Data Returned', statusCode: 0 })
              Actions.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.error(`WebAPI: Error: ${errorJson} NO JSON data returned. Check the URL: ${url}`)
            } else if (outData.success != null) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              Actions.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.log(`WebAPI: Error Invalid JSON, is the Path and/or URL set correctly? [${path}]`)
            } else if (outValue.success != null || !outValue) {
              errorJson = JSON.stringify({ error, statusCode, success: false })
              Actions.storeValue(errorJson, storage, varName, cache)
              if (debugMode) console.log(`WebAPI: Error Invalid JSON, is the Path and/or URL set correctly? [${path}]`)
            } else {
              Actions.storeValue(outValue, storage, varName, cache)
              Actions.storeValue(jsonData, 1, url, cache)
              Actions.storeValue(url, 1, `${url}_URL`, cache)
              if (debugMode) console.log(`WebAPI: JSON Data values starting from [${path}] stored to: [${varName}]`)
            }
          } else {
            if (debugMode) console.dir(jsonData)
            Actions.storeValue(jsonData, storage, varName, cache)
            Actions.storeValue(jsonData, 1, url, cache)
            Actions.storeValue(url, 1, `${url}_URL`, cache)
            if (debugMode) console.log(`WebAPI: JSON Data Object stored to: [${varName}]`)
          }
          Actions.callNextAction(cache)
        }

        const oldUrl = this.getVariable(1, `${url}_URL`, cache)

        if (url === oldUrl && reUse === 1) {
          let jsonData
          let error
          const res = { statusCode: 200 }

          try {
            jsonData = this.getVariable(1, url, cache)
          } catch (err) {
            error = err
          }

          if (debugMode) console.log('WebAPI: Using previously stored json data from the initial store json action within this command.')

          storeData(error, res, jsonData)
        } else {
          const setHeaders = {}

          // set default required header
          setHeaders['User-Agent'] = 'Other'

          // Because headers are a dictionary ;)
          if (headers) {
            const lines = String(headers).split('\n')
            for (let i = 0; i < lines.length; i++) {
              const header = lines[i].split(':')

              if (lines[i].includes(':') && header.length > 0) {
                const key = header[0] || 'Unknown'
                const value = header[1] || 'Unknown'
                setHeaders[key] = value

                if (debugMode) console.log(`Applied Header: ${lines[i]}`)
              } else {
                if (debugMode) console.error(`WebAPI: Error: Custom Header line ${lines[i]} is wrongly formatted. You must split the key from the value with a colon (:)`)
              }
            }
          }
          if (token) setHeaders.Authorization = `Bearer ${token}`
          if (user && pass) setHeaders.Authorization = `Basic ${Buffer.from(user + ':' + pass).toString('base64')}`

          try {
            const response = await fetch(url, { headers: setHeaders })
            const json = await response.json()
            storeData('', response, json)
          } catch (err) {
            if (debugMode) console.error(err.stack || err)
          }
        }
      } catch (err) {
        if (debugMode) console.error(err.stack || err)
      }
    } else {
      if (debugMode) console.error(`URL [${url}] Is Not Valid`)
    }
  },

  mod () {}
}
<|endoftext|>


<commit_before>import SchedulerRefresh from "./refresh"

class Scheduler {
  constructor(schedulerPolicy) {
    this.schedulerPolicy = schedulerPolicy;
    this.taskInstances = [];
  }

  cancelAll(guid, reason) {
    this.taskInstances.forEach(taskInstance => {
      if (taskInstance._tags[guid]) {
        taskInstance.cancel(reason);
      }
    });
  }

  perform(taskInstance) {
    taskInstance._onFinalize(() => this.scheduleRefresh());
    this.taskInstances.push(taskInstance);
    this.refresh();
  }

  // override
  scheduleRefresh() { }

  refresh() {
    let refresh = new SchedulerRefresh(this.schedulerPolicy, this.taskInstances);
    this.taskInstances = refresh.process();
  }
}

export default Scheduler;
<commit_msg>Write docs for Scheduler<commit_after>import SchedulerRefresh from "./refresh"

// Scheduler base class

// When a Task is performed, it creates an unstarted TaskInstance and
// passes it to the Scheduler to determine when it should run. The
// scheduler consults the schedulerPolicy (e.g. DropPolicy, RestartablePolicy, etc)
// to determine whether the task instance should start executing, be enqueued
// for later execution, or be immediately cancelled. As TaskInstances start
// and run to completion, the Scheduler's `refresh()` method is called to
// give it an opportunity to start (or cancel) previously enqueued task instances,
// as well as update the derived state on Tasks and TaskGroups.

// Every Task has its own Scheduler instance, unless it is part of a group,
// in which case all the Tasks in a group share a single Scheduler.

class Scheduler {
  constructor(schedulerPolicy) {
    this.schedulerPolicy = schedulerPolicy;
    this.taskInstances = [];
  }

  cancelAll(guid, reason) {
    this.taskInstances.forEach(taskInstance => {
      if (taskInstance._tags[guid]) {
        taskInstance.cancel(reason);
      }
    });
  }

  perform(taskInstance) {
    taskInstance._onFinalize(() => this.scheduleRefresh());
    this.taskInstances.push(taskInstance);
    this.refresh();
  }

  // override
  scheduleRefresh() { }

  refresh() {
    let refresh = new SchedulerRefresh(this.schedulerPolicy, this.taskInstances);
    this.taskInstances = refresh.process();
  }
}

export default Scheduler;
<|endoftext|>


<commit_before>import Ember from 'ember';
import UiDropdown from 'semantic-ui-ember/components/ui-dropdown';

export default UiDropdown.extend({
  content: null,
  find_by: 'id',

  initialize: Ember.on('didInsertElement', function() {
    var selected = this.get('selected');
    if (typeof selected !== "undefined" && selected !== null) {
      this.set('boundValue', 'selected');
      this.execute('set selected', Ember.get(selected, this.get('find_by')));
    }

    var value = this.get('value');
    if (typeof value !== "undefined" && value !== null) {
      Ember.deprecate('Bind to selected on ui-dropdown instead of value as semantic doesn\'t update the display when the value is set', false);
      this.set('boundValue', 'value');
      this.execute('set value', Ember.get(value, this.get('find_by')));
    }
  }),

  updateProperty: function(property) {
    return function() {
      if (property === 'selected') {
        this.execute('set ' + property, this.get(`${property}.${this.get('find_by')}`));
      } else {
        this.execute('set ' + property, this.get(property));
      }
    };
  },

  _onChange: function(value, text, $element) {
    if (!$element) {
      return;
    }

    var record = this.get('content').find((item) => {
      var current = Ember.get(item, this.get('find_by'));
      return current === value || current.toString() === value || current === (value || '').toString();
    });
    this.set(this.get('boundValue') || 'selected', record);
  }
});
<commit_msg>Changing from event to method<commit_after>import Ember from 'ember';
import UiDropdown from 'semantic-ui-ember/components/ui-dropdown';

export default UiDropdown.extend({
  content: null,
  find_by: 'id',

  didInsertElement() {
    this._super(...arguments);
    var selected = this.get('selected');
    if (typeof selected !== "undefined" && selected !== null) {
      this.set('boundValue', 'selected');
      this.execute('set selected', Ember.get(selected, this.get('find_by')));
    }

    var value = this.get('value');
    if (typeof value !== "undefined" && value !== null) {
      Ember.deprecate('Bind to selected on ui-dropdown instead of value as semantic doesn\'t update the display when the value is set', false);
      this.set('boundValue', 'value');
      this.execute('set value', Ember.get(value, this.get('find_by')));
    }
  },

  updateProperty: function(property) {
    return function() {
      if (property === 'selected') {
        this.execute('set ' + property, this.get(`${property}.${this.get('find_by')}`));
      } else {
        this.execute('set ' + property, this.get(property));
      }
    };
  },

  _onChange: function(value, text, $element) {
    if (!$element) {
      return;
    }

    var record = this.get('content').find((item) => {
      var current = Ember.get(item, this.get('find_by'));
      return current === value || current.toString() === value || current === (value || '').toString();
    });
    this.set(this.get('boundValue') || 'selected', record);
  }
});
<|endoftext|>


<commit_before>/**
  @module ember-flexberry
*/

import Ember from 'ember';
import EditFormController from './edit-form';

/**
  Controller for the Detail's Edit Forms.
  It lets to interact between agregator's and details's forms.

  This class re-exports to the application as `/controllers/detail-edit-form`.
  So, you can inherit from `./detail-edit-form`, even if file `app/controllers/detail-edit-form.js` is not presented in the application.

  Example:
  ```javascript
  // app/controllers/order.js
  import DetailEditFormController from './detail-edit-form';
  export default DetailEditFormController.extend({
  });
  ```

  @class DetailEditFormController
  @extends EditFormController
*/
export default EditFormController.extend({
  /**
    Service that lets interact between agregator's and detail's form.

    @property flexberryDetailInteractionService
    @type Ember.Service
    @readOnly
    @private
  */
  _flexberryDetailInteractionService: Ember.inject.service('detail-interaction'),

  /**
    A logic value showing if current route has parent one.

    @property _hasParentRoute
    @type Boolean
    @private
    @readOnly
  */
  _hasParentRoute: Ember.computed('modelCurrentAgregatorPathes', function() {
    return this.get('_flexberryDetailInteractionService').hasValues(this.get('modelCurrentAgregatorPathes'));
  }),

  /**
    Flag to enable return to agregator's path if possible.
    It overrides base default value.

    @property returnToAgregatorRoute
    @type Boolean
    @default true
  */
  returnToAgregatorRoute: true,

  /**
    Paths to return to after leaving current route.

    @property modelCurrentAgregatorPathes
    @type Array
  */
  modelCurrentAgregatorPathes: undefined,

  /**
    Current detail's agregators.

    @property modelCurrentAgregators
    @type Array
  */
  modelCurrentAgregators: undefined,

  /**
    Flag: indicates whether to save current model before going to the detail's route.
    This flag is set to `true` when this form is opened from agregator's form.

    @property saveBeforeRouteLeave
    @type Boolean
    @default false
  */
  saveBeforeRouteLeave: false,

  actions: {
    /**
      Handler for button 'Save' click.
      If return path is determined, no rollback happens and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.save
    */
    save() {
      if (this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        throw new Error('\'Save\' operation is not accessible due to current settings.');
      }
      let modelAgregatorRoutes = this.get('modelCurrentAgregatorPathes');
      let modelCurrentAgregators = this.get('modelCurrentAgregators');
      let flexberryDetailInteractionService = this.get('_flexberryDetailInteractionService');
      flexberryDetailInteractionService.set('modelCurrentAgregatorPathes', modelAgregatorRoutes);
      flexberryDetailInteractionService.set('modelCurrentAgregators', modelCurrentAgregators);
      this._super.apply(this, arguments);
    },

    /**
      Handler for button 'Save and close' click.
      If return path is determined, no rollback happens and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.saveAndClose
    */
    saveAndClose() {
      if (this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        throw new Error('\'Save and close\' operation is not accessible due to current settings.');
      }

      this._super.apply(this, arguments);
    },

    /**
      Handler for button 'Delete' click.
      If return path is determined and current model is saved, record marks as deleted and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.delete
    */
    delete() {
      if (this.get('model').get('id') && this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        if (confirm('Are you sure you want to delete that record?')) {
          this.get('model').deleteRecord();
          this.transitionToParentRoute();
        }
      } else {
        this._super.apply(this, arguments);
      }
    },

    /**
      Handler for button 'Close' click.
      If return path is determined, an error is thrown because this action should not be triggered.
      Otherwise base logic is executed.

      @method actions.close
    */
    close() {
      if (!this.get('_hasParentRoute')) {
        this._super.apply(this, arguments);
        return;
      }

      if (this.get('saveBeforeRouteLeave')) {
        this.transitionToParentRoute(true);
        return;
      }

      // If 'saveBeforeRouteLeave' == false & 'close' button has been pressed,
      // before transition to parent route we should validate model and then upload files
      // (if some file components are present on current detail rout),
      // because after transition, all components correspondent to current detail route (including file components)
      // gonna be destroyed, and files won't be uploaded at all.
      let model = this.get('model');
      model.validate().then(() => model.beforeSave({ softSave: true })).then(() => {
        this.transitionToParentRoute(false);
      }, (reason) => {
        this.rejectError(reason);
      });
    }
  },

  /**
    Method to transit to parent's route (previous route).
    If `modelAgregatorRoute` is set, transition to defined path and set flag 'modelNoRollBack' to `true` on controller to prevent rollback of model.
    Then if `parentRoute` is set, transition to defined path.
    Otherwise transition to corresponding list.

    @method transitionToParentRoute
    @param {Boolean} rollBackModel Flag: indicates whether to set flag to roll back model after route leave (if `true`) or not (if `false`).
  */
  transitionToParentRoute(rollBackModel) {
    if (this.get('_hasParentRoute')) {
      if (!rollBackModel) {
        this.set('modelNoRollBack', true);
      }

      let modelAgregatorRoutes = this.get('modelCurrentAgregatorPathes');
      let modelAgregatorRoute = modelAgregatorRoutes.pop();
      let modelCurrentAgregators = this.get('modelCurrentAgregators');
      let modelCurrentAgregator = modelCurrentAgregators.pop();

      let flexberryDetailInteractionService = this.get('_flexberryDetailInteractionService');
      flexberryDetailInteractionService.set('modelCurrentAgregatorPathes', modelAgregatorRoutes);
      flexberryDetailInteractionService.set('modelCurrentAgregators', modelCurrentAgregators);
      flexberryDetailInteractionService.set('modelLastUpdatedDetail', this.get('model'));
      if (modelCurrentAgregator) {
        flexberryDetailInteractionService.set('modelCurrentNotSaved', modelCurrentAgregator);
      }

      this.transitionToRoute(modelAgregatorRoute);
    } else {
      this._super.apply(this, arguments);
    }
  }
});
<commit_msg>Fix Travis build<commit_after>/**
  @module ember-flexberry
*/

import Ember from 'ember';
import EditFormController from './edit-form';

/**
  Controller for the Detail's Edit Forms.
  It lets to interact between agregator's and details's forms.

  This class re-exports to the application as `/controllers/detail-edit-form`.
  So, you can inherit from `./detail-edit-form`, even if file `app/controllers/detail-edit-form.js` is not presented in the application.

  Example:
  ```javascript
  // app/controllers/order.js
  import DetailEditFormController from './detail-edit-form';
  export default DetailEditFormController.extend({
  });
  ```

  @class DetailEditFormController
  @extends EditFormController
*/
export default EditFormController.extend({
  /**
    Service that lets interact between agregator's and detail's form.

    @property flexberryDetailInteractionService
    @type Ember.Service
    @readOnly
    @private
  */
  _flexberryDetailInteractionService: Ember.inject.service('detail-interaction'),

  /**
    A logic value showing if current route has parent one.

    @property _hasParentRoute
    @type Boolean
    @private
    @readOnly
  */
  _hasParentRoute: Ember.computed('modelCurrentAgregatorPathes', function() {
    return this.get('_flexberryDetailInteractionService').hasValues(this.get('modelCurrentAgregatorPathes'));
  }),

  /**
    Flag to enable return to agregator's path if possible.
    It overrides base default value.

    @property returnToAgregatorRoute
    @type Boolean
    @default true
  */
  returnToAgregatorRoute: true,

  /**
    Paths to return to after leaving current route.

    @property modelCurrentAgregatorPathes
    @type Array
  */
  modelCurrentAgregatorPathes: undefined,

  /**
    Current detail's agregators.

    @property modelCurrentAgregators
    @type Array
  */
  modelCurrentAgregators: undefined,

  /**
    Flag: indicates whether to save current model before going to the detail's route.
    This flag is set to `true` when this form is opened from agregator's form.

    @property saveBeforeRouteLeave
    @type Boolean
    @default false
  */
  saveBeforeRouteLeave: false,

  actions: {
    /**
      Handler for button 'Save' click.
      If return path is determined, no rollback happens and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.save
    */
    save() {
      if (this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        throw new Error('\'Save\' operation is not accessible due to current settings.');
      }

      let modelAgregatorRoutes = this.get('modelCurrentAgregatorPathes');
      let modelCurrentAgregators = this.get('modelCurrentAgregators');
      let flexberryDetailInteractionService = this.get('_flexberryDetailInteractionService');
      flexberryDetailInteractionService.set('modelCurrentAgregatorPathes', modelAgregatorRoutes);
      flexberryDetailInteractionService.set('modelCurrentAgregators', modelCurrentAgregators);
      this._super.apply(this, arguments);
    },

    /**
      Handler for button 'Save and close' click.
      If return path is determined, no rollback happens and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.saveAndClose
    */
    saveAndClose() {
      if (this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        throw new Error('\'Save and close\' operation is not accessible due to current settings.');
      }

      this._super.apply(this, arguments);
    },

    /**
      Handler for button 'Delete' click.
      If return path is determined and current model is saved, record marks as deleted and user is redirected to agregator's form.
      Otherwise base logic is executed.

      @method actions.delete
    */
    delete() {
      if (this.get('model').get('id') && this.get('_hasParentRoute') && !this.get('saveBeforeRouteLeave')) {
        if (confirm('Are you sure you want to delete that record?')) {
          this.get('model').deleteRecord();
          this.transitionToParentRoute();
        }
      } else {
        this._super.apply(this, arguments);
      }
    },

    /**
      Handler for button 'Close' click.
      If return path is determined, an error is thrown because this action should not be triggered.
      Otherwise base logic is executed.

      @method actions.close
    */
    close() {
      if (!this.get('_hasParentRoute')) {
        this._super.apply(this, arguments);
        return;
      }

      if (this.get('saveBeforeRouteLeave')) {
        this.transitionToParentRoute(true);
        return;
      }

      // If 'saveBeforeRouteLeave' == false & 'close' button has been pressed,
      // before transition to parent route we should validate model and then upload files
      // (if some file components are present on current detail rout),
      // because after transition, all components correspondent to current detail route (including file components)
      // gonna be destroyed, and files won't be uploaded at all.
      let model = this.get('model');
      model.validate().then(() => model.beforeSave({ softSave: true })).then(() => {
        this.transitionToParentRoute(false);
      }, (reason) => {
        this.rejectError(reason);
      });
    }
  },

  /**
    Method to transit to parent's route (previous route).
    If `modelAgregatorRoute` is set, transition to defined path and set flag 'modelNoRollBack' to `true` on controller to prevent rollback of model.
    Then if `parentRoute` is set, transition to defined path.
    Otherwise transition to corresponding list.

    @method transitionToParentRoute
    @param {Boolean} rollBackModel Flag: indicates whether to set flag to roll back model after route leave (if `true`) or not (if `false`).
  */
  transitionToParentRoute(rollBackModel) {
    if (this.get('_hasParentRoute')) {
      if (!rollBackModel) {
        this.set('modelNoRollBack', true);
      }

      let modelAgregatorRoutes = this.get('modelCurrentAgregatorPathes');
      let modelAgregatorRoute = modelAgregatorRoutes.pop();
      let modelCurrentAgregators = this.get('modelCurrentAgregators');
      let modelCurrentAgregator = modelCurrentAgregators.pop();

      let flexberryDetailInteractionService = this.get('_flexberryDetailInteractionService');
      flexberryDetailInteractionService.set('modelCurrentAgregatorPathes', modelAgregatorRoutes);
      flexberryDetailInteractionService.set('modelCurrentAgregators', modelCurrentAgregators);
      flexberryDetailInteractionService.set('modelLastUpdatedDetail', this.get('model'));
      if (modelCurrentAgregator) {
        flexberryDetailInteractionService.set('modelCurrentNotSaved', modelCurrentAgregator);
      }

      this.transitionToRoute(modelAgregatorRoute);
    } else {
      this._super.apply(this, arguments);
    }
  }
});
<|endoftext|>


<commit_before>import DS from 'ember-data';
import LFSerializer from 'ember-localforage-adapter/serializers/localforage';
import isObject from '../utils/is-object';

export default LFSerializer.extend(DS.EmbeddedRecordsMixin, {
  init: function() {
    this._super(...arguments);
    let owner = Ember.getOwner(this);
    let localStore = owner.lookup('store:local');
    this.set('store', localStore);
  },

  /**
   `serializeBelongsTo` can be used to customize how `DS.belongsTo` properties are serialized.
   If there is set option `odata-id` at serializer and `DS.belongsTo` property is not null,
   then property will be serialized like `ids`.

   @method serializeBelongsTo
   @param {DS.Snapshot} snapshot
   @param {Object} json
   @param {Object} relationship
  */
  serializeBelongsTo(snapshot, json, relationship) {
    var option = this.attrsOption(relationship.key);
    if (!option || option.serialize !== 'odata-id') {
      this._super(snapshot, json, relationship);
      return;
    }

    var key = relationship.key;
    var belongsToId = snapshot.belongsTo(key, { id: true });
    var payloadKey = this.keyForRelationship(key, relationship.kind, 'serialize');
    if (Ember.isNone(belongsToId)) {
      json[payloadKey] = null;
    } else {
      json[payloadKey] = belongsToId;
    }
  },

  extractRelationship (relationshipModelName, relationshipHash) {
    if (isObject(relationshipHash) && Ember.isNone(relationshipHash.type)) {
      relationshipHash.type = relationshipModelName;
    }

    return relationshipHash;
  }
});
<commit_msg>Fix `local-serializer`<commit_after>import DS from 'ember-data';
import LFSerializer from 'ember-localforage-adapter/serializers/localforage';
import isObject from '../utils/is-object';

export default LFSerializer.extend({
  init: function() {
    this._super(...arguments);
    let owner = Ember.getOwner(this);
    let localStore = owner.lookup('store:local');
    this.set('store', localStore);
  },

  extractRelationship (relationshipModelName, relationshipHash) {
    if (isObject(relationshipHash) && Ember.isNone(relationshipHash.type)) {
      relationshipHash.type = relationshipModelName;
    }
    else if (!isObject(relationshipHash) && !Ember.isNone(relationshipHash)) {
      var hash = {
        id: relationshipHash,
        type: relationshipModelName
      };

      relationshipHash = hash;
    }

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


<commit_before>define(function (require) {

	'use strict';

	// var $ = require('jquery');
	var _ = require('underscore');

	var SimDraggable = require('views/sim-draggable');

	var html = require('text!templates/moving-man.html');

	require('less!styles/moving-man');

	/**
	 * Constants
	 */
	var MOVEMENT_STATE_IDLE  = 0;
	var MOVEMENT_STATE_LEFT  = 1;
	var MOVEMENT_STATE_RIGHT = 2;

	/**
	 *
	 */
	var MovingManView = SimDraggable.extend({

		template: _.template(html),

		tagName: 'div',
		className: 'moving-man-view',

		events: {
			'mousedown'  : 'down',
			'touchstart' : 'down'
		},

		initialize: function(options) {
			SimDraggable.prototype.initialize.apply(this, [options]);

			this.simulation = options.simulation;
			this.movingMan  = this.simulation.movingMan;
		},

		render: function() {
			this.renderMovingMan();
			this.bindDragEvents();
			this.resize();
			this.update(0, 0);
		},

		renderMovingMan: function() {
			this.$el.html(this.template());
		},

		down: function(event) {
			event.preventDefault();

			this.dragging = true;
			this.$el.addClass('dragging');

			this.fixTouchEvents(event);

			this.dragX = event.pageX;
		},

		drag: function(event) {
			if (this.dragging) {

				this.fixTouchEvents(event);

				// Get position
				this._xPercent = (event.pageX - this.dragOffset.left) / this.dragBounds.width;
				this._xPosition = (this._xPercent * this.simulation.get('containerWidth')) - this.simulation.get('halfContainerWidth');

				this.movingMan.setMousePosition(this._xPosition);
				this.movingMan.positionDriven(true);

				// Get direction
				if ((event.pageX - this.dragX) > 0)
					this.movementState = MOVEMENT_STATE_RIGHT;
				else if ((event.pageX - this.dragX) < 0)
					this.movementState = MOVEMENT_STATE_LEFT;
				this.dragX = event.pageX;
			}
		},

		dragEnd: function(event) {
			if (this.dragging) {
				this.dragging = false;
				this.$el.removeClass('dragging');

				this.movementState = MOVEMENT_STATE_IDLE;
			}
		},

		update: function(time, delta) {
			this._lastPosition = this._position;
			this._position = this.movingMan.get('position');
			if (this._position === this._lastPosition && !this.updateOnNextFrame)
				return;

			if (this.updateOnNextFrame)
				this.updateOnNextFrame = false;

			// Update position
			this._xPercent  = (this._position + this.simulation.get('halfContainerWidth')) / this.simulation.get('containerWidth');
			this._xPixels   = this._xPercent * this.dragBounds.width;
			this._translate = 'translateX(' + this._xPixels + 'px)';

			this.$el.css({
				'-webkit-transform': this._translate,
				'-ms-transform':     this._translate,
				'-o-transform':      this._translate,
				'transform':         this._translate,
			});

			if (this.movingMan.get('velocity') > 0.1)
				this.movementState = MOVEMENT_STATE_RIGHT;
			else if (this.movingMan.get('velocity') < -0.1)
				this.movementState = MOVEMENT_STATE_LEFT;
			else
				this.movementState = MOVEMENT_STATE_IDLE;

			// Update direction
			if (this.visibleMovementState !== this.movementState) {
				this.visibleMovementState = this.movementState;

				switch (this.movementState) {
					case MOVEMENT_STATE_IDLE:
						this.$el
							.removeClass('left')
							.removeClass('right');
						break;
					case MOVEMENT_STATE_RIGHT:
						this.$el
							.removeClass('left')
							.addClass('right');
						break;
					case MOVEMENT_STATE_LEFT:
						this.$el
							.removeClass('right')
							.addClass('left');
						break;
				}
			}
		}
	});

	return MovingManView;
});
<commit_msg>In moving man view, checking for changes in velocity too and not just position.<commit_after>define(function (require) {

	'use strict';

	// var $ = require('jquery');
	var _ = require('underscore');

	var SimDraggable = require('views/sim-draggable');

	var html = require('text!templates/moving-man.html');

	require('less!styles/moving-man');

	/**
	 * Constants
	 */
	var MOVEMENT_STATE_IDLE  = 0;
	var MOVEMENT_STATE_LEFT  = 1;
	var MOVEMENT_STATE_RIGHT = 2;

	/**
	 *
	 */
	var MovingManView = SimDraggable.extend({

		template: _.template(html),

		tagName: 'div',
		className: 'moving-man-view',

		events: {
			'mousedown'  : 'down',
			'touchstart' : 'down'
		},

		initialize: function(options) {
			SimDraggable.prototype.initialize.apply(this, [options]);

			this.simulation = options.simulation;
			this.movingMan  = this.simulation.movingMan;
		},

		render: function() {
			this.renderMovingMan();
			this.bindDragEvents();
			this.resize();
			this.update(0, 0);
		},

		renderMovingMan: function() {
			this.$el.html(this.template());
		},

		down: function(event) {
			event.preventDefault();

			this.dragging = true;
			this.$el.addClass('dragging');

			this.fixTouchEvents(event);

			this.dragX = event.pageX;
		},

		drag: function(event) {
			if (this.dragging) {

				this.fixTouchEvents(event);

				// Get position
				this._xPercent = (event.pageX - this.dragOffset.left) / this.dragBounds.width;
				this._xPosition = (this._xPercent * this.simulation.get('containerWidth')) - this.simulation.get('halfContainerWidth');

				this.movingMan.setMousePosition(this._xPosition);
				this.movingMan.positionDriven(true);

				// Get direction
				if ((event.pageX - this.dragX) > 0)
					this.movementState = MOVEMENT_STATE_RIGHT;
				else if ((event.pageX - this.dragX) < 0)
					this.movementState = MOVEMENT_STATE_LEFT;
				this.dragX = event.pageX;
			}
		},

		dragEnd: function(event) {
			if (this.dragging) {
				this.dragging = false;
				this.$el.removeClass('dragging');

				this.movementState = MOVEMENT_STATE_IDLE;
			}
		},

		update: function(time, delta) {
			this._lastPosition = this._position;
			this._position = this.movingMan.get('position');

			this._lastVelocity = this._velocity;
			this._velocity = this.movingMan.get('velocity');

			if (!this.updateOnNextFrame && this._position === this._lastPosition && this._velocity === this._lastVelocity)
				return;

			if (this.updateOnNextFrame)
				this.updateOnNextFrame = false;

			// Update position
			this._xPercent  = (this._position + this.simulation.get('halfContainerWidth')) / this.simulation.get('containerWidth');
			this._xPixels   = this._xPercent * this.dragBounds.width;
			this._translate = 'translateX(' + this._xPixels + 'px)';

			this.$el.css({
				'-webkit-transform': this._translate,
				'-ms-transform':     this._translate,
				'-o-transform':      this._translate,
				'transform':         this._translate,
			});

			if (this.movingMan.get('velocity') > 0.1)
				this.movementState = MOVEMENT_STATE_RIGHT;
			else if (this.movingMan.get('velocity') < -0.1)
				this.movementState = MOVEMENT_STATE_LEFT;
			else
				this.movementState = MOVEMENT_STATE_IDLE;

			// Update direction
			if (this.visibleMovementState !== this.movementState) {
				this.visibleMovementState = this.movementState;

				switch (this.movementState) {
					case MOVEMENT_STATE_IDLE:
						this.$el
							.removeClass('left')
							.removeClass('right');
						break;
					case MOVEMENT_STATE_RIGHT:
						this.$el
							.removeClass('left')
							.addClass('right');
						break;
					case MOVEMENT_STATE_LEFT:
						this.$el
							.removeClass('right')
							.addClass('left');
						break;
				}
			}
		}
	});

	return MovingManView;
});
<|endoftext|>


<commit_before>'use strict';

angular.module('OpiferNestedContent', ['ui.sortable'])
    /**
     * Template Service
     */
    .factory('TemplateService', ['$resource', function($resource) {
        return $resource(Routing.generate('opifer_eav_api_template'), {}, {
            index: {method: 'GET', params: {}}
        });
    }])

    /**
     * Render the nested content
     */
    .directive('nestedContent', ['$compile', function($compile) {
        var tpl =
            '
' +
            '

' +
            '
' +
            '<select class="form-control" ng-options="template.name for (key, template) in templates" ng-model="selected" ng-change="addSubject()">' +
            '    <option value="">Add template...</option>' +
            '</select>'
        ;

        return {
            restrict: 'E',
            template: tpl,
            scope: {
                ids: '@',
                attribute: '@'
            },
            link: function(scope, element, attrs) {

                scope.addSubject = function() {
                    // Add the template to the subjects array
                    scope.subjects.push(this.selected);

                    // Clear the select field so we can re-use it for adding more
                    // nested content.
                    this.selected = null;
                };

                scope.removeSubject = function(index) {
                    // Remove the subject from the subjects array
                    scope.subjects.splice(index, 1);
                };
            },
            controller: function($scope, $http, $attrs, TemplateService) {
                // Query all available templates to make them available in the
                // select field.
                $scope.templates = TemplateService.index();
                $scope.subjects = [];

                // Retrieve all predefined nested content and add them to the
                // subjects array.
                if ($scope.ids !== undefined) {
                    var ids = $scope.ids.split(',');
                    for (var i = 0; i < ids.length; i++) {
                        $scope.subjects.push({name: ids[i]});
                    };
                }
            }
        };
    }])

    /**
     * render the nested content form
     *
     * Requests a form type and manually compiles the return html
     */
    .directive('nestedContentForm', ['$compile', '$http', '$sce', function($compile, $http, $sce) {
        return {
            template:
                '
'+
                '   ' +
                '
'+
                '
'+
                '

'+
                '

'+
                '
{{ subject.data.title }}
'+
                '
'+
                '           {{ subject.data.templateName }}'+
                '
'+
                '
'+
                '
Delete'+
                '
 '+
                '

'+
                '   ' +
                '
' +
                '

'+
                '
' +
                '
',
            replace: true,
            link: function (scope, element, attrs) {
                scope.subject.data = {};
                scope.subject.form = '';

                // Request the form template and compile it
                $http.post(Routing.generate('opifer_eav_form_render', {
                    attribute: scope.attribute,
                    id: scope.subject.name,
                    index: scope.$index
                }), {}).success(function(data) {
                    scope.subject.form = data.form;
                    scope.subject.data = data.content;

                    if (scope.subject.data.pivotedAttributes.coverImage) {
                        scope.subject.data.pivotedAttributes.coverImage = Routing.generate('liip_imagine_filter', {'path':  scope.subject.data.pivotedAttributes.coverImage, 'filter' : 'medialibrary'});
                    }

                    // If the subject's name is not an ID, it means it's a new nested content
                    // form, so don't hide it.
                    if (isNaN(parseFloat(scope.subject.name)) || !isFinite(scope.subject.name)) {
                        scope.hidden = false;
                    }
                });

                // Hide/Show the nested content form
                scope.toggle = function() {
                    if (scope.hidden == true) {
                        scope.hidden = false;
                    } else {
                        scope.hidden = true;
                    }
                }
            },
            controller: function($scope, $http, $attrs, TemplateService) {
                // Initially hide each form, to keep the form view clean.
                $scope.hidden = true;
            }
        };
    }])

    /**
     * Compile the passed html
     */
    .directive('compile', function ($compile) {
        return {
            restrict: 'A',
            replace: true,
            link: function (scope, element, attrs) {
                scope.$watch(attrs.compile, function(html) {
                    element.html(html);
                    $compile(element.contents())(scope);
                });
            }
        };
    })
;
<commit_msg>Changed undefined check<commit_after>'use strict';

angular.module('OpiferNestedContent', ['ui.sortable'])
    /**
     * Template Service
     */
    .factory('TemplateService', ['$resource', function($resource) {
        return $resource(Routing.generate('opifer_eav_api_template'), {}, {
            index: {method: 'GET', params: {}}
        });
    }])

    /**
     * Render the nested content
     */
    .directive('nestedContent', ['$compile', function($compile) {
        var tpl =
            '
' +
            '

' +
            '
' +
            '<select class="form-control" ng-options="template.name for (key, template) in templates" ng-model="selected" ng-change="addSubject()">' +
            '    <option value="">Add template...</option>' +
            '</select>'
        ;

        return {
            restrict: 'E',
            template: tpl,
            scope: {
                ids: '@',
                attribute: '@'
            },
            link: function(scope, element, attrs) {

                scope.addSubject = function() {
                    // Add the template to the subjects array
                    scope.subjects.push(this.selected);

                    // Clear the select field so we can re-use it for adding more
                    // nested content.
                    this.selected = null;
                };

                scope.removeSubject = function(index) {
                    // Remove the subject from the subjects array
                    scope.subjects.splice(index, 1);
                };
            },
            controller: function($scope, $http, $attrs, TemplateService) {
                // Query all available templates to make them available in the
                // select field.
                $scope.templates = TemplateService.index();
                $scope.subjects = [];

                // Retrieve all predefined nested content and add them to the
                // subjects array.
                if (typeof $scope.ids !== 'undefined') {

                    var ids = $scope.ids.split(',');
                    for (var i = 0; i < ids.length; i++) {
                        $scope.subjects.push({name: ids[i]});
                    };
                }
            }
        };
    }])

    /**
     * render the nested content form
     *
     * Requests a form type and manually compiles the return html
     */
    .directive('nestedContentForm', ['$compile', '$http', '$sce', function($compile, $http, $sce) {
        return {
            template:
                '
'+
                '   ' +
                '
'+
                '
'+
                '

'+
                '

'+
                '
{{ subject.data.title }}
'+
                '
'+
                '           {{ subject.data.templateName }}'+
                '
'+
                '
'+
                '
Delete'+
                '
 '+
                '

'+
                '   ' +
                '
' +
                '

'+
                '
' +
                '
',
            replace: true,
            link: function (scope, element, attrs) {
                scope.subject.data = {};
                scope.subject.form = '';

                // Request the form template and compile it
                $http.post(Routing.generate('opifer_eav_form_render', {
                    attribute: scope.attribute,
                    id: scope.subject.name,
                    index: scope.$index
                }), {}).success(function(data) {
                    scope.subject.form = data.form;
                    scope.subject.data = data.content;

                    if (scope.subject.data.pivotedAttributes.coverImage) {
                        scope.subject.data.pivotedAttributes.coverImage = Routing.generate('liip_imagine_filter', {'path':  scope.subject.data.pivotedAttributes.coverImage, 'filter' : 'medialibrary'});
                    }

                    // If the subject's name is not an ID, it means it's a new nested content
                    // form, so don't hide it.
                    if (isNaN(parseFloat(scope.subject.name)) || !isFinite(scope.subject.name)) {
                        scope.hidden = false;
                    }
                });

                // Hide/Show the nested content form
                scope.toggle = function() {
                    if (scope.hidden == true) {
                        scope.hidden = false;
                    } else {
                        scope.hidden = true;
                    }
                }
            },
            controller: function($scope, $http, $attrs, TemplateService) {
                // Initially hide each form, to keep the form view clean.
                $scope.hidden = true;
            }
        };
    }])

    /**
     * Compile the passed html
     */
    .directive('compile', function ($compile) {
        return {
            restrict: 'A',
            replace: true,
            link: function (scope, element, attrs) {
                scope.$watch(attrs.compile, function(html) {
                    element.html(html);
                    $compile(element.contents())(scope);
                });
            }
        };
    })
;
<|endoftext|>