Skip to content

Commit

Permalink
Merge pull request #95 from ansibleguy76/release/v4.0.15
Browse files Browse the repository at this point in the history
v4.0.15 into main
  • Loading branch information
ansibleguy76 authored Aug 9, 2023
2 parents 3ccf599 + 6283129 commit 1e990c5
Show file tree
Hide file tree
Showing 18 changed files with 293 additions and 173 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.0.15] - 2023-08-09

### Added

- Installation video to documentation
- add fnGetNumberedName as local function

### Fixed

- Table expression issue fixed

## [4.0.14] - 2023-08-03

### Added
Expand Down Expand Up @@ -559,7 +570,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow change password for current local user
- Start tracking versions

[Unreleased]: https://github.com/ansibleguy76/ansibleforms/compare/4.0.14...HEAD
[Unreleased]: https://github.com/ansibleguy76/ansibleforms/compare/4.0.15...HEAD

[4.0.15]: https://github.com/ansibleguy76/ansibleforms/compare/4.0.14...4.0.15

[4.0.14]: https://github.com/ansibleguy76/ansibleforms/compare/4.0.13...4.0.14

Expand Down
4 changes: 2 additions & 2 deletions app_versions.gradle
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ext.version_code = 40014
ext.version_name = "4.0.14"
ext.version_code = 40015
ext.version_name = "4.0.15"
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "ansible_forms_vue",
"version": "4.0.14",
"version": "4.0.15",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"start": "nodemon --exec 'vue-cli-service serve --mode development'",
"remove": "rm -rdf ./../server/views || exit 0",
"copy": "cp -R dist ../server/views",
"copy": "cp -R dist ../server/views && cp ./../docs/_data/help.yaml ../server",
"bundle": "npm run build && npm run remove && npm run copy",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
Expand Down
105 changes: 6 additions & 99 deletions client/src/components/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -904,14 +904,15 @@
// instead of taking the default value, see if it needs to be evaluated
// allowing dynamic defaults
getDefaultValue(fieldname,value){
if(value!=undefined){
var _value = this.replacePlaceholderInString(value).value
// console.log(`${fieldname} -> ${value} -> ${_value}`)
if(this.fieldOptions[fieldname].evalDefault){
var r=undefined
try{
r=eval(_value)
r=Helpers.evalSandbox(_value)
return r
}catch(e){
console.log(`Error evaluating default value : ${e}`)
Expand Down Expand Up @@ -1301,100 +1302,6 @@
//----------------------------------------------------------------
startDynamicFieldsLoop() {
// this.$toast("Start eval")
function matchRuleShort(str, rule) {
var escapeRegex = (str) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); // eslint-disable-line
return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str); // eslint-disable-line
}
function compareProps(x1,x2,p){
for(let i=0;i<p.length;i++){
const x=p[i]
if(!matchRuleShort(x1[x],x2[x])){
return false
}
}
return true
}
function comparePropsRegex(x1,x2,p){
for(let i=0;i<p.length;i++){
const x=p[i]
if(!x1[x].match(x2[x])){
return false
}
}
return true
}
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
class fnArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
distinctBy(...args) {
return this.filter((a, i) => this.findIndex((s) => compareProps(a,s,args)) === i)
}
filterBy(...args) {
let props=Object.keys(args[0])
return this.filter((x)=>{
return compareProps(x,args[0],props)
})
}
regexBy(...args) {
let props=Object.keys(args[0])
return this.filter((x)=>{
return comparePropsRegex(x,args[0],props)
})
}
selectAttr(...args) {
let props=Object.keys(args[0])
return this.map((x)=>{
let o = {}
for(let i=0;i<props.length;i++){
o[props[i]]=x[args[0][props[i]]]
}
return o
})
}
}
// console.log("invoking field expressions and queries")
var ref=this; // a reference to 'this'
ref.watchdog=0 // a counter how many times we retry to find a value
Expand Down Expand Up @@ -1435,18 +1342,18 @@
// check if direct object attempt
// console.log(placeholderCheck.value)
if(placeholderCheck.value.at(0)=="{" && placeholderCheck.value.at(-1)=="}"){
result=eval(`Object.assign(${placeholderCheck.value})`)
result=Helpers.evalSandbox(`Object.assign(${placeholderCheck.value})`)
}else{
result=eval(placeholderCheck.value)
result=Helpers.evalSandbox(placeholderCheck.value)
}
if(item.type=="expression" || item.type=="html") Vue.set(ref.form, item.name, result);
if((item.type=="query")||(item.type=="enum")) Vue.set(ref.queryresults, item.name, [].concat(result));
// table is special. if external data is passed. we take that instead of results.
if(item.type=="table" && !ref.defaults(item.name)){
if(item.type=="table" && !ref.defaults[item.name]){
Vue.set(ref.form, item.name, [].concat(result));
}
if(item.type=="table" && ref.defaults(item.name)){
if(item.type=="table" && ref.defaults[item.name]){
Vue.set(ref.form, item.name, [].concat(ref.defaults[item.name]));
}
if(placeholderCheck.hasPlaceholders){ // if placeholders were found we set this a variable dynamic field.
Expand Down
154 changes: 154 additions & 0 deletions client/src/lib/Helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,161 @@ var Helpers = {
} else{
return `$(${match})` // return original
}
},
evalSandbox(expression){
// local autonumbering
function fnGetNumberedName(names,pattern,value,fillgap=false){
var nr=null
var nrsequence
var regex
var nrs
var re=new RegExp("[^\#]*(\#+)[^\#]*") // eslint-disable-line
var patternmatch=re.exec(pattern)
if(!names || !Array.isArray(names)){
console.log("fnGetNumberedName, No input or no array")
return value
}
if(patternmatch && patternmatch.length==2){
nrsequence=patternmatch[1]
regex="^" + pattern.replace(nrsequence,"([0-9]{"+nrsequence.length+"})") + "$"
nrs=names.map((item)=>{
var regexp=new RegExp(regex,"g");
var matches=regexp.exec(item)
if(matches && matches.length==2){
return parseInt(matches[1])
}else{
null
}
}).filter((item)=>(item))
var gaps=nrs.reduce(function(acc, cur, ind, arr) {
var diff = cur - arr[ind-1];
if (diff > 1) {
var i = 1;
while (i < diff) {
acc.push(arr[ind-1]+i);
i++;
}
}
return acc;
}, []);
var max=(nrs.length>0)?Math.max(...nrs):null
var gap=(gaps.length>0)?Math.min(...gaps):null
if(max){
nr=max+1
}
if(fillgap && gap){
nr=gap
}
if(nr){
var tmp = pattern.replace(nrsequence,nr.toString().padStart(nrsequence.length,"0"))
return tmp
}else{
console.log("fnGetNumberedName, no pattern matches found in the list")
return value
}
}else{
console.log("fnGetNumberedName, no pattern found, use ### for numbers")
return value
}
}
function matchRuleShort(str, rule) {
var escapeRegex = (str) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); // eslint-disable-line
return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str); // eslint-disable-line
}

function compareProps(x1,x2,p){
for(let i=0;i<p.length;i++){
const x=p[i]

if(!matchRuleShort(x1[x],x2[x])){
return false
}
}
return true
}

function comparePropsRegex(x1,x2,p){
for(let i=0;i<p.length;i++){
const x=p[i]

if(!x1[x].match(x2[x])){
return false
}
}
return true
}

function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}

function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}


class fnArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
distinctBy(...args) {
return this.filter((a, i) => this.findIndex((s) => compareProps(a,s,args)) === i)
}
filterBy(...args) {
let props=Object.keys(args[0])
return this.filter((x)=>{
return compareProps(x,args[0],props)
})
}
regexBy(...args) {
let props=Object.keys(args[0])
return this.filter((x)=>{
return comparePropsRegex(x,args[0],props)
})
}
selectAttr(...args) {
let props=Object.keys(args[0])

return this.map((x)=>{
let o = {}
for(let i=0;i<props.length;i++){
o[props[i]]=x[args[0][props[i]]]
}
return o
})
}
}
return eval(expression)
}


};

export default Helpers
34 changes: 22 additions & 12 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,35 @@ doks:
item_icon: brackets-curly
- item_name: FAQ
item_url: '/faq'
item_icon: square-question
github_url: https://github.com/ansibleguy76
item_icon: square-question
social:
- item_icon: github
item_name: Ansible Forms on Github
item_url: https://github.com/ansibleguy76
- item_icon: docker
item_name: Ansible Forms on Docker Hub
item_url: https://hub.docker.com/r/ansibleguy/ansibleforms
- item_icon: youtube
item_name: Video's about ansible and Ansible Forms
item_url: https://www.youtube.com/@ansibleguy76/videos
footer:
content:
logo:
text:
image: true
copyright: Copyright &copy; 2023. - AnsibleForms <br>All rights reserved.
social_list:
#- network_name: facebook
# profile_url: '#'
#- network_name: twitter
# profile_url: '#'
#- network_name: instagram
# profile_url: '#'
#- network_name: youtube
# profile_url: '#'
social:
- item_icon: github
item_name: Ansible Forms on Github
item_url: https://github.com/ansibleguy76
- item_icon: docker
item_name: Ansible Forms on Docker Hub
item_url: https://hub.docker.com/r/ansibleguy/ansibleforms
- item_icon: youtube
item_name: Video's about ansible and Ansible Forms
item_url: https://www.youtube.com/@ansibleguy76/videos
google_analytics:
tracking_code: # Add your Google Analytics tracking code to activate Google Analytics
tracking_code: G-P2KE4SYQ47
comments:
disqus_forum_shortname: # Add your disqus forum shortname to activate comments

Expand Down
Loading

0 comments on commit 1e990c5

Please sign in to comment.