Nikola Ignjatovic 4 лет назад
Родитель
Сommit
a4cf45c263

+ 14
- 0
package-lock.json Просмотреть файл

"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"dom-scroll-into-view": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.0.1.tgz",
"integrity": "sha1-Mqu5Lw2P7KYhUWKu9D5LRJq42Zw="
},
"dom-serializer": { "dom-serializer": {
"version": "0.2.2", "version": "0.2.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
"whatwg-fetch": "^3.4.1" "whatwg-fetch": "^3.4.1"
} }
}, },
"react-autocomplete": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/react-autocomplete/-/react-autocomplete-1.8.1.tgz",
"integrity": "sha1-67vEAABqqRrVOLLRRye55+XQYxA=",
"requires": {
"dom-scroll-into-view": "1.0.1",
"prop-types": "^15.5.10"
}
},
"react-dev-utils": { "react-dev-utils": {
"version": "11.0.4", "version": "11.0.4",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz",

+ 1
- 0
package.json Просмотреть файл

"lodash.isempty": "^4.4.0", "lodash.isempty": "^4.4.0",
"owasp-password-strength-test": "^1.3.0", "owasp-password-strength-test": "^1.3.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-autocomplete": "^1.8.1",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-helmet-async": "^1.0.9", "react-helmet-async": "^1.0.9",
"react-i18next": "^11.10.0", "react-i18next": "^11.10.0",

+ 2
- 1
src/App.js Просмотреть файл

import history from './store/utils/history'; import history from './store/utils/history';
//import Header from './components/Header/Header'; //import Header from './components/Header/Header';
import "react-responsive-carousel/lib/styles/carousel.min.css"; import "react-responsive-carousel/lib/styles/carousel.min.css";
// import Header from './components/Header/Header';
// import Sidebar from './components/Sidebar/Sidebar'; // import Sidebar from './components/Sidebar/Sidebar';
import AppRoutes from './AppRoutes'; import AppRoutes from './AppRoutes';


</> </>
</Router> </Router>


);
);


export default App; export default App;

+ 1
- 1
src/assets/styles/_variables.scss Просмотреть файл

$base-font-size: 16px; $base-font-size: 16px;
$base-font-size-md: 14px; $base-font-size-md: 14px;


$font-family: 'Avenir Next';
$font-family: "Source Sans Pro",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";


// Colors // Colors
$color-primary: #024f86; $color-primary: #024f86;

+ 47
- 7
src/components/CreateScrapeRequest/CreateScrapeRequest.js Просмотреть файл

import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import Select from 'react-select' import Select from 'react-select'
import { prices, beds, types, lifeStyles } from '../../constants/filters'; import { prices, beds, types, lifeStyles } from '../../constants/filters';
import './CreateScrapeRequest.scss' import './CreateScrapeRequest.scss'
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { states } from '../../constants/states'
import Autocomplete from 'react-autocomplete';
import { useTranslation } from 'react-i18next';



export function matchStateToTerm(state, value) {
return (
state.label.toLowerCase().indexOf(value.toLowerCase()) !== -1
)
}
const CreateScrapeRequest = ({ handleRequest }) => { const CreateScrapeRequest = ({ handleRequest }) => {


const { t } = useTranslation();
const [requestObject, setRequestObject] = useState({ location: '' }) const [requestObject, setRequestObject] = useState({ location: '' })
const { t } = useTranslation();



const handleChangePriceType = async selectedOption => { const handleChangePriceType = async selectedOption => {
setRequestObject(s => ({ ...s, price: selectedOption.value })) setRequestObject(s => ({ ...s, price: selectedOption.value }))
console.log("requestObject", requestObject) console.log("requestObject", requestObject)
return ( return (
<div className="card card-primary"> <div className="card card-primary">
<div className="card-header">
<h3 className="card-title">{t('createScrapeRequest.Title')}</h3>
</div>
<form > <form >
<div className="card-body"> <div className="card-body">
<div className="row"> <div className="row">
<div className="col-md-3">
{/* <div className="col-md-3">
<div className="form-group"> <div className="form-group">
<input type="text" className="form-control input-field cursor-pointer" value={requestObject.location} placeholder={t('createScrapeRequest.LocationPlaceholder')} onChange={e => setRequestObject(s => ({ ...s, location: e.target.value }))} /> <input type="text" className="form-control input-field cursor-pointer" value={requestObject.location} placeholder={t('createScrapeRequest.LocationPlaceholder')} onChange={e => setRequestObject(s => ({ ...s, location: e.target.value }))} />
</div> </div>
</div> */}
<div className="col-md-3">
<div className="form-group">
<Autocomplete
menuStyle={{
padding: ".375rem .75rem",
fontSize: '1rem',
fontWeight: '400',
lineHeight: 1.5,
color: "#495057",
backgroundColor: '#fff',
backgroundClip: "padding-box",
border: "1px solid #ced4da",
borderRadius: ".25rem",
boxShadow: "inset 0 0 0 transparent",
transition: " border-color .15s ease-in-out,box-shadow .15s ease-in-out",
background: 'rgba(255, 255, 255, 0.9)',
position: 'fixed',
overflow: 'auto',
maxHeight: '50%',
zIndex: 2001
}}
renderInput={(props) => <input {...props} type="text" className="form-control input-field cursor-pointer" placeholder={t('createScrapeRequest.LocationPlaceholder')} />}
getItemValue={(item) => item.label}
items={states.map(s => ({ label: s }))}
renderItem={(item, isHighlighted) =>
<div style={{ background: isHighlighted ? 'lightgray' : 'white', }}>
{item.label}
</div>
}
shouldItemRender={matchStateToTerm}
value={requestObject.location}
onChange={(e, val) => setRequestObject(s => ({ ...s, location: val }))}
onSelect={(val) => setRequestObject(s => ({ ...s, location: val }))}
/>
</div>
</div> </div>
<div className="col-md-2"> <div className="col-md-2">
<div className="form-group"> <div className="form-group">

+ 3
- 3
src/components/ScrapeRequest/ScrappeStatus.jsx Просмотреть файл

const { t } = useTranslation(); const { t } = useTranslation();
console.log("id", id) console.log("id", id)
if (status === 'requested') if (status === 'requested')
return <button type="submit" className="btn btn-xs btn-block btn-primary" onClick={() => handleExecute(id)}><i className="fa fa-bell" ></i>{t('common.execute')}</button>
return <button type="submit" className="btn btn-sm btn-block btn-primary" onClick={() => handleExecute(id)}><i className="fa fa-bell"></i>{t('common.execute')}</button>
else if (status === 'done') else if (status === 'done')
return <span className='badge bg-success'>Done</span>
return <span className='badge bg-success text-lg'>Done</span>
else else
return <span className='badge bg-warning'>Pending</span>
return <span className='badge bg-danger text-lg'>Pending</span>


} }



+ 4
- 6
src/components/ScrapeRequests/ScrapeRequests.js Просмотреть файл



return ( return (
<div className="card"> <div className="card">
<div className="card-header">
<h3 className="card-title">{t('scrapeRequests.Title')}</h3>
</div>

{scrappes.length === 0 ? <tbody><tr><td><span className='center-align'>Nothing to show</span></td></tr></tbody> : {scrappes.length === 0 ? <tbody><tr><td><span className='center-align'>Nothing to show</span></td></tr></tbody> :
<div className="card-body p-0"> <div className="card-body p-0">
<table className="table table-sm"> <table className="table table-sm">
<thead> <thead>
<tr> <tr>
<th className='font-weight-bold'>{t('scrapeRequests.Columns.Scrape')}</th>
<th>{t('scrapeRequests.Columns.Filters')}</th>
<th>{t('scrapeRequests.Columns.Status')}</th>
<th className='text-black-50 font-weight-bold'>{t('scrapeRequests.Columns.Scrape')}</th>
<th className='text-black-50 font-weight-bold'>{t('scrapeRequests.Columns.Filters')}</th>
<th className='text-black-50 font-weight-bold'>{t('scrapeRequests.Columns.Status')}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

+ 1002
- 0
src/constants/states.js
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 7
- 4
src/pages/HomePage/HomePage.js Просмотреть файл

import CreateScrapeRequest from '../../components/CreateScrapeRequest/CreateScrapeRequest'; import CreateScrapeRequest from '../../components/CreateScrapeRequest/CreateScrapeRequest';
import ScrapeRequests from '../../components/ScrapeRequests/ScrapeRequests'; import ScrapeRequests from '../../components/ScrapeRequests/ScrapeRequests';
import { createScrappes, executeScrappes, getAllScrappes } from '../../request/scrappe'; import { createScrappes, executeScrappes, getAllScrappes } from '../../request/scrappe';
import { useTranslation } from 'react-i18next';

const HomePage = () => { const HomePage = () => {
const [scrappes, setScrappes] = useState([]) const [scrappes, setScrappes] = useState([])
const { t } = useTranslation();
useEffect(() => { useEffect(() => {
getAllScrappes().then(res => setScrappes(res.data)) getAllScrappes().then(res => setScrappes(res.data))
const interval = setInterval(() => { const interval = setInterval(() => {


return ( return (
<> <>
<h1 className="lead text-center" >Scrapper </h1>

<h1 className="lead text-center" style={{ fontSize: '80px' }}>{t('scrapeRequests.Columns.Scrape')} </h1>
<hr></hr>
<h2 className="lead text-center text-muted" style={{ fontSize: '40px' }}>https://www.apartments.com/</h2>
<br></br>
<CreateScrapeRequest handleRequest={handleRequest} /> <CreateScrapeRequest handleRequest={handleRequest} />
<ScrapeRequests scrappes={scrappes} handleExecute={handleExecute} /> <ScrapeRequests scrappes={scrappes} handleExecute={handleExecute} />
</> </>

+ 9
- 3
src/pages/ScrapeResults/ScrapeResultsPage.js Просмотреть файл

return ( return (
<> <>
<Link to="/" className="navbar-brand">
<span className="brand-text font-weight-light">Back</span>
</Link>
<nav className="main-header navbar navbar-expand-md navbar-light navbar-white">
<div className="container">
<Link to="/" className="navbar-brand">
<span className="brand-text font-weight-light">Back to Scrape</span>
</Link>
</div>
</nav>
<ScrappeDetails details = {scrappeDetails} /> <ScrappeDetails details = {scrappeDetails} />
<div className ='content' > <div className ='content' >
<div className="container"> <div className="container">

Загрузка…
Отмена
Сохранить