Files
old-web/app/views/publishRealEstate.ejs

349 lines
11 KiB
Plaintext
Raw Normal View History

2020-02-03 14:57:36 +01:00
<br>
2020-03-19 15:24:58 +01:00
2020-03-11 22:32:10 +01:00
<form id="publishForm" method="POST" novalidate >
2020-02-04 01:02:32 +01:00
<div class="row">
2020-02-14 10:15:33 +01:00
<div class="col s12">
2020-02-04 01:02:32 +01:00
<ul class="tabs">
2020-03-11 22:32:10 +01:00
<li class="tab col s3"><a href="#publishBasicData">Osnovni podaci</a></li>
<li class="tab col s3"><a href="#publishAdditionalData">Dodatni podaci</a></li>
<li class="tab col s2"><a href="#publishLocation">Lokacija</a></li>
<li class="tab col s2"><a href="#publishPhotos">Fotografije</a></li>
<li class="tab col s2"><a href="#publishEnd">Kraj</a></li>
2020-02-04 01:02:32 +01:00
</ul>
</div>
<div id="publishBasicData" class="col s12">
<%- include("./publishBasicData.ejs") %>
</div>
<div id="publishAdditionalData" class="col s12">
<%- include("./publishAdditionalData.ejs") %>
</div>
2020-02-07 14:05:00 +01:00
<div id="publishLocation" class="col s12">
<%- include("./publishLocation.ejs") %>
2020-02-04 01:02:32 +01:00
</div>
2020-02-13 17:08:49 +01:00
<div id="publishPhotos" class="col s12">
<%- include("./publishPhotos.ejs") %>
</div>
2020-02-04 01:02:32 +01:00
<div id="publishEnd" class="col s12">
<%- include("./publishEnd.ejs") %>
</div>
</div>
2020-03-20 15:40:38 +01:00
<input type="hidden" name="editingRealEstate" id="editingRealEstate" value="">
2020-02-04 01:02:32 +01:00
</form>
<script>
2020-03-11 22:32:10 +01:00
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getFileName(fileName) {
const encodedFileName = (uuidv4() + fileName).replace(/\s+/g, '');
return encodedFileName;
}
function upload() {
var file = $('#selector')[0].files[0];
uploadFile(file)
}
async function generateSignedURL(file) {
const fileName = getFileName(file.name);
const response = await fetch('/generateSignedURL?filename=' + fileName);
if (!response.ok) {
throw new Error('Network response for fetch was not ok.');
}
let signedUrl = await response.text();
signedUrl = signedUrl.replace(/\"/g, "")
await uploadFile(file, fileName, signedUrl);
return fileName;
}
function uploadFile(file, fileName, url) {
return fetch(url, {
method: 'PUT',
headers: new Headers({'content-type': 'image/*'}),
mode: 'cors',
body: file
})
.then(response => response.text())
.then (response => {
return response;
}
)
.catch(error => $("#status").html(error)
)
.then(response => {
$("#imageUrls").val($("#imageUrls").val()+ fileName+"|");
});
}
2020-02-12 11:44:56 +01:00
2020-02-04 01:02:32 +01:00
$(document).ready(function(){
$('.tabs').tabs();
2020-02-07 14:05:00 +01:00
2020-03-24 11:10:16 +01:00
const editingRealEstate = <%- JSON.stringify(editingRealEstate) %>;
2020-03-20 15:40:38 +01:00
$("#editingRealEstate").val(editingRealEstate);
2020-03-23 12:26:08 +01:00
2020-03-24 11:10:16 +01:00
const currentRealEstatePhotosUrls = <%-JSON.stringify(realEstatePhotosUrls)%>;
2020-03-20 15:40:38 +01:00
2020-03-11 22:32:10 +01:00
// Manual dropzone init
const dropzoneOptions = {
url: "/photos-upload", //can be a function that returns url ?
autoProcessQueue:false, //not to upload files automaticly
method: "put", //or post
parallelUploads: 1,
2020-03-12 22:46:47 +01:00
uploadMultiple: false,
2020-03-11 22:32:10 +01:00
addRemoveLinks: true,
maxFilesize: 2, //MB,
resizeWidth: 600,
2020-03-12 22:46:47 +01:00
maxFiles: 10,
2020-03-11 22:32:10 +01:00
acceptedFiles: "image/*",
dictDefaultMessage: `<span class="text-center">
<h3>Prevuci fotografije ili klikni za dodavanje!</h3>
(Maksimalno 10 fotografija.)
</span>`,
dictResponseError: 'Error uploading file!',
dictRemoveFile: 'Izbriši ',
dictFileTooBig: 'Fajl je prevelik!',
dictInvalidFileType: 'Iabrani fajl nije fotografija!',
2020-03-23 12:26:08 +01:00
dictMaxFilesExceeded: 'Dostigli ste maksimalan broj fotografija!',
init: function () {
2020-03-24 11:10:16 +01:00
let fileCountOnServer = currentRealEstatePhotosUrls.length; // The number of files already uploaded
2020-03-23 12:26:08 +01:00
this.options.maxFiles = this.options.maxFiles - fileCountOnServer;
if (editingRealEstate) {
2020-03-24 11:10:16 +01:00
for (let i=0; i<currentRealEstatePhotosUrls.length; i++) {
let fileName = currentRealEstatePhotosUrls[i].replace("https://storage.cloud.google.com/marketalarm-photos/", "");
2020-03-23 12:26:08 +01:00
var mockFile = { name: fileName, size: 12345, type: 'image/jpeg', accepted: true, status: Dropzone.ACCEPTED };
this.options.addedfile.call(this, mockFile);
2020-03-24 11:10:16 +01:00
this.options.thumbnail.call(this, mockFile, currentRealEstatePhotosUrls[i]);
2020-03-23 12:26:08 +01:00
this.files.push(mockFile);
mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete');
}
};
this.on("addedfile", function(event) {
while (this.files.length > this.options.maxFiles) {
2020-03-24 11:10:16 +01:00
this.removeFile(this.files[0]); //automaticly removing if more then 10 files
2020-03-23 12:26:08 +01:00
}
});
this.on("removedfile", function(event) {
let fileCountOnPreview = this.files.length;
2020-03-24 11:10:16 +01:00
this.options.maxFiles = 10; //resets allowed number of files
2020-03-23 12:26:08 +01:00
this._updateMaxFilesReachedClass();
});
}
}
2020-03-11 22:32:10 +01:00
var photosUploader = new Dropzone('#photos-upload', dropzoneOptions);
//VALIDATION - WiP
2020-02-12 23:43:59 +01:00
//Helper validation functions
const isValidEmail = $email => {
const simpleEmailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return $email && $email.length < 250 && simpleEmailRegex.test($email);
};
const isPresent = $input => {
return $input && $input!=="" && $input != null;
};
const isNumber = $input => {
const simpleNumberRegex = /([0-9]+[.|,][0-9])|([0-9][.|,][0-9]+)|([0-9]+)/;
return $input && $input.length <250 && simpleNumberRegex.test($input) && !isNaN($input);
};
const isInteger = $input => {
const simpleIntegerRegex = /^([+-]?[1-9]\d*|0)$/;
return $input && $input.length <250 && simpleIntegerRegex.test($input);
};
2020-02-12 11:44:56 +01:00
const form = document.querySelector("#publishForm");
function showErrors(form, errors) {
// We loop through all the inputs and show the errors for that input
//_.each(form.querySelectorAll("input[name], select[name]"), function(input) {
// Since the errors can be null if no errors were found we need to handle
// that
showErrorsForInput(input, errors && errors[input.name]);
// });
}
// Shows the errors for a specific input
function showErrorsForInput(input, errors) {
// This is the root of the input
var formGroup = closestParent(input.parentNode, "form-group"),
// Find where the error messages will be insert into
messages = formGroup.querySelector(".messages");
// First we remove any old messages and resets the classes
resetFormGroup(formGroup);
// If we have errors
if (errors) {
// we first mark the group has having errors
formGroup.classList.add("has-error");
// then we append all the errors
$.each(errors, function(error) {
addError(messages, errors[error]);
});
2020-02-12 23:43:59 +01:00
2020-02-12 11:44:56 +01:00
} else {
// otherwise we simply mark it as success
formGroup.classList.add("has-success");
}
}
// Recusively finds the closest parent that has the specified class
function closestParent(child, className) {
if (!child || child == document) {
return null;
}
if (child.classList.contains(className)) {
return child;
} else {
return closestParent(child.parentNode, className);
}
}
function resetFormGroup(formGroup) {
formGroup.classList.remove("has-error");
formGroup.classList.remove("has-success");
$.each(formGroup.querySelectorAll(".help-block.error"), function(el) {
el.parentNode.removeChild(el);
});
}
// Adds the specified error with the following markup
// <p class="help-block error">[message]</p>
function addError(messages, error) {
var block = document.createElement("p");
block.classList.add("help-block");
block.classList.add("error");
block.innerText = error;
messages.appendChild(block);
}
2020-02-12 23:43:59 +01:00
const validate = (input) => {
let valid=true;
let errorMsg =[];
let constraint = input.constraint[0];
switch (constraint) {
case "required":
valid = isPresent ($(`#${input.dbField}`).val());
errorMsg = ["Ovo je obavezno polje."];
break;
case "numerical":
valid = isNumber ($(`#${input.dbField}`).val());
errorMsg = ["Unesite brojcanu vrijednost."];
break;
case "integer":
valid = isInteger ($(`#${input.dbField}`).val());
errorMsg = ["Unesite cijeli broj."];
break;
default :
valid = true;
}
if (!valid) {
const inputField = document.querySelector(`#${input.dbField}`);
showErrorsForInput( inputField, errorMsg);
return false;
} else {
return true;
}
}
2020-03-12 22:46:47 +01:00
$("#submit").click( async function (e) {
e.preventDefault();
2020-03-11 22:32:10 +01:00
2020-02-13 10:43:30 +01:00
if (marker) {
const currentLocation = marker.getPosition();
2020-02-07 14:05:00 +01:00
$("#lat").val(currentLocation.lat());
2020-02-12 23:43:59 +01:00
2020-02-07 14:05:00 +01:00
$("#lng").val(currentLocation.lng());
$("#locationInput").val(
document.getElementById("autocompleteInput").value
2020-02-13 10:43:30 +01:00
);
} else {
$("#lat").val(0);
$("#lng").val(0);
}
2020-02-12 23:43:59 +01:00
//Tag for checking of error presence
let hasErrors = false;
//Check if email is valid
const validEmail = isValidEmail($("#email").val());
//Show messeges for invalid email is present
if (!validEmail) {
const errorMsgs = ["Unesite validan email."];
const email = document.querySelector("#email");
showErrorsForInput( email, errorMsgs)
2020-02-12 23:43:59 +01:00
hasErrors = true;
};
//Check if other input fields are valid - vratiti se na ovo!!
//const basicInputInputs= document.getElementById("basic-inputs").getElementsByTagName("input");
//alert(JSON.stringify(""));
/*
$.each(basicInputInputs, function (input) {
alert(input);
validate (input);
})
for (const input of basicInputInputs ) {
alert(input.getAttribute(name));
validate (input);
} */
2020-03-23 12:26:08 +01:00
2020-03-24 11:10:16 +01:00
//Filter all files to exclude ones that are already uploaded during the ad publish
//But keep them stored to know that they are not deleted from ad
let filesForUpload =[];
if(editingRealEstate) {
let currentPhotosFilenames = currentRealEstatePhotosUrls.map( url => {
return url.replace("https://storage.cloud.google.com/marketalarm-photos/", "");
})
photosUploader.files.map( file => {
if ( currentPhotosFilenames.includes(file.name) ) {
return $("#imageUrls").val($("#imageUrls").val()+ file.name+"|");
} else if (file.status!=="error") {
return filesForUpload.push(file);
}
});
2020-03-23 12:26:08 +01:00
2020-03-24 11:10:16 +01:00
} else {
photosUploader.files.map( file => {
if (file.status!=="error") {
return filesForUpload.push(file);
}
})
}
2020-03-12 22:46:47 +01:00
2020-03-24 11:10:16 +01:00
const asyncUpload =[];
filesForUpload.forEach( file => {
2020-03-12 22:46:47 +01:00
asyncUpload.push(generateSignedURL(file));
})
2020-03-24 11:10:16 +01:00
2020-03-11 22:32:10 +01:00
if (!hasErrors) {
2020-03-12 22:46:47 +01:00
await Promise.all(asyncUpload);
2020-03-11 22:32:10 +01:00
$("#publishForm").submit();
2020-02-12 23:43:59 +01:00
};
2020-03-12 22:46:47 +01:00
2020-02-07 14:05:00 +01:00
});
2020-02-04 01:02:32 +01:00
});
2020-02-07 12:26:29 +01:00
2020-02-04 01:02:32 +01:00
</script>