diff --git a/lib/schema.js b/lib/schema.js index b2f6e45..7d54b66 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -3,7 +3,7 @@ const fs = require('fs'); const moment = require('moment'); const glob = require('glob'); const Ajv = require('ajv'); -const ajv = new Ajv(); +const ajv = new Ajv({ allErrors: true, jsonPointers: true }); const addSchemas = () => { const schemaFiles = glob.sync('./lib/**/*.json'); @@ -28,12 +28,18 @@ const addSchemas = () => { }); ajv.addKeyword('isNotEmpty', { - type: 'string', - validate: (schema, data) => { - return typeof data === 'string' && data.trim() !== ''; + validate: function validate(schema, data){ + const result = typeof data === 'string' && data.trim() !== ''; + if(!result){ + console.log('result', result); + validate.errors = [{ keyword: 'isNotEmpty', message: 'Cannot be an empty string', params: { keyword: 'isNotEmpty' } }]; + } + return result; }, - errors: false + errors: true }); + + require('ajv-errors')(ajv); }; const validateJson = (schema, json) => { diff --git a/lib/schemas/editProduct.json b/lib/schemas/editProduct.json index 3e11583..0e8033c 100644 --- a/lib/schemas/editProduct.json +++ b/lib/schemas/editProduct.json @@ -6,17 +6,23 @@ "type": "string" }, "productPermalink": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 2 }, "productTitle": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 5 }, "productPrice": { "type": "string", "format": "amount" }, "productDescription": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 25 }, "productPublished": { "type": "boolean" @@ -34,6 +40,14 @@ "type": ["number", "null"] } }, + "errorMessage": { + "isNotEmpty": "This is my custom error message", + "properties": { + "productPrice": "Should be a full 2 decimal value. Eg: 10.99", + "productPublished": "Should be either true or false", + "productComment": "Should be either true or false" + } + }, "required": [ "productId" ] diff --git a/lib/schemas/newProduct.json b/lib/schemas/newProduct.json index 4cb3556..8183105 100644 --- a/lib/schemas/newProduct.json +++ b/lib/schemas/newProduct.json @@ -3,17 +3,23 @@ "type": "object", "properties": { "productPermalink": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 2 }, "productTitle": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 5 }, "productPrice": { "type": "string", "format": "amount" }, "productDescription": { - "type": "string" + "type": "string", + "isNotEmpty": true, + "minLength": 25 }, "productPublished": { "type": "boolean" @@ -31,6 +37,13 @@ "type": ["number", "null"] } }, + "errorMessage": { + "properties": { + "productPrice": "Should be a full 2 decimal value. Eg: 10.99", + "productPublished": "Should be either true or false", + "productComment": "Should be either true or false" + } + }, "required": [ "productPermalink", "productTitle", diff --git a/package-lock.json b/package-lock.json index 00fe407..a692e45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -610,6 +610,11 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, "align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", @@ -1377,7 +1382,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -4046,7 +4052,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -10137,7 +10144,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } diff --git a/package.json b/package.json index 08e0542..a83d687 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "@adyen/api-library": "^2.1.7", "ajv": "^6.10.2", + "ajv-errors": "^1.0.1", "async": "^2.6.3", "axios": "^0.19.0", "bcryptjs": "^2.4.3", diff --git a/public/javascripts/admin.js b/public/javascripts/admin.js index 3f8a417..d75ebf7 100644 --- a/public/javascripts/admin.js +++ b/public/javascripts/admin.js @@ -218,6 +218,12 @@ $(document).ready(function (){ showNotification(msg.message, 'success', false, '/admin/product/edit/' + msg.productId); }) .fail(function(msg){ + if(msg.responseJSON.length > 0){ + var errorMessages = validationErrors(msg.responseJSON); + $('#validationModalBody').html(errorMessages); + $('#validationModal').modal('show'); + return; + } showNotification(msg.responseJSON.message, 'danger'); }); } @@ -250,6 +256,13 @@ $(document).ready(function (){ showNotification(msg.message, 'success', true); }) .fail(function(msg){ + if(msg.responseJSON.length > 0){ + var errorMessages = validationErrors(msg.responseJSON); + console.log('errorMessages', errorMessages); + $('#validationModalBody').html(errorMessages); + $('#validationModal').modal('show'); + return; + } showNotification(msg.responseJSON.message, 'danger'); }); } @@ -842,3 +855,11 @@ function globalSearch(){ feather.replace(); }); } + +function validationErrors(errors){ + var errorMessage = ''; + errors.forEach((value) => { + errorMessage += `

${value.dataPath.replace('/', '')} - ${value.message}

`; + }); + return errorMessage; +} diff --git a/public/javascripts/admin.min.js b/public/javascripts/admin.min.js index ad7bb17..27f4cd3 100644 --- a/public/javascripts/admin.min.js +++ b/public/javascripts/admin.min.js @@ -1 +1 @@ -function globalSearch(){$("#global-search-results").empty(),$.ajax({type:"POST",url:"/admin/searchall",data:{searchValue:$("#global-search-value").val()}}).done(e=>{$("#global-search").html('');let t=!1;if(e.customers.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Customer
    \n
    ${e.firstName} ${e.lastName}
    \n
    ${e.email}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.orders.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Order
    \n
    ${e.orderFirstname} ${e.orderLastname}
    \n
    ${moment(e.orderDate).format("YYYY/MM/DD")}
    \n
    ${e.orderEmail}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.products.forEach(e=>{t=!0;const a=`
  • \n
    \n
    Product
    \n
    ${e.productTitle}
    \n
    ${$("#currencySymbol").val()}${numeral(e.productPrice).format("0.00")}
    \n
    \n
  • `;$("#global-search-results").append(a)}),!0===t)$("#global-search-results").removeClass("invisible");else{const e='
  • \n
    \n
    Nothing found
    \n
    \n
  • ';$("#global-search-results").append(e),$("#global-search-results").removeClass("invisible")}feather.replace()})}$(document).ready(function(){if($.ajaxSetup({headers:{"csrf-token":$('meta[name="csrfToken"]').attr("content")}}),$(document).on("click","#btnGenerateAPIkey",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(e){$("#apiKey").val(e.apiKey),showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(e){e.preventDefault();var t=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:t}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(e){e.preventDefault();var t=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),i=$("#product_optOptions").val(),s={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(s=JSON.parse($("#productOptions").val()));var n='
  • ';n+='
    ',n+='
    '+t+"
    ",n+='
    '+a+"
    ",n+='
    '+o+"
    ",n+='
    '+i+"
    ",n+='
    ',n+='',n+="
  • ",$("#product_opt_wrapper").append(n),s[t]={optName:t,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(e){return 0===e||e})},$("#productOptions").val(JSON.stringify(s)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$(document).on("click","#btnSettingsUpdate",function(e){$("#settingsForm").submit()}),$("#settingsForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(document).on("click","#orderStatusUpdate",function(e){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserAdd",function(e){$("#userNewForm").submit()}),$("#userNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/insert",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/user/edit/"+e.userId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".userDelete").on("click",function(){confirm("Are you sure you want to delete?")&&$.ajax({method:"POST",url:"/admin/user/delete",data:{userId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserEdit",function(e){$("#userEditForm").submit()}),$("#userEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/update",data:{userId:$("#userId").val(),usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val(),userAdmin:$("#userPassword").is(":checked")}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/insert",data:{productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/product/edit/"+e.productId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/update",data:{productId:$("#productId").val(),productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){confirm("Are you sure you want to delete this image?")&&$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-product").on("click",function(){confirm("Are you sure you want to delete this product?")&&$.ajax({method:"POST",url:"/admin/product/delete",data:{productId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#validatePermalink",function(e){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/validatePermalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(e){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(e){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(e){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#lookupCustomer",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/customer/lookup",data:{customerEmail:$("#customerEmail").val()}}).done(function(e){showNotification(e.message,"success"),$("#orderFirstName").val(e.customer.firstName),$("#orderLastName").val(e.customer.lastName),$("#orderAddress1").val(e.customer.address1),$("#orderAddress2").val(e.customer.address2),$("#orderCountry").val(e.customer.country),$("#orderState").val(e.customer.state),$("#orderPostcode").val(e.customer.postcode),$("#orderPhone").val(e.customer.phone)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#orderCreate",function(e){e.preventDefault(),0===$("#createOrderForm").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/order/create",data:{orderStatus:$("#orderStatus").val(),email:$("#customerEmail").val(),firstName:$("#orderFirstName").val(),lastName:$("#orderLastName").val(),address1:$("#orderAddress1").val(),address2:$("#orderAddress2").val(),country:$("#orderCountry").val(),state:$("#orderState").val(),postcode:$("#orderPostcode").val(),phone:$("#orderPhone").val(),orderComment:$("#orderComment").val()}}).done(function(e){showNotification(e.message,"success"),window.location=`/admin/order/view/${e.orderId}`}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#sendTestEmail").on("click",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(e){showNotification(e,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".orderFilterByStatus",function(e){e.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$('input[class="publishedState"]').change(function(){$.ajax({method:"POST",url:"/admin/product/publishedState",data:{id:this.id,state:this.checked}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#updateCustomer").validator().on("click",function(e){e.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/customer/update",data:{customerId:$("#customerId").val(),email:$("#email").val(),firstName:$("#firstName").val(),lastName:$("#lastName").val(),address1:$("#address1").val(),address2:$("#address2").val(),country:$("#country").val(),state:$("#state").val(),postcode:$("#postcode").val(),phone:$("#phone").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#deleteCustomer").on("click",function(e){e.preventDefault(),$.ajax({method:"DELETE",url:"/admin/customer",data:{customerId:$("#customerId").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/customers")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#footerHtml").length){var e=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});e.setValue(e.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var t=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(t.getValue(),{indent:" ",autosemicolon:!0});t.setValue(a)}$(document).on("click","#btnPageUpdate",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/page",data:{pageId:$("#pageId").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnPageDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/page/delete",data:{pageId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#discountNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/create",data:{code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/settings/discount/edit/"+e.discountId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/update",data:{discountId:$("#discountId").val(),code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountStart").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM",showOtherMonths:!0}),$("#discountEnd").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM"}),$(document).on("click","#btnDiscountDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"DELETE",url:"/admin/settings/discount/delete",data:{discountId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-new",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/menu/new",data:{navMenu:$("#newNavMenu").val(),navLink:$("#newNavLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-update",function(e){e.preventDefault();var t=$(this).attr("data-id"),a=$("#menuId-"+t);$.ajax({method:"POST",url:"/admin/settings/menu/update",data:{navId:a.find(".navId").val(),navMenu:a.find(".navMenu").val(),navLink:a.find(".navLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click",".settings-menu-delete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/menu/delete",data:{menuId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#draggable_list").length&&$("#draggable_list").sortable({update:function(){var e=[];$(".navId").each(function(t){e.push($($(".navId")[t]).val())}),$.ajax({data:{order:e},type:"POST",url:"/admin/settings/menu/saveOrder"}).done(function(){showNotification("Menu order saved","success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger",!0)})}}),$(document).on("click","#uploadButton",function(e){e.preventDefault();var t=new FormData($("#uploadForm")[0]);t.append("productId",$("#productId").val()),$.ajax({method:"POST",url:"/admin/file/upload",processData:!1,contentType:!1,cache:!1,data:t}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#global-search-value").on("keyup",e=>{""===$("#global-search-value").val()&&($("#global-search-results").empty(),$("#global-search-results").addClass("invisible"));let t=3;/^\d*\.?\d*$/.test($("#global-search-value").val())&&(t=1),$("#global-search-value").val().length>t&&($("#global-search").html(''),globalSearch())}),$("#globalSearchModal").on("shown.bs.modal",function(){$("#global-search-value").focus()}),$("body").on("click",".gr-click",e=>{$("#global-search-value").val();const t=$(e.currentTarget).closest(".global-result").attr("data-url");t&&(window.location=t)})}); \ No newline at end of file +function globalSearch(){$("#global-search-results").empty(),$.ajax({type:"POST",url:"/admin/searchall",data:{searchValue:$("#global-search-value").val()}}).done(e=>{$("#global-search").html('');let t=!1;if(e.customers.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Customer
    \n
    ${e.firstName} ${e.lastName}
    \n
    ${e.email}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.orders.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Order
    \n
    ${e.orderFirstname} ${e.orderLastname}
    \n
    ${moment(e.orderDate).format("YYYY/MM/DD")}
    \n
    ${e.orderEmail}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.products.forEach(e=>{t=!0;const a=`
  • \n
    \n
    Product
    \n
    ${e.productTitle}
    \n
    ${$("#currencySymbol").val()}${numeral(e.productPrice).format("0.00")}
    \n
    \n
  • `;$("#global-search-results").append(a)}),!0===t)$("#global-search-results").removeClass("invisible");else{const e='
  • \n
    \n
    Nothing found
    \n
    \n
  • ';$("#global-search-results").append(e),$("#global-search-results").removeClass("invisible")}feather.replace()})}function validationErrors(e){var t="";return e.forEach(e=>{t+=`

    ${e.dataPath.replace("/","")} - ${e.message}

    `}),t}$(document).ready(function(){if($.ajaxSetup({headers:{"csrf-token":$('meta[name="csrfToken"]').attr("content")}}),$(document).on("click","#btnGenerateAPIkey",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(e){$("#apiKey").val(e.apiKey),showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(e){e.preventDefault();var t=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:t}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(e){e.preventDefault();var t=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),s=$("#product_optOptions").val(),i={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(i=JSON.parse($("#productOptions").val()));var n='
  • ';n+='
    ',n+='
    '+t+"
    ",n+='
    '+a+"
    ",n+='
    '+o+"
    ",n+='
    '+s+"
    ",n+='
    ',n+='',n+="
  • ",$("#product_opt_wrapper").append(n),i[t]={optName:t,optLabel:a,optType:o,optOptions:$.grep(s.split(","),function(e){return 0===e||e})},$("#productOptions").val(JSON.stringify(i)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$(document).on("click","#btnSettingsUpdate",function(e){$("#settingsForm").submit()}),$("#settingsForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(document).on("click","#orderStatusUpdate",function(e){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserAdd",function(e){$("#userNewForm").submit()}),$("#userNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/insert",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/user/edit/"+e.userId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".userDelete").on("click",function(){confirm("Are you sure you want to delete?")&&$.ajax({method:"POST",url:"/admin/user/delete",data:{userId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserEdit",function(e){$("#userEditForm").submit()}),$("#userEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/update",data:{userId:$("#userId").val(),usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val(),userAdmin:$("#userPassword").is(":checked")}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/insert",data:{productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/product/edit/"+e.productId)}).fail(function(e){if(e.responseJSON.length>0){var t=validationErrors(e.responseJSON);return $("#validationModalBody").html(t),void $("#validationModal").modal("show")}showNotification(e.responseJSON.message,"danger")}))}),$("#productEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/update",data:{productId:$("#productId").val(),productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){if(e.responseJSON.length>0){var t=validationErrors(e.responseJSON);return console.log("errorMessages",t),$("#validationModalBody").html(t),void $("#validationModal").modal("show")}showNotification(e.responseJSON.message,"danger")}))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){confirm("Are you sure you want to delete this image?")&&$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-product").on("click",function(){confirm("Are you sure you want to delete this product?")&&$.ajax({method:"POST",url:"/admin/product/delete",data:{productId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#validatePermalink",function(e){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/validatePermalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(e){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(e){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(e){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#lookupCustomer",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/customer/lookup",data:{customerEmail:$("#customerEmail").val()}}).done(function(e){showNotification(e.message,"success"),$("#orderFirstName").val(e.customer.firstName),$("#orderLastName").val(e.customer.lastName),$("#orderAddress1").val(e.customer.address1),$("#orderAddress2").val(e.customer.address2),$("#orderCountry").val(e.customer.country),$("#orderState").val(e.customer.state),$("#orderPostcode").val(e.customer.postcode),$("#orderPhone").val(e.customer.phone)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#orderCreate",function(e){e.preventDefault(),0===$("#createOrderForm").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/order/create",data:{orderStatus:$("#orderStatus").val(),email:$("#customerEmail").val(),firstName:$("#orderFirstName").val(),lastName:$("#orderLastName").val(),address1:$("#orderAddress1").val(),address2:$("#orderAddress2").val(),country:$("#orderCountry").val(),state:$("#orderState").val(),postcode:$("#orderPostcode").val(),phone:$("#orderPhone").val(),orderComment:$("#orderComment").val()}}).done(function(e){showNotification(e.message,"success"),window.location=`/admin/order/view/${e.orderId}`}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#sendTestEmail").on("click",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(e){showNotification(e,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".orderFilterByStatus",function(e){e.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$('input[class="publishedState"]').change(function(){$.ajax({method:"POST",url:"/admin/product/publishedState",data:{id:this.id,state:this.checked}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#updateCustomer").validator().on("click",function(e){e.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/customer/update",data:{customerId:$("#customerId").val(),email:$("#email").val(),firstName:$("#firstName").val(),lastName:$("#lastName").val(),address1:$("#address1").val(),address2:$("#address2").val(),country:$("#country").val(),state:$("#state").val(),postcode:$("#postcode").val(),phone:$("#phone").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#deleteCustomer").on("click",function(e){e.preventDefault(),$.ajax({method:"DELETE",url:"/admin/customer",data:{customerId:$("#customerId").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/customers")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#footerHtml").length){var e=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});e.setValue(e.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var t=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(t.getValue(),{indent:" ",autosemicolon:!0});t.setValue(a)}$(document).on("click","#btnPageUpdate",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/page",data:{pageId:$("#pageId").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnPageDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/page/delete",data:{pageId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#discountNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/create",data:{code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/settings/discount/edit/"+e.discountId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/update",data:{discountId:$("#discountId").val(),code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountStart").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM",showOtherMonths:!0}),$("#discountEnd").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM"}),$(document).on("click","#btnDiscountDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"DELETE",url:"/admin/settings/discount/delete",data:{discountId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-new",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/menu/new",data:{navMenu:$("#newNavMenu").val(),navLink:$("#newNavLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-update",function(e){e.preventDefault();var t=$(this).attr("data-id"),a=$("#menuId-"+t);$.ajax({method:"POST",url:"/admin/settings/menu/update",data:{navId:a.find(".navId").val(),navMenu:a.find(".navMenu").val(),navLink:a.find(".navLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click",".settings-menu-delete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/menu/delete",data:{menuId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#draggable_list").length&&$("#draggable_list").sortable({update:function(){var e=[];$(".navId").each(function(t){e.push($($(".navId")[t]).val())}),$.ajax({data:{order:e},type:"POST",url:"/admin/settings/menu/saveOrder"}).done(function(){showNotification("Menu order saved","success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger",!0)})}}),$(document).on("click","#uploadButton",function(e){e.preventDefault();var t=new FormData($("#uploadForm")[0]);t.append("productId",$("#productId").val()),$.ajax({method:"POST",url:"/admin/file/upload",processData:!1,contentType:!1,cache:!1,data:t}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#global-search-value").on("keyup",e=>{""===$("#global-search-value").val()&&($("#global-search-results").empty(),$("#global-search-results").addClass("invisible"));let t=3;/^\d*\.?\d*$/.test($("#global-search-value").val())&&(t=1),$("#global-search-value").val().length>t&&($("#global-search").html(''),globalSearch())}),$("#globalSearchModal").on("shown.bs.modal",function(){$("#global-search-value").focus()}),$("body").on("click",".gr-click",e=>{$("#global-search-value").val();const t=$(e.currentTarget).closest(".global-result").attr("data-url");t&&(window.location=t)})}); \ No newline at end of file diff --git a/routes/product.js b/routes/product.js index 66c9f5f..525d2fb 100644 --- a/routes/product.js +++ b/routes/product.js @@ -249,10 +249,7 @@ router.post('/admin/product/update', restrict, checkAccess, async (req, res) => // Validate the body again schema const schemaValidate = validateJson('editProduct', productDoc); if(!schemaValidate.result){ - res.status(400).json({ - message: 'Form invalid. Please check values and try again.', - error: schemaValidate.errors - }); + res.status(400).json(schemaValidate.errors); return; } diff --git a/test/specs/products.js b/test/specs/products.js index 30be9d4..fb88b84 100644 --- a/test/specs/products.js +++ b/test/specs/products.js @@ -64,7 +64,7 @@ test('[Success] Add a product', async t => { productPermalink: 'test-jacket', productTitle: 'Test Jacket', productPrice: '100.00', - productDescription: 'Test desc', + productDescription: 'Test product description used to describe the product', productPublished: true, productTags: 'organic, jacket', productOptions: { @@ -94,7 +94,7 @@ test('[Fail] Add a product - Duplicate permalink', async t => { productPermalink: 'test-jacket', productTitle: 'Test Jacket - blue', productPrice: '100.00', - productDescription: 'Test desc blue', + productDescription: 'Test product description used to describe the product', productPublished: true, productTags: 'organic, jacket, blue', productOptions: { @@ -124,7 +124,7 @@ test('[Success] Update a product', async t => { productId: g.products[0]._id, productTitle: 'Test Jacket', productPrice: '200.00', - productDescription: 'Test desc', + productDescription: 'Test product description used to describe the product', productPublished: true, productTags: 'organic, jacket', productOptions: { diff --git a/views/layouts/layout.hbs b/views/layouts/layout.hbs index 7592b5b..2e5460b 100644 --- a/views/layouts/layout.hbs +++ b/views/layouts/layout.hbs @@ -259,27 +259,8 @@ {{/if}} {{#if admin}} - + {{> partials/globalSearchModal}} + {{> partials/validationModal}} {{/if}} {{> partials/confirmModal}}