From 1106f9256054231a5acc14a3ba62b97b8b1adc92 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Tue, 5 Nov 2019 07:19:36 +0100 Subject: [PATCH 01/20] add accordion for additional filters --- app/public/accordion.css | 41 +++++++++++++++++++++++++++++++++ app/views/layout.ejs | 1 + app/views/realEstateFilters.ejs | 22 +++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 app/public/accordion.css diff --git a/app/public/accordion.css b/app/public/accordion.css new file mode 100644 index 0000000..b438731 --- /dev/null +++ b/app/public/accordion.css @@ -0,0 +1,41 @@ +.accordion label { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + background-color: #02adba; + color: white; + padding-left: 15px; + height: 3em; + line-height: 0.5em; + font-size: medium; + cursor: pointer; + border-bottom: 1px solid #bdbdbd; + border-top: 1px solid #ffffff; +} +.accordion p { + color: #424242; + padding: 10px; + font-size: 0.8em; + line-height: 1.7em; + opacity: 0; + display: none; + text-align: left; + background-color: #fff; + margin: 0px; +} +#tm:checked ~ .hiddentext { + display: block; + opacity: 1; +} +input#tm { + display: none; + position: relative; +} +.arrow { + color: #02adba; +} + +.accordion-title { + font-size: 2em; +} diff --git a/app/views/layout.ejs b/app/views/layout.ejs index 7856ad6..49109e9 100644 --- a/app/views/layout.ejs +++ b/app/views/layout.ejs @@ -19,6 +19,7 @@ + diff --git a/app/views/realEstateFilters.ejs b/app/views/realEstateFilters.ejs index 1b3eb01..3aaac2e 100644 --- a/app/views/realEstateFilters.ejs +++ b/app/views/realEstateFilters.ejs @@ -4,7 +4,9 @@
Cijena


-
+
+
+

@@ -23,7 +25,9 @@
Površina


-
+
+
+

@@ -43,7 +47,9 @@
Površina okućnice


-
+
+
+

@@ -58,6 +64,16 @@ <% } %> +
+
+
+ + +

Filteri

+
+
+
+
Dalje -- 2.47.3 From 5cab9ee7c4dd3ff705aae280f9c3200acc3f8341 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Fri, 15 Nov 2019 09:07:56 +0100 Subject: [PATCH 02/20] remove accordion files and import --- app/public/accordion.css | 41 ---------------------------------------- app/views/layout.ejs | 1 - 2 files changed, 42 deletions(-) delete mode 100644 app/public/accordion.css diff --git a/app/public/accordion.css b/app/public/accordion.css deleted file mode 100644 index b438731..0000000 --- a/app/public/accordion.css +++ /dev/null @@ -1,41 +0,0 @@ -.accordion label { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - background-color: #02adba; - color: white; - padding-left: 15px; - height: 3em; - line-height: 0.5em; - font-size: medium; - cursor: pointer; - border-bottom: 1px solid #bdbdbd; - border-top: 1px solid #ffffff; -} -.accordion p { - color: #424242; - padding: 10px; - font-size: 0.8em; - line-height: 1.7em; - opacity: 0; - display: none; - text-align: left; - background-color: #fff; - margin: 0px; -} -#tm:checked ~ .hiddentext { - display: block; - opacity: 1; -} -input#tm { - display: none; - position: relative; -} -.arrow { - color: #02adba; -} - -.accordion-title { - font-size: 2em; -} diff --git a/app/views/layout.ejs b/app/views/layout.ejs index 49109e9..7856ad6 100644 --- a/app/views/layout.ejs +++ b/app/views/layout.ejs @@ -19,7 +19,6 @@ - -- 2.47.3 From fd8592c581d8bcadc494c8f8f27f4132c08a22ed Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Fri, 15 Nov 2019 09:29:02 +0100 Subject: [PATCH 03/20] modify materialize tabs style to match Kivi color scheme --- app/public/main.css | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/public/main.css b/app/public/main.css index 2e0d7d4..2454e3a 100644 --- a/app/public/main.css +++ b/app/public/main.css @@ -110,3 +110,20 @@ h3 { .collection a.collection-item:not(.active):hover { background-color: rgba(2, 173, 186, 0.2); } + +.tabs .tab a { + color: #02adba; + -webkit-transition: color 0.28s ease, background-color 0.28s ease; + transition: color 0.28s ease, background-color 0.28s ease; +} +.tabs .tab a:focus, +.tabs .tab a:focus.active { + background-color: rgba(2, 173, 186, 0.2); +} +.tabs .tab a:hover, +.tabs .tab a.active { + color: #02adba; +} +.tabs .indicator { + background-color: #02adba; +} -- 2.47.3 From 002a8e8572f037cc729b6b207cdb3b51b0158e3c Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Mon, 18 Nov 2019 06:42:22 +0100 Subject: [PATCH 04/20] add more filters to different tab on filters page; update css --- app/public/main.css | 20 ++++ app/views/advancedFilters.ejs | 30 +++++ app/views/realEstateFilters.ejs | 203 ++------------------------------ app/views/standardFilters.ejs | 188 +++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 190 deletions(-) create mode 100644 app/views/advancedFilters.ejs create mode 100644 app/views/standardFilters.ejs diff --git a/app/public/main.css b/app/public/main.css index 2454e3a..dcbc0d7 100644 --- a/app/public/main.css +++ b/app/public/main.css @@ -127,3 +127,23 @@ h3 { .tabs .indicator { background-color: #02adba; } + +[type="checkbox"].filled-in:checked + span:not(.lever):after { + border: 2px solid #02adba; + background-color: #02adba; +} +[type="checkbox"].filled-in:not(:checked) + span:not(.lever):after { + background-color: transparent; + border: 2px solid #02adba; +} + +.distinguished { + border: 2px solid #02adba; + border-radius: 4px; + padding: 5px 5px 3px 5px; + margin-left: -5px; +} + +p > label { + color: black; +} diff --git a/app/views/advancedFilters.ejs b/app/views/advancedFilters.ejs new file mode 100644 index 0000000..22b019c --- /dev/null +++ b/app/views/advancedFilters.ejs @@ -0,0 +1,30 @@ +
+ +

+ +

+ +

+ +

+ +

+ +

+ +
+

+ +

diff --git a/app/views/realEstateFilters.ejs b/app/views/realEstateFilters.ejs index 3aaac2e..caf3c23 100644 --- a/app/views/realEstateFilters.ejs +++ b/app/views/realEstateFilters.ejs @@ -1,76 +1,17 @@ +
-
- -
-
Cijena
-

-
-
-
-
- -
-
-
- - -
-
- -
-
- -
- -
-
Površina
-

-
-
-
-
- -
-
-
- - -
-
- -
-
- -
- - <% if(hasGardenSize) { %> -
-
Površina okućnice
-

-
-
-
-
- -
-
-
- - -
-
- -
-
- <% } %> -
-
- - -

Filteri

-
+ +
+
+ <%- include("./standardFilters.ejs") %> +
+
+ <%- include("./advancedFilters.ejs") %>
@@ -82,125 +23,7 @@
diff --git a/app/views/standardFilters.ejs b/app/views/standardFilters.ejs new file mode 100644 index 0000000..423d694 --- /dev/null +++ b/app/views/standardFilters.ejs @@ -0,0 +1,188 @@ +
+ +
+
Cijena
+

+
+
+
+
+ +
+
+
+ + +
+
+ +
+
+ +
+ +
+
Površina
+

+
+
+
+
+ +
+
+
+ + +
+
+ +
+
+ +
+ +<% if(hasGardenSize) { %> +
+
Površina okućnice
+

+
+
+
+
+ +
+
+
+ + +
+
+ +
+
+<% } %> + + -- 2.47.3 From e42531ff57da13000402be321b6649186e4f35cb Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Mon, 18 Nov 2019 06:44:10 +0100 Subject: [PATCH 05/20] specify and use custom css class for checkbox labels --- app/public/main.css | 2 +- app/views/advancedFilters.ejs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/public/main.css b/app/public/main.css index dcbc0d7..1163246 100644 --- a/app/public/main.css +++ b/app/public/main.css @@ -144,6 +144,6 @@ h3 { margin-left: -5px; } -p > label { +.checkbox-label { color: black; } diff --git a/app/views/advancedFilters.ejs b/app/views/advancedFilters.ejs index 22b019c..ff54fa7 100644 --- a/app/views/advancedFilters.ejs +++ b/app/views/advancedFilters.ejs @@ -1,21 +1,21 @@

-

-

-

-

- -

+<% for (const filter of advancedBooleanFilterObjects){ %> +

+ +

+<% } %> -

- -

+
+<% for (const filter of advancedRangeFilterObjects){ %> +
+

+ <%= filter.title %> +

+
+ " + > + +
+
+ " + > + +
+
+<% } %> -

- -

+
+<% for (const filter of advancedSegmentSelectFilterObjects){ %> +
+

+ + <% for (const segmentObject of filter.values) { %> + + <% } %> + +
+<% } %>

-- 2.47.3 From ade28eb981739408c23c1fcdbd9e4b04380af3d4 Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Sun, 8 Dec 2019 00:58:06 +0100 Subject: [PATCH 10/20] Moved API Google Map key to env variables. --- app/config/appConfig.js | 5 ++++- app/views/location.ejs | 2 +- development.env | 3 +++ tmp.env | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 tmp.env diff --git a/app/config/appConfig.js b/app/config/appConfig.js index 0ed1e6b..ec9f851 100644 --- a/app/config/appConfig.js +++ b/app/config/appConfig.js @@ -30,6 +30,8 @@ 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 || ""; + module.exports = { APP_PORT, APP_URL, @@ -39,5 +41,6 @@ module.exports = { AWS_EMAIL_CONFIG, MAX_REAL_ESTATES_IN_EMAIL, MAX_REAL_ESTATES_IN_FIRST_EMAIL, - PRINT_CRAWLER_DEBUG + PRINT_CRAWLER_DEBUG, + API_MAP_KEY }; diff --git a/app/views/location.ejs b/app/views/location.ejs index 5347281..01a25ef 100644 --- a/app/views/location.ejs +++ b/app/views/location.ejs @@ -177,5 +177,5 @@ }); }); - diff --git a/development.env b/development.env index 3a63a34..89f0a1e 100644 --- a/development.env +++ b/development.env @@ -14,6 +14,9 @@ MAX_REAL_ESTATES_IN_FIRST_EMAIL=Max number of real estates that will be shown in #=============== GOOGLE ANALYTICS =============# GA_ID=Google Analytics ID +#=============== GOOGLE MAPS =============# +API_MAP_KEY=(your-key-here) + #=============== AWS SDK EMAIL SETTINGS =======# AWS_KEY_ID=(your-key-here) AWS_SECRET_ACCESS_KEY=(your-key-here) diff --git a/tmp.env b/tmp.env new file mode 100644 index 0000000..456f11b --- /dev/null +++ b/tmp.env @@ -0,0 +1 @@ +API_MAP_KEY="AIzaSyBuqZ6MWvDrquwc-TN6rPS6188D608Zj3Q" \ No newline at end of file -- 2.47.3 From ef4fff4e7097e75ace8f67d42bc1ba8cb718271e Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Sun, 8 Dec 2019 22:16:31 +0100 Subject: [PATCH 11/20] Finished map key to env --- tmp.env | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tmp.env diff --git a/tmp.env b/tmp.env deleted file mode 100644 index 456f11b..0000000 --- a/tmp.env +++ /dev/null @@ -1 +0,0 @@ -API_MAP_KEY="AIzaSyBuqZ6MWvDrquwc-TN6rPS6188D608Zj3Q" \ No newline at end of file -- 2.47.3 From dee7c6000ae7195ad9e89b225c044c040d9bd136 Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Wed, 11 Dec 2019 01:24:18 +0100 Subject: [PATCH 12/20] WiP - changed db helpers --- app/helpers/db/realEstate.js | 44 ++++++++++++++++++++++++++++++--- app/helpers/db/searchRequest.js | 39 ++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index 0282645..435bdab 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -87,7 +87,22 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { sizeMax, adType, realEstateType, - areaToSearch + areaToSearch, + // + gardenSizeMin, + gardenSizeMax, + numberOfRoomsMin, + numberOfRoomsMax, + numberOfFloorsMin, + numberOfFloorsMax, + floorMin, + floorMax, + includeIncompleteAds, + balcony, + elevator, + newBuilding, + accessRoadType + // } = searchRequest; const longitudeColumn = sequelize.col("locationLong"); @@ -115,7 +130,9 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { ); const geoSearchQueryPart = sequelize.where(contains, true); - + //Does not work with incomplete data + //issue https://github.com/sequelize/sequelize/issues/11564 + const query = { adType, realEstateType, @@ -127,7 +144,28 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { [Op.lte]: sizeMax, [Op.gte]: sizeMin }, - [Op.and]: geoSearchQueryPart + [Op.and]: geoSearchQueryPart, + // + gardenSize: { + [Op.lte]: gardenSizeMax, + [Op.gte]: gardenSizeMin, + }, + numberOfRooms: { + [Op.lte]: numberOfRoomsMax, + [Op.gte]: numberOfRoomsMin, + }, + numberOfFloors: { + [Op.lte]: numberOfFloorsMax, + [Op.gte]: numberOfFloorsMin, + }, + floor: { + [Op.lte]: floorMax, + [Op.gte]: floorMin, + }, + accessRoadType, + balcony, + newBuilding, + elevator }; const order = [["updatedAt", "desc"]]; diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index 6e47b5d..7fa3c55 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -43,6 +43,11 @@ const findSearchRequestsForRealEstate = async realEstate => { adType, realEstateType, subscribed: true, + // + accessRoadType, + balcony, + newBuilding, + elevator, [Op.and]: geoSearchQueryPart }; @@ -63,7 +68,39 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: area }; } - + // + if (gardenSize) { + query.gardenSizeMin = { + [Op.lte]: gardenSize + }; + query.gardenSizeMax = { + [Op.gte]: gardenSize + }; + } + if (numberOfRooms) { + query.numberOfRoomsMin = { + [Op.lte]: numberOfRooms + }; + query.numberOfRoomsMax = { + [Op.gte]: numberOfRooms + }; + } + if (numberOfFloors) { + query.numberOfFloorsMin = { + [Op.lte]: numberOfFloors + }; + query.numberOfFloorsMax = { + [Op.gte]: numberOfFloors + }; + } + if (floor) { + query.floorMin = { + [Op.lte]: floor + }; + query.floorMax = { + [Op.gte]: floor + }; + } return await db.SearchRequest.findAll({ where: query }); }; -- 2.47.3 From e6e1688a49b73af8c9b85428e7fdea4a4032dd85 Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Wed, 11 Dec 2019 22:44:26 +0100 Subject: [PATCH 13/20] Changed searchRequest helper --- app/helpers/db/searchRequest.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index 7fa3c55..3fff2e5 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -5,8 +5,11 @@ const Op = sequelize.Op; const getSearchRequest = async searchRequestId => { try { + console.log("test"); return await db.SearchRequest.findByPk(searchRequestId); + } catch (error) { + console.log("searchrequest.js",error); return null; } }; @@ -22,7 +25,16 @@ const findSearchRequestsForRealEstate = async realEstate => { adType, realEstateType, locationLat, - locationLong + locationLong, + // + accessRoadType, + balcony, + newBuilding, + elevator, + gardenSize, + numberOfRooms, + numberOfFloors, + floor } = realEstate; if (!locationLat || !locationLong) { -- 2.47.3 From e83712fb33155037420127274bf1410d6f33d5ab Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Fri, 13 Dec 2019 00:45:28 +0100 Subject: [PATCH 14/20] Changed acces road type check and include incomplete --- app/controllers/realEstateFilters.js | 2 +- app/helpers/db/realEstate.js | 130 ++++++++++++++++++++++++--- app/helpers/db/searchRequest.js | 13 ++- 3 files changed, 129 insertions(+), 16 deletions(-) diff --git a/app/controllers/realEstateFilters.js b/app/controllers/realEstateFilters.js index 7d6c06e..ab9eed4 100644 --- a/app/controllers/realEstateFilters.js +++ b/app/controllers/realEstateFilters.js @@ -120,6 +120,7 @@ const getFilters = async (req, res) => { }; const postFilters = async (req, res) => { + const searchRequest = await currentSearchRequest(req); if (!searchRequest || !searchRequest.dataValues) { @@ -232,7 +233,6 @@ const postFilters = async (req, res) => { searchRequest.gardenSizeMin = gardenSizeMin; searchRequest.gardenSizeMax = gardenSizeMax; } - await searchRequest.save(); res.redirect(nextStepUrl); diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index 435bdab..b2de369 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -130,9 +130,12 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { ); const geoSearchQueryPart = sequelize.where(contains, true); - //Does not work with incomplete data - //issue https://github.com/sequelize/sequelize/issues/11564 - + + //Query for case of complete ads + + //WIP This wont work, need to separate queries by adType and realEstateType + //because for example flat does not have gardenSize and that can't be in query + const query = { adType, realEstateType, @@ -148,33 +151,134 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { // gardenSize: { [Op.lte]: gardenSizeMax, - [Op.gte]: gardenSizeMin, + [Op.gte]: gardenSizeMin }, numberOfRooms: { [Op.lte]: numberOfRoomsMax, - [Op.gte]: numberOfRoomsMin, + [Op.gte]: numberOfRoomsMin }, numberOfFloors: { [Op.lte]: numberOfFloorsMax, - [Op.gte]: numberOfFloorsMin, + [Op.gte]: numberOfFloorsMin }, floor: { [Op.lte]: floorMax, - [Op.gte]: floorMin, + [Op.gte]: floorMin + }, + accessRoadType: { + [Op.or]: { + [Op.eq]: 'ANY', + [Op.eq]: accessRoadType + } }, - accessRoadType, balcony, newBuilding, elevator }; + + //Query for case of incomplete ads + const queryIncludeIncomplete = { + adType, + realEstateType, + price: { + [Op.or] : { + [Op.and] : { + [Op.lte]: priceMax, + [Op.gte]: priceMin + }, + [Op.is] : null + } + }, + area: { + [Op.or] : { + [Op.and]: { + [Op.lte]: sizeMax, + [Op.gte]: sizeMin + }, + [Op.is]: null + } + }, + [Op.and]: geoSearchQueryPart, + // + gardenSize: { + [Op.or] : { + [Op.and]: { + [Op.lte]: gardenSizeMax, + [Op.gte]: gardenSizeMin + }, + [Op.is]: null + } + }, + numberOfRooms: { + [Op.or]: { + [Op.and]: { + [Op.lte]: numberOfRoomsMax, + [Op.gte]: numberOfRoomsMin + }, + [Op.is]: null + } + }, + numberOfFloors: { + [Op.or] : { + [Op.and]: { + [Op.lte]: numberOfFloorsMax, + [Op.gte]: numberOfFloorsMin + }, + [Op.is]: null + } + }, + floor: { + [Op.or] : { + [Op.and]: { + [Op.lte]: floorMax, + [Op.gte]: floorMin + }, + [Op.is]: null + } + }, + accessRoadType: { + [Op.or]: { + [Op.eq]: 'ANY', + [Op.eq]: accessRoadType, + [Op.is]: null + } + }, + balcony: { + [Op.or]: { + [Op.eq]: balcony, + [Op.is]: null + } + }, + newBuilding: { + [Op.or]: { + [Op.eq]: newBuilding, + [Op.is]: null + } + }, + elevator: { + [Op.or]: { + [Op.eq]: elevator, + [Op.is]: null + } + } + }; const order = [["updatedAt", "desc"]]; - return await db.RealEstate.findAll({ - where: query, - limit: maxResults, - order - }); + if(!includeIncompleteAds) { + return await db.RealEstate.findAll({ + where: query, + limit: maxResults, + order + }); + } else { + return await db.RealEstate.findAll({ + where: queryIncludeIncomplete, + limit: maxResults, + order + }); + } + }; module.exports = { diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index 3fff2e5..a075c01 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -5,7 +5,7 @@ const Op = sequelize.Op; const getSearchRequest = async searchRequestId => { try { - console.log("test"); + return await db.SearchRequest.findByPk(searchRequestId); } catch (error) { @@ -51,12 +51,13 @@ const findSearchRequestsForRealEstate = async realEstate => { const geoSearchQueryPart = sequelize.where(contains, true); + //WIP This wont work, need to separate queries by adType and realEstateType + //because for example flat does not have gardenSize and that can't be in query const query = { adType, realEstateType, subscribed: true, // - accessRoadType, balcony, newBuilding, elevator, @@ -113,6 +114,14 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: floor }; } + if (accessRoadType) { + query.accessRoadType = { + [Op.or]: { + [Op.eq]: 'ANY', + [Op.eq]: accessRoadType + } + } + } return await db.SearchRequest.findAll({ where: query }); }; -- 2.47.3 From 5a2fdb7291b3581320062750cfd769e80f75eb0c Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Sat, 14 Dec 2019 01:10:48 +0100 Subject: [PATCH 15/20] Queries for db search changed. Needs testing. --- app/helpers/db/realEstate.js | 200 ++++++++++++++++++-------------- app/helpers/db/searchRequest.js | 34 ++++-- 2 files changed, 137 insertions(+), 97 deletions(-) diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index b2de369..9dd4dfe 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -88,7 +88,6 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { adType, realEstateType, areaToSearch, - // gardenSizeMin, gardenSizeMax, numberOfRoomsMin, @@ -102,7 +101,6 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { elevator, newBuilding, accessRoadType - // } = searchRequest; const longitudeColumn = sequelize.col("locationLong"); @@ -131,52 +129,30 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { const geoSearchQueryPart = sequelize.where(contains, true); - //Query for case of complete ads + //General queries contain only attributes that are defined for every searchreq - //WIP This wont work, need to separate queries by adType and realEstateType - //because for example flat does not have gardenSize and that can't be in query - + //Query for case of complete ads const query = { - adType, - realEstateType, - price: { - [Op.lte]: priceMax, - [Op.gte]: priceMin - }, - area: { - [Op.lte]: sizeMax, - [Op.gte]: sizeMin - }, - [Op.and]: geoSearchQueryPart, - // - gardenSize: { - [Op.lte]: gardenSizeMax, - [Op.gte]: gardenSizeMin - }, - numberOfRooms: { - [Op.lte]: numberOfRoomsMax, - [Op.gte]: numberOfRoomsMin - }, - numberOfFloors: { - [Op.lte]: numberOfFloorsMax, - [Op.gte]: numberOfFloorsMin - }, - floor: { - [Op.lte]: floorMax, - [Op.gte]: floorMin - }, - accessRoadType: { - [Op.or]: { - [Op.eq]: 'ANY', - [Op.eq]: accessRoadType - } - }, - balcony, - newBuilding, - elevator - }; + adType, + realEstateType, + price: { + [Op.lte]: priceMax, + [Op.gte]: priceMin + }, + area: { + [Op.lte]: sizeMax, + [Op.gte]: sizeMin + }, + accessRoadType: { + [Op.or]: { + [Op.eq]: 'ANY', + [Op.eq]: accessRoadType + } + }, + [Op.and]: geoSearchQueryPart + } - //Query for case of incomplete ads + //Query for case of incomplete ads const queryIncludeIncomplete = { adType, realEstateType, @@ -198,44 +174,6 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { [Op.is]: null } }, - [Op.and]: geoSearchQueryPart, - // - gardenSize: { - [Op.or] : { - [Op.and]: { - [Op.lte]: gardenSizeMax, - [Op.gte]: gardenSizeMin - }, - [Op.is]: null - } - }, - numberOfRooms: { - [Op.or]: { - [Op.and]: { - [Op.lte]: numberOfRoomsMax, - [Op.gte]: numberOfRoomsMin - }, - [Op.is]: null - } - }, - numberOfFloors: { - [Op.or] : { - [Op.and]: { - [Op.lte]: numberOfFloorsMax, - [Op.gte]: numberOfFloorsMin - }, - [Op.is]: null - } - }, - floor: { - [Op.or] : { - [Op.and]: { - [Op.lte]: floorMax, - [Op.gte]: floorMin - }, - [Op.is]: null - } - }, accessRoadType: { [Op.or]: { [Op.eq]: 'ANY', @@ -243,25 +181,109 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { [Op.is]: null } }, - balcony: { + [Op.and]: geoSearchQueryPart + } + + //Every other attribute is checked separately and included in query only if it is defined + if (gardenSizeMax && gardenSizeMin) { + query.gardenSize = { + [Op.lte]: gardenSizeMax, + [Op.gte]: gardenSizeMin + } + queryIncludeIncomplete.gardenSize = { + [Op.or] : { + [Op.and]: { + [Op.lte]: gardenSizeMax, + [Op.gte]: gardenSizeMin + }, + [Op.is]: null + } + } + } + + if (numberOfRoomsMin && numberOfRoomsMax) { + query.numberOfRooms = { + [Op.lte]: numberOfRoomsMax, + [Op.gte]: numberOfRoomsMin + } + queryIncludeIncomplete.numberOfRooms = { + [Op.or] : { + [Op.and]: { + [Op.lte]: numberOfRoomsMax, + [Op.gte]: numberOfRoomsMin + }, + [Op.is]: null + } + } + } + + if (numberOfFloorsMin && numberOfFloorsMax) { + query.numberOfFloors = { + [Op.lte]: numberOfFloorsMax, + [Op.gte]: numberOfFloorsMin + } + queryIncludeIncomplete.numberOfFloors = { + [Op.or] : { + [Op.and]: { + [Op.lte]: numberOfFloorsMax, + [Op.gte]: numberOfFloorsMin + }, + [Op.is]: null + } + } + } + + if (floorMin && floorMax) { + query.floor = { + [Op.lte]: floorMax, + [Op.gte]: floorMin + } + queryIncludeIncomplete.floor = { + [Op.or] : { + [Op.and]: { + [Op.lte]: floorMax, + [Op.gte]: floorMin + }, + [Op.is]: null + } + } + } + + if (balcony) { + query.balcony = { + [Op.eq]: balcony + } + queryIncludeIncomplete.balcony = { [Op.or]: { [Op.eq]: balcony, [Op.is]: null } - }, - newBuilding: { + } + } + + if (newBuilding) { + query.newBuilding = { + [Op.eq]: newBuilding + } + queryIncludeIncomplete.newBuilding = { [Op.or]: { [Op.eq]: newBuilding, [Op.is]: null } - }, - elevator: { + } + } + + if (elevator) { + query.elevator = { + [Op.eq]: elevator + } + queryIncludeIncomplete.elevator = { [Op.or]: { [Op.eq]: elevator, [Op.is]: null } } - }; + } const order = [["updatedAt", "desc"]]; diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index a075c01..54faeb3 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -26,7 +26,6 @@ const findSearchRequestsForRealEstate = async realEstate => { realEstateType, locationLat, locationLong, - // accessRoadType, balcony, newBuilding, @@ -51,19 +50,15 @@ const findSearchRequestsForRealEstate = async realEstate => { const geoSearchQueryPart = sequelize.where(contains, true); - //WIP This wont work, need to separate queries by adType and realEstateType - //because for example flat does not have gardenSize and that can't be in query + //General query contains only attributes that are defined for every realestate - not null const query = { adType, realEstateType, subscribed: true, - // - balcony, - newBuilding, - elevator, [Op.and]: geoSearchQueryPart }; + //Every other attribute is checked separately and included in query only if it is defined if (price) { query.priceMin = { [Op.lte]: price @@ -81,7 +76,7 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: area }; } - // + if (gardenSize) { query.gardenSizeMin = { [Op.lte]: gardenSize @@ -90,6 +85,7 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: gardenSize }; } + if (numberOfRooms) { query.numberOfRoomsMin = { [Op.lte]: numberOfRooms @@ -98,6 +94,7 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: numberOfRooms }; } + if (numberOfFloors) { query.numberOfFloorsMin = { [Op.lte]: numberOfFloors @@ -106,6 +103,7 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: numberOfFloors }; } + if (floor) { query.floorMin = { [Op.lte]: floor @@ -114,6 +112,7 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.gte]: floor }; } + if (accessRoadType) { query.accessRoadType = { [Op.or]: { @@ -122,6 +121,25 @@ const findSearchRequestsForRealEstate = async realEstate => { } } } + + if (balcony) { + query.balcony = { + [Op.eq]: balcony + } + } + + if (newBuilding) { + query.newBuilding = { + [Op.eq]: newBuilding + } + } + + if (elevator) { + query.elevator = { + [Op.eq]: elevator + } + } + return await db.SearchRequest.findAll({ where: query }); }; -- 2.47.3 From 76f4ed0a301961346e18484da8418ce3b8650896 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Mon, 16 Dec 2019 22:04:37 +0100 Subject: [PATCH 16/20] apply prettier --- app/controllers/realEstateFilters.js | 1 - app/helpers/db/realEstate.js | 97 ++++++++++++++-------------- app/helpers/db/searchRequest.js | 16 ++--- 3 files changed, 55 insertions(+), 59 deletions(-) diff --git a/app/controllers/realEstateFilters.js b/app/controllers/realEstateFilters.js index ab9eed4..17f5e58 100644 --- a/app/controllers/realEstateFilters.js +++ b/app/controllers/realEstateFilters.js @@ -120,7 +120,6 @@ const getFilters = async (req, res) => { }; const postFilters = async (req, res) => { - const searchRequest = await currentSearchRequest(req); if (!searchRequest || !searchRequest.dataValues) { diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index 9dd4dfe..5d37167 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -131,42 +131,42 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { //General queries contain only attributes that are defined for every searchreq - //Query for case of complete ads + //Query for case of complete ads const query = { - adType, - realEstateType, - price: { - [Op.lte]: priceMax, - [Op.gte]: priceMin - }, - area: { - [Op.lte]: sizeMax, - [Op.gte]: sizeMin - }, - accessRoadType: { - [Op.or]: { - [Op.eq]: 'ANY', - [Op.eq]: accessRoadType - } - }, - [Op.and]: geoSearchQueryPart - } - + adType, + realEstateType, + price: { + [Op.lte]: priceMax, + [Op.gte]: priceMin + }, + area: { + [Op.lte]: sizeMax, + [Op.gte]: sizeMin + }, + accessRoadType: { + [Op.or]: { + [Op.eq]: "ANY", + [Op.eq]: accessRoadType + } + }, + [Op.and]: geoSearchQueryPart + }; + //Query for case of incomplete ads const queryIncludeIncomplete = { adType, realEstateType, price: { - [Op.or] : { - [Op.and] : { + [Op.or]: { + [Op.and]: { [Op.lte]: priceMax, [Op.gte]: priceMin }, - [Op.is] : null + [Op.is]: null } }, area: { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: sizeMax, [Op.gte]: sizeMin @@ -176,118 +176,118 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { }, accessRoadType: { [Op.or]: { - [Op.eq]: 'ANY', + [Op.eq]: "ANY", [Op.eq]: accessRoadType, [Op.is]: null } }, [Op.and]: geoSearchQueryPart - } + }; //Every other attribute is checked separately and included in query only if it is defined if (gardenSizeMax && gardenSizeMin) { query.gardenSize = { [Op.lte]: gardenSizeMax, [Op.gte]: gardenSizeMin - } + }; queryIncludeIncomplete.gardenSize = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: gardenSizeMax, [Op.gte]: gardenSizeMin }, [Op.is]: null } - } + }; } if (numberOfRoomsMin && numberOfRoomsMax) { query.numberOfRooms = { [Op.lte]: numberOfRoomsMax, [Op.gte]: numberOfRoomsMin - } + }; queryIncludeIncomplete.numberOfRooms = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: numberOfRoomsMax, [Op.gte]: numberOfRoomsMin }, [Op.is]: null } - } + }; } - + if (numberOfFloorsMin && numberOfFloorsMax) { query.numberOfFloors = { [Op.lte]: numberOfFloorsMax, [Op.gte]: numberOfFloorsMin - } + }; queryIncludeIncomplete.numberOfFloors = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: numberOfFloorsMax, [Op.gte]: numberOfFloorsMin }, [Op.is]: null } - } + }; } if (floorMin && floorMax) { query.floor = { [Op.lte]: floorMax, [Op.gte]: floorMin - } + }; queryIncludeIncomplete.floor = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: floorMax, [Op.gte]: floorMin }, [Op.is]: null } - } + }; } if (balcony) { query.balcony = { [Op.eq]: balcony - } + }; queryIncludeIncomplete.balcony = { [Op.or]: { [Op.eq]: balcony, [Op.is]: null } - } + }; } - + if (newBuilding) { query.newBuilding = { [Op.eq]: newBuilding - } + }; queryIncludeIncomplete.newBuilding = { [Op.or]: { [Op.eq]: newBuilding, [Op.is]: null } - } + }; } - + if (elevator) { query.elevator = { [Op.eq]: elevator - } + }; queryIncludeIncomplete.elevator = { [Op.or]: { [Op.eq]: elevator, [Op.is]: null } - } + }; } const order = [["updatedAt", "desc"]]; - if(!includeIncompleteAds) { + if (!includeIncompleteAds) { return await db.RealEstate.findAll({ where: query, limit: maxResults, @@ -300,7 +300,6 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { order }); } - }; module.exports = { diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index 54faeb3..bbb7cc0 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -5,11 +5,9 @@ const Op = sequelize.Op; const getSearchRequest = async searchRequestId => { try { - return await db.SearchRequest.findByPk(searchRequestId); - } catch (error) { - console.log("searchrequest.js",error); + console.log("searchrequest.js", error); return null; } }; @@ -116,30 +114,30 @@ const findSearchRequestsForRealEstate = async realEstate => { if (accessRoadType) { query.accessRoadType = { [Op.or]: { - [Op.eq]: 'ANY', + [Op.eq]: "ANY", [Op.eq]: accessRoadType } - } + }; } if (balcony) { query.balcony = { [Op.eq]: balcony - } + }; } if (newBuilding) { query.newBuilding = { [Op.eq]: newBuilding - } + }; } if (elevator) { query.elevator = { [Op.eq]: elevator - } + }; } - + return await db.SearchRequest.findAll({ where: query }); }; -- 2.47.3 From c672b3ab9f6ef373535e7faa3232e7021c3f83be Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Tue, 17 Dec 2019 11:18:58 +0100 Subject: [PATCH 17/20] First review changes: applied prettier, ternary and changed accesRoadType filter --- .gitignore | 2 + app/helpers/db/realEstate.js | 125 +++++++++++++++----------------- app/helpers/db/searchRequest.js | 16 ++-- package-lock.json | 26 +++++++ package.json | 2 + 5 files changed, 94 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index b24fc61..d0441a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules/ .env .idea/ +.eslintrc +.vscode/ \ No newline at end of file diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index 9dd4dfe..c7709db 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -2,7 +2,6 @@ const db = require("../../models/index"); const sequelize = require("sequelize"); const Op = sequelize.Op; - const bulkUpsertRealEstates = async realEstateData => { try { const fieldsToUpdateIfDuplicate = [ @@ -131,42 +130,36 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { //General queries contain only attributes that are defined for every searchreq - //Query for case of complete ads + //Query for case of complete ads const query = { - adType, - realEstateType, - price: { - [Op.lte]: priceMax, - [Op.gte]: priceMin - }, - area: { - [Op.lte]: sizeMax, - [Op.gte]: sizeMin - }, - accessRoadType: { - [Op.or]: { - [Op.eq]: 'ANY', - [Op.eq]: accessRoadType - } - }, - [Op.and]: geoSearchQueryPart - } - + adType, + realEstateType, + price: { + [Op.lte]: priceMax, + [Op.gte]: priceMin + }, + area: { + [Op.lte]: sizeMax, + [Op.gte]: sizeMin + }, + [Op.and]: geoSearchQueryPart + }; + //Query for case of incomplete ads const queryIncludeIncomplete = { adType, realEstateType, price: { - [Op.or] : { - [Op.and] : { + [Op.or]: { + [Op.and]: { [Op.lte]: priceMax, [Op.gte]: priceMin }, - [Op.is] : null + [Op.is]: null } }, area: { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: sizeMax, [Op.gte]: sizeMin @@ -174,133 +167,129 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { [Op.is]: null } }, - accessRoadType: { - [Op.or]: { - [Op.eq]: 'ANY', - [Op.eq]: accessRoadType, - [Op.is]: null - } - }, [Op.and]: geoSearchQueryPart - } + }; //Every other attribute is checked separately and included in query only if it is defined if (gardenSizeMax && gardenSizeMin) { query.gardenSize = { [Op.lte]: gardenSizeMax, [Op.gte]: gardenSizeMin - } + }; queryIncludeIncomplete.gardenSize = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: gardenSizeMax, [Op.gte]: gardenSizeMin }, [Op.is]: null } - } + }; } if (numberOfRoomsMin && numberOfRoomsMax) { query.numberOfRooms = { [Op.lte]: numberOfRoomsMax, [Op.gte]: numberOfRoomsMin - } + }; queryIncludeIncomplete.numberOfRooms = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: numberOfRoomsMax, [Op.gte]: numberOfRoomsMin }, [Op.is]: null } - } + }; } - + if (numberOfFloorsMin && numberOfFloorsMax) { query.numberOfFloors = { [Op.lte]: numberOfFloorsMax, [Op.gte]: numberOfFloorsMin - } + }; queryIncludeIncomplete.numberOfFloors = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: numberOfFloorsMax, [Op.gte]: numberOfFloorsMin }, [Op.is]: null } - } + }; } if (floorMin && floorMax) { query.floor = { [Op.lte]: floorMax, [Op.gte]: floorMin - } + }; queryIncludeIncomplete.floor = { - [Op.or] : { + [Op.or]: { [Op.and]: { [Op.lte]: floorMax, [Op.gte]: floorMin }, [Op.is]: null } - } + }; } if (balcony) { query.balcony = { [Op.eq]: balcony - } + }; queryIncludeIncomplete.balcony = { [Op.or]: { [Op.eq]: balcony, [Op.is]: null } - } + }; } - + if (newBuilding) { query.newBuilding = { [Op.eq]: newBuilding - } + }; queryIncludeIncomplete.newBuilding = { [Op.or]: { [Op.eq]: newBuilding, [Op.is]: null } - } + }; } - + if (elevator) { query.elevator = { [Op.eq]: elevator - } + }; queryIncludeIncomplete.elevator = { [Op.or]: { [Op.eq]: elevator, [Op.is]: null } - } + }; + } + + if (accessRoadType !== "ANY") { + query.accessRoadType = { + [Op.eq]: accessRoadType + }; + queryIncludeIncomplete.accessRoadType = { + [Op.or]: { + [Op.eq]: accessRoadType, + [Op.is]: null + } + }; } const order = [["updatedAt", "desc"]]; - if(!includeIncompleteAds) { - return await db.RealEstate.findAll({ - where: query, - limit: maxResults, - order - }); - } else { - return await db.RealEstate.findAll({ - where: queryIncludeIncomplete, - limit: maxResults, - order - }); - } - + return db.RealEstate.findAll({ + where: includeIncompleteAds ? queryIncludeIncomplete : query, + limit: maxResults, + order + }); }; module.exports = { diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index 54faeb3..bbb7cc0 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -5,11 +5,9 @@ const Op = sequelize.Op; const getSearchRequest = async searchRequestId => { try { - return await db.SearchRequest.findByPk(searchRequestId); - } catch (error) { - console.log("searchrequest.js",error); + console.log("searchrequest.js", error); return null; } }; @@ -116,30 +114,30 @@ const findSearchRequestsForRealEstate = async realEstate => { if (accessRoadType) { query.accessRoadType = { [Op.or]: { - [Op.eq]: 'ANY', + [Op.eq]: "ANY", [Op.eq]: accessRoadType } - } + }; } if (balcony) { query.balcony = { [Op.eq]: balcony - } + }; } if (newBuilding) { query.newBuilding = { [Op.eq]: newBuilding - } + }; } if (elevator) { query.elevator = { [Op.eq]: elevator - } + }; } - + return await db.SearchRequest.findAll({ where: query }); }; diff --git a/package-lock.json b/package-lock.json index b18ae09..9661459 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1052,6 +1052,14 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "eslint-plugin-prettier": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz", + "integrity": "sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA==", + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1271,6 +1279,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -3179,6 +3192,19 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", diff --git a/package.json b/package.json index 7b5441f..75a7cc4 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "compression": "^1.7.4", "dotenv": "^7.0.0", "ejs": "^2.6.1", + "eslint-plugin-prettier": "^3.1.2", "express": "^4.16.4", "express-ejs-layouts": "^2.5.0", "express-layout": "^0.1.0", @@ -44,6 +45,7 @@ "node-fetch": "^2.3.0", "node-schedule": "^1.3.2", "pg": "^7.10.0", + "prettier": "^1.19.1", "react-step-wizard": "^5.1.0", "sequelize": "^5.18.4", "sequelize-cli": "^5.5.0" -- 2.47.3 From 251437f815f1dc06bf703ca16d260dff19b16f4c Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Wed, 18 Dec 2019 02:04:31 +0100 Subject: [PATCH 18/20] Changed searchRequest to include case of incomplete ads wanted. --- app/common/enums.js | 49 +++++++++++++++++++++++++++++++++ app/helpers/db/searchRequest.js | 39 ++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/app/common/enums.js b/app/common/enums.js index 4737346..33cb41e 100644 --- a/app/common/enums.js +++ b/app/common/enums.js @@ -104,6 +104,13 @@ const AD_CATEGORY = { id: "FLAT", title: "Stan", hasGardenSize: false, + hasAccesRoadType: true, + hasBalconyProp: true, + hasNewBuildingProp: true, + hasElevatorProp: true, + hasNumberOfRoom: true, + hasNumberOfFloors: false, + hasFloorProp: true, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS @@ -112,6 +119,13 @@ const AD_CATEGORY = { id: "HOUSE", title: "Kuća", hasGardenSize: true, + hasAccesRoadType: true, + hasBalconyProp: true, + hasNewBuildingProp: true, + hasElevatorProp: false, + hasNumberOfRoom: true, + hasNumberOfFloors: true, + hasFloorProp: false, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS, @@ -121,6 +135,13 @@ const AD_CATEGORY = { id: "OFFICE", title: "Kancelarija", hasGardenSize: false, + hasAccesRoadType: true, + hasBalconyProp: false, + hasNewBuildingProp: true, + hasElevatorProp: true, + hasNumberOfRoom: true, + hasNumberOfFloors: false, + hasFloorProp: true, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS @@ -129,6 +150,13 @@ const AD_CATEGORY = { id: "LAND", title: "Zemljište", hasGardenSize: false, + hasAccesRoadType: true, + hasBalconyProp: false, + hasNewBuildingProp: false, + hasElevatorProp: false, + hasNumberOfRoom: false, + hasNumberOfFloors: false, + hasFloorProp: false, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: LAND_SIZE_SLIDER_OPTIONS @@ -137,6 +165,13 @@ const AD_CATEGORY = { id: "APARTMENT", title: "Apartman", hasGardenSize: false, + hasAccesRoadType: true, + hasBalconyProp: true, + hasNewBuildingProp: true, + hasElevatorProp: true, + hasNumberOfRoom: true, + hasNumberOfFloors: false, + hasFloorProp: true, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS @@ -145,6 +180,13 @@ const AD_CATEGORY = { id: "GARAGE", title: "Garaža", hasGardenSize: false, + hasAccesRoadType: true, + hasBalconyProp: false, + hasNewBuildingProp: false, + hasElevatorProp: false, + hasNumberOfRoom: false, + hasNumberOfFloors: false, + hasFloorProp: false, priceSliderOptionsSale: GARAGE_PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: GARAGE_PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: GARAGE_SIZE_SLIDER_OPTIONS @@ -153,6 +195,13 @@ const AD_CATEGORY = { id: "COTTAGE", title: "Vikendica", hasGardenSize: true, + hasAccesRoadType: true, + hasBalconyProp: true, + hasNewBuildingProp: true, + hasElevatorProp: false, + hasNumberOfRoom: true, + hasNumberOfFloors: true, + hasFloorProp: false, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE, priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS, diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index bbb7cc0..dcb36a0 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -2,6 +2,7 @@ const db = require("../../models/index"); const sequelize = require("sequelize"); const Op = sequelize.Op; +const { AD_CATEGORY } = require("../../common/enums"); const getSearchRequest = async searchRequestId => { try { @@ -48,15 +49,20 @@ const findSearchRequestsForRealEstate = async realEstate => { const geoSearchQueryPart = sequelize.where(contains, true); - //General query contains only attributes that are defined for every realestate - not null + //General query contains only attributes that are defined for every RealEstate - not null const query = { adType, realEstateType, subscribed: true, [Op.and]: geoSearchQueryPart }; + //Needed for defining which attribute should exist or not + const realEstateTypeObject = AD_CATEGORY[realEstateType]; + //Needed to decide on including incomplete RealEstates data + let checkForIncompleteWanted = false; - //Every other attribute is checked separately and included in query only if it is defined + //Attributes are checked separately and included in query only if defined + //Price and area should be defined for every property if (price) { query.priceMin = { [Op.lte]: price @@ -64,6 +70,8 @@ const findSearchRequestsForRealEstate = async realEstate => { query.priceMax = { [Op.gte]: price }; + } else { + checkForIncompleteWanted = true; } if (area) { @@ -73,8 +81,10 @@ const findSearchRequestsForRealEstate = async realEstate => { query.sizeMax = { [Op.gte]: area }; + } else { + checkForIncompleteWanted = true; } - + //Other attributes can be defined or not depending on RealEstate type if (gardenSize) { query.gardenSizeMin = { [Op.lte]: gardenSize @@ -82,6 +92,8 @@ const findSearchRequestsForRealEstate = async realEstate => { query.gardenSizeMax = { [Op.gte]: gardenSize }; + } else if (realEstateTypeObject.hasGardenSize) { + checkForIncompleteWanted = true; } if (numberOfRooms) { @@ -91,6 +103,8 @@ const findSearchRequestsForRealEstate = async realEstate => { query.numberOfRoomsMax = { [Op.gte]: numberOfRooms }; + } else if (realEstateTypeObject.hasNumberOfRoom) { + checkForIncompleteWanted = true; } if (numberOfFloors) { @@ -100,6 +114,8 @@ const findSearchRequestsForRealEstate = async realEstate => { query.numberOfFloorsMax = { [Op.gte]: numberOfFloors }; + } else if (realEstateTypeObject.hasNumberOfFloors) { + checkForIncompleteWanted = true; } if (floor) { @@ -109,6 +125,8 @@ const findSearchRequestsForRealEstate = async realEstate => { query.floorMax = { [Op.gte]: floor }; + } else if (realEstateTypeObject.hasFloorProp) { + checkForIncompleteWanted = true; } if (accessRoadType) { @@ -118,26 +136,41 @@ const findSearchRequestsForRealEstate = async realEstate => { [Op.eq]: accessRoadType } }; + } else if (realEstateTypeObject.hasAccesRoadType) { + checkForIncompleteWanted = true; } if (balcony) { query.balcony = { [Op.eq]: balcony }; + } else if (realEstateTypeObject.hasBalconyProp) { + checkForIncompleteWanted = true; } if (newBuilding) { query.newBuilding = { [Op.eq]: newBuilding }; + } else if (realEstateTypeObject.hasNewBuildingProp) { + checkForIncompleteWanted = true; } if (elevator) { query.elevator = { [Op.eq]: elevator }; + } else if (realEstateTypeObject.hasElevatorProp) { + checkForIncompleteWanted = true; } + //If one of the attributes that exists for property type is null + //we include in query to check if incomplete real estates are accepted + if (checkForIncompleteWanted) { + query.includeIncompleteAds = { + [Op.eq]: true + }; + } return await db.SearchRequest.findAll({ where: query }); }; -- 2.47.3 From bee390aa1572d764784a19425dc7352872fa1b5a Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Wed, 18 Dec 2019 21:49:12 +0100 Subject: [PATCH 19/20] RealEstate included even is price is null. --- app/helpers/db/realEstate.js | 9 +++++++-- app/helpers/db/searchRequest.js | 3 +-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/helpers/db/realEstate.js b/app/helpers/db/realEstate.js index c7709db..ebeb84c 100644 --- a/app/helpers/db/realEstate.js +++ b/app/helpers/db/realEstate.js @@ -135,8 +135,13 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => { adType, realEstateType, price: { - [Op.lte]: priceMax, - [Op.gte]: priceMin + [Op.or]: { + [Op.and]: { + [Op.lte]: priceMax, + [Op.gte]: priceMin + }, + [Op.is]: null + } }, area: { [Op.lte]: sizeMax, diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js index dcb36a0..808637a 100644 --- a/app/helpers/db/searchRequest.js +++ b/app/helpers/db/searchRequest.js @@ -63,6 +63,7 @@ const findSearchRequestsForRealEstate = async realEstate => { //Attributes are checked separately and included in query only if defined //Price and area should be defined for every property + if (price) { query.priceMin = { [Op.lte]: price @@ -70,8 +71,6 @@ const findSearchRequestsForRealEstate = async realEstate => { query.priceMax = { [Op.gte]: price }; - } else { - checkForIncompleteWanted = true; } if (area) { -- 2.47.3 From ef5de27c067cabfa24080a0d54bdc379c46987ad Mon Sep 17 00:00:00 2001 From: Naida Vatric Date: Wed, 18 Dec 2019 22:21:56 +0100 Subject: [PATCH 20/20] Add currency to price filters - added above input --- app/views/standardFilters.ejs | 67 +++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/app/views/standardFilters.ejs b/app/views/standardFilters.ejs index 423d694..27a6bba 100644 --- a/app/views/standardFilters.ejs +++ b/app/views/standardFilters.ejs @@ -1,66 +1,73 @@ -
+
-
Cijena
-

+
Cijena (KM)
+

-
+
- - +
- +
-
+
-
Površina
-

+
Površina (m2)
+

-
+
- - +
- +
-
+
<% if(hasGardenSize) { %> -
-
Površina okućnice
-

-
-
-
+
+
Površina okućnice (m2)
+

+
+
+
-
-
-
- - -
-
- -
+
+
+
+
+
+ +
+
<% } %>