Gallery and other stuff
This commit is contained in:
@@ -96,7 +96,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 < actualNoOfResults; 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]);
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ module.exports = {
|
|||||||
}, {
|
}, {
|
||||||
test: /.json?$/,
|
test: /.json?$/,
|
||||||
loader: 'json-loader',
|
loader: 'json-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader']
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
web/components/Gallery.js
Normal file
64
web/components/Gallery.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default class Gallery extends React.Component {
|
||||||
|
onPrevClick (e) {
|
||||||
|
this.props.dispatch({type: 'PREV_IMAGE'});
|
||||||
|
}
|
||||||
|
|
||||||
|
onNextClick (e) {
|
||||||
|
this.props.dispatch({type: 'NEXT_IMAGE'});
|
||||||
|
}
|
||||||
|
|
||||||
|
onImageDotClick (index, e) {
|
||||||
|
this.props.dispatch({type: 'VIEW_IMAGE', action: {index}})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {images, imageIndex} = this.props;
|
||||||
|
if (!images || images.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const showPrev = imageIndex > 0;
|
||||||
|
const showNext = imageIndex < images.length - 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ld-image-container">
|
||||||
|
<img src={images[imageIndex]}></img>
|
||||||
|
{showPrev ?
|
||||||
|
<div
|
||||||
|
className='prev-button'
|
||||||
|
onClick={this.onPrevClick.bind(this)}>
|
||||||
|
<div>
|
||||||
|
<svg fill="white" version="1.1" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 512 512">
|
||||||
|
<path d="M213.7,256L213.7,256L213.7,256L380.9,81.9c4.2-4.3,4.1-11.4-0.2-15.8l-29.9-30.6c-4.3-4.4-11.3-4.5-15.5-0.2L131.1,247.9 c-2.2,2.2-3.2,5.2-3,8.1c-0.1,3,0.9,5.9,3,8.1l204.2,212.7c4.2,4.3,11.2,4.2,15.5-0.2l29.9-30.6c4.3-4.4,4.4-11.5,0.2-15.8 L213.7,256z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
{showNext ?
|
||||||
|
<div
|
||||||
|
className='next-button'
|
||||||
|
onClick={this.onNextClick.bind(this)}>
|
||||||
|
<div>
|
||||||
|
<svg fill="white" version="1.1" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 512 512">
|
||||||
|
<path d="M298.3,256L298.3,256L298.3,256L131.1,81.9c-4.2-4.3-4.1-11.4,0.2-15.8l29.9-30.6c4.3-4.4,11.3-4.5,15.5-0.2l204.2,212.7 c2.2,2.2,3.2,5.2,3,8.1c0.1,3-0.9,5.9-3,8.1L176.7,476.8c-4.2,4.3-11.2,4.2-15.5-0.2L131.3,446c-4.3-4.4-4.4-11.5-0.2-15.8 L298.3,256z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
<div className="image-dots">
|
||||||
|
{images.map((img, index) => {
|
||||||
|
let cls = 'image-dot'
|
||||||
|
if (index === imageIndex) {
|
||||||
|
cls += ' selected'
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div onClick={this.onImageDotClick.bind(this, index)} className={cls}></div>
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Gallery from './gallery';
|
||||||
|
|
||||||
export default class ListingDetails extends React.Component {
|
export default class ListingDetails extends React.Component {
|
||||||
onReadMore (e) {
|
onReadMore (e) {
|
||||||
@@ -14,8 +15,12 @@ export default class ListingDetails extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {listing, descriptionExpanded} = this.props;
|
const {listing, descriptionExpanded} = this.props;
|
||||||
|
if (!listing) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const descriptionClasses = descriptionExpanded ? "ld-description expanded" : "ld-description";
|
const descriptionClasses = descriptionExpanded ? "ld-description expanded" : "ld-description";
|
||||||
|
const images = listing.images.map((image) => ({original: image, thumbnail: image}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ld-container">
|
<div className="ld-container">
|
||||||
<div className="ld-header">
|
<div className="ld-header">
|
||||||
@@ -37,9 +42,10 @@ export default class ListingDetails extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ld-details">
|
<div className="ld-details">
|
||||||
<div className="ld-image-container">
|
<Gallery
|
||||||
<img src={listing.images[0]}></img>
|
dispatch={this.props.dispatch}
|
||||||
</div>
|
images={listing.images}
|
||||||
|
imageIndex={this.props.imageIndex} />
|
||||||
<div className="ld-price-address-box">
|
<div className="ld-price-address-box">
|
||||||
<div className="ld-price">
|
<div className="ld-price">
|
||||||
{listing.price}
|
{listing.price}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ class Main extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
listingDetails: false,
|
listingDetails: false,
|
||||||
|
listings: (new Map()),
|
||||||
|
imageIndex: 0,
|
||||||
filters: {
|
filters: {
|
||||||
minPrice: 0
|
minPrice: 0
|
||||||
}
|
}
|
||||||
@@ -97,7 +99,7 @@ class Main extends React.Component {
|
|||||||
marker.addListener('click', () => {
|
marker.addListener('click', () => {
|
||||||
console.log('clicking...')
|
console.log('clicking...')
|
||||||
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
this.dispatch({type: 'VIEW_LISTING_DETAILS', action: {
|
||||||
id: index
|
id: prop.url
|
||||||
}})
|
}})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -141,10 +143,12 @@ class Main extends React.Component {
|
|||||||
const children = [];
|
const children = [];
|
||||||
|
|
||||||
if (this.state.listingDetails) {
|
if (this.state.listingDetails) {
|
||||||
const listing = this.state.listings[this.state.listingId];
|
console.log('CURRENT LISTINGS', this.state.listings);
|
||||||
|
const listing = this.state.listings.get(this.state.listingId);
|
||||||
console.log(this.state);
|
console.log(this.state);
|
||||||
children.push(<ListingDetails
|
children.push(<ListingDetails
|
||||||
listing={listing}
|
listing={listing}
|
||||||
|
imageIndex={this.state.imageIndex}
|
||||||
dispatch={this.dispatch.bind(this)}
|
dispatch={this.dispatch.bind(this)}
|
||||||
descriptionExpanded={this.state.descriptionExpanded}
|
descriptionExpanded={this.state.descriptionExpanded}
|
||||||
onBackClick={this.onBackClick.bind(this)}/>);
|
onBackClick={this.onBackClick.bind(this)}/>);
|
||||||
|
|||||||
3678
web/dist/app.bundle.js
vendored
3678
web/dist/app.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
61
web/dist/main.css
vendored
61
web/dist/main.css
vendored
@@ -596,15 +596,69 @@ html {
|
|||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-dots {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-dot {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin: 0 5px;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
box-shadow: 0 1px 0 #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-dot.selected {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.ld-image-container {
|
.ld-image-container {
|
||||||
height: 375px;
|
height: 375px;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ld-image-container .prev-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ld-image-container .next-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ld-image-container .prev-button div,
|
||||||
|
.ld-image-container .next-button div {
|
||||||
|
width: 50px;
|
||||||
|
position: absolute;
|
||||||
|
top: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ld-image-container .next-button div {
|
||||||
|
right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ld-image-container img {
|
.ld-image-container img {
|
||||||
width: 100%;
|
/*width: 100%;*/
|
||||||
height: 100%;
|
/*height: 100%;*/
|
||||||
|
max-height: 375px;
|
||||||
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ld-price-address-box {
|
.ld-price-address-box {
|
||||||
@@ -672,6 +726,9 @@ html {
|
|||||||
background-image: #fff;
|
background-image: #fff;
|
||||||
background-image: -webkit-gradient(bottom,from(#fff),to(hsla(0,0%,100%,0)));
|
background-image: -webkit-gradient(bottom,from(#fff),to(hsla(0,0%,100%,0)));
|
||||||
background-image: -webkit-linear-gradient(bottom,#fff,hsla(0,0%,100%,0));
|
background-image: -webkit-linear-gradient(bottom,#fff,hsla(0,0%,100%,0));
|
||||||
|
|
||||||
|
background-image: -moz-gradient(bottom,from(#fff),to(hsla(0,0%,100%,0)));
|
||||||
|
background-image: -moz-linear-gradient(bottom,#fff,hsla(0,0%,100%,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
.ld-check-availability {
|
.ld-check-availability {
|
||||||
|
|||||||
@@ -10,13 +10,20 @@ const viewListingDetails= ({type, action}, component) => {
|
|||||||
component.setState({
|
component.setState({
|
||||||
listingDetails: true,
|
listingDetails: true,
|
||||||
listingId: action.id,
|
listingId: action.id,
|
||||||
descriptionExpanded: false
|
descriptionExpanded: false,
|
||||||
|
imageIndex: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const listingsLoaded = ({type, action}, component) => {
|
const listingsLoaded = ({type, action}, component) => {
|
||||||
|
const currentListings = component.state.listings;
|
||||||
|
|
||||||
|
for(const listing of action.listings) {
|
||||||
|
currentListings.set(listing.url, listing)
|
||||||
|
}
|
||||||
|
|
||||||
component.setState({
|
component.setState({
|
||||||
listings: action.listings
|
listings: currentListings
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,10 +33,35 @@ const expandDescription = ({type, action}, component) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const prevImage = ({type, action}, component) => {
|
||||||
|
const index = component.state.imageIndex;
|
||||||
|
if (index > 0) {
|
||||||
|
component.setState({
|
||||||
|
imageIndex: index - 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextImage = ({type, action}, component) => {
|
||||||
|
const index = component.state.imageIndex;
|
||||||
|
component.setState({
|
||||||
|
imageIndex: index + 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewImage = ({type, action}, component) => {
|
||||||
|
component.setState({
|
||||||
|
imageIndex: action.index
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
'SET_MIN_PRICE': setMinPrice,
|
'SET_MIN_PRICE': setMinPrice,
|
||||||
'LISTINGS_LOADED': listingsLoaded,
|
'LISTINGS_LOADED': listingsLoaded,
|
||||||
'EXPAND_DESCRIPTION': expandDescription,
|
'EXPAND_DESCRIPTION': expandDescription,
|
||||||
|
'PREV_IMAGE': prevImage,
|
||||||
|
'NEXT_IMAGE': nextImage,
|
||||||
|
'VIEW_IMAGE': viewImage,
|
||||||
'VIEW_LISTING_DETAILS': viewListingDetails
|
'VIEW_LISTING_DETAILS': viewListingDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,14 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"react": "^15.3.2",
|
||||||
|
"react-dom": "^15.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
"babel-core": "^6.18.2",
|
"babel-core": "^6.18.2",
|
||||||
"babel-loader": "^6.2.7",
|
"babel-loader": "^6.2.7",
|
||||||
"babel-preset-es2015": "^6.18.0",
|
"babel-preset-es2015": "^6.18.0",
|
||||||
"babel-preset-react": "^6.16.0",
|
"babel-preset-react": "^6.16.0",
|
||||||
"react": "^15.3.2",
|
|
||||||
"react-dom": "^15.3.2",
|
|
||||||
"react-image-gallery": "^0.7.15"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"webpack": "^1.13.3",
|
"webpack": "^1.13.3",
|
||||||
"webpack-dev-server": "^1.16.2"
|
"webpack-dev-server": "^1.16.2"
|
||||||
}
|
}
|
||||||
|
|||||||
1550
web/yarn.lock
1550
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user