10 Commits

Author SHA1 Message Date
GotPPay
7567b27bb8 only log errors 2017-11-22 12:42:48 +01:00
GotPPay
755973e42d Only log errors 2017-11-22 12:37:51 +01:00
GotPPay
9d9110bf63 new web-app.bundle 2017-11-13 21:13:34 +01:00
GotPPay
50b737d5ac url port removal 2017-11-13 21:06:00 +01:00
GotPPay
02410a8c3c css fix, url fix 2017-11-13 19:46:26 +01:00
GotPPay
1c25fe6502 css fix; url fix 2017-11-13 19:40:30 +01:00
Bilal
7f3f08c65c izmjene na serveru 2017-11-13 18:34:43 +00:00
GotPPay
2974480b83 css fix ; url fix 2017-11-13 19:26:43 +01:00
Bilal
2e2551f3c3 changed localhost to public ip 2017-11-06 19:52:57 +00:00
GotPPay
ec9a29e04d welcome popeup + mobile friendly 2017-11-06 14:38:47 +01:00
26 changed files with 27882 additions and 174 deletions

View File

@@ -752,7 +752,7 @@ router.get('/search/listings', function () {
//Get only ads with location //Get only ads with location
query = Object.assign(query, { query = Object.assign(query, {
has_map: true hasMap: true
}); });
//AND //AND

View File

@@ -97,7 +97,7 @@ router.get ('/search/listings', async (req, res, next) => {
//Get only ads with location //Get only ads with location
query = Object.assign (query, { query = Object.assign (query, {
has_map: true, hasMap: true,
}); });
//AND //AND

1
common/config.js Normal file
View File

@@ -0,0 +1 @@
export const BASE_URL = '138.68.67.31';

View File

@@ -0,0 +1 @@
RENTAL_FROM_PAGE=1 RENTAL_TO_PAGE=45 PROSTOR_FROM_PAGE=1 PROSTOR_TO_PAGE=26 MONGO_URL=mongodb://localhost:27017/kivi node /home/bilal/kivi/crawler/build/crawler.js > /home/bilal/crawler.log

View File

@@ -39,11 +39,11 @@ async function crawlAll() {
await saver.connect(); await saver.connect();
await saver.save(results); await saver.save(results);
} catch (e) { } catch (e) {
console.log("Error saving. Trying next saver! ", e); console.log("[E] Error saving. Trying next saver! ", e);
} }
} }
} catch (e) { } catch (e) {
console.log("Error crawling. Trying next crawler! ", e); console.log("[E] Error crawling. Trying next crawler! ", e);
} }
} }

View File

@@ -12,10 +12,10 @@ export default class MongoSaver {
if (!saver.ready) { if (!saver.ready) {
MongoClient.connect(saver.url, (err, db) => { MongoClient.connect(saver.url, (err, db) => {
if (err) { if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err); console.log('[E] Unable to connect to the mongoDB server. Error:', err);
reject(err); reject(err);
} else { } else {
console.log('Connection established to', this.url); //console.log('[I] Connection established to', this.url);
saver.db = db; saver.db = db;
saver.collection = db.collection('listings'); saver.collection = db.collection('listings');
saver.ready = true; saver.ready = true;
@@ -43,7 +43,7 @@ export default class MongoSaver {
//Close connection //Close connection
await this.disconnect(); await this.disconnect();
} catch (e) { } catch (e) {
console.log("error closing", e); console.log("[E] Error closing connection", e);
} }
} }

View File

@@ -113,7 +113,7 @@ export default class OlxCrawler {
return data; return data;
} catch (e) { } catch (e) {
console.error('Exception caught: ' + e.message); console.error('[E] Exception caught: ' + e.message);
} }
return null; return null;
@@ -121,7 +121,7 @@ export default class OlxCrawler {
async indexPage(pageNr, maxResults = 1000) { async indexPage(pageNr, maxResults = 1000) {
try { try {
console.log('Starting to index page: ' + pageNr); //console.log('Starting to index page: ' + pageNr);
const url = `http://www.olx.ba/pretraga?vrsta=samoprodaja&sort_order=desc&kategorija=23&sort_po=datum&kanton=9&stranica=${pageNr}`; const url = `http://www.olx.ba/pretraga?vrsta=samoprodaja&sort_order=desc&kategorija=23&sort_po=datum&kanton=9&stranica=${pageNr}`;
const res = await fetch(url); const res = await fetch(url);
@@ -138,7 +138,7 @@ export default class OlxCrawler {
let actualNoOfResults = (hrefs.length <= maxResults) ? hrefs.length : maxResults; let actualNoOfResults = (hrefs.length <= maxResults) ? hrefs.length : maxResults;
for (let i = 0; i < hrefs.length; i++) { for (let i = 0; i < hrefs.length; i++) {
console.log(`indexing: ${hrefs[i]}`); //console.log(`indexing: ${hrefs[i]}`);
const singleData = await this.indexSingle(hrefs[i]); const singleData = await this.indexSingle(hrefs[i]);
@@ -150,7 +150,7 @@ export default class OlxCrawler {
return results; return results;
} catch (e) { } catch (e) {
console.error('Exception caught:' + e); console.error('[E] Exception caught:' + e);
} }
} }

View File

@@ -166,11 +166,11 @@ export default class ProstorCrawler {
//images: cloudinaryImages //images: cloudinaryImages
images, images,
}; };
console.log (data); //console.log (data);
return data; return data;
} catch (e) { } catch (e) {
console.error ('Exception caught: ' + e.message); console.error ('[E] Exception caught: ' + e.message);
} }
return null; return null;
@@ -178,7 +178,7 @@ export default class ProstorCrawler {
async indexPage (pageNr, maxResults = 1000) { async indexPage (pageNr, maxResults = 1000) {
try { try {
console.log ('Starting to index page: ' + pageNr); //console.log ('Starting to index page: ' + pageNr);
const url = `http://prostor.ba/index.php`; const url = `http://prostor.ba/index.php`;
const data = new FormData (); const data = new FormData ();
@@ -208,7 +208,7 @@ export default class ProstorCrawler {
const results = {}; const results = {};
for (const href of hrefs) { for (const href of hrefs) {
console.log (`indexing: ${href}`); //console.log (`indexing: ${href}`);
const singleData = await this.indexSingle (href); const singleData = await this.indexSingle (href);
@@ -221,7 +221,7 @@ export default class ProstorCrawler {
return results; return results;
} catch (e) { } catch (e) {
console.error ('Exception caught:' + e); console.error ('[E] Exception caught:' + e);
} }
} }

View File

@@ -22,7 +22,6 @@ import {
export default class RentalCrawler { export default class RentalCrawler {
constructor (fromPage = 0, toPage = 10, maxResults = 1000) { constructor (fromPage = 0, toPage = 10, maxResults = 1000) {
console.log ('Rental Crawler');
this.fromPage = fromPage; this.fromPage = fromPage;
this.toPage = toPage; this.toPage = toPage;
@@ -70,7 +69,7 @@ export default class RentalCrawler {
dataJson = JSON.parse (dataJsonString); dataJson = JSON.parse (dataJsonString);
break; break;
} catch (e) { } catch (e) {
console.log ('No JSON string'); //console.log ('No JSON string');
if (i === lastN) throw e; if (i === lastN) throw e;
} }
} }
@@ -95,7 +94,6 @@ export default class RentalCrawler {
lng = dataJson['re_realEstates_longitude']; lng = dataJson['re_realEstates_longitude'];
hasMap = true; hasMap = true;
} catch (e) { } catch (e) {
console.log ('error : ' + e);
//This ad has no JSON string, informations should be retrieved using HTML selectors //This ad has no JSON string, informations should be retrieved using HTML selectors
time = undefined; time = undefined;
lat = 0; lat = 0;
@@ -183,7 +181,7 @@ export default class RentalCrawler {
return data; return data;
} catch (e) { } catch (e) {
console.error ('Exception caught: ' + e.message); console.error ('[E] Exception caught: ' + e.message);
} }
return null; return null;
@@ -191,7 +189,7 @@ export default class RentalCrawler {
async indexPage (pageNr, maxResults = 1000) { async indexPage (pageNr, maxResults = 1000) {
try { try {
console.log ('Starting to index page: ' + pageNr); //console.log ('Starting to index page: ' + pageNr);
const url = 'http://www.rental.ba/pretraga/prodaja-1/stranica-' + pageNr; const url = 'http://www.rental.ba/pretraga/prodaja-1/stranica-' + pageNr;
@@ -227,7 +225,7 @@ export default class RentalCrawler {
const results = {}; const results = {};
for (const href of hrefs) { for (const href of hrefs) {
console.log (`indexing: ${href}`); //console.log (`indexing: ${href}`);
const singleData = await this.indexSingle (href); const singleData = await this.indexSingle (href);
@@ -240,7 +238,7 @@ export default class RentalCrawler {
return results; return results;
} catch (e) { } catch (e) {
console.error ('Exception caught:' + e); console.error ('[E] Exception caught:' + e);
} }
} }

27652
web/dist/app.bundle.js vendored

File diff suppressed because one or more lines are too long

BIN
web/dist/static/images/rent_0.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
web/dist/static/images/rent_0_mobile.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
web/dist/static/images/rent_1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
web/dist/static/images/rent_1_mobile.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
web/dist/static/images/sale_0.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
web/dist/static/images/sale_0_mobile.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
web/dist/static/images/sale_1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
web/dist/static/images/sale_1_mobile.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

170
web/dist/welcome.css vendored
View File

@@ -5,25 +5,25 @@
/*}*/ /*}*/
.welcome-container h1 { .welcome-container h1 {
font-size: 2em; font-size: 1.2em;
text-align: center; text-align: center;
} }
.welcome-container h2 { .welcome-container h2 {
padding-bottom: 25px; /*padding-bottom: 25px;*/
color: #2d3138; color: #2d3138;
font-size: 26px; font-size: 1em;
font-weight: 200; font-weight: 200;
text-align: center; text-align: center;
letter-spacing: .59px; letter-spacing: .59px;
} }
.welcome-container-bg { .welcome-container-bg {
/*background-color: rgb(92, 192, 99);*/ /*background-color: rgb(92, 192, 99);*/
background-image: url('static/map.jpg'); /*background-image: url('static/map.jpg');*/
/*background-image: url('static/images/sa-bg.jpg');*/ background-image: url('static/images/sa-bg.jpg');
background-size: auto 100%;
/*background-position: center;*/ /*background-position: center;*/
-moz-filter: blur(5px); -moz-filter: blur(5px);
-o-filter: blur(5px); -o-filter: blur(5px);
@@ -40,26 +40,154 @@
} }
.welcome-container { .welcome-container {
position: fixed; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top:0;
bottom:0;
z-index: 0; z-index: 0;
margin-left: 20px; /*margin-left: 20px;
margin-right: 20px; margin-right: 20px;*/
height: 100%; height: 100%;
padding: 100px; /*padding: 100px;*/
} }
.welcome-content { .welcome-content {
/*height: 100%;*/ /*height: 100%;*/
margin: 0 auto; /*margin: 0 auto;*/
width: 600px; width: 240px;
background-color: hsla(0,0%,100%,.95); background-color: hsla(0,0%,100%,.95);
box-shadow: 0 2px 4px 0 rgba(73,73,73,.1); box-shadow: 0 2px 4px 0 rgba(73,73,73,.1);
padding: 50px; margin-left: auto;
margin-right: auto;
margin-top:40%;
/*padding: 50px;*/
} }
.welcome-content .gmaps-places-input-welcome { .buy-button-active {
height: 80px;
width: 100%; width: 80px;
background:url('static/images/sale_1_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 10%;
margin-right: 5%;
}
.buy-button-inactive {
height: 80px;
width: 80px;
background:url('static/images/sale_0_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 10%;
margin-right: 5%;
}
.rent-button-active{
height: 80px;
width: 80px;
background:url('static/images/rent_1_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 5%;
}
.rent-button-inactive{
height: 80px;
width: 80px;
background:url('static/images/rent_0_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 5%;
}
.search-button{
background-color: #b6d53b;
margin: 10px;
border: none;
text-align: center;
font-size: 1em;
width: 90%;
margin-left:5%;
margin-right: 5%;
}
@media (min-width: 550px) {
.welcome-container h1 {
font-size: 2em;
text-align: center;
}
.welcome-container h2 {
/*padding-bottom: 25px;*/
color: #2d3138;
font-size: 1.4em;
font-weight: 200;
text-align: center;
letter-spacing: .59px;
}
.welcome-content {
/*height: 100%;*/
/*margin: 0 auto;*/
width: 500px;
background-color: hsla(0,0%,100%,.95);
box-shadow: 0 2px 4px 0 rgba(73,73,73,.1);
margin-left: auto;
margin-right: auto;
margin-top:10%;
/*padding: 50px;*/
}
.buy-button-active {
height: 150px;
width: 150px;
background:url('static/images/sale_1_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 15%;
margin-right: 5%;
}
.buy-button-inactive {
height: 150px;
width: 150px;
background:url('static/images/sale_0_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 15%;
margin-right: 5%;
}
.rent-button-active{
height: 150px;
width: 150px;
background:url('static/images/rent_1_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 5%;
}
.rent-button-inactive{
height: 150px;
width: 150px;
background:url('static/images/rent_0_mobile.png') no-repeat;
background-size: contain;
border: none;
margin-left: 5%;
}
.search-button{
background-color: #b6d53b;
margin: 10px;
border: none;
text-align: center;
font-size: 1.4em;
width: 90%;
margin-left:5%;
margin-right: 5%;
}
} }

View File

@@ -22,7 +22,8 @@ class Main extends React.Component {
filters: { filters: {
rooms: {}, rooms: {},
category: {}, category: {},
status : {} status : {},
adType: 0
}, },
mobileView: 'MAP', mobileView: 'MAP',
contact: { contact: {
@@ -34,6 +35,8 @@ class Main extends React.Component {
} }
} }
console.log("Props : ");
console.log(props.initialState);
if (props.initialState) { if (props.initialState) {
props.initialState.sort = props.initialState.sort || state.sort props.initialState.sort = props.initialState.sort || state.sort
state.filters.rooms = props.initialState.rooms state.filters.rooms = props.initialState.rooms
@@ -49,6 +52,7 @@ class Main extends React.Component {
state.filters.maxSize = props.initialState.maxSize state.filters.maxSize = props.initialState.maxSize
state.filters.minPrice = props.initialState.minPrice state.filters.minPrice = props.initialState.minPrice
state.filters.maxPrice = props.initialState.maxPrice state.filters.maxPrice = props.initialState.maxPrice
state.filters.adType = props.initialState.adType
} }
this.state = state this.state = state
@@ -234,7 +238,8 @@ class Main extends React.Component {
maxSize, maxSize,
minPrice, minPrice,
maxPrice, maxPrice,
category category,
adType
} = this.state.filters } = this.state.filters
const bounds = map.getBounds() const bounds = map.getBounds()
@@ -246,6 +251,7 @@ class Main extends React.Component {
minPrice, minPrice,
maxPrice, maxPrice,
category, category,
adType,
page: this.state.page, page: this.state.page,
pins: true pins: true
}) })
@@ -404,7 +410,8 @@ class Main extends React.Component {
maxSize, maxSize,
minPrice, minPrice,
maxPrice, maxPrice,
category category,
adType
} = this.state.filters } = this.state.filters
const bounds = map.getBounds() const bounds = map.getBounds()
@@ -416,6 +423,7 @@ class Main extends React.Component {
minPrice, minPrice,
maxPrice, maxPrice,
category, category,
adType,
page: this.state.page, page: this.state.page,
sort: this.state.sort sort: this.state.sort
}) })

View File

@@ -1,55 +1,25 @@
import React from 'react' import React from 'react'
import { pacSelectFirst } from '../helpers/googleMaps' import {AD_TYPE_SALE, AD_TYPE_RENT} from '../../../common/enums';
export default class Welcome extends React.Component { export default class Welcome extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.state = { this.state = {
type: 'SALE' type: AD_TYPE_SALE,
} }
} }
componentDidMount () {
const options = {
componentRestrictions: { country: 'BA' },
types: ['geocode']
}
const input = document.getElementById('gmaps-places-input-welcome')
const searchBox = new google.maps.places.Autocomplete(input, options)
pacSelectFirst(input)
input.addEventListener('focus', e => {
e.target.value = ''
})
searchBox.addListener('place_changed', () => {
const place = searchBox.getPlace()
if (place.geometry.viewport) {
const bounds = place.geometry.viewport.toUrlValue()
this.props.onSearch({
bounds,
type: this.state.type
})
} else {
const location = place.geometry.location
this.props.onSearch({
location,
type: this.state.type
})
}
})
}
onSaleClick () { onSaleClick () {
this.setState({ this.setState({
type: 'SALE' type: AD_TYPE_SALE,
}) })
} }
onRentClick () { onRentClick () {
this.setState({ this.setState({
type: 'RENT' type: AD_TYPE_RENT,
}) })
} }
@@ -63,15 +33,11 @@ export default class Welcome extends React.Component {
<div className='welcome-content'> <div className='welcome-content'>
<h1>KIVI</h1> <h1>KIVI</h1>
<h2>Pronađi svoj novi dom!</h2> <h2>Pronađi svoj novi dom!</h2>
<button <div>
onClick={this.onSaleClick.bind(this)}>Kupovina</button> <button className={this.state.type===AD_TYPE_SALE?'buy-button-active':'buy-button-inactive'} onClick={this.onSaleClick.bind(this)}></button>
<button onClick={this.onRentClick.bind(this)}>Iznajmljivanje</button> <button className={this.state.type===AD_TYPE_RENT?'rent-button-active':'rent-button-inactive'} onClick={this.onRentClick.bind(this)}></button>
<input </div>
type='text' <button className='search-button' onClick={()=>this.props.onSearch({adType: this.state.type})} >TRAŽI</button>
placeholder='Unesite adresu, naselje ili grad'
className='where-to'
id='gmaps-places-input-welcome'
/>
</div> </div>
</div> </div>

View File

@@ -1,84 +1,84 @@
import React from 'react' import React from 'react';
import {render} from 'react-dom' import {render} from 'react-dom';
import Main from './components/Main' import Main from './components/Main';
import Welcome from './components/Welcome' import Welcome from './components/Welcome';
const getInitialState = url => { const getInitialState = url => {
const params = window.location.search.substr(1).split('&') const params = window.location.search.substr (1).split ('&');
const initialState = { const initialState = {
rooms: {}, rooms: {},
category: {} category: {},
} };
for (const param of params) { for (const param of params) {
const [key, value] = param.split('=') const [key, value] = param.split ('=');
if (key === 'rooms' && value !== '') { if (key === 'rooms' && value !== '') {
initialState.rooms = {} initialState.rooms = {};
value.split(',').forEach(k => { value.split (',').forEach (k => {
initialState.rooms[parseInt(k)] = true initialState.rooms[parseInt (k)] = true;
}) });
} }
if (key === 'category' && value !== '') { if (key === 'category' && value !== '') {
initialState.category = {} initialState.category = {};
value.split(',').forEach(k => { value.split (',').forEach (k => {
initialState.category[parseInt(k)] = true initialState.category[parseInt (k)] = true;
}) });
} }
if (key === 'sort') { if (key === 'sort') {
initialState.sort = value initialState.sort = value;
} }
if (key === 'bounds') { if (key === 'bounds') {
initialState.bounds = value initialState.bounds = value;
} }
if (key === 'listingId') { if (key === 'listingId') {
initialState.listingId = value initialState.listingId = value;
} }
if (key === 'type') { if (key === 'adType') {
initialState.type = value initialState.adType = value;
} }
if (key === 'zoom') { if (key === 'zoom') {
initialState.zoom = parseInt(value) initialState.zoom = parseInt (value);
} }
if (['minSize', 'maxSize', 'minPrice', 'maxPrice'].includes(key)) { if (['minSize', 'maxSize', 'minPrice', 'maxPrice'].includes (key)) {
initialState[key] = parseFloat(value) initialState[key] = parseFloat (value);
} }
} }
return initialState return initialState;
} };
const root = document.getElementById('root') const root = document.getElementById ('root');
const initialState = getInitialState(window.location) const initialState = getInitialState (window.location);
const renderMain = (additionalState = {}) => { const renderMain = (additionalState = {}) => {
const main = <Main initialState={{...initialState, ...additionalState}} /> const main = <Main initialState={{...initialState, ...additionalState}} />;
render(main, root) render (main, root);
} };
renderMain() //renderMain ();
// disable temp // disable temp
/*
if (Object.keys(initialState).length === 2 && if (
window.localStorage.getItem('lastLoad') == null) { Object.keys (initialState).length === 2 &&
const onSearch = ({bounds, type, location}) => { window.localStorage.getItem ('lastLoad') == null
window.location = `/?bounds=${bounds}&type=${type}` ) {
//renderMain({ const onSearch = ({adType}) => {
//bounds,
//type console.log("onSearch()");
//}) //window.location = `/?adType=${adType}`;
} renderMain({adType})
const welcome = <Welcome onSearch={onSearch} /> };
render(welcome, root) const welcome = <Welcome onSearch={onSearch} />;
render (welcome, root);
} else { } else {
renderMain() renderMain ();
} }
*/

View File

@@ -1,11 +1,9 @@
import fetch from 'isomorphic-fetch' import fetch from 'isomorphic-fetch'
import {BASE_URL} from '../../../common/config'
const BASE_URL = 'localhost';
//const BASE_URL = '192.168.0.13';
export const saveContactRequest = (listingId, params) => { export const saveContactRequest = (listingId, params) => {
let url = `http://${BASE_URL}:3001/api/contact/${listingId}` let url = `http://${BASE_URL}/api/contact/${listingId}`
return fetch(url, { return fetch(url, {
method: 'POST', method: 'POST',
@@ -18,7 +16,7 @@ export const saveContactRequest = (listingId, params) => {
} }
export const loadListing = id => { export const loadListing = id => {
let url = `http://${BASE_URL}:3001/api/search/listings/${id}` let url = `http://${BASE_URL}/api/search/listings/${id}`
return fetch( return fetch(
url, url,
@@ -37,6 +35,7 @@ export const loadProperties = (
maxSize = '', maxSize = '',
rooms = {}, rooms = {},
category = {}, category = {},
adType=1,
page = 1, page = 1,
pins = false, pins = false,
sort = '' sort = ''
@@ -50,7 +49,7 @@ export const loadProperties = (
// TODO: handle errors // TODO: handle errors
//return fetch(process.env.API_URL + '/api/search', { //return fetch(process.env.API_URL + '/api/search', {
let url = `http://${BASE_URL}:3001/api/search/listings?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}&minSize=${minSize}&maxSize=${maxSize}&category=${allCategories}&page=${page}&pins=${pins}&sort=${sort}` let url = `http://${BASE_URL}/api/search/listings?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}&minSize=${minSize}&maxSize=${maxSize}&adType=${adType}&category=${allCategories}&page=${page}&pins=${pins}&sort=${sort}`
return fetch( return fetch(
url, url,

View File

@@ -1,3 +1,5 @@
import {BASE_URL} from '../../../common/config'
export const formatPrice = p => { export const formatPrice = p => {
if (isNaN(p)) { if (isNaN(p)) {
return 'Po dogovoru' return 'Po dogovoru'
@@ -33,8 +35,7 @@ S poštovanjem
} }
export const listingUrl = (id) => { export const listingUrl = (id) => {
// TODO: fix this once removing hardcoded values return `http://${BASE_URL}/?listingId=${id}`
return `http://localhost:8080/?listingId=${id}`
} }
export const isMobile = () => window.matchMedia("(max-width: 768px)").matches export const isMobile = () => window.matchMedia("(max-width: 768px)").matches

View File

@@ -59,13 +59,15 @@ export default class Router {
sort, sort,
rooms = {}, rooms = {},
category = {}, category = {},
zoom zoom,
adType
} = this.state } = this.state
if (listingId) { if (listingId) {
params.push(`listingId=${listingId}`) params.push(`listingId=${listingId}`)
} }
params.push(`adType=${adType}`);
params.push(`sort=${sort}`) params.push(`sort=${sort}`)
params.push(`bounds=${bounds}`) params.push(`bounds=${bounds}`)
params.push(`zoom=${zoom}`) params.push(`zoom=${zoom}`)

View File

@@ -3,7 +3,13 @@ module.exports = {
output: { output: {
path: __dirname + "/dist", path: __dirname + "/dist",
filename: "app.bundle.js", filename: "app.bundle.js",
publicPath: "http://0.0.0.0:8080/" publicPath: "http://138.68.67.31:8080/"
},
devServer: {
// .. rest of devserver options
host: '0.0.0.0',
disableHostCheck: true
}, },
module: { module: {
loaders: [ loaders: [