1
0
Fork 0
mirror of synced 2024-05-18 19:52:39 +12:00

Added support for multiple nested children

This commit is contained in:
Eldad Fux 2020-04-25 23:33:35 +03:00
parent f6e997e461
commit 98f97ccc0a
15 changed files with 157 additions and 139 deletions

View file

@ -209,43 +209,13 @@ $utopia->get('/console/database/document')
$page = new View(__DIR__.'/../../views/console/database/document.phtml');
$page->setParam('collection', $collection);
$layout
->setParam('title', APP_NAME.' - Database Document')
->setParam('body', $page);
});
$utopia->get('/console/database/form')
->desc('Platform console project database form')
->label('permission', 'public')
->label('scope', 'console')
->param('collection', '', function () { return new UID(); }, 'Collection unique ID.')
->param('namespace', 'project-document', function () { return new Text(256); }, 'Namespace for vars.', true)
->param('key', 'data', function () { return new Text(256); }, 'Object main key.', true)
->param('parent', 1, function () { return new Range(0, 1); }, 'Is parent?.', true)
->action(function ($collection, $namespace, $key, $parent) use ($layout, $projectDB) {
Authorization::disable();
$collection = $projectDB->getDocument($collection, false);
Authorization::reset();
if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
throw new Exception('Collection not found', 404);
}
$page = new View(__DIR__.'/../../views/console/database/form.phtml');
$page
->setParam('db', $projectDB)
->setParam('collection', $collection)
->setParam('namespace', $namespace)
->setParam('key', $key)
->setParam('parent', $parent)
;
$layout
->setPath(__DIR__.'/../../views/layouts/strip.phtml')
->setParam('title', APP_NAME.' - Database Form')
->setParam('title', APP_NAME.' - Database Document')
->setParam('body', $page);
});

View file

@ -180,9 +180,9 @@
<h4 class="margin-bottom">
<div class="pull-start margin-end-large margin-bottom-small">
<button type="button" disabled class="margin-bottom strip round" data-move-down><i class="icon-down-dir"></i></button>
<button type="button" class="margin-bottom strip round" data-move-down><i class="icon-down-dir"></i></button>
<button type="button" class="margin-bottom strip round" data-move-up><i class="icon-up-dir"></i></button>
<button type="button" disabled class="margin-bottom strip round" data-move-down><i class="icon-down-dir"></i></button>
<button type="button" disabled class="margin-bottom strip round" data-move-up><i class="icon-up-dir"></i></button>
</div>
@ -383,7 +383,6 @@
<input name="default" type="text" />
</div>
<div class="margin-bottom">
<input name="required" type="hidden" data-forms-switch data-cast-to="boolean" /> Required <span class="tooltip" data-tooltip="Mark whether this is a required attribute"><i class="icon-info-circled"></i></span>
</div>

View file

@ -1,8 +1,12 @@
<?php
use Utopia\View;
use Appwrite\Database\Validator\Authorization;
$collection = $this->getParam('collection', null);
$db = $this->getParam('db', null);
$rules = $collection->getAttribute('rules', []);
$namespace = 'project-document';
?>
<div
data-service="database.getCollection"
@ -16,7 +20,7 @@ $rules = $collection->getAttribute('rules', []);
data-param-collection-id="{{router.params.collection}}"
data-param-document-id="{{router.params.id}}"
data-scope="sdk"
data-event="load"
data-event="load,database.updateDocument"
data-name="project-document"
data-success="default">
@ -58,9 +62,10 @@ $rules = $collection->getAttribute('rules', []);
data-name="project-document"
data-scope="sdk"
data-event="submit"
data-success="alert,trigger"
data-success="alert,trigger{{|documentSuccess}}"
data-success-param-alert-text="Updated document successfully"
data-success-param-trigger-events="database.xupdateDocument"
data-success-param-trigger-events="database.updateDocument"
data-success-param-redirect-url="/console/database/document?id={{serviceData.$id}}&collection={{router.params.collection}}&project={{router.params.project}}"
data-failure="alert"
data-failure-param-alert-text="Failed to update document"
data-failure-param-alert-classname="error">
@ -70,7 +75,7 @@ $rules = $collection->getAttribute('rules', []);
<div class="box">
<?php if(empty($rules)): ?>
<div class="margin-bottom-xl margin-top-xl margin-end margin-start text-align-center">
<h4 class="text-fade text-size-small">No attribute rules added yet.<br /><br /><a data-ls-attrs="href=/console/database/collection/update?id={{router.params.collection}}&project={{router.params.project}}">Update Collection</a></h4>
<h4 class="text-fade text-size-small">No attribute rules added yet.<br /><br /><a data-ls-attrs="href=/console/database/collection/settings?id={{router.params.collection}}&project={{router.params.project}}">Update Collection</a></h4>
</div>
<?php else: ?>
<?php
@ -79,7 +84,7 @@ $rules = $collection->getAttribute('rules', []);
$comp
->setParam('collection', $collection)
->setParam('namespace', 'project-document')
->setParam('namespace', $namespace)
->setParam('key', 'data')
->setParam('parent', 1)
;
@ -155,4 +160,47 @@ $rules = $collection->getAttribute('rules', []);
</ul>
</div>
</div>
</div>
</div>
<?php foreach($rules as $rule):
$key = (isset($rule['key'])) ? $rule['key'] : '';
$label = (isset($rule['label'])) ? $rule['label'] : '';
$type = (isset($rule['type'])) ? $rule['type'] : '';
$list = (isset($rule['list'])) ? $rule['list'] : false;
$array = (isset($rule['array'])) ? $rule['array'] : false;
if($type !== 'document') {
continue;
}
?>
<?php foreach($list as $item):
if($item === $collection->getId()) {
continue; // Do not allow rec recrusion
}
Authorization::disable(); //TODO Try and avoid calling the DB from the template
$childCollection = $db->getDocument($item, false);
Authorization::reset();
if(!$childCollection->getId()) {
continue;
}
?>
<script type="text/html" id="collection-<?php echo ($array) ? 'array-' : ''; ?><?php echo $this->escape($childCollection->getId()); ?>">
<?php
$comp = new View(__DIR__.'/form.phtml');
$comp
->setParam('collection', $childCollection)
->setParam('namespace', ($array) ? 'node' : $namespace.'.'.$key)
->setParam('key', $key)
->setParam('array', $array)
->setParam('parent', 0)
;
echo $comp->render();
?>
</script>
<?php endforeach; ?>
<?php endforeach; ?>

View file

@ -4,26 +4,27 @@ use Utopia\View;
$collection = $this->getParam('collection', null);
$rules = $collection->getAttribute('rules', []);
$key = $this->getParam('key', 'data');
$key = $this->getParam('key', null);
$parent = $this->getParam('parent', true);
$namespace = $this->getParam('namespace', 'project-document');
$array = $this->getParam('array', false);
?>
<?php if($parent): ?>
<input name="documentId" type="hidden" data-ls-bind="{{router.params.id}}" />
<input name="collectionId" type="hidden" data-ls-bind="{{router.params.collection}}" />
<?php else: ?>
<div class="margin-bottom-small text-size-small" data-ls-if="({{<?php echo $this->escape($namespace); ?>.$id}})">
<?php /*<div class="margin-bottom-small text-size-small" data-ls-if="({{<?php echo $this->escape($namespace); ?>.$id}})">
<span data-ls-bind="Document #{{<?php echo $this->escape($namespace); ?>.$id}}"></span> &nbsp;
<a data-ls-attrs="href=/console/database/document?id={{<?php echo $this->escape($namespace); ?>.$id}}&collection={{<?php echo $this->escape($namespace); ?>.$collection}}&project={{router.params.project}}" class="pull-end" target="_blank">Edit in a new window <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom-small text-size-small" data-ls-if="(!{{<?php echo $this->escape($namespace); ?>.$id}})">
Create a new child document
</div>
<hr class="margin-top-small margin-bottom-small" />
</div> */ ?>
<?php endif; ?>
<fieldset name="<?php echo $this->escape($key); ?>" data-cast-to="object">
<fieldset name="<?php echo $this->escape($key); ?>"<?php if(!$array): ?> data-cast-to="object"<?php endif; ?>>
<?php if(!$parent): ?>
<input name="$id" type="hidden" data-ls-bind="{{<?php echo $this->escape($namespace); ?>.$id}}" />
<input name="$collection" type="hidden" data-ls-bind="<?php echo $this->escape($collection->getId()); ?>" />
@ -50,6 +51,7 @@ $namespace = $this->getParam('namespace', 'project-document');
;
$loop
->setParam('type', $type)
->setParam('key', $key)
->setParam('array', $array)
->setParam('required', $required)
@ -63,17 +65,17 @@ $namespace = $this->getParam('namespace', 'project-document');
<?php echo $this->escape($label); ?>
<?php if($array): ?>
<span class="text-size-small text-fade">&nbsp;&nbsp;(Array)</span>
<span class="text-size-small text-fade">&nbsp;(Array)</span>
<?php endif; ?>
<?php if($required): ?>
<span class="text-size-xs text-danger text-fade">&nbsp;required</span>
<?php endif; ?>
<?php if(!$required): ?>
<span class="text-size-xs text-fade">&nbsp;optional</span>
<?php endif; ?>
</label>
<?php if($required): ?>
<div class="text-size-xs text-danger text-fade">required</div>
<?php endif; ?>
<?php if(!$required): ?>
<div class="text-size-xs text-fade">optional</div>
<?php endif; ?>
<div class="margin-top-small margin-bottom">
<?php if(!$array): ?>

View file

@ -1,10 +1,16 @@
<?php
$key = $this->getParam('key', '');
$type = $this->getParam('type', '');
$required = $this->getParam('required', '');
$comp = $this->getParam('comp', '');
$namespace = $this->getParam('namespace', '');
$list = $this->getParam('list', []);
$comp->setParam('namespace', 'node.');
$comp->setParam('namespace', 'node');
if($type === 'document') {
$comp->setParam('key', null);
}
?>
<input type="hidden" name="<?php echo $this->escape($key); ?>"<?php if($required): ?> required<?php endif; ?> data-cast-to="array-empty">
@ -31,7 +37,7 @@ $comp->setParam('namespace', 'node.');
<?php echo $comp->render(); ?>
</div>
</div>
<hr class="margin-top-no" />
</li>
</ul>
</ul>

View file

@ -1,31 +1,19 @@
<?php
$key = $this->getParam('key', '');
$array = $this->getParam('array', false);
$required = $this->getParam('required', '');
$namespace = $this->getParam('namespace', '');
$array = $this->getParam('array', false);
$list = $this->getParam('list', []);
$list = (is_array($list)) ? $list : [];
$list = ($array) ? $list : array_shift($list);
?>
<?php if($array): ?>
<div class="drop-list bottom end" data-ls-ui-open="" data-button-text="" data-button-icon="icon-plus" data-button-selector="[data-toggler]" data-button-class="round dark small margin-top-negative-large pull-end" data-blur="1" tabindex="1">
<ul class="margin-top-negative-small">
<li data-move-up>
<button type="button" class="link"><i class="icon-up-dir"></i> Move Up</button>
</li>
<li data-move-down>
<button type="button" class="link"><i class="icon-down-dir"></i> Move Down</button>
</li>
<li data-remove>
<button type="button" class="link"><i class="icon-cancel"></i> Remove</button>
</li>
</ul>
</div>
<?php endif; ?>
<div class="info">
<?php if(!empty($list)): ?>
<div data-ls-template="/console/database/form?collection=<?php echo $this->escape($list); ?>&namespace=<?php echo $this->escape($namespace); ?>&key=<?php echo $this->escape($key); ?>&parent=0&project={{router.params.project}}&version={{env.VERSION}}&buster={{project-collection.dateUpdated}}" class="margin-bottom-negative-small"></div>
<?php endif; ?>
</div>
<div data-ls-template="collection-array-{{<?php echo $this->escape($namespace); ?>.$collection}}" data-type="script" class="margin-bottom-negative-small"></div>
<?php else: ?>
<hr class="margin-top-no" />
<div class="clear">
<a data-ls-if="(!{{<?php echo $this->escape($namespace); ?>.$id}})" data-ls-attrs="href=/console/database/document?&collection=<?php echo $this->escape($list); ?>&project={{router.params.project}}" class="pull-end text-size-small">New Document <i class="icon-link-ext"></i></a>
<a data-ls-if="({{<?php echo $this->escape($namespace); ?>.$id}})" data-ls-attrs="href=/console/database/document?id={{<?php echo $this->escape($namespace); ?>.$id}}&collection=<?php echo $this->escape($list); ?>&project={{router.params.project}}" class="pull-end text-size-small"><span data-ls-bind="Document #{{<?php echo $this->escape($namespace); ?>.$id}}"></span> <i class="icon-link-ext"></i></a>
</div>
<div data-ls-template="collection-<?php echo $this->escape($list); ?>" data-type="script" class="margin-bottom-negative-small"></div>
<hr />
<?php endif; ?>

View file

@ -108,7 +108,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<tbody data-ls-loop="project-files.files" data-ls-as="file">
<tr>
<td class="hide">
<img src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" loading="lazy" width="30" height="30" />
<img src="" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
</td>
<td data-title="Name: " class="text-one-liner">
<div data-ui-modal class="box modal width-large close" data-button-text="{{file.name}}" data-button-class="link text-size-small" data-button-element="span">
@ -169,7 +169,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<div class="margin-bottom-small">File Preview</div>
<div class="margin-bottom-small">
<img src="" class="file-preview" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="100%" height="100%" />
<img src="" class="file-preview" data-ls-attrs="src=//{{env.DOMAIN}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
</div>
<div class="margin-bottom-tiny">

View file

@ -2585,9 +2585,9 @@ let thresh=1000;if(Math.abs($value)<thresh){return $value+" B";}
let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;++u;}while(Math.abs($value)>=thresh&&u<units.length-1);return($value.toFixed(1)+'<span class="text-size-small unit">'+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentRequired",function($value,rule,filter){if(!$value||$value==='false'){return'';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');console.log('isnew?');console.log(document);console.log(document.$id);if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return $value;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
@ -2604,7 +2604,7 @@ throw new Error("This callback is only valid for forms");};},alert:function(text
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
document.dispatchEvent(new CustomEvent(events[i]));}};},setId:function name(params){},default:function(){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&collection.$id===document.$id){for(const[key,value]of Object.entries(document)){delete document[key];}
if(collection.rules){for(let index=0;index<collection.rules.length;index++){const element=collection.rules[index];switch(element.type){case'text':case'email':case'url':case'ip':document[element.key]=element.default||'';break;case'numeric':document[element.key]=element.default||'0';break;case'boolean':document[element.key]=element.default||false;break;default:document[element.key]=null;break;}
if(collection.rules){for(let index=0;index<collection.rules.length;index++){const element=collection.rules[index];switch(element.type){case'text':case'email':case'url':case'ip':document[element.key]=element.default||'';break;case'numeric':document[element.key]=element.default||'0';break;case'boolean':document[element.key]=element.default||false;break;case'document':document[element.key]=element.default||{'$id':'','$collection':'','$permissions':{}};break;default:document[element.key]=null;break;}
if(element.array){document[element.key]=[];}}}}}};let getParams=function getParams(func){const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,"");functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==="("){functionAsString=functionAsString.slice(1,-1);}
while((match=REGEX_PARAMETERS_VALUES.exec(functionAsString))){params.push(match[1]);}
return params;};let getValue=function(key,prefix,data){let result=null;if(!key){return null;}
@ -2638,7 +2638,7 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
if(target){target=document.getElementById(target);}
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){var button=document.createElement("button");let template=element.children[0].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
element.disabled=true;alerts.add({text:"Copied to clipboard",class:""},3000);});let check=function(){if(!element.value){return;}
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}

View file

@ -300,9 +300,9 @@ let thresh=1000;if(Math.abs($value)<thresh){return $value+" B";}
let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;++u;}while(Math.abs($value)>=thresh&&u<units.length-1);return($value.toFixed(1)+'<span class="text-size-small unit">'+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentRequired",function($value,rule,filter){if(!$value||$value==='false'){return'';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');console.log('isnew?');console.log(document);console.log(document.$id);if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return $value;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
@ -319,7 +319,7 @@ throw new Error("This callback is only valid for forms");};},alert:function(text
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
document.dispatchEvent(new CustomEvent(events[i]));}};},setId:function name(params){},default:function(){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&collection.$id===document.$id){for(const[key,value]of Object.entries(document)){delete document[key];}
if(collection.rules){for(let index=0;index<collection.rules.length;index++){const element=collection.rules[index];switch(element.type){case'text':case'email':case'url':case'ip':document[element.key]=element.default||'';break;case'numeric':document[element.key]=element.default||'0';break;case'boolean':document[element.key]=element.default||false;break;default:document[element.key]=null;break;}
if(collection.rules){for(let index=0;index<collection.rules.length;index++){const element=collection.rules[index];switch(element.type){case'text':case'email':case'url':case'ip':document[element.key]=element.default||'';break;case'numeric':document[element.key]=element.default||'0';break;case'boolean':document[element.key]=element.default||false;break;case'document':document[element.key]=element.default||{'$id':'','$collection':'','$permissions':{}};break;default:document[element.key]=null;break;}
if(element.array){document[element.key]=[];}}}}}};let getParams=function getParams(func){const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,"");functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==="("){functionAsString=functionAsString.slice(1,-1);}
while((match=REGEX_PARAMETERS_VALUES.exec(functionAsString))){params.push(match[1]);}
return params;};let getValue=function(key,prefix,data){let result=null;if(!key){return null;}
@ -353,7 +353,7 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
if(target){target=document.getElementById(target);}
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){var button=document.createElement("button");let template=element.children[0].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
element.disabled=true;alerts.add({text:"Copied to clipboard",class:""},3000);});let check=function(){if(!element.value){return;}
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -387,27 +387,25 @@ window.ls.filter
break;
}
})
.add("documentRequired", function($value, rule, filter) {
if(!$value || $value === 'false') {
return '';
}
return 'required';
})
.add("documentAction", function(container) {
let collection = container.get('project-collection');
let document = container.get('project-document');
console.log('isnew?');
console.log(document);
console.log(document.$id);
if(collection && document && !document.$id) {
return 'database.createDocument';
}
return 'database.updateDocument';
})
.add("documentSuccess", function(container) {
let document = container.get('project-document');
if(document && !document.$id) {
return ',redirect';
}
return '';
})
.add("firstElement", function($value) {
if($value && $value[0]) {
return $value[0];

View file

@ -5,39 +5,42 @@
selector: "data-forms-add",
repeat: false,
controller: function(element, view, container, document) {
var button = document.createElement("button");
let template = element.children[0].cloneNode(true);
let as = element.getAttribute('data-ls-as');
let counter = 0;
button.type = "button";
button.innerText = "Add";
button.classList.add("reverse");
button.addEventListener('click', function() {
container.addNamespace(as, 'new-' + counter++);
console.log(container.namespaces, container.get(as), as);
container.set(as, null, true, true);
let child = template.cloneNode(true);
view.render(child);
element.appendChild(child);
element.style.visibility = 'visible';
let inputs = child.querySelectorAll('input,textarea');
for (let index = 0; index < inputs.length; ++index) {
if(inputs[index].type !== 'hidden') {
inputs[index].focus();
break;
}
}
});
element.after(button);
for (var i = 0; i < element.children.length; i++) {
let button = document.createElement("button");
let template = element.children[i].cloneNode(true);
let as = element.getAttribute('data-ls-as');
let counter = 0;
button.type = "button";
button.innerText = "Add";
button.classList.add("reverse");
button.classList.add("margin-end-small");
button.addEventListener('click', function() {
container.addNamespace(as, 'new-' + counter++);
console.log(container.namespaces, container.get(as), as);
container.set(as, null, true, true);
let child = template.cloneNode(true);
view.render(child);
element.appendChild(child);
element.style.visibility = 'visible';
let inputs = child.querySelectorAll('input,textarea');
for (let index = 0; index < inputs.length; ++index) {
if(inputs[index].type !== 'hidden') {
inputs[index].focus();
break;
}
}
});
element.after(button);
}
}
});
})(window);

View file

@ -150,6 +150,10 @@
case 'boolean':
document[element.key] = element.default || false;
break;
case 'document':
document[element.key] = element.default || {'$id': '', '$collection': '', '$permissions': {}};
break;
default:
document[element.key] = null;

View file

@ -372,7 +372,7 @@ fieldset {
.text-size-small;
text-align: @config-end;
color: var(--config-color-fade);
margin-top: -20px;
margin-top: -15px;
margin-bottom: 0;
}