Collection UI updates
This commit is contained in:
parent
25e893f712
commit
531247deb4
|
@ -486,8 +486,8 @@ $logs = $this->getParam('logs', null);
|
|||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart background-image-no border-no margin-bottom-no">
|
||||
<input
|
||||
type="hidden"
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Created=documentsCreate,Read=documentsRead,Updated=documentsUpdate,Deleted=documentsDelete"
|
||||
data-show-y-axis="true"
|
||||
|
@ -540,34 +540,88 @@ $logs = $this->getParam('logs', null);
|
|||
|
||||
<label class="margin-bottom-small">Permissions</label>
|
||||
|
||||
<p class="text-fade text-size-small">Choose the permissions model for this collection.</p>
|
||||
<p class="text-fade text-size-small">Configure the permissions matrix for this collection.</p>
|
||||
|
||||
<hr class="margin-top-small" />
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-1"><input name="permission" value="collection" type="radio" class="margin-top-tiny" data-ls-bind="{{project-collection.permission}}" /></div>
|
||||
<div class="col span-11">
|
||||
<b>Collection Level</b>
|
||||
<p class="text-fade margin-top-tiny">With Collection Level permissions, you assign permissions only once in the collection.</p>
|
||||
<p class="text-fade margin-top-tiny">In this permission level, permissions assigned to collection takes the precedence and documents permissions are ignored.</p>
|
||||
<div data-ls-if="{{project-collection.permission}} === 'collection'">
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
|
||||
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$read}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'any' for wildcard access</div>
|
||||
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$write}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'any' for wildcard access</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="permissions-matrix margin-bottom-large"
|
||||
data-ls-attrs="x-init=console.log({{project-collection}})"
|
||||
x-data="{permissions: []}">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px;">Role</th>
|
||||
<th style="text-align: center; width: 30px">Read</th>
|
||||
<th style="text-align: center; width: 30px">Create</th>
|
||||
<th style="text-align: center; width: 30px">Update</th>
|
||||
<th style="text-align: center; width: 30px">Delete</th>
|
||||
<th style="width: 10px"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="permission in permissions">
|
||||
<tr>
|
||||
<td>
|
||||
<label></label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="read" id="read" value="1"/>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="create" id="create" value="1"/>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="update" id="update" value="1"/>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="delete" id="delete" value="1"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" @click="deleteRow(index)"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<tr>
|
||||
<td style="vertical-align: middle">
|
||||
<input type="text" name="permission" id="permission" />
|
||||
</td>
|
||||
<td style="text-align: center">
|
||||
<input type="checkbox" name="read" id="read" value="1"/>
|
||||
</td>
|
||||
<td style="text-align: center">
|
||||
<input type="checkbox" name="create" id="create" value="1"/>
|
||||
</td>
|
||||
<td style="text-align: center">
|
||||
<input type="checkbox" name="update" id="update" value="1"/>
|
||||
</td>
|
||||
<td style="text-align: center">
|
||||
<input type="checkbox" name="delete" id="delete" value="1"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="icon-trash"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @click="addRow()">Add</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<hr class="margin-top-no" />
|
||||
|
||||
<label class="margin-bottom-small">Document Security</label>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-1"><input name="permission" value="document" type="radio" class="margin-top-no" data-ls-bind="{{project-collection.permission}}" /></div>
|
||||
<div class="col span-1"><input name="documentSecurity" value="false" type="checkbox" class="margin-top-no" data-ls-bind="{{project-collection.documentSecurity}}" /></div>
|
||||
<div class="col span-11">
|
||||
<b>Document Level</b>
|
||||
<p class="text-fade margin-top-tiny">With Document Level permissions, you have granular access control over every document. Users will only be able to access documents for which they have explicit permissions.</p>
|
||||
<p class="text-fade margin-top-tiny">In this permission level, document permissions take precedence and collection permissions are ignored.</p>
|
||||
<b>Enabled</b>
|
||||
<p class="text-fade margin-top-tiny">With Document Security enabled, users will be able to access documents for which they have <i>either</i> Document or Collection permissions.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -584,9 +638,9 @@ $logs = $this->getParam('logs', null);
|
|||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
|
|
|
@ -131,9 +131,8 @@
|
|||
<label for="collection-name">Name</label>
|
||||
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<input type="hidden" id="collection-permission" name="permission" required value="collection" />
|
||||
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-permissions" name="permissions" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-documentSecurity" name="documentSecurity" required data-cast-to="boolean" value="false" />
|
||||
|
||||
<hr />
|
||||
|
||||
|
|
4
public/dist/scripts/app-all.js
vendored
4
public/dist/scripts/app-all.js
vendored
|
@ -4048,7 +4048,7 @@ return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url
|
|||
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;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;console.log(functionAsString);let indexOfArguments=functionAsString.indexOf('(');if(indexOfArguments!==-1){functionAsString=functionAsString.slice(indexOfArguments,-1);}
|
||||
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;let indexOfArguments=functionAsString.indexOf('(');if(indexOfArguments!==-1){functionAsString=functionAsString.slice(indexOfArguments,-1);}
|
||||
functionAsString=functionAsString.replaceAll('={}',"");functionAsString=functionAsString.replaceAll('=[]',"");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;}
|
||||
|
@ -4063,7 +4063,7 @@ running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm
|
|||
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
|
||||
let method=container.path(scope+"."+parsedAction);if(!method){throw new Error('Method "'+scope+"."+parsedAction+'" not found');}
|
||||
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
|
||||
if(Promise.resolve(result)!==result){result=new Promise((resolve,reject)=>{resolve(result);});}
|
||||
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
|
||||
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
|
||||
if(!element){return;}
|
||||
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");if(service){container.set(service.replace(".","-"),data,true,true);}
|
||||
|
|
4
public/dist/scripts/app.js
vendored
4
public/dist/scripts/app.js
vendored
|
@ -713,7 +713,7 @@ return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url
|
|||
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;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;console.log(functionAsString);let indexOfArguments=functionAsString.indexOf('(');if(indexOfArguments!==-1){functionAsString=functionAsString.slice(indexOfArguments,-1);}
|
||||
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;let indexOfArguments=functionAsString.indexOf('(');if(indexOfArguments!==-1){functionAsString=functionAsString.slice(indexOfArguments,-1);}
|
||||
functionAsString=functionAsString.replaceAll('={}',"");functionAsString=functionAsString.replaceAll('=[]',"");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;}
|
||||
|
@ -728,7 +728,7 @@ running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm
|
|||
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
|
||||
let method=container.path(scope+"."+parsedAction);if(!method){throw new Error('Method "'+scope+"."+parsedAction+'" not found');}
|
||||
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
|
||||
if(Promise.resolve(result)!==result){result=new Promise((resolve,reject)=>{resolve(result);});}
|
||||
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
|
||||
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
|
||||
if(!element){return;}
|
||||
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");if(service){container.set(service.replace(".","-"),data,true,true);}
|
||||
|
|
16
public/scripts/permissions-matrix.js
Normal file
16
public/scripts/permissions-matrix.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
(function(window){
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.store('permissions', {
|
||||
_permissions: [],
|
||||
permissions() {
|
||||
return (this._permissions ?? []);
|
||||
},
|
||||
addRow() {
|
||||
|
||||
},
|
||||
deleteRow(index) {
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
})(window);
|
5
public/styles/comps/permissions-matrix.less
Normal file
5
public/styles/comps/permissions-matrix.less
Normal file
|
@ -0,0 +1,5 @@
|
|||
.permissions-matrix {
|
||||
tr {
|
||||
vertical-align: center;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue