connecting to remote mysql db, saving market alerts
This commit is contained in:
18
backend/MarketAlert.js
Normal file
18
backend/MarketAlert.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const Sequelize = require("sequelize");
|
||||
const sequelize = require("./db.js");
|
||||
const MarketAlert = sequelize.define("market_alert", {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true
|
||||
},
|
||||
olx_url: Sequelize.STRING,
|
||||
last_date: Sequelize.STRING,
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = MarketAlert;
|
||||
8
backend/db.js
Normal file
8
backend/db.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const Sequelize = require("sequelize");
|
||||
const sequelize = new Sequelize("sql7274844", "sql7274844", "upMgevlgak", {
|
||||
host: "sql7.freemysqlhosting.net",
|
||||
dialect: "mysql",
|
||||
operatorsAliases: false
|
||||
});
|
||||
|
||||
module.exports = sequelize;
|
||||
@@ -3,13 +3,19 @@ let cheerio = require("cheerio");
|
||||
let express = require("express");
|
||||
const path = require("path");
|
||||
const bodyParser = require("body-parser");
|
||||
let fs = require("fs");
|
||||
const MarketAlert = require("./MarketAlert");
|
||||
const sequelize = require("./db.js");
|
||||
|
||||
const app = express();
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
const port = process.env.PORT || 5000;
|
||||
|
||||
app.get("/api/:url", async (req, res) => {
|
||||
let url = "https://www.olx.ba/pretraga?" + req.params.url;
|
||||
let url =
|
||||
"https://www.olx.ba/pretraga?" +
|
||||
req.params.url +
|
||||
"&sort_order=desc&sort_po=datum";
|
||||
let appts = [];
|
||||
response = await fetch(url);
|
||||
const body = await response.text();
|
||||
@@ -18,7 +24,13 @@ app.get("/api/:url", async (req, res) => {
|
||||
|
||||
$("#rezultatipretrage")
|
||||
.find(".listitem")
|
||||
.each(async (i, elem) => {
|
||||
.each(async (index, elem) => {
|
||||
if (index == 0) {
|
||||
lastItemDate = $(elem)
|
||||
.find(".cijena > .datum > div")
|
||||
.first()
|
||||
.attr("data-cijelidatum");
|
||||
}
|
||||
const id = $(elem)
|
||||
.find("a")
|
||||
.first()
|
||||
@@ -33,7 +45,32 @@ app.get("/api/:url", async (req, res) => {
|
||||
.attr("src");
|
||||
appts.push({ url: id, price: cijena, image });
|
||||
});
|
||||
res.json(appts);
|
||||
const [dan, mjesec, godina] = lastItemDate
|
||||
.split(". u ")[0]
|
||||
.split(".")
|
||||
.map(el => Number(el));
|
||||
const [sati, minute] = lastItemDate
|
||||
.split(". u ")[1]
|
||||
.split(":")
|
||||
.map(el => Number(el));
|
||||
last_date = String(new Date(godina, mjesec, dan, sati, minute));
|
||||
res.json({
|
||||
last_date,
|
||||
items: appts
|
||||
});
|
||||
});
|
||||
|
||||
app.post("/api/marketalerts", function(req, res) {
|
||||
const { email, last_date, olx_url } = req.body;
|
||||
|
||||
sequelize.sync().then(() =>
|
||||
MarketAlert.create({
|
||||
olx_url,
|
||||
last_date,
|
||||
email
|
||||
})
|
||||
);
|
||||
res.json({ message: "Market Alert Created!" });
|
||||
});
|
||||
|
||||
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
|
||||
|
||||
242
backend/package-lock.json
generated
242
backend/package-lock.json
generated
@@ -4,6 +4,11 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/geojson": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz",
|
||||
"integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.12.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
|
||||
@@ -23,6 +28,11 @@
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.3",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
|
||||
@@ -63,6 +73,15 @@
|
||||
"parse5": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"cls-bluebird": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
|
||||
"integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
|
||||
"requires": {
|
||||
"is-bluebird": "^1.0.2",
|
||||
"shimmer": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
|
||||
@@ -107,6 +126,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.3.0.tgz",
|
||||
"integrity": "sha512-4SRaSj+PqmrS1soW5/Avd7eJIM2JJIqLLmwhRqIGleZM/8KwZq80njbSS2Iqas+6oARkSkLDHEk4mm78q3JlIg=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -155,6 +179,11 @@
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"dottie": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz",
|
||||
"integrity": "sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw=="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
@@ -241,6 +270,19 @@
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"generic-pool": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.5.0.tgz",
|
||||
"integrity": "sha512-dEkxmX+egB2o4NR80c/q+xzLLzLX+k68/K8xv81XprD+Sk7ZtP14VugeCz+fUwv5FzpWq40pPtAkzPRqT8ka9w=="
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
|
||||
@@ -273,6 +315,11 @@
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inflection": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
|
||||
"integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
@@ -283,11 +330,35 @@
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
|
||||
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
|
||||
},
|
||||
"is-bluebird": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
|
||||
"integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
|
||||
"integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
@@ -321,11 +392,64 @@
|
||||
"mime-db": "~1.37.0"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.23.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz",
|
||||
"integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.23",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.23.tgz",
|
||||
"integrity": "sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "1.6.4",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.6.4.tgz",
|
||||
"integrity": "sha512-ZYbYgK06HKfxU45tYYLfwW5gKt8BslfE7FGyULNrf2K2fh+DuEX+e0QKsd2ObpZkMILefaVn8hsakVsTFqravQ==",
|
||||
"requires": {
|
||||
"denque": "1.3.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "4.1.3",
|
||||
"named-placeholders": "1.1.1",
|
||||
"seq-queue": "0.0.5",
|
||||
"sqlstring": "2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz",
|
||||
"integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=",
|
||||
"requires": {
|
||||
"lru-cache": "2.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
|
||||
"integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus="
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
||||
@@ -379,6 +503,11 @@
|
||||
"ipaddr.js": "1.8.0"
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
@@ -410,6 +539,15 @@
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"retry-as-promised": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.2.tgz",
|
||||
"integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=",
|
||||
"requires": {
|
||||
"bluebird": "^3.4.6",
|
||||
"debug": "^2.6.9"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -420,6 +558,11 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
||||
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
|
||||
@@ -440,6 +583,50 @@
|
||||
"statuses": "~1.4.0"
|
||||
}
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sequelize": {
|
||||
"version": "4.42.0",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.42.0.tgz",
|
||||
"integrity": "sha512-qxAYnX4rcv7PbNtEidb56REpxNJCdbN0qyk1jb3+e6sE7OrmS0nYMU+MFVbNTJtZfSpOEEL1TX0TkMw+wzZBxg==",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"cls-bluebird": "^2.1.0",
|
||||
"debug": "^3.1.0",
|
||||
"depd": "^1.1.0",
|
||||
"dottie": "^2.0.0",
|
||||
"generic-pool": "^3.4.0",
|
||||
"inflection": "1.12.0",
|
||||
"lodash": "^4.17.1",
|
||||
"moment": "^2.20.0",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"retry-as-promised": "^2.3.2",
|
||||
"semver": "^5.5.0",
|
||||
"terraformer-wkt-parser": "^1.1.2",
|
||||
"toposort-class": "^1.0.1",
|
||||
"uuid": "^3.2.1",
|
||||
"validator": "^10.4.0",
|
||||
"wkx": "^0.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
|
||||
@@ -456,6 +643,16 @@
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||
},
|
||||
"shimmer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
|
||||
"integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
@@ -469,6 +666,28 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"terraformer": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.9.tgz",
|
||||
"integrity": "sha512-YlmQ1fsMWTkKGDGibCRWgmLzrpDRUr63Q025LJ/taYQ6j1Yb8q9McKF7NBi6ACAyUXO6F/bl9w6v4MY307y5Ag==",
|
||||
"requires": {
|
||||
"@types/geojson": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"terraformer-wkt-parser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.2.0.tgz",
|
||||
"integrity": "sha512-QU3iA54St5lF8Za1jg1oj4NYc8sn5tCZ08aNSWDeGzrsaV48eZk1iAVWasxhNspYBoCqdHuoot1pUTUrE1AJ4w==",
|
||||
"requires": {
|
||||
"@types/geojson": "^1.0.0",
|
||||
"terraformer": "~1.0.5"
|
||||
}
|
||||
},
|
||||
"toposort-class": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
||||
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.16",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
||||
@@ -493,10 +712,33 @@
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"wkx": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.6.tgz",
|
||||
"integrity": "sha512-LHxXlzRCYQXA9ZHgs8r7Gafh0gVOE8o3QmudM1PIkOdkXXjW7Thcl+gb2P2dRuKgW8cqkitCRZkkjtmWzpHi7A==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"express": "^4.16.4",
|
||||
"node-fetch": "^2.3.0"
|
||||
"mysql2": "^1.6.4",
|
||||
"node-fetch": "^2.3.0",
|
||||
"sequelize": "^4.42.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import React from "react";
|
||||
import Select from "react-select";
|
||||
import { connect } from "react-redux";
|
||||
import { CATEGORY_SELECT, ITEMS_CHANGED } from "constants/actionTypes";
|
||||
import {
|
||||
CATEGORY_SELECT,
|
||||
ITEMS_CHANGED,
|
||||
USER_DATA_CHANGED
|
||||
} from "constants/actionTypes";
|
||||
import { hoc, areObjectEqual } from "utils/helpers";
|
||||
import { createOlxLink } from "utils/createOlxLink";
|
||||
import axios from "axios";
|
||||
@@ -23,13 +27,15 @@ const mapStateToProps = state => {
|
||||
category: state.category,
|
||||
options: state.options,
|
||||
subcategory: state.subcategory,
|
||||
items: state.items
|
||||
items: state.items,
|
||||
userdata: state.userdata
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onCategoryChanged: option => dispatch({ type: CATEGORY_SELECT, option }),
|
||||
onItemsChanged: items => dispatch({ type: ITEMS_CHANGED, items })
|
||||
onItemsChanged: items => dispatch({ type: ITEMS_CHANGED, items }),
|
||||
onUserDataChange: change => dispatch({ type: USER_DATA_CHANGED, ...change })
|
||||
});
|
||||
|
||||
let lastUpdateTime = null;
|
||||
@@ -38,13 +44,26 @@ class App extends React.Component {
|
||||
componentDidMount() {
|
||||
interval = setInterval(() => {
|
||||
if (lastUpdateTime && Date.now() - lastUpdateTime > 2000) {
|
||||
const { category, options, subcategory, onItemsChanged } = this.props;
|
||||
const {
|
||||
category,
|
||||
options,
|
||||
subcategory,
|
||||
onItemsChanged,
|
||||
onUserDataChange
|
||||
} = this.props;
|
||||
let url = createOlxLink(category, subcategory, options);
|
||||
url = encodeURI(url);
|
||||
onUserDataChange({ info: "olx_url", value: url });
|
||||
if (url) {
|
||||
axios
|
||||
.get(`/api/${url}`)
|
||||
.then(response => onItemsChanged(response.data))
|
||||
.then(response => {
|
||||
onItemsChanged(response.data.items);
|
||||
onUserDataChange({
|
||||
info: "last_date",
|
||||
value: response.data.last_date
|
||||
});
|
||||
})
|
||||
.catch(error => console.log(error));
|
||||
}
|
||||
lastUpdateTime = null;
|
||||
@@ -84,7 +103,6 @@ class App extends React.Component {
|
||||
Nekretnine: <DeepCategoryWrapper {...Nekretnine.properties} />
|
||||
})}
|
||||
<ItemsContainer />
|
||||
<NotificationModal />
|
||||
{items.length ? <NotificationModal /> : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from "react";
|
||||
import { notificationmodalwrapper } from "utils/notificationmodalwrapper";
|
||||
import axios from "axios";
|
||||
|
||||
const modalStyle = function() {
|
||||
let top = 50;
|
||||
let left = 50;
|
||||
let top = 20;
|
||||
let left = 20;
|
||||
|
||||
return {
|
||||
position: "absolute",
|
||||
@@ -26,6 +27,24 @@ class NotificationModal extends React.Component {
|
||||
this.props.onModalClose();
|
||||
};
|
||||
|
||||
handleInput = e => {
|
||||
this.props.onUserDataChange({ info: "email", value: e.target.value });
|
||||
};
|
||||
|
||||
handleSaveMarketAlert = () => {
|
||||
const {
|
||||
userdata: { email, last_date, olx_url }
|
||||
} = this.props;
|
||||
axios
|
||||
.post("/api/marketalerts", {
|
||||
email,
|
||||
last_date,
|
||||
olx_url
|
||||
})
|
||||
.then(response => console.log(response.data))
|
||||
.catch(error => console.log(error));
|
||||
};
|
||||
|
||||
render() {
|
||||
const { modal } = this.props;
|
||||
|
||||
@@ -35,12 +54,14 @@ class NotificationModal extends React.Component {
|
||||
|
||||
<div style={modalStyle()} aria-labelledby="modal-label" hidden={!modal}>
|
||||
<div>
|
||||
<h4 id="modal-label">Text in a modal</h4>
|
||||
<input type="radio" name="send-option" value="Email" />
|
||||
Email
|
||||
<br />
|
||||
<input type="radio" name="send-option" value="SMS" />
|
||||
SMS <br />
|
||||
<input
|
||||
type="email"
|
||||
placeholder="email"
|
||||
onChange={this.handleInput}
|
||||
/>
|
||||
<button onClick={this.handleSaveMarketAlert}>
|
||||
Save Market Alert
|
||||
</button>
|
||||
<button onClick={this.handleClose}>Close Modal</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,3 +4,4 @@ export const OPTION_CHANGE = "OPTION_CHANGE";
|
||||
export const ITEMS_CHANGED = "ITEMS_CHANGED";
|
||||
export const MODAL_CLOSE = "MODAL_CLOSE";
|
||||
export const MODAL_OPEN = " MODAL_OPEN";
|
||||
export const USER_DATA_CHANGED = "USER_DATA_CHANGED";
|
||||
|
||||
@@ -3,6 +3,7 @@ import subcategory from "./reducers/subcategory";
|
||||
import options from "./reducers/options";
|
||||
import items from "./reducers/items";
|
||||
import modal from "./reducers/modal";
|
||||
import userdata from "./reducers/userdata";
|
||||
import { combineReducers } from "redux";
|
||||
|
||||
export default combineReducers({
|
||||
@@ -10,5 +11,6 @@ export default combineReducers({
|
||||
subcategory,
|
||||
options,
|
||||
items,
|
||||
modal
|
||||
modal,
|
||||
userdata
|
||||
});
|
||||
|
||||
10
frontend-react/src/reducers/userdata.js
Normal file
10
frontend-react/src/reducers/userdata.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { USER_DATA_CHANGED } from "constants/actionTypes";
|
||||
|
||||
export default (state = {}, action) => {
|
||||
switch (action.type) {
|
||||
case USER_DATA_CHANGED:
|
||||
return { ...state, [action.info]: action.value };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
@@ -1,15 +1,21 @@
|
||||
import { connect } from "react-redux";
|
||||
import { MODAL_CLOSE, MODAL_OPEN } from "constants/actionTypes";
|
||||
import {
|
||||
MODAL_CLOSE,
|
||||
MODAL_OPEN,
|
||||
USER_DATA_CHANGED
|
||||
} from "constants/actionTypes";
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
modal: state.modal
|
||||
modal: state.modal,
|
||||
userdata: state.userdata
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onModalOpen: () => dispatch({ type: MODAL_OPEN }),
|
||||
onModalClose: () => dispatch({ type: MODAL_CLOSE })
|
||||
onModalClose: () => dispatch({ type: MODAL_CLOSE }),
|
||||
onUserDataChange: change => dispatch({ type: USER_DATA_CHANGED, ...change })
|
||||
});
|
||||
|
||||
export const notificationmodalwrapper = component =>
|
||||
|
||||
100
package-lock.json
generated
100
package-lock.json
generated
@@ -1,3 +1,101 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"denque": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.3.0.tgz",
|
||||
"integrity": "sha512-4SRaSj+PqmrS1soW5/Avd7eJIM2JJIqLLmwhRqIGleZM/8KwZq80njbSS2Iqas+6oARkSkLDHEk4mm78q3JlIg=="
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
|
||||
"integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "1.6.4",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.6.4.tgz",
|
||||
"integrity": "sha512-ZYbYgK06HKfxU45tYYLfwW5gKt8BslfE7FGyULNrf2K2fh+DuEX+e0QKsd2ObpZkMILefaVn8hsakVsTFqravQ==",
|
||||
"requires": {
|
||||
"denque": "1.3.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "4.1.3",
|
||||
"named-placeholders": "1.1.1",
|
||||
"seq-queue": "0.0.5",
|
||||
"sqlstring": "2.3.1"
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz",
|
||||
"integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=",
|
||||
"requires": {
|
||||
"lru-cache": "2.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
|
||||
"integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus="
|
||||
}
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user