Compare commits

...

9 Commits

Author SHA1 Message Date
Naida Vatric
981faeb610 For review view ad page. 2020-03-14 15:34:18 +01:00
Naida Vatric
a36fba09eb Merged finished kivi-input in view 2020-03-14 14:09:36 +01:00
Naida Vatric
6821f61e55 Flexslider fixed. 2020-03-03 22:03:41 +01:00
Naida Vatric
54d9822fc8 Flexslider vs Materilize debugg. 2020-03-03 17:02:20 +01:00
Naida Vatric
b80577ef6b WiP Ad preview page - flexslider problem. 2020-02-24 23:15:48 +01:00
Naida Vatric
d36d7f413d Initialized flex slider 2020-02-24 15:41:28 +01:00
Naida Vatric
9c63bdfbe2 Started photo gallery. 2020-02-23 23:05:28 +01:00
Naida Vatric
2218e6888a Added map to kivi ad preview. 2020-02-23 01:52:43 +01:00
Naida Vatric
16d004c1ab WiP Started kivi original ad view. 2020-02-14 13:38:31 +01:00
16 changed files with 408 additions and 16 deletions

View File

@@ -34,7 +34,7 @@ const MAX_REAL_ESTATES_IN_FIRST_EMAIL =
const PRINT_CRAWLER_DEBUG = process.env.PRINT_CRAWLER_DEBUG_INFO || 0;
const API_MAP_KEY = process.env.API_MAP_KEY || "";
const GOOGLE_MAP_KEY = process.env.GOOGLE_MAP_KEY || "";
const PROSTOR_LOGIN = {
EMAIL: process.env.PROSTOR_LOGIN_EMAIL,
@@ -51,9 +51,8 @@ module.exports = {
MAX_REAL_ESTATES_IN_EMAIL,
MAX_REAL_ESTATES_IN_FIRST_EMAIL,
PRINT_CRAWLER_DEBUG,
API_MAP_KEY,
GOOGLE_MAP_KEY,
STAGING,
CHECK_UP_DAYS,
PROSTOR_LOGIN
};

View File

@@ -10,6 +10,8 @@ const {
ACCESS_ROAD_TYPE,
HEATING_TYPE
} = require("../common/enums");
const { APP_URL } = require("../config/appConfig");
const {
BASIC_BOOLEAN_PUBLISH,
BASIC_SEGMENT_PUBLISH,
@@ -174,6 +176,10 @@ const getPublishInputs = async (req, res) => {
const postPublishInputs = async (req, res) => {
const kiviOriginal = await currentKiviRealEstate(req);
if (!kiviOriginal || !kiviOriginal.kiviAdId) {
res.render("notFound", { title: " " });
return;
}
const realEstate = await findRealEstateByAgencyId(kiviOriginal.kiviAdId);
if (!realEstate || !realEstate.dataValues) {
@@ -306,6 +312,8 @@ const postPublishInputs = async (req, res) => {
kiviOriginal.email = contactEmail;
//console.log("realEstate", realEstate);
await realEstate.save();
await kiviOriginal.save();

View File

@@ -6,6 +6,7 @@ const {
const { createKiviOriginal } = require("../helpers/db/kiviOriginal");
const { AD_CATEGORY, AD_TYPE, AD_AGENCY } = require("../common/enums");
const { APP_URL } = require("../config/appConfig");
const getPublishTypes = async (req, res) => {
const kiviOriginal = await currentKiviRealEstate(req);
@@ -70,6 +71,8 @@ const postPublishTypes = async (req, res) => {
realEstate.adType = adTypeStringId;
realEstate.realEstateType = selectedRealEstateType;
//Url override
realEstate.url = `${APP_URL}/preglednekretnine/${realEstate.id}`;
await realEstate.save();
} else {
@@ -77,11 +80,12 @@ const postPublishTypes = async (req, res) => {
const newKiviOriginal = await createKiviOriginal({
email: ""
});
const newKiviAdViewUrl = `${APP_URL}/preglednekretnine/${realEstate.id}`;
const newRealEstate = await createRealEstate({
adType: adTypeStringId,
realEstateType: selectedRealEstateType,
url: "http://localhost:5000/",
url: newKiviAdViewUrl,
originAgencyName: AD_AGENCY.KIVI,
agencyObjectId: newKiviOriginal.kiviAdId
});

View File

@@ -0,0 +1,202 @@
const { findRealEstateByAgencyId } = require("../helpers/db/realEstate");
const { findPhotosForKiviAd } = require("../helpers/db/kiviOriginalAdsPhotos");
const { currentKiviRealEstate, currentRealEstate } = require("../helpers/url");
const {
BASIC_BOOLEAN_PUBLISH,
BASIC_SEGMENT_PUBLISH,
ADDITIONAL_BOOLEAN_PUBLISH,
ADDITIONAL_SEGMENT_PUBLISH,
BASIC_INPUT_PUBLISH,
ADDITIONAL_INPUT_PUBLISH
} = require("../common/publishEnums");
const { AD_CATEGORY, AD_TYPE } = require("../common/enums");
const getViewRealEstate = async (req, res) => {
//Variation if we acces to real estate previews via kiviAdId
/*
const kiviOriginal = await currentKiviRealEstate(req);
if (!kiviOriginal || !kiviOriginal.kiviAdId) {
res.render("notFound", { title: " " });
return;
}
const realEstate = await findRealEstateByAgencyId(kiviOriginal.kiviAdId); */
const realEstate = await currentRealEstate(req);
if (!realEstate || !realEstate.dataValues) {
res.render("notFound", { title: " " });
return;
}
const pageTitle = "Pregled nekretnine";
const {
price,
area,
adType,
agencyObjectId,
realEstateType,
locationLat,
locationLong,
accessRoadType,
heatingType,
balcony,
newBuilding,
elevator,
recentlyAdapted,
gardenSize,
numberOfRooms,
numberOfFloors,
floor,
water,
electricity,
drainageSystem,
registeredInZkBooks,
parking,
garage,
gas,
antiTheftDoor,
airCondition,
phoneConnection,
cableTV,
internet,
basementAttic,
storeRoom,
videoSurveillance,
alarm,
suitableForStudents,
includingBills,
animalsAllowed,
pool,
exchange,
urbanPlanPermit,
buildingPermit,
furnishingType,
shortDescription,
streetName,
title,
longDescription
} = realEstate;
//Categorize all database values by value type - input, boolean or segment selected
const allInputValues = {
price,
area,
gardenSize,
numberOfRooms,
numberOfFloors,
floor,
title,
shortDescription,
streetName,
longDescription
};
const allBooleanValues = {
balcony,
elevator,
newBuilding,
recentlyAdapted,
water,
electricity,
drainageSystem,
registeredInZkBooks,
parking,
garage,
gas,
antiTheftDoor,
airCondition,
phoneConnection,
cableTV,
internet,
basementAttic,
storeRoom,
videoSurveillance,
alarm,
suitableForStudents,
includingBills,
animalsAllowed,
pool,
exchange,
urbanPlanPermit,
buildingPermit
};
const allSegmentSelectedValues = {
furnishingType,
accessRoadType,
heatingType
};
//We need titles of fields ex Balkon, Novogradnja
const ALL_BOOLEAN_FIELDS = [
...BASIC_BOOLEAN_PUBLISH,
...ADDITIONAL_BOOLEAN_PUBLISH
];
const ALL_INPUT_FIELDS = [
...BASIC_INPUT_PUBLISH,
...ADDITIONAL_INPUT_PUBLISH
];
const ALL_SEGMENT_FIELDS = [
...BASIC_SEGMENT_PUBLISH,
...ADDITIONAL_SEGMENT_PUBLISH
];
//On view add page we will show only values that are not - null, or "", or undefined
const forShowing = value => {
return value !== false && value !== null && value !== "";
};
//Filter all values to be shown on page or not
//For showing on page we also need title ex. "Balkon"
const booleanFields = ALL_BOOLEAN_FIELDS.filter(object => {
return forShowing(allBooleanValues[object.dbField]);
});
const inputFields = ALL_INPUT_FIELDS.filter(object => {
return forShowing(allInputValues[object.dbField]);
});
const segmentFields = ALL_SEGMENT_FIELDS.filter(object => {
return forShowing(allSegmentSelectedValues[object.dbField]);
});
//Photo urls from Google storage bucket
const kiviAdId = agencyObjectId;
const urlGooglePrefix =
"https://storage.cloud.google.com/marketalarm-photos/";
const realEstatePhotosData = await findPhotosForKiviAd(kiviAdId);
const realEstatePhotosUrls = realEstatePhotosData.map(row => {
return urlGooglePrefix + row.dataValues.photoUrl;
});
const showRealEstateType = AD_CATEGORY[realEstateType].title.toUpperCase();
let showAdType = "";
switch (adType) {
case AD_TYPE.AD_TYPE_SALE.stringId:
showAdType = AD_TYPE.AD_TYPE_SALE.title.toUpperCase();
break;
case AD_TYPE.AD_TYPE_RENT.stringId:
showAdType = AD_TYPE.AD_TYPE_RENT.title.toUpperCase();
break;
default:
showAdType = "-";
break;
}
res.render("viewRealEstate", {
title: pageTitle,
booleanFields,
inputFields,
allInputValues,
segmentFields,
allSegmentSelectedValues,
locationLat,
locationLong,
showAdType,
showRealEstateType,
realEstatePhotosUrls
});
};
module.exports = {
getViewRealEstate
};

View File

@@ -2,6 +2,7 @@ const { createSearchRequest } = require("../helpers/db/searchRequest");
const { createRealEstate } = require("../helpers/db/realEstate");
const { createKiviOriginal } = require("../helpers/db/kiviOriginal");
const { AD_TYPE, AD_CATEGORY, AD_AGENCY } = require("../common/enums");
const { APP_URL } = require("../config/appConfig");
const getWelcome = (req, res) => {
res.render("welcome", {
@@ -38,12 +39,13 @@ const postWelcome = async (req, res) => {
const newKiviOriginal = await createKiviOriginal({
email: ""
});
//Temporary url because we have cyclic id call - need to override for safety measures
const newKiviAdViewUrl = `${APP_URL}/preglednekretnine/${newKiviOriginal.kiviAdId}`;
const newRealEstate = await createRealEstate({
adType: adTypeStringId,
realEstateType: AD_CATEGORY.FLAT.id,
//Temp variable because of the not null constraints
url: "http://localhost:5000/",
url: newKiviAdViewUrl,
originAgencyName: AD_AGENCY.KIVI,
agencyObjectId: newKiviOriginal.kiviAdId
});

View File

@@ -12,6 +12,20 @@ const bulkUpsertKiviPhotos = async kiviPhotosData => {
}
};
module.exports = {
bulkUpsertKiviPhotos
const findPhotosForKiviAd = async id => {
try {
return db.KiviOriginalAdsPhotos.findAll({
where: {
kiviAdId: id
}
});
} catch (error) {
console.log("kiviOriginalAdsPhotos.js", error);
return null;
}
};
module.exports = {
bulkUpsertKiviPhotos,
findPhotosForKiviAd
};

View File

@@ -1,6 +1,7 @@
const { getSearchRequest } = require("./db/searchRequest");
const { getRealEstateById } = require("./db/realEstate");
const { getKiviOriginalById } = require("./db/kiviOriginal");
const validator = require("validator");
const currentSearchRequest = async req => {
const searchRequestId =
@@ -19,7 +20,7 @@ const currentRealEstate = async req => {
const currentKiviRealEstate = async req => {
const kiviRealEstateId =
req && req.params ? req.params["kiviRealEstateId"] : null;
if (!kiviRealEstateId) return null;
if (!kiviRealEstateId || !validator.isUUID(kiviRealEstateId)) return null;
return await getKiviOriginalById(kiviRealEstateId);
};

View File

@@ -169,6 +169,26 @@ h3 {
right: auto;
}
.dont-break-out {
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-moz-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
.flex-direction-nav li a {
height: 50px;
}
.slider .slides li {
opacity: 1;
position: relative;
}
.dropzone {
background: white;
border-radius: 10px;

View File

@@ -15,6 +15,7 @@ const {
getPublishInputs,
postPublishInputs
} = require("../controllers/publishRealEstate");
const { getViewRealEstate } = require("../controllers/viewRealEstate");
const {
getQueryReview,
postQueryReview
@@ -45,6 +46,8 @@ router.post("/objavinekretninu", postPublishTypes);
router.get("/podacionekretnini/:kiviRealEstateId", getPublishInputs);
router.post("/podacionekretnini/:kiviRealEstateId", postPublishInputs);
router.get("/preglednekretnine/:realEstateId", getViewRealEstate);
router.get("/lokacija/:searchRequestId", getLocation);
router.post("/lokacija/:searchRequestId", postLocation);

View File

@@ -27,6 +27,10 @@
<meta charset="UTF-8" />
<link rel="stylesheet" href="/assets/main.css">
<link rel="stylesheet" href="/assets/segment.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.7.2/flexslider.css" type="text/css" media="screen" />
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.7.2/jquery.flexslider.js"></script>
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png">

View File

@@ -217,7 +217,7 @@
});
</script>
<script
src="https://maps.googleapis.com/maps/api/js?key=<%= process.env.API_MAP_KEY %>&language=bs&libraries=places&callback=initMap"
src="https://maps.googleapis.com/maps/api/js?key=<%= process.env.GOOGLE_MAP_KEY %>&language=bs&libraries=places&callback=initMap"
async
defer
></script>

View File

@@ -185,7 +185,7 @@
</script>
<script
src="https://maps.googleapis.com/maps/api/js?key=<%= process.env.API_MAP_KEY %>&language=bs&libraries=places&callback=initMap"
src="https://maps.googleapis.com/maps/api/js?key=<%= process.env.GOOGLE_MAP_KEY %>&language=bs&libraries=places&callback=initMap"
async
defer
></script>

View File

@@ -0,0 +1,129 @@
<br/>
<div class="row col s12 center-align">
<div class="col s6 center-align distinguished">
<div><%= showAdType %> </div>
</div>
<div class="col s6 center-align distinguished">
<%= showRealEstateType %>
</div>
</div>
<section class="slider">
<div class="flexslider" >
<ul class="slides">
<% for (const photoUrl of realEstatePhotosUrls) { %>
<li class="flex-li">
<img src=<%= photoUrl %> alt=""/>
</li>
<% } %>
</ul>
</div>
</section>
<br/>
<br>
<div class="row col s12">
<% for (const field of inputFields){ %>
<p>
<span class="col s4"><%= field.title %></span>
<span class="col s8 distinguished dont-break-out"><%= allInputValues[field.dbField] %></span>
</p>
<br>
<% } %>
</div>
<br>
<div class="row">
<% for (const field of segmentFields){ %>
<p>
<span class="col s4"><%= field.title.replace(/>/g,'') %></span>
<% for (const segmentObject of field.values) { %>
<% if (allSegmentSelectedValues[field.dbField] === segmentObject.id) { %>
<span class="col s8 distinguished"><%= segmentObject.title.replace(/>/g,'') %></span>
<% } %>
<% } %>
</p>
<br>
<% } %>
</div>
<br>
<div class="row col s12">
<% for (const field of booleanFields){ %>
<p class="col s4">
<span>&#10003;</span>
<span><%= field.title %></span>
</p>
<% } %>
</div>
<div class="row center-align ">
<div class="distinguished">
<span>Lokacija nekretnine</span>
</div>
<br>
<br>
<div class="col s12">
<div id="map"></div>
</div>
</div>
<script type="text/javascript">
$(window).load(function() {
$('.flexslider').flexslider({
animation: "slide",
smoothHeight: true
});
});
</script>
<script>
//Setting up image gallery - carousel
//Setting up location map
let map;
function initMap() {
const BOSNIA_BOUNDS = {
north: 45.7,
south: 41.69,
west: 15.55,
east: 20.77
};
const ESTATE_COORDINATES = {
lat: <%= locationLat %>,
lng: <%= locationLong %>
};
const mapElement = document.getElementById("map");
const restrictMapPanningToBosniaOnly = {
latLngBounds: BOSNIA_BOUNDS,
strictBounds: true
};
const initialMapParams = {
center: ESTATE_COORDINATES,
zoom: 13,
restriction: restrictMapPanningToBosniaOnly,
mapTypeControl: false,
panControl: false,
zoomControl: true,
streetViewControl: false
};
map = new google.maps.Map(mapElement, initialMapParams);
marker = new google.maps.Marker({
position: ESTATE_COORDINATES,
map: map,
});
}
</script>
<script
src="https://maps.googleapis.com/maps/api/js?key=<%= process.env.GOOGLE_MAP_KEY %>&language=bs&libraries=places&callback=initMap"
async
defer
></script>

View File

@@ -19,7 +19,7 @@ CHECK_UP_DAYS=Check up email is sent after this number of days without notificat
GA_ID=Google Analytics ID
#=============== GOOGLE MAPS =============#
API_MAP_KEY=(your-key-here)
GOOGLE_MAP_KEY=(your-key-here)
#=============== GOOGLE STORAGE =============#
GOOGLE_APPLICATION_CREDENTIALS="Path to json key file"

11
package-lock.json generated
View File

@@ -4162,6 +4162,11 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"validator": {
"version": "10.11.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
}
}
},
@@ -4944,9 +4949,9 @@
"integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g=="
},
"validator": {
"version": "10.11.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
"integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ=="
},
"vary": {
"version": "1.1.2",

View File

@@ -54,7 +54,8 @@
"react-step-wizard": "^5.1.0",
"sequelize": "^5.18.4",
"sequelize-cli": "^5.5.0",
"validate.js": "^0.13.1"
"validate.js": "^0.13.1",
"validator": "^12.2.0"
},
"devDependencies": {
"nodemon": "^1.19.0"