feat: improve validation errors and loosen up in validation based on user requests
This commit is contained in:
parent
095b7ade2d
commit
b6f6b3fc3a
19
public/js.js
19
public/js.js
|
@ -128,6 +128,14 @@ function populate(){
|
|||
}
|
||||
|
||||
await Promise.all(elems.map(async (el) => {
|
||||
|
||||
console.log({ dataset: el.dataset })
|
||||
if (Object.keys(el.dataset).includes('optional') && ['', undefined, null].includes(el.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const humanName = el.placeholder || el.id || el.dataset?.var || 'ukendt';
|
||||
|
||||
if(el.dataset.is === 'number'){
|
||||
try {
|
||||
const number = parseInt(el.value);
|
||||
|
@ -135,23 +143,23 @@ function populate(){
|
|||
}
|
||||
catch(e) { throw {
|
||||
el: el,
|
||||
name: 'Client-side input validering',
|
||||
name: `Valideringsfejl for feltet '${humanName}'`,
|
||||
message: 'Værdien kunne ikke konverteres til et tal'
|
||||
}; }
|
||||
}
|
||||
else if(el.dataset.is === 'boolean') {
|
||||
if(typeof(el.checked) !== 'boolean') throw {
|
||||
el: el,
|
||||
name: 'Client-side input validering',
|
||||
name: `Valideringsfejl for feltet '${humanName}'`,
|
||||
message: 'Checkboxens værdi er ikke gyldig :S'
|
||||
};
|
||||
addValue(el.dataset.var, el.checked);
|
||||
}
|
||||
else if(el.dataset.is === 'string'){
|
||||
if(typeof(el.value) !== 'string' || el.value === '') throw{
|
||||
if(typeof(el.value) !== 'string' || el.value === '') throw {
|
||||
el: el,
|
||||
name: 'Client-side input validering',
|
||||
message: 'Teksten kunne ikke valideres'
|
||||
name: `Valideringsfejl for feltet '${humanName}'`,
|
||||
message: 'Teksten er tom eller ugyldig'
|
||||
};
|
||||
addValue(el.dataset.var, el.value);
|
||||
}
|
||||
|
@ -165,6 +173,7 @@ function populate(){
|
|||
});
|
||||
}
|
||||
|
||||
// TODO: fix this !
|
||||
function modal_toggle(name){
|
||||
const modal = document.querySelector(`#modal-${name}`);
|
||||
if(modal.className.includes('show')){
|
||||
|
|
|
@ -1 +1 @@
|
|||
var isBool=a=>typeof a=='boolean',isString=a=>typeof a=='string',{keys}=Object,$=str=>{const elems=document.querySelectorAll(str);if(!elems)throw Error(`DOM elem '${str}' not found`);return (elems.length==1)?elems[0]:elems};window.pdfgen={data:{},conf:{disabled:[]}};function merge_obj(obj1,obj2){if(!obj1)return obj2;for(const k of keys(obj2))typeof obj2[k]!=='object'?obj1[k]=obj2[k]:obj1[k]=merge_obj(obj1[k],obj2[k]);return obj1}function error(err){err.name&&err.message?alert(`${err.name}\n${err.message}`):isString((err))&&alert(err);err.el&&typeof err.el=='object'&&document.body.contains(err.el)&&setTimeout(()=>{err.el.focus();err.el.select()},100)}async function cvrapi(el){var cvr=el.value;let resjson=null;if(!/\d{8}/g.test(cvr))return error({el:el,name:'Forkert CVR format',message:' '});var resobj=await fetch(`/api/cvr/${cvr}`);try {resjson=await resobj.json()} catch (e) {return error({el:el,name:'Kunne ikke parse respons body til JSON',message:'Serveren svarede ikke korrekt, skriv gerne en fejlrapport.'})}if(resobj.status==404)return error({el:el,name:'Kunne ikke finde et firma',message:`med CVR-nummer ${cvr}`});if(!resobj.ok)return error({el:el,name:'Server error',message:el.error});return resjson}function format_date(d=new Date()){var is_date=Object.prototype.toString.call(d)=='[object Date]';if(!is_date&&isString(d))try {d=new Date(d)} catch (e) {throw e} else if(!is_date)throw Error('Invalid date!');return`${d.getDate()}/${d.getMonth()+1}/${d.getFullYear()}`}function populate(){return new Promise(async (resolve,reject)=>{let elems=[...document.getElementsByClassName('var')];elems=elems.filter(el=>!window.pdfgen.conf.disabled.includes(el.id));var addValue=(key,val)=>{if(key.includes('.')){const all_keys=[].concat(key.split('.')),keys=key.split('.').reverse();let obj={};obj[keys.shift()]=val;for(const[,k] of keys.entries()){const deep={};deep[k]=obj;obj=deep}window.pdfgen.data=merge_obj(window.pdfgen.data,obj)}else window.pdfgen.data[key]=val};await Promise.all(elems.map(async el=>{if(el.dataset.is=='number')try {var number=parseInt(el.value);addValue(el.dataset.var,number)} catch (e) {throw {el:el,name:'Client-side input validering',message:'Værdien kunne ikke konverteres til et tal'}} else if(el.dataset.is=='boolean'){if(!isBool(el.checked))throw {el:el,name:'Client-side input validering',message:'Checkboxens værdi er ikke gyldig :S'};addValue(el.dataset.var,el.checked)} else if(el.dataset.is=='string'){if(!isString(el.value)||el.value=='')throw {el:el,name:'Client-side input validering',message:'Teksten kunne ikke valideres'};addValue(el.dataset.var,el.value)}})).then(()=>resolve()).catch(e=>{e.el&&(e.el.className+=' vali_err',setTimeout(()=>e.el.className=e.el.className.replaceAll('\ vali_err',''),3800));return reject(e)})})}function modal_toggle(name){var modal=document.querySelector(`#modal-${name}`);modal.className.includes('show')?modal.className=modal.className.replaceAll('\ show',''):modal.className+=' show'}window.addEventListener('DOMContentLoaded',e=>{var inputs=[...document.querySelectorAll('input.var[type="file"]')];inputs.filter(el=>el.dataset.is=='image').forEach(el=>el.addEventListener('change',async evt=>{!window.pdfgen.data.files&&(window.pdfgen.data.files={});let resjson;var data=new FormData();if(!el.files[0])throw {el:el,name:'Client-side input validering',message:'Du mangler at vælge en fil til upload'};data.append('file',el.files[0]);var resobj=await fetch('/pdf/upload/image',{method:'POST',body:data});try {resjson=await resobj.json()} catch (e) {throw {el:el,name:'Kunne ikke parse respons body til JSON',message:'Serveren svarede ikke korrekt, skriv gerne en fejlrapport.'}}if(!resobj.ok){if(!resjson.error)return reject(resjson);throw {el:el,name:'Kunne ikke uploade fil',message:resjson.error}}window.file_reset_timer&&setTimeout(()=>{delete window.pdfgen.data.files[el.dataset.var];if(el.dataset.preview)$(`#${el.dataset.preview}`).innerHTML=''},window.file_reset_timer);if(el.dataset.preview){var preview_container=$(`#${el.dataset.preview}`),preview_img=document.createElement('img');preview_container.innerHTML='';preview_img.className='image_preview';preview_img.src=`file/${resjson.fileid}`;preview_container.appendChild(preview_img)}window.pdfgen.data.files[el.dataset.var]=resjson.fileid}))});
|
||||
var isBool=a=>typeof a=='boolean',isString=a=>typeof a=='string',{keys}=Object,$=str=>{const elems=document.querySelectorAll(str);if(!elems)throw Error(`DOM elem '${str}' not found`);return (elems.length==1)?elems[0]:elems};window.pdfgen={data:{},conf:{disabled:[]}};function merge_obj(obj1,obj2){if(!obj1)return obj2;for(const k of keys(obj2))typeof obj2[k]!=='object'?obj1[k]=obj2[k]:obj1[k]=merge_obj(obj1[k],obj2[k]);return obj1}function error(err){err.name&&err.message?alert(`${err.name}\n${err.message}`):isString((err))&&alert(err);err.el&&typeof err.el=='object'&&document.body.contains(err.el)&&setTimeout(()=>{err.el.focus();err.el.select()},100)}async function cvrapi(el){var cvr=el.value;let resjson=null;if(!/\d{8}/g.test(cvr))return error({el:el,name:'Forkert CVR format',message:' '});var resobj=await fetch(`/api/cvr/${cvr}`);try {resjson=await resobj.json()} catch (e) {return error({el:el,name:'Kunne ikke parse respons body til JSON',message:'Serveren svarede ikke korrekt, skriv gerne en fejlrapport.'})}if(resobj.status==404)return error({el:el,name:'Kunne ikke finde et firma',message:`med CVR-nummer ${cvr}`});if(!resobj.ok)return error({el:el,name:'Server error',message:el.error});return resjson}function format_date(d=new Date()){var is_date=Object.prototype.toString.call(d)=='[object Date]';if(!is_date&&isString(d))try {d=new Date(d)} catch (e) {throw e} else if(!is_date)throw Error('Invalid date!');return`${d.getDate()}/${d.getMonth()+1}/${d.getFullYear()}`}function populate(){return new Promise(async (resolve,reject)=>{let elems=[...document.getElementsByClassName('var')];elems=elems.filter(el=>!window.pdfgen.conf.disabled.includes(el.id));var addValue=(key,val)=>{if(key.includes('.')){const all_keys=[].concat(key.split('.')),keys=key.split('.').reverse();let obj={};obj[keys.shift()]=val;for(const[,k] of keys.entries()){const deep={};deep[k]=obj;obj=deep}window.pdfgen.data=merge_obj(window.pdfgen.data,obj)}else window.pdfgen.data[key]=val};await Promise.all(elems.map(async el=>{if(keys(el.dataset).includes('optional')&&['',void 0,null].includes(el.value))return;var humanName=el.placeholder||el.id||el.dataset?.var||'ukendt';if(el.dataset.is=='number')try {var number=parseInt(el.value);addValue(el.dataset.var,number)} catch (e) {throw {el:el,name:`Valideringsfejl for feltet '${humanName}'`,message:'Værdien kunne ikke konverteres til et tal'}} else if(el.dataset.is=='boolean'){if(!isBool(el.checked))throw {el:el,name:`Valideringsfejl for feltet '${humanName}'`,message:'Checkboxens værdi er ikke gyldig :S'};addValue(el.dataset.var,el.checked)} else if(el.dataset.is=='string'){if(!isString(el.value)||el.value=='')throw {el:el,name:`Valideringsfejl for feltet '${humanName}'`,message:'Teksten er tom eller ugyldig'};addValue(el.dataset.var,el.value)}})).then(()=>resolve()).catch(e=>{e.el&&(e.el.className+=' vali_err',setTimeout(()=>e.el.className=e.el.className.replaceAll('\ vali_err',''),3800));return reject(e)})})}function modal_toggle(name){var modal=document.querySelector(`#modal-${name}`);modal.className.includes('show')?modal.className=modal.className.replaceAll('\ show',''):modal.className+=' show'}window.addEventListener('DOMContentLoaded',e=>{var inputs=[...document.querySelectorAll('input.var[type="file"]')];inputs.filter(el=>el.dataset.is=='image').forEach(el=>el.addEventListener('change',async evt=>{!window.pdfgen.data.files&&(window.pdfgen.data.files={});let resjson;var data=new FormData();if(!el.files[0])throw {el:el,name:'Client-side input validering',message:'Du mangler at vælge en fil til upload'};data.append('file',el.files[0]);var resobj=await fetch('/pdf/upload/image',{method:'POST',body:data});try {resjson=await resobj.json()} catch (e) {throw {el:el,name:'Kunne ikke parse respons body til JSON',message:'Serveren svarede ikke korrekt, skriv gerne en fejlrapport.'}}if(!resobj.ok){if(!resjson.error)return reject(resjson);throw {el:el,name:'Kunne ikke uploade fil',message:resjson.error}}window.file_reset_timer&&setTimeout(()=>{delete window.pdfgen.data.files[el.dataset.var];if(el.dataset.preview)$(`#${el.dataset.preview}`).innerHTML=''},window.file_reset_timer);if(el.dataset.preview){var preview_container=$(`#${el.dataset.preview}`),preview_img=document.createElement('img');preview_container.innerHTML='';preview_img.className='image_preview';preview_img.src=`file/${resjson.fileid}`;preview_container.appendChild(preview_img)}window.pdfgen.data.files[el.dataset.var]=resjson.fileid}))});
|
||||
|
|
|
@ -24,14 +24,16 @@
|
|||
<meta name="twitter:description" content="Simpel, open source faktura pdf generering. Generer en faktura uden at blive overvældet af reklamer der ikke respekterer for dit privatliv.">
|
||||
<meta name="twitter:title" content="FriFaktura.dk · simpel faktura generering, uden reklamer eller dataindsamling.">
|
||||
<%
|
||||
const cssUrl = process.env.NODE_ENV === 'development' ? '/css.css' : '/css.min.css'
|
||||
const cssVersion = 1;
|
||||
const cssUrl = process.env.NODE_ENV === 'development' ? '/css.css' : '/css.min.css?v=${cssVersion}'
|
||||
%>
|
||||
<link rel="stylesheet" type="text/css" href="<%= cssUrl %>" />
|
||||
<script>
|
||||
window.file_reset_timer = <%= locals.file_reset_timer ? file_reset_timer : 0 %>;
|
||||
window.file_reset_timer = <%= locals?.file_reset_timer ? file_reset_timer : 0 %>;
|
||||
</script>
|
||||
<%
|
||||
const jsUrl = process.env.NODE_ENV === 'development' ? '/js.js' : '/js.min.js';
|
||||
const jsVersion = 2;
|
||||
const jsUrl = process.env.NODE_ENV === 'development' ? '/js.js' : `/js.min.js?v=${jsVersion}`;
|
||||
%>
|
||||
<script src="<%= jsUrl %>"></script>
|
||||
<script src="/rain.min.js"></script>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<label>Navn</label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="private_seller_cpr" data-var="seller.cpr" class="var small" type="text" data-is="string" placeholder="Indtast CPR" />
|
||||
<input id="private_seller_cpr" data-var="seller.cpr" class="var small" type="text" data-is="string" data-optional placeholder="Indtast CPR" />
|
||||
</div>
|
||||
<div class="doublecell">
|
||||
<input style="width: 100%" id="private_seller_name" data-var="seller.name" class="var small" type="text" data-is="string" placeholder="Indtast navn" />
|
||||
|
@ -193,10 +193,10 @@
|
|||
<div></div>
|
||||
<div></div>
|
||||
<div>
|
||||
<input class="var small" type="text" data-var="accountno" data-is="string" value="12312312" />
|
||||
<input class="var small" type="text" data-var="accountno" data-is="string" data-optional value="12312312" />
|
||||
</div>
|
||||
<div>
|
||||
<input class="var small" type="text" data-var="regno" data-is="string" value="1234" />
|
||||
<input class="var small" type="text" data-var="regno" data-is="string" data-optional value="1234" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -474,7 +474,7 @@
|
|||
$('#submit').addEventListener('click', async (event) => {
|
||||
|
||||
// validate stuff manually put in window.pdfgen.data from js in this template file
|
||||
if(!Array.isArray(window.pdfgen.data.work) || !window.pdfgen.data.work.length) {
|
||||
if (!Array.isArray(window.pdfgen.data.work) || !window.pdfgen.data.work.length) {
|
||||
return error({
|
||||
el: document.getElementById('work_desc'),
|
||||
name: 'Du mangler at tilføje produkt eller service',
|
||||
|
@ -482,7 +482,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if(typeof(window.pdfgen.data.seller) !== 'object') {
|
||||
if (typeof(window.pdfgen.data.seller) !== 'object') {
|
||||
return error({
|
||||
el: document.getElementById('seller_cvr_input'),
|
||||
name: 'Du mangler at indtaste dit firmas oplysninger',
|
||||
|
@ -490,7 +490,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if(typeof(window.pdfgen.data.buyer) !== 'object') {
|
||||
if (typeof(window.pdfgen.data.buyer) !== 'object') {
|
||||
let el = null;
|
||||
if(Array.isArray(window.pdfgen.conf.disabled)){
|
||||
if(window.pdfgen.conf.disabled.length) {
|
||||
|
|
|
@ -13,6 +13,17 @@ function hasLogo(){
|
|||
return (locals.files && locals.files.logo);
|
||||
}
|
||||
|
||||
function accountInfo() {
|
||||
const result = '';
|
||||
if (typeof locals?.accountno === 'number') {
|
||||
result += `& & \\textbf{Konto nr.:} & ${locals.accountno} \\\\\n`;
|
||||
}
|
||||
if (typeof locals?.regno === 'number') {
|
||||
result += `& & \\textbf{Reg nr.:} & ${locals.regno} \\\\n`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
%>\documentclass[a4paper]{article}
|
||||
|
||||
\usepackage{fancyhdr, graphicx, tabularx, changepage, multicol, array}
|
||||
|
@ -58,8 +69,7 @@ function hasLogo(){
|
|||
<%- buyer["name"] %> & & \textbf{Fakturanummer:} & <%= invoiceno %> \\
|
||||
<%- buyer["address"] %>, <%- buyer["zipcode"] %> <%- buyer["city"] %> & & \textbf{Fakturadato:} & <%= sent_date %> \\
|
||||
<%= locals.buyer['vat'] ? 'CVR ' + buyer['vat'] + ' ' : '' %>& & \textbf{Forfaldsdato:} & <%= pay_date %> \\
|
||||
& & \textbf{Konto nr.:} & <%= accountno %> \\
|
||||
& & \textbf{Reg nr.:} & <%= regno %> \\ \\ \\ \\
|
||||
<%- accountInfo() %> \\ \\ \\
|
||||
|
||||
\textbf{\textsf{Beskrivelse}} & \textbf{\textsf{Antal}} & \textbf{\textsf{Pris}} & \textbf{\textsf{Sum}} \\
|
||||
\hline \\
|
||||
|
|
Loading…
Reference in New Issue