Ver código fonte

version 1.4.2 small changes for ebook plugin

trendschau 4 anos atrás
pai
commit
3cebe0426c

+ 19 - 3
system/Assets.php

@@ -16,6 +16,7 @@ class Assets
 		$this->inlineJS			= array();
 		$this->inlineCSS		= array();
 		$this->editorJS 		= array();
+		$this->editorCSS 		= array();		
 		$this->editorInlineJS 	= array();
 		$this->svgSymbols		= array();
 		$this->imageUrl 		= false;
@@ -207,12 +208,12 @@ class Assets
 
 	public function renderCSS()
 	{
-		return implode('', $this->CSS) . implode('', $this->inlineCSS);
+		return implode("\n", $this->CSS) . implode("\n", $this->inlineCSS);
 	}
 	
 	public function renderJS()
 	{
-		return implode('', $this->JS) . implode('', $this->inlineJS);
+		return implode("\n", $this->JS) . implode("\n", $this->inlineJS);
 	}
 
 	public function renderSvg()
@@ -236,9 +237,24 @@ class Assets
 		$this->editorInlineJS[] = '<script>' . $JS . '</script>';
 	}
 
+	public function addEditorCSS($CSS)
+	{
+		$CSSfile = $this->getFileUrl($CSS);
+		
+		if($CSSfile)
+		{
+			$this->editorCSS[] = '<link rel="stylesheet" href="' . $CSSfile . '" />';
+		}
+	}
+
 	public function renderEditorJS()
 	{
-		return implode('', $this->editorJS) . implode('', $this->editorInlineJS);
+		return implode("\n", $this->editorJS) . implode("\n", $this->editorInlineJS);
+	}
+
+	public function renderEditorCSS()
+	{
+		return implode("\n", $this->editorCSS);
 	}
 
 	/**

+ 4 - 0
system/Controllers/MetaApiController.php

@@ -7,6 +7,7 @@ use Slim\Http\Response;
 use Typemill\Models\WriteYaml;
 use Typemill\Models\WriteMeta;
 use Typemill\Models\Folder;
+use Typemill\Events\OnMetaDefinitionsLoaded;
 
 class MetaApiController extends ContentController
 {
@@ -60,6 +61,9 @@ class MetaApiController extends ContentController
 			$metatabs = array_merge_recursive($metatabs, $themeSettings['metatabs']);
 		}
 
+		# dispatch meta 
+		$metatabs 		= $this->c->dispatcher->dispatch('onMetaDefinitionsLoaded', new OnMetaDefinitionsLoaded($metatabs))->getData();
+
 		return $metatabs;
 	}
 

+ 14 - 0
system/Events/OnMetaDefinitionsLoaded.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace Typemill\Events;
+
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Event for markdown.
+ */
+
+class OnMetaDefinitionsLoaded extends BaseEvent
+{
+
+}

+ 7 - 0
system/Models/Validation.php

@@ -133,6 +133,13 @@ class Validation
 		}, 'not secure. For code please use markdown `inline-code` or ````fenced code blocks````.');
 	}
 
+	# return valitron standard object
+	public function returnValitron(array $params)
+	{
+		return new Validator($params);
+	}
+
+
 	/**
 	* validation for signup form
 	* 

+ 5 - 0
system/Plugin.php

@@ -133,6 +133,11 @@ abstract class Plugin implements EventSubscriberInterface
 		$this->container->assets->addInlineCSS($CSS);		
 	}
 
+	protected function addEditorCSS($CSS)
+	{
+		$this->container->assets->addEditorCSS($CSS);
+	}
+
 	protected function activateAxios()
 	{
 		$this->container->assets->activateAxios();		

+ 1 - 0
system/author/editor/editor-blox.twig

@@ -23,6 +23,7 @@
 		  	:errors="formErrors[currentTab]" 
 		  	:schema="formDefinitions[currentTab]"
 		  	:formdata="formData[currentTab]"
+		  	:item="item"
 		  	v-on:saveform="saveForm">
 		  </component>
 

+ 3 - 3
system/author/js/vue-blox.js

@@ -31,7 +31,7 @@ const contentComponent = Vue.component('content-block', {
 			compmarkdown: '',
 			componentType: '',
 			disabled: false,
-			load: false,
+//fix			load: false,
 			newblock: false,
 		}
 	},
@@ -1386,7 +1386,7 @@ const imageComponent = Vue.component('image-component', {
 			maxsize: 5, // megabyte
 			imgpreview: false,
 			showmedialib: false,
-			load: false,
+//fix			load: false,
 			imgmeta: false,
 			imgalt: '',
 			imgtitle: '',
@@ -1683,7 +1683,7 @@ const fileComponent = Vue.component('file-component', {
 		return {
 			maxsize: 5, // megabyte
 			showmedialib: false,
-			load: false,
+//fix			load: false,
 			filemeta: false,
 			filetitle: '',
 			fileextension: '',

+ 5 - 477
system/author/js/vue-meta.js

@@ -11,479 +11,6 @@ Vue.filter('translate', function (value) {
   }
 })
 
-Vue.component('component-text', {
-	props: ['class', 'id', 'description', 'maxlength', 'hidden', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="text"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :hidden="hidden"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-hidden', {
-	props: ['class', 'id', 'maxlength', 'required', 'disabled', 'name', 'type', 'value', 'errors'],
-	template: '<div class="hidden">' +
-				'<input type="hidden"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :name="name"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-textarea', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	data: function () {
-		return {
-			textareaclass: ''
-		 }
-	},
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<textarea rows="8" ' +
-					' :id="id"' +
-					' :class="textareaclass"' +
-					' :readonly="readonly"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +  
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="formatValue(value)"' +
-					' @input="update($event, name)"></textarea>' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-		formatValue: function(value)
-		{
-			if(value !== null && typeof value === 'object')
-			{
-				this.textareaclass = 'codearea';
-				return JSON.stringify(value, undefined, 4);
-			}
-			return value;
-		},
-	},
-})
-
-Vue.component('component-url', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="url"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +			  	
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-number', {
-	props: ['class', 'id', 'description', 'min', 'max', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="number"' + 
-					' :id="id"' +
-					' :min="min"' +
-					' :min="max"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-email', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="email"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-tel', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="tel"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-password', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="password"' + 
-					' :id="id"' +
-					' :maxlength="maxlength"' +
-					' :readonly="readonly"' +
-					' :required="required"' +
-					' :disabled="disabled"' +
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					'@input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-date', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="date" ' +
-					' :id="id"' +
-					' :readonly="readonly"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +  
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					' @input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-color', {
-	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<input type="color" ' +
-					' :id="id"' +
-					' :readonly="readonly"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +  
-					' :name="name"' +
-					' :placeholder="placeholder"' +
-					' :value="value"' +
-					' @input="update($event, name)">' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-select', {
-	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'name', 'type', 'options', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-			    '<select' + 
-					' :id="id"' +
-					' :name="name"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +
-					' v-model="value"' + 
-			    	' @change="update($event,name)">' +
-			      	'<option v-for="option,optionkey in options" v-bind:value="optionkey">{{option}}</option>' +
-			    '</select>' +
-			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  '</div>',
-	methods: {
-		update: function($event, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
-		},
-	},
-})
-
-Vue.component('component-checkbox', {
-	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<label class="control-group">{{ checkboxlabel|translate }}' +
-				  '<input type="checkbox"' + 
-					' :id="id"' +
-					' :readonly="readonly"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +
-				    ' :name="name"' + 
-				    ' v-model="value"' +
-				    ' @change="update($event, value, name)">' +				
-			  	  '<span class="checkmark"></span>' +
-			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-				  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  	'</label>' +  
-			  '</div>',
-	methods: {
-		update: function($event, value, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : value});
-		},
-	},
-})
-
-Vue.component('component-checkboxlist', {
-	props: ['class', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'options', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<label v-for="option, optionvalue in options" class="control-group">{{ option }}' +
-				  '<input type="checkbox"' + 
-					' :id="optionvalue"' +
-				  	' :value="optionvalue"' + 
-				  	' v-model="value" ' + 
-				  	' @change="update($event, value, optionvalue, name)">' +
-			  	  '<span class="checkmark"></span>' +
-			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-			  	  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  	'</label>' +
-			  '</div>',
-	methods: {
-		update: function($event, value, optionvalue, name)
-		{
-			/* if value (array) for checkboxlist is not initialized yet */
-			if(value === true || value === false)
-			{
-				value = [optionvalue];
-			}
-			FormBus.$emit('forminput', {'name': name, 'value' : value});
-		},
-	},
-})
-
-Vue.component('component-radio', {
-	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'options', 'label', 'name', 'type', 'value', 'errors'],
-	template: '<div class="large">' +
-				'<label>{{ label|translate }}</label>' +
-				'<label v-for="option,optionvalue in options" class="control-group">{{ option }}' +
-				  '<input type="radio"' + 
-					' :id="id"' +
-					' :readonly="readonly"' +
-					' :required="required"' +  
-					' :disabled="disabled"' +
-				  	' :name="name"' +
-				  	' :value="optionvalue"' + 
-				  	' v-model="value" ' + 
-				  	' @change="update($event, value, name)">' +				
-			  	  '<span class="radiomark"></span>' +
-			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
-				  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
-			  	'</label>' +  
-			  '</div>',
-	methods: {
-		update: function($event, value, name)
-		{
-			FormBus.$emit('forminput', {'name': name, 'value' : value});
-		},
-	},
-})
-
-Vue.component('component-customfields', {
-	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'options', 'label', 'name', 'type', 'value', 'errors'],
-	data: function () {
-		return {
-			fielderrors: false,
-			fielddetails: {},
-			disableaddbutton: false,
-		 }
-	},
-	template: '<div class="large">' +
-				'<label class="mb2">{{ label|translate }}</label>' +
-			  	'<div class="fielddescription mb2 f7">{{ description|translate }}</div>' +
-			  	'<div v-if="errors[name]" class="error mb2 f7">{{ errors[name] }}</div>' +
-			  	'<transition name="fade"><div v-if="fielderrors" class="error mb2 f7">{{ fielderrors }}</div></transition>' +
-	  			'<transition-group name="fade" tag="div">' + 
-	  				'<div class="customrow flex items-start mb3" v-for="(pairobject, pairindex) in value" :key="pairindex">' +
-						'<input type="text" placeholder="key" class="customkey" :class="pairobject.keyerror" :value="pairobject.key" @input="updatePairKey(pairindex,$event)">' +
-				  		'<div class="mt3"><svg class="icon icon-dots-two-vertical"><use xlink:href="#icon-dots-two-vertical"></use></svg></div>' + 
-		  			  	'<textarea placeholder="value" class="customvalue pa3" :class="pairobject.valueerror" v-html="pairobject.value" @input="updatePairValue(pairindex,$event)"></textarea>' +
-						'<button class="bg-tm-red white bn ml2 h1 w2 br1" @click.prevent="deleteField(pairindex)"><svg class="icon icon-minus"><use xlink:href="#icon-minus"></use></svg></button>' +
-					'</div>' +
-				'</transition-group>' +
-				'<button :disabled="disableaddbutton" class="bg-tm-green white bn br1 pa2 f6" @click.prevent="addField()"><svg class="icon icon-plus f7"><use xlink:href="#icon-plus"></use></svg> Add Fields</button>' +
-			  '</div>',
-	mounted: function(){
-		if(this.value === null || this.value.length == 0)
-		{
-			this.value = [{}];
-			this.disableaddbutton = 'disabled';
-		}
-	},
-	methods: {
-		update: function(value, name)
-		{
-			this.fielderrors = false;
-			this.errors = false;
-			FormBus.$emit('forminput', {'name': name, 'value': value});
-		},
-		updatePairKey: function(index,event)
-		{
-			this.value[index].key = event.target.value;
-
-			var regex = /^[a-z0-9]+$/i;
-
-			if(!this.keyIsUnique(event.target.value,index))
-			{
-				this.value[index].keyerror = 'red';
-				this.fielderrors = 'Error: The key already exists';
-				this.disableaddbutton = 'disabled';
-				return;
-			}
-			else if(!regex.test(event.target.value))
-			{
-				this.value[index].keyerror = 'red';
-				this.fielderrors = 'Error: Only alphanumeric for keys allowed';
-				this.disableaddbutton = 'disabled';
-				return;
-			}
-
-			delete this.value[index].keyerror;
-			this.disableaddbutton = false;
-			this.update(this.value,this.name);
-		},
-		keyIsUnique: function(keystring, index)
-		{
-			for(obj in this.value)
-			{
-				if( (obj != index) && (this.value[obj].key == keystring) )
-				{
-					return false;
-				}
-			}
-			return true;
-		},
-		updatePairValue: function(index, event)
-		{
-			this.value[index].value = event.target.value;
-			
-			var regex = /<.*(?=>)/gm;
-			if(event.target.value == '' || regex.test(event.target.value))
-			{
-				this.value[index].valueerror = 'red';
-				this.fielderrors = 'Error: No empty values or html tags are allowed';				
-			}
-			else
-			{
-				delete this.value[index].valueerror;
-				this.update(this.value,this.name);
-			}
-		},
-		addField: function()
-		{
-			for(object in this.value)
-			{
-				if(Object.keys(this.value[object]).length === 0)
-				{
-					return;
-				}
-			}
-			this.value.push({});
-			this.disableaddbutton = 'disabled';
-		},
-		deleteField: function(index)
-		{
-			this.value.splice(index,1);
-			this.disableaddbutton = false;
-			this.update(this.value,this.name);
-		},
-	},
-})
 
 Vue.component('tab-meta', {
 	props: ['saved', 'errors', 'formdata', 'schema'],
@@ -524,6 +51,7 @@ let meta = new Vue({
 			formData: [],
 			formErrors: {},
 			formErrorsReset: {},
+			item: false,
 			saved: false,
 		}
 	},
@@ -567,11 +95,11 @@ let meta = new Vue({
 
         	self.formData = response.data.metadata;
 
-        	var item = response.data.item;
-        	if(item.elementType == "folder" && item.contains == "posts")
+        	self.item = response.data.item;
+        	if(self.item.elementType == "folder" && self.item.contains == "posts")
         	{
-        		posts.posts = item.folderContent;
-	        	posts.folderid = item.keyPath;
+        		posts.posts = self.item.folderContent;
+	        	posts.folderid = self.item.keyPath;
         	}
         	else
         	{

+ 475 - 0
system/author/js/vue-shared.js

@@ -1,3 +1,478 @@
+Vue.component('component-text', {
+	props: ['class', 'id', 'description', 'maxlength', 'hidden', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="text"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :hidden="hidden"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-hidden', {
+	props: ['class', 'id', 'maxlength', 'required', 'disabled', 'name', 'type', 'value', 'errors'],
+	template: '<div class="hidden">' +
+				'<input type="hidden"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :name="name"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-textarea', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	data: function () {
+		return {
+			textareaclass: ''
+		 }
+	},
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<textarea rows="8" ' +
+					' :id="id"' +
+					' :class="textareaclass"' +
+					' :readonly="readonly"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +  
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="formatValue(value)"' +
+					' @input="update($event, name)"></textarea>' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+		formatValue: function(value)
+		{
+			if(value !== null && typeof value === 'object')
+			{
+				this.textareaclass = 'codearea';
+				return JSON.stringify(value, undefined, 4);
+			}
+			return value;
+		},
+	},
+})
+
+Vue.component('component-url', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="url"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +			  	
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-number', {
+	props: ['class', 'id', 'description', 'min', 'max', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="number"' + 
+					' :id="id"' +
+					' :min="min"' +
+					' :min="max"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-email', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="email"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-tel', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="tel"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-password', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="password"' + 
+					' :id="id"' +
+					' :maxlength="maxlength"' +
+					' :readonly="readonly"' +
+					' :required="required"' +
+					' :disabled="disabled"' +
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					'@input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-date', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="date" ' +
+					' :id="id"' +
+					' :readonly="readonly"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +  
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					' @input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-color', {
+	props: ['class', 'id', 'description', 'maxlength', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<input type="color" ' +
+					' :id="id"' +
+					' :readonly="readonly"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +  
+					' :name="name"' +
+					' :placeholder="placeholder"' +
+					' :value="value"' +
+					' @input="update($event, name)">' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-select', {
+	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'name', 'type', 'options', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+			    '<select' + 
+					' :id="id"' +
+					' :name="name"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +
+					' v-model="value"' + 
+			    	' @change="update($event,name)">' +
+			      	'<option v-for="option,optionkey in options" v-bind:value="optionkey">{{option}}</option>' +
+			    '</select>' +
+			  	'<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	'<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  '</div>',
+	methods: {
+		update: function($event, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : $event.target.value});
+		},
+	},
+})
+
+Vue.component('component-checkbox', {
+	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<label class="control-group">{{ checkboxlabel|translate }}' +
+				  '<input type="checkbox"' + 
+					' :id="id"' +
+					' :readonly="readonly"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +
+				    ' :name="name"' + 
+				    ' v-model="value"' +
+				    ' @change="update($event, value, name)">' +				
+			  	  '<span class="checkmark"></span>' +
+			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+				  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  	'</label>' +  
+			  '</div>',
+	methods: {
+		update: function($event, value, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : value});
+		},
+	},
+})
+
+Vue.component('component-checkboxlist', {
+	props: ['class', 'description', 'readonly', 'required', 'disabled', 'label', 'checkboxlabel', 'options', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<label v-for="option, optionvalue in options" class="control-group">{{ option }}' +
+				  '<input type="checkbox"' + 
+					' :id="optionvalue"' +
+				  	' :value="optionvalue"' + 
+				  	' v-model="value" ' + 
+				  	' @change="update($event, value, optionvalue, name)">' +
+			  	  '<span class="checkmark"></span>' +
+			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+			  	  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  	'</label>' +
+			  '</div>',
+	methods: {
+		update: function($event, value, optionvalue, name)
+		{
+			/* if value (array) for checkboxlist is not initialized yet */
+			if(value === true || value === false)
+			{
+				value = [optionvalue];
+			}
+			FormBus.$emit('forminput', {'name': name, 'value' : value});
+		},
+	},
+})
+
+Vue.component('component-radio', {
+	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'options', 'label', 'name', 'type', 'value', 'errors'],
+	template: '<div class="large">' +
+				'<label>{{ label|translate }}</label>' +
+				'<label v-for="option,optionvalue in options" class="control-group">{{ option }}' +
+				  '<input type="radio"' + 
+					' :id="id"' +
+					' :readonly="readonly"' +
+					' :required="required"' +  
+					' :disabled="disabled"' +
+				  	' :name="name"' +
+				  	' :value="optionvalue"' + 
+				  	' v-model="value" ' + 
+				  	' @change="update($event, value, name)">' +				
+			  	  '<span class="radiomark"></span>' +
+			  	  '<span v-if="errors[name]" class="error">{{ errors[name] }}</span>' +
+				  '<span v-else class="fielddescription"><small>{{ description|translate }}</small></span>' +
+			  	'</label>' +  
+			  '</div>',
+	methods: {
+		update: function($event, value, name)
+		{
+			FormBus.$emit('forminput', {'name': name, 'value' : value});
+		},
+	},
+})
+
+Vue.component('component-customfields', {
+	props: ['class', 'id', 'description', 'readonly', 'required', 'disabled', 'options', 'label', 'name', 'type', 'value', 'errors'],
+	data: function () {
+		return {
+			fielderrors: false,
+			fielddetails: {},
+			disableaddbutton: false,
+		 }
+	},
+	template: '<div class="large">' +
+				'<label class="mb2">{{ label|translate }}</label>' +
+			  	'<div class="fielddescription mb2 f7">{{ description|translate }}</div>' +
+			  	'<div v-if="errors[name]" class="error mb2 f7">{{ errors[name] }}</div>' +
+			  	'<transition name="fade"><div v-if="fielderrors" class="error mb2 f7">{{ fielderrors }}</div></transition>' +
+	  			'<transition-group name="fade" tag="div">' + 
+	  				'<div class="customrow flex items-start mb3" v-for="(pairobject, pairindex) in value" :key="pairindex">' +
+						'<input type="text" placeholder="key" class="customkey" :class="pairobject.keyerror" :value="pairobject.key" @input="updatePairKey(pairindex,$event)">' +
+				  		'<div class="mt3"><svg class="icon icon-dots-two-vertical"><use xlink:href="#icon-dots-two-vertical"></use></svg></div>' + 
+		  			  	'<textarea placeholder="value" class="customvalue pa3" :class="pairobject.valueerror" v-html="pairobject.value" @input="updatePairValue(pairindex,$event)"></textarea>' +
+						'<button class="bg-tm-red white bn ml2 h1 w2 br1" @click.prevent="deleteField(pairindex)"><svg class="icon icon-minus"><use xlink:href="#icon-minus"></use></svg></button>' +
+					'</div>' +
+				'</transition-group>' +
+				'<button :disabled="disableaddbutton" class="bg-tm-green white bn br1 pa2 f6" @click.prevent="addField()"><svg class="icon icon-plus f7"><use xlink:href="#icon-plus"></use></svg> Add Fields</button>' +
+			  '</div>',
+	mounted: function(){
+		if(typeof this.value === 'undefined' || this.value === null || this.value.length == 0)
+		{
+			var initialvalue = [{}];
+			this.update(initialvalue, this.name);
+			this.disableaddbutton = 'disabled';
+		}
+	},
+	methods: {
+		update: function(value, name)
+		{
+			this.fielderrors = false;
+			this.errors = false;
+			FormBus.$emit('forminput', {'name': name, 'value': value});
+		},
+		updatePairKey: function(index,event)
+		{
+			this.value[index].key = event.target.value;
+
+			var regex = /^[a-z0-9]+$/i;
+
+			if(!this.keyIsUnique(event.target.value,index))
+			{
+				this.value[index].keyerror = 'red';
+				this.fielderrors = 'Error: The key already exists';
+				this.disableaddbutton = 'disabled';
+				return;
+			}
+			else if(!regex.test(event.target.value))
+			{
+				this.value[index].keyerror = 'red';
+				this.fielderrors = 'Error: Only alphanumeric for keys allowed';
+				this.disableaddbutton = 'disabled';
+				return;
+			}
+
+			delete this.value[index].keyerror;
+			this.disableaddbutton = false;
+			this.update(this.value,this.name);
+		},
+		keyIsUnique: function(keystring, index)
+		{
+			for(obj in this.value)
+			{
+				if( (obj != index) && (this.value[obj].key == keystring) )
+				{
+					return false;
+				}
+			}
+			return true;
+		},
+		updatePairValue: function(index, event)
+		{
+			this.value[index].value = event.target.value;
+			
+			var regex = /<.*(?=>)/gm;
+			if(event.target.value == '' || regex.test(event.target.value))
+			{
+				this.value[index].valueerror = 'red';
+				this.fielderrors = 'Error: No empty values or html tags are allowed';				
+			}
+			else
+			{
+				delete this.value[index].valueerror;
+				this.update(this.value,this.name);
+			}
+		},
+		addField: function()
+		{
+			for(object in this.value)
+			{
+				if(Object.keys(this.value[object]).length === 0)
+				{
+					return;
+				}
+			}
+			this.value.push({});
+			this.disableaddbutton = 'disabled';
+		},
+		deleteField: function(index)
+		{
+			this.value.splice(index,1);
+			this.disableaddbutton = false;
+			this.update(this.value,this.name);
+		},
+	},
+})
+
 Vue.component('component-image', {
 	props: ['class', 'id', 'description', 'maxlength', 'hidden', 'readonly', 'required', 'disabled', 'placeholder', 'label', 'name', 'type', 'value', 'errors'],
 	template: '<div class="large img-component">' +

Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
system/author/js/vue.min.js


+ 2 - 1
system/author/layouts/layoutBlox.twig

@@ -19,10 +19,11 @@
 		<link rel="stylesheet" href="{{ base_url }}/system/author/css/normalize.css" />
 		<link rel="stylesheet" href="{{ base_url }}/system/author/css/tachyons.min.css" />
 		<link rel="stylesheet" href="{{ base_url }}/system/author/css/style.css?20201107" />
-		<link rel="stylesheet" href="{{ base_url }}/system/author/css/color-picker.min.css" />
 
 		{{ assets.renderCSS() }}
 
+		{{ assets.renderEditorCSS() }}		
+
 	</head>
 	<body>
 		

+ 2 - 0
system/author/layouts/layoutEditor.twig

@@ -21,6 +21,8 @@
 
 		{{ assets.renderCSS() }}
 
+		{{ assets.renderEditorCSS() }}
+
 	</head>
 	<body>
 

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff