foxxy
Version:
Foxx framework based on RiotJS + ArangoDB/Foxx
457 lines (410 loc) • 18 kB
JavaScript
var Common = {
init: function init(){
$.fn.serializeObject = function() {
var o = {}
var a = this.serializeArray()
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]]
}
o[this.name].push(this.value || '')
} else {
o[this.name] = this.value || ''
}
})
return o
}
},
startEditor: function(name, mode, id) {
console.log("Editor", name)
var editor = ace.edit(name)
editor.getSession().setMode(mode)
editor.setOptions({
maxLines: Infinity,
//enableEmmet: mode == "ace/mode/html",
theme: 'ace/theme/twilight',
tabSize: 2, useSoftTabs: true
})
editor.getSession().setUseWrapMode(true)
editor.getSession().setValue(unescape($("#"+id).val()))
editor.getSession().on('change', function(){ $("#"+id).val(editor.getSession().getValue()); })
return editor;
},
buildForm: function buildForm(obj, fields, formId, back_str, callback) {
var html = ""
var uploads = []
var _this = this
var editors = []
var values = []
var positions = []
var wysiwygs = []
var html_editors = []
var usetab = false
var tabs = []
var tab_last_id = ''
var y = 0
var _html = ''
fields.forEach(function(l, i) {
if (l.tab) {
if (y > 0) html += "</div>"
if (usetab == false) html += '<ul uk-tab>'
if (usetab == false) tabs = []
usetab = true
html += '<li><a href="#">' + l.tab + '</a></li>'
if (html != '') {
tabs.push(_html)
_html = ''
}
tab_last_id = l.id
y = 0
} else {
if (l.h !== undefined) {
_html += '<div class="uk-grid uk-grid-small uk-margin-top"><h3>'+ l.h +'</h3></div>'
}
else {
if (l.r && y > 0) _html += '</div>'
if (l.r) _html += '<div class="uk-grid uk-grid-small">'
if (l.c && l.c.indexOf("uk-width") == -1) l.c = "uk-width-" + l.c
var validation = l.j
if (obj['_key'] && l.ju) validation = l.ju
var hidden = ''
if(l.t === 'hidden') hidden = 'uk-hidden'
_html += '<div class="'+ l.c + ' ' + hidden +'">'
var title = l.l
if (_.isString(validation)) {
if (validation.indexOf('required') > 0) {
title = "<strong>" + title + "*</strong>"
}
} else {
if (validation && validation._flags.presence === "required") {
title = "<strong>" + title + "*</strong>"
}
}
if(!((l.t === "file" || l.t === "image") && obj._id === undefined))
_html += '<label for="" class="uk-form-label">'+ title +'</label>'
var value = obj[l.n]
if(l.tr && obj[l.n]) value = obj[l.n][window.localStorage.getItem('foxx-locale')]
if (value === undefined) value = ""
//value = escape(value)
if(l.t.match(/string/)) {
_html += '<input type="'+(l.t.split(":").length == 2 ? l.t.split(":")[1] : "text")+'" id="'+l.n+'" class="uk-input" name="'+ l.n +'" value="" autocomplete="off"><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
values.push([l.n, value])
}
if(l.t.match(/password/)) {
_html += '<input type="password" id="'+l.n+'" class="uk-input" name="'+ l.n +'" value="" autocomplete="off"><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
}
if(l.t === "integer") {
_html += '<input type="number" id="'+l.n+'" class="uk-input" name="'+ l.n +'" value="'+value+'" autocomplete="off"><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
values.push([l.n, value])
}
if(l.t === "float") {
_html += '<input type="text" id="'+l.n+'" class="uk-input" name="'+ l.n +'" value="'+value+'" autocomplete="off"><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
values.push([l.n, value])
}
if(l.t === "hidden") _html += '<input type="hidden" id="'+l.n+'" name="'+ l.n +'" value="'+value+'"></div><div data-hint="'+ l.n +'">'
if(l.t === "date") _html += '<div><div class="uk-inline"><span class="uk-form-icon" uk-icon="icon: calendar"></span><input type="date" id="'+l.n+'" data-date-format="YYYY/MM/DD" class="uk-input" name="'+ l.n +'" value="'+value+'"></div><div data-hint="'+ l.n +'" class="uk-text-danger"></div></div>'
if(l.t === "time") _html += '<div><div class="uk-inline"><span class="uk-form-icon" uk-icon="icon: calendar"></span><input type="time" id="'+l.n+'" class="uk-input" name="'+ l.n +'" value="'+value+'"></div><div data-hint="'+ l.n +'" class="uk-text-danger"></div></div>'
if(l.t === "text") _html += '<textarea id="'+l.n+'" class="uk-textarea" name="'+ l.n +'" style="'+l.s+'">'+ value +'</textarea><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
if(l.t === "wysiwyg") {
wysiwygs.push(l.n)
_html += '<div id="wysiwyg_'+l.n+'"></div><input type="hidden" id="'+l.n+'" name="'+ l.n +'" value="" /><div data-hint="'+ l.n +'" class="uk-text-danger"></div>'
values.push([l.n, value])
}
if(l.t.match(/^code/)) {
_html += '<input type="hidden" id="'+l.n+'" name="'+ l.n +'" value="">'
values.push([l.n, value])
_html += '<div id="editor_'+l.n+'" class="editor" style="'+l.s+'"></div>'
editors.push(["editor_"+l.n, "ace/mode/" + l.t.split(":")[1], l.n])
}
if (l.t == 'html') {
_html += '<input type="hidden" id="'+l.n+'" name="'+ l.n +'" value="">'
_html += '<div id="html_editor_'+l.n+'" data-name="'+l.n+'" class="html_editor" style="'+l.s+'"></div>'
html_editors.push([l.n, value])
}
if(l.t === "list") {
_html += '<select name="'+ l.n +'" style="width:100%" class="uk-select select_list" id="'+l.n+'">'
l.d.forEach(function(o) {
selected = ""
if(value === o[0]) selected="selected='selected'"
_html += '<option value="'+ o[0] +'" '+selected+'>'+ o[1] +'</option>'
})
_html += '</select>'
}
if(l.t === "multilist") {
_html += '<select name="'+ l.n +'" style="width:100%" class="uk-select select_mlist" multiple="multiple" id="'+l.n+'">'
l.d.forEach(function(o) {
selected = ""
if(value && value.indexOf(o[0]) >= 0) selected="selected='selected'"
_html += '<option value="'+ o[0] +'" '+selected+'>'+ o[1] +'</option>'
})
_html += '</select>'
}
if(l.t === "tags") {
_html +='<select name="'+l.n+'" style="width:100%" class="select_tag" multiple="multiple">'
var tags = l.d[0]
if(l.tr) tags = _.flatten(_.compact(_.map(l.d[0], function(t) { return t[window.localStorage.getItem('foxx-locale')]})))
tags = _.filter(tags, function(t) { return t != "undefined" })
_.uniq(tags).forEach(function(v) {
if(v != 'undefined' || v != '') {
selected = ""
if(value && value.indexOf(v) >= 0) selected="selected='selected'"
_html += '<option value="'+ v +'" '+selected+'>'+ v +'</option>'
}
})
_html +='</select>'
}
if(l.t === "map") {
if(value === "") value = [0,0]
_html += '<div class="uk-text-center" id="'+l.n+'_infos"><span class="uk-label"></span></div>'
_html += '<div id="map_'+l.n+'" class="map" style="'+l.s+'"></div>'
_html += '<input id="'+l.n+'_lat" type="hidden" name="'+l.n+'" value="'+value[0]+'" />'
_html += '<input id="'+l.n+'_lng" type="hidden" name="'+l.n+'" value="'+value[1]+'" />'
positions.push([l.n, value])
}
if(l.t === "image" && obj._id) {
_html += '<div id="upload-drop_'+l.n+'" class="js-upload uk-placeholder uk-text-center">'
_html += ' <span uk-icon="icon: cloud-upload"></span>'
_html += ' <span class="uk-text-middle">Attach images by dropping them here or</span>'
_html += ' <div uk-form-custom>'
_html += ' <input type="file" multiple>'
_html += ' <span class="uk-link">selecting one</span>'
_html += ' </div>'
_html += '</div>'
_html += '<progress id="progressbar_'+l.n+'" class="uk-progress" value="0" max="100" hidden></progress>'
_html += '<images i18n="'+l.tr+'" field="'+l.n+'" id="'+obj._id+'" />'
uploads.push([obj._key, obj._id.split('/')[0], l.n, '*.(jpg|jpeg|gif|png)', 'progressbar_'+l.n, '#upload-drop_'+l.n, l.tr])
}
if(l.t === "file" && obj._id) {
_html += '<div id="upload-drop_'+l.n+'" class="js-upload uk-placeholder uk-text-center">'
_html += ' <span uk-icon="icon: cloud-upload"></span>'
_html += ' <span class="uk-text-middle">Attach binaries by dropping them here or</span>'
_html += ' <div uk-form-custom>'
_html += ' <input type="file" multiple>'
_html += ' <span class="uk-link">selecting one</span>'
_html += ' </div>'
_html += '</div>'
_html += '<progress id="progressbar_'+l.n+'" class="uk-progress" value="0" max="100" hidden></progress>'
_html += '<files i18n="'+l.tr+'" field="'+l.n+'" id="'+obj._id+'" />'
uploads.push([obj._key, obj._id.split('/')[0], l.n, '*.*', 'progressbar_'+l.n, '#upload-drop_'+l.n, l.tr])
}
if(l.t === "boolean") {
var checked = obj[l.n] === true ? " checked='checked' " : ''
_html += ' <input name="'+ l.n +'" '+ checked +' class="uk-checkbox" type="checkbox" value="1" /> '
}
_html += '</div>'
if (!usetab) {
html += _html
_html = ''
}
if (l.endtab == true) {
if (html != '') tabs.push(_html)
_html = ''
usetab = false
html += '</ul><ul class="uk-switcher">{{'+tab_last_id+'}}</ul>'
}
y++
}
}
})
html += '</div>'
if (tabs.length > 0) {
var switcher = ""
_.each(tabs, function (t) { if (t!='') switcher += "<li>" + t + "</li>" })
html = html.replace('{{'+ tab_last_id +'}}', switcher)
}
html += '<hr><div class="uk-grid uk-grid-small uk-text-right"><div class="uk-width-1-1">'
if (back_str != undefined) {
html += '<a href="#'+ back_str +'" class="uk-button">Back</a> '
}
html += '<input type="submit" class="uk-button uk-button-primary" value="Save" /></div></div><hr>'
$(formId).html(html)
values.forEach(function(v, i) {
$(formId+" #" + v[0]).val(v[1])
})
html_editors.forEach(function (e, i) {
$('#html_editor_' + e[0]).contentEditor({ value: e[1].html || '' })
$("#" + e[0]).val(JSON.stringify(e[1]))
})
editors.forEach(function(e, i) {
_this.startEditor(e[0], e[1], e[2])
})
wysiwygs.forEach(function(e, i) {
const editor = pell.init({
element: document.getElementById("wysiwyg_"+e),
onChange: function(html) { $("#"+e).val(html) }
})
editor.content.innerHTML = $("#"+e).val()
})
$("button").attr("type", "button") // TODO : remove once Pell accept PR
positions.forEach(function(p, i) {
var mymap = L.map('map_' + p[0], { dragging: true, tap: false}).setView(p[1], 6)
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 20,
ext: 'png',
}).addTo(mymap)
mymap.scrollWheelZoom.disable()
var marker = L.marker(p[1], { draggable: true }).addTo(mymap)
$('#'+p[0]+'_infos span').html(p[1].join(', '))
marker.on('dragend', function(data) {
var coords = data.target.getLatLng()
$('#'+p[0]+'_lat').val(coords.lat)
$('#'+p[0]+'_lng').val(coords.lng)
$('#'+p[0]+'_infos span').html([coords.lat, coords.lng].join(', '))
})
})
var _this = this
uploads.forEach(function(u) {
_this.prepare_upload(u[0], u[1], u[2], u[3], u[4], u[5], u[6])
})
riot.mount("images"); riot.mount("files")
riot.update()
if(callback !== undefined) {
callback()
}
},
checkLogin: function checkLogin() {
this.ajax(url + "auth/whoami", "GET", "", function(d) {
if(d.username === null) document.location.href = "login.html";
})
},
saveForm: function (formID, path, objID, opts) {
objID = objID||""
opts = opts||{}
var _this = this
var json = $("#"+ formID).serializeObject()
_.each(json, function(v, k) { if(k.split('-')[0] == "trumbowyg") delete json[k] })
$('.select_tag, .select_mlist').each(function(i, st) {
if(typeof json[$(st).attr("name")] === "string") {
json[$(st).attr("name")] = [ json[$(st).attr("name")] ]
}
})
$("div[data-hint]").html("")
var selector = "#" + formID + " textarea, #"+ formID + " input, #"+ formID + " select"
$(selector).removeClass("uk-form-danger")
$(selector).removeClass("uk-form-success")
$(selector).addClass("uk-form-success")
_this.ajax(url + path + "/" + objID, "POST", JSON.stringify(json), function(d) {
if(d.errors.length > 0) {
d.errors.forEach(function(e) {
$("#" + e.path).removeClass("uk-form-success")
$("#" + e.path).addClass("uk-form-danger")
$("div[data-hint="+e.path+"]").html("<div>"+e.message.replace(/"(.*)"/, '').trim()+"</div>")
})
} else {
UIkit.notification({
message : 'Successfully saved!',
status : 'success',
timeout : 1000,
pos : 'bottom-right'
});
if(objID == "" && _.isEmpty(opts)) {
objID = d.data._key
if(path.split('/')[0] != 'datasets')
path = path.split("/").length == 2 ? path.split("/")[1] : path
route("/"+ path +"/" + objID + "/edit")
}
if(!_.isEmpty(opts)) {
riot.mount("#"+opts.id, _.last(formID.split("_")) + "_crud_index", opts)
}
}
setTimeout(function() {
$(selector).removeClass("uk-form-success")
}, 300 )
})
},
ajax: function(url, method, dataForm, callback, errorCallback) {
if(typeof(errorCallback) === "undefined") errorCallback = function() {}
$.ajax({
url: url,
data: dataForm || "",
type: method,
beforeSend: function(xhr){
var x = localStorage.getItem('X-Session-Id')
if(x !== null) {
xhr.setRequestHeader('foxx-locale', localStorage.getItem('foxx-locale'))
xhr.setRequestHeader('X-Session-Id', localStorage.getItem('X-Session-Id'))
}
},
success: function(data, textStatus, request) {
if(request.getResponseHeader('X-Session-Id'))
localStorage.setItem('X-Session-Id',request.getResponseHeader('X-Session-Id'))
callback(data)
},
statusCode: {
401: function() { document.location.href = "login.html" },
500: errorCallback(),
503: function() {
localStorage.removeItem('X-Session-Id')
localStorage.removeItem('foxx-locale')
document.location.href = "login.html"
}
}
});
},
get: function(url, callback, errorCallback) {
this.ajax(url, "GET", "", callback, errorCallback)
},
delete: function(url, callback, errorCallback) {
this.ajax(url, "DELETE", "", callback, errorCallback)
},
post: function(url, json, callback, errorCallback) {
this.ajax(url, "POST", json, callback, errorCallback)
},
patch: function(url, json, callback, errorCallback) {
this.ajax(url, "PATCH", json, callback, errorCallback)
},
put: function(url, json, callback, errorCallback) {
this.ajax(url, "PUT", json, callback, errorCallback)
},
array_diff: function(a, b) {
return a.filter(function(i) {return b.indexOf(i) < 0;});
},
keys: function(h) {
var keys = []
for(var k in h) keys.push(k)
return keys
},
prepare_upload: function(key, collection, field, filter, progressbar_id, drop_id, i18n) {
var bar = document.getElementById(progressbar_id);
UIkit.upload(drop_id, {
url: url + '/uploads/' + key + '/' + collection + '/' + field, // upload url,
multiple: true,
allow: filter,
error: function () {
console.log('error', arguments);
},
beforeSend: function(env) {
env.headers = {
'X-Session-Id': localStorage.getItem('X-Session-Id'),
'foxx-locale': i18n == true ? localStorage.getItem('foxx-locale') : null
}
},
loadStart: function (e) {
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function () {
bar.value = 100;
setTimeout(function(){
bar.setAttribute('hidden', null);
riot.mount("images"); riot.mount("files")
riot.update()
}, 250);
}
});
}
};
module.exports = Common;