Compare commits
20 Commits
bugfix/tim
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| b995123a36 | |||
|
|
0ed58d6fa1 | ||
|
|
29666babbc | ||
|
|
2c16bbf3e7 | ||
|
|
8231127099 | ||
|
|
531f133875 | ||
|
|
4fa241ad60 | ||
|
|
3cccdab368 | ||
|
|
ebb1304eeb | ||
|
|
8c4f67b106 | ||
|
|
26c4954e37 | ||
|
|
91e84f5cf1 | ||
| 8161f62ce0 | |||
| f2c7aec2d3 | |||
|
|
67ea0587db | ||
|
|
eaaee3c14a | ||
|
|
28b25da1ad | ||
|
|
c3c0ad74a7 | ||
|
|
aa4c994069 | ||
|
|
ad1c728876 |
BIN
KapitelGeschaftsidee_GruppeData.pdf
Normal file
BIN
KapitelGeschaftsidee_GruppeData.pdf
Normal file
Binary file not shown.
BIN
Travopti_Docs.pdf
Normal file
BIN
Travopti_Docs.pdf
Normal file
Binary file not shown.
@ -14,14 +14,50 @@ const port = process.env.PORT
|
|||||||
const search = require("./routes/search");
|
const search = require("./routes/search");
|
||||||
const regions = require("./routes/regions");
|
const regions = require("./routes/regions");
|
||||||
const countries = require("./routes/countries");
|
const countries = require("./routes/countries");
|
||||||
const climate = require("./routes/climate");
|
|
||||||
const places = require("./routes/place");
|
const places = require("./routes/place");
|
||||||
const update = require("./routes/update");
|
const update = require("./routes/update");
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// Swagger API doc set up
|
||||||
|
const swaggerJsdoc = require('swagger-jsdoc');
|
||||||
|
const swaggerUi = require('swagger-ui-express');
|
||||||
|
const swaggerOptions = {
|
||||||
|
swaggerDefinition: {
|
||||||
|
openapi: "3.0.0",
|
||||||
|
info: {
|
||||||
|
title: "TravOpti API",
|
||||||
|
version: "1.0.0",
|
||||||
|
description:
|
||||||
|
"Enable intrest controlled region searching with this API\n" +
|
||||||
|
"No API Key required.",
|
||||||
|
license: {
|
||||||
|
name: "Licensing Pending",
|
||||||
|
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtu.be"
|
||||||
|
},
|
||||||
|
contact: {
|
||||||
|
name: "travOpti",
|
||||||
|
url: "https://travopti.de/home",
|
||||||
|
email: "feedback@travopti.de"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
servers: [
|
||||||
|
{
|
||||||
|
url: "https://travopti.de/api/v1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
apis: [
|
||||||
|
"./Routes/*.js",
|
||||||
|
"./Models/handleClimateUpdate.js",
|
||||||
|
"./Models/handleClimateUpdateV2.js",
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const swaggerDocs = swaggerJsdoc(swaggerOptions);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
// Connect to MariaDB
|
||||||
const dbConn = await dbConnection();
|
const dbConn = await dbConnection();
|
||||||
|
|
||||||
// Express middleware
|
// Express middleware
|
||||||
@ -29,12 +65,12 @@ const app = express();
|
|||||||
app.use(express.static(path.join(__dirname, "../../dist")));
|
app.use(express.static(path.join(__dirname, "../../dist")));
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
app.use('/api/v1/doc', swaggerUi.serve, swaggerUi.setup(swaggerDocs, {explorer: false, docExpansion: "list"}));
|
||||||
|
|
||||||
// Express routes
|
// Express routes
|
||||||
app.use(search(dbConn));
|
app.use(search(dbConn));
|
||||||
app.use(regions(dbConn));
|
app.use(regions(dbConn));
|
||||||
app.use(countries(dbConn));
|
app.use(countries(dbConn));
|
||||||
app.use(climate(dbConn));
|
|
||||||
app.use(places(dbConn));
|
app.use(places(dbConn));
|
||||||
app.use(update(dbConn))
|
app.use(update(dbConn))
|
||||||
|
|
||||||
@ -52,7 +88,6 @@ const app = express();
|
|||||||
console.log(`Travopti backend listening at http://localhost:${port}`)
|
console.log(`Travopti backend listening at http://localhost:${port}`)
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO: logging
|
|
||||||
console.error("Failed to start the webserver");
|
console.error("Failed to start the webserver");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
const axios = require("axios")
|
const axios = require("axios")
|
||||||
const getPlacePhoto = require("./getPlacePhoto.js")
|
const getPlacePhoto = require("./getPlacePhoto.js")
|
||||||
|
|
||||||
const fields = "photos,place_id,name,rating,geometry"
|
const fields = "photos,place_id,name,rating,geometry" // Parameters for Google Place API
|
||||||
|
|
||||||
module.exports = async (q) => {
|
module.exports = async (q) => {
|
||||||
const res = await axios.get(
|
const res = await axios.get(
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
const axios = require("axios")
|
const axios = require("axios")
|
||||||
const getPlacePhoto = require("./getPlacePhoto.js")
|
const getPlacePhoto = require("./getPlacePhoto.js")
|
||||||
|
|
||||||
const radius = 20000
|
const radius = 20000 // Search radius in meters
|
||||||
const rankby = "prominence"
|
const rankby = "prominence" // Sorting of results
|
||||||
const types = "tourist_attraction"
|
const types = "tourist_attraction" // Category which shall be searched
|
||||||
|
|
||||||
module.exports = async (lat, lng) => {
|
module.exports = async (lat, lng) => {
|
||||||
const res = await axios.get(
|
const res = await axios.get(
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
exports.getBYTdataByRegion = async (dbConn, id, travelstyle = 1) => {
|
|
||||||
const res = await dbConn.query(
|
|
||||||
`SELECT
|
|
||||||
region_id,
|
|
||||||
travelstyle,
|
|
||||||
average_per_day AS average_per_day_costs,
|
|
||||||
accomodation AS accommodation_costs,
|
|
||||||
food AS food_costs,
|
|
||||||
water AS water_costs,
|
|
||||||
local_transportation AS local_transportation_costs,
|
|
||||||
entertainment AS entertainment_costs
|
|
||||||
FROM regions_byt
|
|
||||||
WHERE region_id = ? AND travelstyle = ?`,
|
|
||||||
[id, travelstyle]
|
|
||||||
);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getAllBYTdata = async (dbConn, travelstyle = 1) => {
|
|
||||||
const res = await dbConn.query(
|
|
||||||
`SELECT
|
|
||||||
region_id,
|
|
||||||
travelstyle,
|
|
||||||
average_per_day AS average_per_day_costs,
|
|
||||||
accomodation AS accommodation_costs,
|
|
||||||
food AS food_costs,
|
|
||||||
water AS water_costs,
|
|
||||||
local_transportation AS local_transportation_costs,
|
|
||||||
entertainment AS entertainment_costs
|
|
||||||
FROM regions_byt
|
|
||||||
WHERE travelstyle = ?`,
|
|
||||||
[travelstyle]
|
|
||||||
);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getTrivagoData = async (dbConn, id) => {
|
|
||||||
const region = await dbConn.query(
|
|
||||||
`...`,
|
|
||||||
[id]
|
|
||||||
);
|
|
||||||
return region;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -58,17 +58,6 @@ module.exports = async (dbConn) => {
|
|||||||
|
|
||||||
|
|
||||||
return regions.map(region => {
|
return regions.map(region => {
|
||||||
/*
|
|
||||||
const emptyArr = Array.from({ length: 12 }, () => null)
|
|
||||||
if (region.avg_price_relative === null) region.avg_price_relative = undefined
|
|
||||||
if (region.temperature_mean === null) region.temperature_mean = undefined
|
|
||||||
if (region.temperature_mean_min === null) region.temperature_mean_min = undefined
|
|
||||||
if (region.temperature_mean_max === null) region.temperature_mean_max = undefined
|
|
||||||
if (region.precipitation === null) region.precipitation = undefined
|
|
||||||
if (region.rain_days === null) region.rain_days = undefined
|
|
||||||
if (region.sun_hours === null) region.sun_hours = undefined
|
|
||||||
if (region.humidity === null) region.humidity = undefined
|
|
||||||
*/
|
|
||||||
region.tags = tags.filter(tag => tag.region_id === region.region_id).map(tag => {
|
region.tags = tags.filter(tag => tag.region_id === region.region_id).map(tag => {
|
||||||
delete tag.region_id
|
delete tag.region_id
|
||||||
return tag
|
return tag
|
||||||
|
|||||||
@ -11,15 +11,11 @@ module.exports = async (dbConn) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (k = 0; k < presets.length; k++) {
|
for (k = 0; k < presets.length; k++) {
|
||||||
//if (presets[k].values.toString().includes("|")) {
|
|
||||||
const value = presets[k].value
|
const value = presets[k].value
|
||||||
presets[k].value = value.split("|");
|
presets[k].value = value.split("|");
|
||||||
for (i = 0; i < presets[k].value.length; i++) {
|
for (i = 0; i < presets[k].value.length; i++) {
|
||||||
presets[k].value[i] = parseFloat(presets[k].value[i])
|
presets[k].value[i] = parseFloat(presets[k].value[i])
|
||||||
}
|
}
|
||||||
//} else {
|
|
||||||
// presets[k].values = parseInt(presets[k].values)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
return presets;
|
return presets;
|
||||||
};
|
};
|
||||||
@ -1,11 +1,12 @@
|
|||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
// TODO: Automatically retrieve dates via aviable Data and get rid of random dates
|
// Constants
|
||||||
|
// TODO: Automatically retrieve dates via aviable Data from database and get rid of "random" dates
|
||||||
const rangeStartDate = '2019-01' // If no date is given, this date will be used as startDate
|
const rangeStartDate = '2019-01' // If no date is given, this date will be used as startDate
|
||||||
const rangeEndDate = '2020-05'// If no date is given, this date will be used as endDate
|
const rangeEndDate = '2020-05'// If no date is given, this date will be used as endDate
|
||||||
|
|
||||||
// TODO: call method periodically, not over API
|
// TODO: call method periodically, not over API (fine for prototyping, tho)
|
||||||
module.exports = async (dbConn, startDate = rangeStartDate, endDate = rangeEndDate) => {
|
module.exports = async (dbConn, startDate = rangeStartDate, endDate = rangeEndDate) => {
|
||||||
console.log('update climate with:', startDate, endDate);
|
console.log('update climate with:', startDate, endDate);
|
||||||
|
|
||||||
@ -54,7 +55,6 @@ async function createClimateObjectFrom(src, startDate, endDate) {
|
|||||||
sun_hours: element.sunshine,
|
sun_hours: element.sunshine,
|
||||||
humidity: element.humidity ? element.humidity : null
|
humidity: element.humidity ? element.humidity : null
|
||||||
}
|
}
|
||||||
//console.log(result)
|
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
return retVal
|
return retVal
|
||||||
@ -62,7 +62,6 @@ async function createClimateObjectFrom(src, startDate, endDate) {
|
|||||||
|
|
||||||
async function writeToDatabase(dbConn, climateObjArr) {
|
async function writeToDatabase(dbConn, climateObjArr) {
|
||||||
for (const element of climateObjArr) {
|
for (const element of climateObjArr) {
|
||||||
//console.log(element)
|
|
||||||
try {
|
try {
|
||||||
await dbConn.query(`
|
await dbConn.query(`
|
||||||
INSERT INTO region_climate
|
INSERT INTO region_climate
|
||||||
|
|||||||
@ -2,10 +2,11 @@ const axios = require('axios')
|
|||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
// TODO: Automatically retrieve dates via aviable Data from database and get rid of "random" dates
|
||||||
const rangeStartDate = '2019-01-01' // If no date is given, this date will be used as startDate
|
const rangeStartDate = '2019-01-01' // If no date is given, this date will be used as startDate
|
||||||
const rangeEndDate = '2019-12-31'// If no date is given, this date will be used as endDate
|
const rangeEndDate = '2019-12-31'// If no date is given, this date will be used as endDate
|
||||||
|
|
||||||
// TODO: call method periodically, not over API
|
// TODO: call method periodically, not over API (fine for prototyping, tho)
|
||||||
module.exports = async (dbConn, startDate = rangeStartDate, endDate = rangeEndDate) => {
|
module.exports = async (dbConn, startDate = rangeStartDate, endDate = rangeEndDate) => {
|
||||||
console.log('update climate with:', startDate, endDate);
|
console.log('update climate with:', startDate, endDate);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
const axios = require("axios")
|
const axios = require("axios")
|
||||||
const getRegions = require("../models/getRegions.js")
|
const getRegions = require("../models/getRegions.js")
|
||||||
|
|
||||||
const fields = "geometry"
|
const fields = "geometry" // Parameters for Google Places API
|
||||||
|
|
||||||
module.exports = async (dbConn) => {
|
module.exports = async (dbConn) => {
|
||||||
const regions = await getRegions(dbConn)
|
const regions = await getRegions(dbConn)
|
||||||
|
|||||||
247
backend/package-lock.json
generated
247
backend/package-lock.json
generated
@ -4,6 +4,45 @@
|
|||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apidevtools/json-schema-ref-parser": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-n4YBtwQhdpLto1BaUCyAeflizmIbaloGShsPyRtFf5qdFJxfssj+GgLavczgKJFa3Bq+3St2CKcpRJdjtB4EBw==",
|
||||||
|
"requires": {
|
||||||
|
"@jsdevtools/ono": "^7.1.0",
|
||||||
|
"call-me-maybe": "^1.0.1",
|
||||||
|
"js-yaml": "^3.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@apidevtools/openapi-schemas": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-QoPaxGXfgqgGpK1p21FJ400z56hV681a8DOcZt3J5z0WIHgFeaIZ4+6bX5ATqmOoCpRCsH4ITEwKaOyFMz7wOA=="
|
||||||
|
},
|
||||||
|
"@apidevtools/swagger-methods": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-1Vlm18XYW6Yg7uHunroXeunWz5FShPFAdxBbPy8H6niB2Elz9QQsCoYHMbcc11EL1pTxaIr9HXz2An/mHXlX1Q=="
|
||||||
|
},
|
||||||
|
"@apidevtools/swagger-parser": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-Irqybg4dQrcHhZcxJc/UM4vO7Ksoj1Id5e+K94XUOzllqX1n47HEA50EKiXTCQbykxuJ4cYGIivjx/MRSTC5OA==",
|
||||||
|
"requires": {
|
||||||
|
"@apidevtools/json-schema-ref-parser": "^8.0.0",
|
||||||
|
"@apidevtools/openapi-schemas": "^2.0.2",
|
||||||
|
"@apidevtools/swagger-methods": "^3.0.0",
|
||||||
|
"@jsdevtools/ono": "^7.1.0",
|
||||||
|
"call-me-maybe": "^1.0.1",
|
||||||
|
"openapi-types": "^1.3.5",
|
||||||
|
"z-schema": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jsdevtools/ono": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qS/a24RA5FEoiJS9wiv6Pwg2c/kiUo3IVUQcfeM9JvsR6pM8Yx+yl/6xWYLckZCT5jpLNhslgjiA8p/XcGyMRQ=="
|
||||||
|
},
|
||||||
"@sindresorhus/is": {
|
"@sindresorhus/is": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||||
@ -50,29 +89,6 @@
|
|||||||
"negotiator": "0.6.2"
|
"negotiator": "0.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent-base": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
|
|
||||||
"requires": {
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"debug": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
|
||||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
|
||||||
"requires": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ansi-align": {
|
"ansi-align": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
|
||||||
@ -126,6 +142,14 @@
|
|||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"requires": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"array-flatten": {
|
"array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
@ -142,8 +166,7 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"basic-auth": {
|
"basic-auth": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@ -196,7 +219,6 @@
|
|||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -248,6 +270,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"call-me-maybe": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms="
|
||||||
|
},
|
||||||
"camelcase": {
|
"camelcase": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||||
@ -342,11 +369,15 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"commander": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-JrDGPAKjMGSP1G0DUoaceEJ3DZgAfr/q6X7FVk4+U5KxUSKviYGM2k6zWkfyyBHy5rAtzgYJFa1ro2O9PtoxwQ=="
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"configstore": {
|
"configstore": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
@ -444,6 +475,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
},
|
},
|
||||||
|
"doctrine": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
|
||||||
|
"requires": {
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dot-prop": {
|
"dot-prop": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
|
||||||
@ -505,6 +544,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||||
},
|
},
|
||||||
|
"esutils": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
|
||||||
|
},
|
||||||
"etag": {
|
"etag": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
@ -598,6 +642,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||||
},
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||||
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||||
@ -622,6 +671,19 @@
|
|||||||
"pump": "^3.0.0"
|
"pump": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||||
|
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"glob-parent": {
|
"glob-parent": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
||||||
@ -700,30 +762,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/httpolyglot/-/httpolyglot-0.1.2.tgz",
|
||||||
"integrity": "sha1-5NNH/omEpi9GfUBg31J/GFH2mXs="
|
"integrity": "sha1-5NNH/omEpi9GfUBg31J/GFH2mXs="
|
||||||
},
|
},
|
||||||
"https-proxy-agent": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
|
||||||
"requires": {
|
|
||||||
"agent-base": "6",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"debug": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
|
||||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
|
||||||
"requires": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@ -750,6 +788,15 @@
|
|||||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
@ -856,6 +903,15 @@
|
|||||||
"integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
|
"integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "3.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||||
|
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"esprima": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"json-buffer": {
|
"json-buffer": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
|
||||||
@ -885,6 +941,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
},
|
},
|
||||||
|
"lodash.get": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||||
|
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
|
||||||
|
},
|
||||||
|
"lodash.isequal": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
|
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||||
|
},
|
||||||
"long": {
|
"long": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
@ -988,7 +1054,6 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -1169,11 +1234,15 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"openapi-types": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-1.3.5.tgz",
|
||||||
|
"integrity": "sha512-11oi4zYorsgvg5yBarZplAqbpev5HkuVNPlZaPTknPDzAynq+lnJdXAmruGWP0s+dNYZS7bjM+xrTpJw7184Fg=="
|
||||||
|
},
|
||||||
"p-cancelable": {
|
"p-cancelable": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
|
||||||
@ -1214,6 +1283,11 @@
|
|||||||
"util": "^0.10.3"
|
"util": "^0.10.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||||
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.7",
|
"version": "0.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||||
@ -1452,6 +1526,11 @@
|
|||||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sprintf-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||||
|
},
|
||||||
"sqlstring": {
|
"sqlstring": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz",
|
||||||
@ -1526,6 +1605,39 @@
|
|||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"swagger-jsdoc": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-wHrmRvE/OQa3d387YIrRNPvsPwxkJc0tAYeCVa359gUIKPjC4ReduFhqq/+4erLUS79kY1T5Fv0hE0SV/PgBig==",
|
||||||
|
"requires": {
|
||||||
|
"commander": "5.0.0",
|
||||||
|
"doctrine": "3.0.0",
|
||||||
|
"glob": "7.1.6",
|
||||||
|
"js-yaml": "3.13.1",
|
||||||
|
"swagger-parser": "9.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"swagger-parser": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-oxOHUaeNetO9ChhTJm2fD+48DbGbLD09ZEOwPOWEqcW8J6zmjWxutXtSuOiXsoRgDWvORYlImbwM21Pn+EiuvQ==",
|
||||||
|
"requires": {
|
||||||
|
"@apidevtools/swagger-parser": "9.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"swagger-ui-dist": {
|
||||||
|
"version": "3.28.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.28.0.tgz",
|
||||||
|
"integrity": "sha512-aPkfTzPv9djSiZI1NUkWr5HynCUsH+jaJ0WSx+/t19wq7MMGg9clHm9nGoIpAtqml1G51ofI+I75Ym72pukzFg=="
|
||||||
|
},
|
||||||
|
"swagger-ui-express": {
|
||||||
|
"version": "4.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz",
|
||||||
|
"integrity": "sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g==",
|
||||||
|
"requires": {
|
||||||
|
"swagger-ui-dist": "^3.18.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"term-size": {
|
"term-size": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
|
||||||
@ -1651,6 +1763,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||||
},
|
},
|
||||||
|
"validator": {
|
||||||
|
"version": "12.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
|
||||||
|
"integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ=="
|
||||||
|
},
|
||||||
"vary": {
|
"vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
@ -1668,8 +1785,7 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"write-file-atomic": {
|
"write-file-atomic": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
@ -1693,6 +1809,25 @@
|
|||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
||||||
|
},
|
||||||
|
"z-schema": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==",
|
||||||
|
"requires": {
|
||||||
|
"commander": "^2.7.1",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"lodash.isequal": "^4.5.0",
|
||||||
|
"validator": "^12.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "2.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,9 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"mysql2": "^2.1.0",
|
"mysql2": "^2.1.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"sqlstring": "^2.3.2"
|
"sqlstring": "^2.3.2",
|
||||||
|
"swagger-jsdoc": "^4.0.0",
|
||||||
|
"swagger-ui-express": "^4.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^2.0.4"
|
"nodemon": "^2.0.4"
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
const router = require("express").Router()
|
|
||||||
|
|
||||||
// Models
|
|
||||||
const handleClimateUpdate = require("../models/handleClimateUpdate.js")
|
|
||||||
const handleClimateUpdateV2 = require("../models/handleClimateUpdateV2.js")
|
|
||||||
|
|
||||||
module.exports = dbConn => {
|
|
||||||
router.put("/api/v1/climate/update", async (req, res) => {
|
|
||||||
const update = await handleClimateUpdate(dbConn)
|
|
||||||
res.json(update)
|
|
||||||
});
|
|
||||||
|
|
||||||
router.put("/api/v1/climate/update/v2", async (req, res) => {
|
|
||||||
const update = await handleClimateUpdateV2(dbConn)
|
|
||||||
res.json(update)
|
|
||||||
});
|
|
||||||
|
|
||||||
return router;
|
|
||||||
};
|
|
||||||
@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Countries
|
||||||
|
* description: Access country data.
|
||||||
|
*/
|
||||||
|
|
||||||
const router = require("express").Router();
|
const router = require("express").Router();
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@ -8,10 +15,37 @@ const getCountryById = require("../models/getCountryById.js");
|
|||||||
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
||||||
|
|
||||||
module.exports = dbConn => {
|
module.exports = dbConn => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /countries:
|
||||||
|
* get:
|
||||||
|
* summary: Get all countries
|
||||||
|
* tags: [Countries]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns aviable data for all countries
|
||||||
|
*/
|
||||||
router.get("/api/v1/countries", async (req, res) => {
|
router.get("/api/v1/countries", async (req, res) => {
|
||||||
res.json(await getCountries(dbConn));
|
res.json(await getCountries(dbConn));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /countries/{id}:
|
||||||
|
* get:
|
||||||
|
* summary: Get a specific country by id
|
||||||
|
* tags: [Countries]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* example: 23
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns aviable data for the country
|
||||||
|
* example: test
|
||||||
|
*/
|
||||||
router.get("/api/v1/countries/:id", async (req, res) => {
|
router.get("/api/v1/countries/:id", async (req, res) => {
|
||||||
const id = sqlSanitzer(req.params.id);
|
const id = sqlSanitzer(req.params.id);
|
||||||
res.json(await getCountryById(dbConn, id))
|
res.json(await getCountryById(dbConn, id))
|
||||||
|
|||||||
@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Places
|
||||||
|
* description: Access to the Google Place API via the Key used in backend. Only for manual use in the prototype application!
|
||||||
|
*/
|
||||||
|
|
||||||
const router = require("express").Router()
|
const router = require("express").Router()
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@ -9,11 +16,51 @@ const getPlacePhoto = require("../models/getPlacePhoto.js")
|
|||||||
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
||||||
|
|
||||||
module.exports = dbConn => {
|
module.exports = dbConn => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /place:
|
||||||
|
* get:
|
||||||
|
* summary: Get a specific place
|
||||||
|
* tags: [Places]
|
||||||
|
* parameters:
|
||||||
|
* - name: "q"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* description: "Querystring, by which the place is searched"
|
||||||
|
* example: Berlin
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns a place from the google places API.
|
||||||
|
*/
|
||||||
router.get("/api/v1/place", async (req, res) => {
|
router.get("/api/v1/place", async (req, res) => {
|
||||||
const place = await getPlace(req.query.q)
|
const place = await getPlace(req.query.q)
|
||||||
res.json(place)
|
res.json(place)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /place/nearby:
|
||||||
|
* get:
|
||||||
|
* summary: Get nearby touristic places
|
||||||
|
* tags: [Places]
|
||||||
|
* parameters:
|
||||||
|
* - name: "lat"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: float
|
||||||
|
* description: "Latitiude"
|
||||||
|
* example: 52.520365
|
||||||
|
* - name: "lng"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: float
|
||||||
|
* description: "Longitude"
|
||||||
|
* example: 13.403509
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns nearby places from the google places API.
|
||||||
|
*/
|
||||||
router.get("/api/v1/place/nearby", async (req, res) => {
|
router.get("/api/v1/place/nearby", async (req, res) => {
|
||||||
const lat = req.query.lat
|
const lat = req.query.lat
|
||||||
const lng = req.query.lng
|
const lng = req.query.lng
|
||||||
@ -21,6 +68,23 @@ module.exports = dbConn => {
|
|||||||
res.json(place)
|
res.json(place)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /place/photo:
|
||||||
|
* get:
|
||||||
|
* summary: Get a photo for a place
|
||||||
|
* tags: [Places]
|
||||||
|
* parameters:
|
||||||
|
* - name: "photoref"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* description: "Photo_Reference which is returned for a place by Google Places API"
|
||||||
|
* example: CmRaAAAAbupojmH94negtiCnLGdfx2azxhVTEDI1rtTrYnQ7KclEI-Yy9_YGxN9h63AKrCzd22kk5z-UiK7fS4-zXnO5OqfNRZu2hrmfcp8b77rItediibAVovOOA5LnyJ9YYuofEhAAr0Im0zuiAtbDKPjbPUSBGhTFkSrH6FZxenbo1bCkdCXaUMhOug
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns the matching url to the photo.
|
||||||
|
*/
|
||||||
router.get("/api/v1/place/photo", async (req, res) => {
|
router.get("/api/v1/place/photo", async (req, res) => {
|
||||||
const photoref = req.query.photoref
|
const photoref = req.query.photoref
|
||||||
const photo = await getPlacePhoto(photoref)
|
const photo = await getPlacePhoto(photoref)
|
||||||
|
|||||||
@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Regions
|
||||||
|
* description: Access region data.
|
||||||
|
*/
|
||||||
|
|
||||||
const router = require("express").Router();
|
const router = require("express").Router();
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@ -12,6 +19,16 @@ const _ = require('lodash')
|
|||||||
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
||||||
|
|
||||||
module.exports = dbConn => {
|
module.exports = dbConn => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /regions:
|
||||||
|
* get:
|
||||||
|
* summary: Get all regions
|
||||||
|
* tags: [Regions]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns available data for all regions
|
||||||
|
*/
|
||||||
router.get("/api/v1/regions", async (req, res) => {
|
router.get("/api/v1/regions", async (req, res) => {
|
||||||
const data = await getRegions(dbConn)
|
const data = await getRegions(dbConn)
|
||||||
if (req.query.randomize) {
|
if (req.query.randomize) {
|
||||||
@ -22,6 +39,21 @@ module.exports = dbConn => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /regions/{id}:
|
||||||
|
* get:
|
||||||
|
* summary: Get a specific region by id
|
||||||
|
* tags: [Regions]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns available data for the region
|
||||||
|
*/
|
||||||
router.get("/api/v1/regions/:id", async (req, res) => {
|
router.get("/api/v1/regions/:id", async (req, res) => {
|
||||||
console.log(typeof req.params.id)
|
console.log(typeof req.params.id)
|
||||||
const id = sqlSanitzer(req.params.id);
|
const id = sqlSanitzer(req.params.id);
|
||||||
@ -29,14 +61,49 @@ module.exports = dbConn => {
|
|||||||
res.json(await getRegionById(dbConn, id))
|
res.json(await getRegionById(dbConn, id))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /regions/{id}/image:
|
||||||
|
* get:
|
||||||
|
* summary: Get image for specific region
|
||||||
|
* tags: [Regions]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns the image for a specific region
|
||||||
|
* "404":
|
||||||
|
* description: Returns a placeholder image for the region
|
||||||
|
*/
|
||||||
router.get('/api/v1/regions/:id/image', (req, res) => {
|
router.get('/api/v1/regions/:id/image', (req, res) => {
|
||||||
|
console.log("HERE")
|
||||||
if (fs.existsSync(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`))) {
|
if (fs.existsSync(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`))) {
|
||||||
res.sendFile(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`))
|
console.log("EXISTS")
|
||||||
|
res.status(200).sendFile(path.join(__dirname, `../data/regions/images/${req.params.id}.jpg`))
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, `../data/regions/images/x.png`))
|
console.log("NOT EXISTS")
|
||||||
|
res.status(404).sendFile(path.join(__dirname, `../data/regions/images/x.png`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /regions/{id}/nearby:
|
||||||
|
* get:
|
||||||
|
* summary: Get nearby places of a specific region by id
|
||||||
|
* tags: [Regions]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns all nearby places for the region
|
||||||
|
*/
|
||||||
router.get("/api/v1/regions/:id/nearby", async (req,res) => {
|
router.get("/api/v1/regions/:id/nearby", async (req,res) => {
|
||||||
const id = sqlSanitzer(req.params.id);
|
const id = sqlSanitzer(req.params.id);
|
||||||
res.json(await getRegionNearbyById(dbConn,id))
|
res.json(await getRegionNearbyById(dbConn,id))
|
||||||
|
|||||||
@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Search
|
||||||
|
* description: Access the search algorithm and the data provided for searching.
|
||||||
|
*/
|
||||||
|
|
||||||
const router = require("express").Router();
|
const router = require("express").Router();
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@ -12,8 +19,47 @@ const oldToNewQuerySyntax = require("../util/oldToNewQuerySyntax.js")
|
|||||||
const { getUniqueTags } = require("../models/getTags.js");
|
const { getUniqueTags } = require("../models/getTags.js");
|
||||||
|
|
||||||
module.exports = dbConn => {
|
module.exports = dbConn => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /search:
|
||||||
|
* get:
|
||||||
|
* summary: Get Searchresults
|
||||||
|
* tags: [Search]
|
||||||
|
* parameters:
|
||||||
|
* - name: "q"
|
||||||
|
* in: "query"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* description: "Base64 encoded JS-Object with searchparameters"
|
||||||
|
* example: eyJmcm9tIjoxNTkzNjQ4MDAwMDAwLCJ0byI6MTU5NDI1MjgwMDAwMCwidGFncyI6W119
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns the region information and scores for the searchresults
|
||||||
|
*/
|
||||||
router.get("/api/v1/search", searchHandler(dbConn));
|
router.get("/api/v1/search", searchHandler(dbConn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /search/presets:
|
||||||
|
* get:
|
||||||
|
* summary: Get the presets for the search parameters
|
||||||
|
* tags: [Search]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns all presets for the search parameters
|
||||||
|
*/
|
||||||
router.get("/api/v1/search/presets", presetHandler(dbConn));
|
router.get("/api/v1/search/presets", presetHandler(dbConn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /search/tags:
|
||||||
|
* get:
|
||||||
|
* summary: Get the existing searchtags
|
||||||
|
* tags: [Search]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Returns all existing searchtags
|
||||||
|
*/
|
||||||
router.get("/api/v1/search/tags", tagsHandler(dbConn));
|
router.get("/api/v1/search/tags", tagsHandler(dbConn));
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Update
|
||||||
|
* description: Endpoint for updating region specific data. Only for manual use in the prototype application!
|
||||||
|
*/
|
||||||
|
|
||||||
const router = require("express").Router();
|
const router = require("express").Router();
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
|
const handleClimateUpdate = require("../models/handleClimateUpdate.js")
|
||||||
|
const handleClimateUpdateV2 = require("../models/handleClimateUpdateV2.js")
|
||||||
const handleUpdateRegionNearby = require("../models/handleUpdateRegionNearby.js")
|
const handleUpdateRegionNearby = require("../models/handleUpdateRegionNearby.js")
|
||||||
const handleUpdateRegionNearbyById = require("../models/handleUpdateRegionNearbyById.js")
|
const handleUpdateRegionNearbyById = require("../models/handleUpdateRegionNearbyById.js")
|
||||||
const handleUpdateRegionNearbyImgUrl = require("../models/handleUpdateRegionNearbyImgUrl.js")
|
const handleUpdateRegionNearbyImgUrl = require("../models/handleUpdateRegionNearbyImgUrl.js")
|
||||||
@ -10,24 +19,114 @@ const handleUpdateRegionNearbyImgUrlById = require("../models/handleUpdateRegion
|
|||||||
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
const sqlSanitzer = require("../util/sqlstring_sanitizer.js")
|
||||||
|
|
||||||
module.exports = dbConn => {
|
module.exports = dbConn => {
|
||||||
router.patch("/api/v1/update/regions/all/nearby", async (req, res) => {
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/climate/v1:
|
||||||
|
* put:
|
||||||
|
* summary: Pull monthly data from meteostat API V1
|
||||||
|
* tags: [Update]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Update information is logged in backend
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/climate/v1", async (req, res) => {
|
||||||
|
const update = await handleClimateUpdate(dbConn)
|
||||||
|
res.json(update)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/climate/v2:
|
||||||
|
* put:
|
||||||
|
* summary: Pull daily data from meteostat API V2. Data is written to Travopti database and must be processed manually before it can be used.
|
||||||
|
* tags: [Update]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Update information is logged in backend
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/climate/v2", async (req, res) => {
|
||||||
|
const update = await handleClimateUpdateV2(dbConn)
|
||||||
|
res.json(update)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/regions/all/nearby:
|
||||||
|
* put:
|
||||||
|
* summary: Updates all nearby data for all regions
|
||||||
|
* tags: [Update]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Updates all nearby data for all regions
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/regions/all/nearby", async (req, res) => {
|
||||||
res.json(await handleUpdateRegionNearby(dbConn))
|
res.json(await handleUpdateRegionNearby(dbConn))
|
||||||
});
|
});
|
||||||
|
|
||||||
router.patch("/api/v1/update/regions/all/lonlat", async (req,res) => {
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/regions/all/lonlat:
|
||||||
|
* put:
|
||||||
|
* summary: Updates all coordinate data for all regions
|
||||||
|
* tags: [Update]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Updates all coordinate data for all regions
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/regions/all/lonlat", async (req,res) => {
|
||||||
res.json(await handleRegionLonLat(dbConn))
|
res.json(await handleRegionLonLat(dbConn))
|
||||||
});
|
});
|
||||||
|
|
||||||
router.patch("/api/v1/update/regions/:id/nearby", async (req, res) => {
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/regions/all/nearby/image:
|
||||||
|
* put:
|
||||||
|
* summary: Updates the nearby image urls for all regions
|
||||||
|
* tags: [Update]
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Updates the nearby image urls for all regions
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/regions/all/nearby/image", async (req, res) => {
|
||||||
|
res.json(await handleUpdateRegionNearbyImgUrl(dbConn))
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /update/regions/{id}/nearby:
|
||||||
|
* put:
|
||||||
|
* summary: Updates the nearby data for a specific region
|
||||||
|
* tags: [Update]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Updates the nearby data for a specific region
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/regions/:id/nearby", async (req, res) => {
|
||||||
const id = sqlSanitzer(req.params.id);
|
const id = sqlSanitzer(req.params.id);
|
||||||
res.json(await handleUpdateRegionNearbyById(dbConn, id))
|
res.json(await handleUpdateRegionNearbyById(dbConn, id))
|
||||||
});
|
});
|
||||||
|
|
||||||
router.patch("/api/v1/update/regions/all/nearby/imgurl", async (req, res) => {
|
/**
|
||||||
res.json(await handleUpdateRegionNearbyImgUrl(dbConn))
|
* @swagger
|
||||||
});
|
* /update/regions/{id}/nearby/image:
|
||||||
|
* put:
|
||||||
router.patch("/api/v1/update/regions/:id/nearby/imgurl", async (req, res) => {
|
* summary: Updates the nearby image urls for a specific region
|
||||||
|
* tags: [Update]
|
||||||
|
* parameters:
|
||||||
|
* - name: "id"
|
||||||
|
* in: "path"
|
||||||
|
* required: true
|
||||||
|
* type: int
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: Updates the nearby image urls for a specific region
|
||||||
|
*/
|
||||||
|
router.put("/api/v1/update/regions/:id/nearby/image", async (req, res) => {
|
||||||
const id = sqlSanitzer(req.params.id);
|
const id = sqlSanitzer(req.params.id);
|
||||||
res.json(await handleUpdateRegionNearbyImgUrlById(dbConn, id))
|
res.json(await handleUpdateRegionNearbyImgUrlById(dbConn, id))
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,10 +14,20 @@ exports.base64ToObj = function(base64) {
|
|||||||
return JSON.parse(atob(base64));
|
return JSON.parse(atob(base64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a base64 encoded object.
|
||||||
|
* @param base64 encoded object
|
||||||
|
* @returns {string} decoded object
|
||||||
|
*/
|
||||||
function atob(base64) {
|
function atob(base64) {
|
||||||
return Buffer.from(base64, 'base64').toString('binary')
|
return Buffer.from(base64, 'base64').toString('binary')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes an object as base64 string.
|
||||||
|
* @param string The object to encode
|
||||||
|
* @returns {string} base64 encoded object
|
||||||
|
*/
|
||||||
function btoa(string) {
|
function btoa(string) {
|
||||||
return Buffer.from(string).toString('base64')
|
return Buffer.from(string).toString('base64')
|
||||||
}
|
}
|
||||||
@ -1,3 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Seperate Strings created via GROUP_CONCAT by database into an array
|
||||||
|
* @param array String with comma-seperated values
|
||||||
|
* @returns [float] array of float values
|
||||||
|
*/
|
||||||
module.exports = (array) => {
|
module.exports = (array) => {
|
||||||
if (array !== null && array !== undefined) {
|
if (array !== null && array !== undefined) {
|
||||||
const value = array
|
const value = array
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
module.exports = function (dbConn) {
|
module.exports = function (dbConn) {
|
||||||
return async function getAllRegionsWithClimatePerMonth(month) {
|
return async function getAllRegionsWithClimatePerMonth(month) {
|
||||||
console.log('getAllRegionsWithClimatePerMonth')
|
console.log('getAllRegionsWithClimatePerMonth')
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
const sqlstring = require("sqlstring")
|
const sqlstring = require("sqlstring")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitizes value if it isn't a numerical value
|
||||||
|
* @param val
|
||||||
|
* @returns string Sanitized String
|
||||||
|
*/
|
||||||
module.exports = (val) => {
|
module.exports = (val) => {
|
||||||
if(!isNaN(val)) {
|
if(!isNaN(val)) { // Checks if the value is a numerical value (in a string)
|
||||||
return val
|
return val
|
||||||
} else {
|
} else {
|
||||||
return sqlstring.escape(val)
|
return sqlstring.escape(val)
|
||||||
|
|||||||
@ -20,6 +20,8 @@ export class GraphComponent implements AfterViewInit {
|
|||||||
formatSting: string;
|
formatSting: string;
|
||||||
@Input()
|
@Input()
|
||||||
graphType = 'line';
|
graphType = 'line';
|
||||||
|
@Input()
|
||||||
|
minMax: number[];
|
||||||
|
|
||||||
readonly randomId = uuidv4();
|
readonly randomId = uuidv4();
|
||||||
|
|
||||||
@ -60,6 +62,14 @@ export class GraphComponent implements AfterViewInit {
|
|||||||
data[i].color = this.colors[i];
|
data[i].color = this.colors[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let axisY: CanvasJS.ChartOptions.ChartAxisY;
|
||||||
|
if (this.minMax) {
|
||||||
|
axisY = {
|
||||||
|
minimum: this.minMax[0],
|
||||||
|
maximum: this.minMax[1]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const chart = new CanvasJS.Chart(this.randomId, {
|
const chart = new CanvasJS.Chart(this.randomId, {
|
||||||
animationEnabled: true,
|
animationEnabled: true,
|
||||||
@ -70,6 +80,7 @@ export class GraphComponent implements AfterViewInit {
|
|||||||
horizontalAlign: 'left',
|
horizontalAlign: 'left',
|
||||||
dockInsidePlotArea: true
|
dockInsidePlotArea: true
|
||||||
},
|
},
|
||||||
|
axisY,
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
<!-- Multi presets -->
|
<!-- Multi presets -->
|
||||||
<mat-step>
|
<mat-step>
|
||||||
<ng-template matStepLabel>Which climate do you prefer?</ng-template>
|
<ng-template matStepLabel>Which climate do you prefer?</ng-template>
|
||||||
|
<div class="flexer">
|
||||||
<div *ngFor="let key of multiPresetsKeys" class="sub-group">
|
<div *ngFor="let key of multiPresetsKeys" class="sub-group">
|
||||||
<span class="label">{{key|translate}}:</span><br>
|
<span class="label">{{key|translate}}:</span><br>
|
||||||
<mat-radio-group [ngModel]="multiPresetSelection[key]" [value]="undefined">
|
<mat-radio-group [ngModel]="multiPresetSelection[key]" [value]="undefined">
|
||||||
@ -36,6 +37,7 @@
|
|||||||
>{{preset.tag_label|translate}}</mat-radio-button>
|
>{{preset.tag_label|translate}}</mat-radio-button>
|
||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
<!-- Single presets -->
|
<!-- Single presets -->
|
||||||
<mat-step>
|
<mat-step>
|
||||||
@ -81,9 +83,9 @@
|
|||||||
<mat-icon>clear</mat-icon>
|
<mat-icon>clear</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="horizontal space center">
|
<div class="horizontal space center-desc">
|
||||||
<span>Search in description </span>
|
|
||||||
<mat-slide-toggle [(ngModel)]="fullText"></mat-slide-toggle>
|
<mat-slide-toggle [(ngModel)]="fullText"></mat-slide-toggle>
|
||||||
|
<span>Search in description </span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -93,19 +95,36 @@
|
|||||||
<span class="title">Climate</span>
|
<span class="title">Climate</span>
|
||||||
<span class="desc">| sweetspot selection</span>
|
<span class="desc">| sweetspot selection</span>
|
||||||
</div>
|
</div>
|
||||||
<app-toggle-slider [(model)]="temperatureMeanMax" [label]="'Temperature'" [max]="45"
|
<app-toggle-slider [(model)]="temperatureMeanMax" [label]="'Temperature (°C)'" [max]="45"
|
||||||
[min]="0"></app-toggle-slider>
|
[min]="0"></app-toggle-slider>
|
||||||
<app-toggle-slider [(model)]="precipitation" [label]="'Precipitation'" [max]="500"
|
<app-toggle-slider [(model)]="precipitation" [label]="'Precipitation (mm)'" [max]="500"
|
||||||
|
[min]="0"></app-toggle-slider>
|
||||||
|
<app-toggle-slider [(model)]="sunHours" [label]="'Sun hours'" [max]="400"
|
||||||
|
[min]="0"></app-toggle-slider>
|
||||||
|
<app-toggle-slider [(model)]="rainDays" [label]="'Rain days'" [max]="31"
|
||||||
[min]="0"></app-toggle-slider>
|
[min]="0"></app-toggle-slider>
|
||||||
</section>
|
</section>
|
||||||
<!-- Financial -->
|
<!-- Financial -->
|
||||||
<section class="group">
|
<section class="group">
|
||||||
<div class="horizontal">
|
<div class="horizontal">
|
||||||
<span class="title">Financial</span>
|
<span class="title">Financial</span>
|
||||||
<span class="desc">| sweetspot selection</span>
|
<span class="desc">| sweetspot selection (€/day)</span>
|
||||||
</div>
|
</div>
|
||||||
<app-toggle-slider [(model)]="accommodation" [label]="'Accommodation'" [max]="60" [min]="0"></app-toggle-slider>
|
<app-toggle-slider [(model)]="costPerDay" [label]="'Total cost'" [max]="400" [min]="0"></app-toggle-slider>
|
||||||
|
<app-toggle-slider [(model)]="accommodation" [label]="'Accommodation'" [max]="200"
|
||||||
|
[min]="0"></app-toggle-slider>
|
||||||
|
<app-toggle-slider [(model)]="localTransport" [label]="'Local transport'" [max]="20"
|
||||||
|
[min]="0"></app-toggle-slider>
|
||||||
</section>
|
</section>
|
||||||
|
<!-- Tags -->
|
||||||
|
<section class="group">
|
||||||
|
<div class="horizontal">
|
||||||
|
<span class="title">Tags</span>
|
||||||
|
<span class="desc">| Search by user ratings</span>
|
||||||
|
</div>
|
||||||
|
<app-multi-tag-select [(model)]="selectedTags" [availableTags]="tags"></app-multi-tag-select>
|
||||||
|
</section>
|
||||||
|
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
> .search-btn {
|
>.search-btn {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,6 +31,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
@ -45,13 +46,18 @@
|
|||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .content {
|
>.content {
|
||||||
margin: 0 2.5rem;
|
// margin: 0 2.5rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
|
||||||
.text-input {
|
.text-input {
|
||||||
min-width: 14rem;
|
min-width: 14rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> app-multi-tag-select {
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.horizontal {
|
.horizontal {
|
||||||
@ -60,7 +66,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.space {
|
&.space {
|
||||||
> * {
|
>* {
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,6 +75,10 @@
|
|||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.center-desc {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -81,15 +91,30 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-evenly;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-left: -0.5rem;
|
||||||
|
margin-right: -0.5rem;
|
||||||
|
|
||||||
> * {
|
>* {
|
||||||
width: 45%;
|
flex-grow: 1;
|
||||||
min-width: 15rem;
|
margin: 0 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-bottom-margin {
|
.small-bottom-margin {
|
||||||
margin-bottom: 0.4rem !important;
|
margin-bottom: 0.4rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flexer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-right: -1rem;
|
||||||
|
|
||||||
|
> .sub-group {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {PresetService} from '../../services/preset.service';
|
|||||||
import {Preset} from '../../interfaces/preset.interface';
|
import {Preset} from '../../interfaces/preset.interface';
|
||||||
import {formatDate} from '@angular/common';
|
import {formatDate} from '@angular/common';
|
||||||
import {SearchService} from '../../services/search.service';
|
import {SearchService} from '../../services/search.service';
|
||||||
|
import {toMinMaxArray} from '../../utils/toMinMaxArray';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search-input',
|
selector: 'app-search-input',
|
||||||
@ -37,7 +38,12 @@ export class SearchInputComponent implements OnInit {
|
|||||||
fullText = false;
|
fullText = false;
|
||||||
temperatureMeanMax: number;
|
temperatureMeanMax: number;
|
||||||
precipitation: number;
|
precipitation: number;
|
||||||
|
rainDays: number;
|
||||||
|
sunHours: number;
|
||||||
accommodation: number;
|
accommodation: number;
|
||||||
|
costPerDay: number;
|
||||||
|
entertainment: number;
|
||||||
|
localTransport: number;
|
||||||
|
|
||||||
readonly today = this.from = formatDate(new Date(), 'yyyy-MM-dd', 'en-GB');
|
readonly today = this.from = formatDate(new Date(), 'yyyy-MM-dd', 'en-GB');
|
||||||
|
|
||||||
@ -124,6 +130,7 @@ export class SearchInputComponent implements OnInit {
|
|||||||
const query: Query = {
|
const query: Query = {
|
||||||
from: new Date(this.from).getTime(),
|
from: new Date(this.from).getTime(),
|
||||||
to: new Date(this.to).getTime(),
|
to: new Date(this.to).getTime(),
|
||||||
|
tags: this.selectedTags
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.textFilter.length > 0) {
|
if (this.textFilter.length > 0) {
|
||||||
@ -131,9 +138,14 @@ export class SearchInputComponent implements OnInit {
|
|||||||
query.textfilter = this.textFilter;
|
query.textfilter = this.textFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.temperature_mean_max = this.temperatureMeanMax ? [this.temperatureMeanMax, this.temperatureMeanMax] : undefined;
|
query.temperature_mean_max = toMinMaxArray(this.temperatureMeanMax);
|
||||||
query.precipitation = this.precipitation ? [this.precipitation, this.precipitation] : undefined;
|
query.precipitation = toMinMaxArray(this.precipitation);
|
||||||
query.accommodation_costs = this.accommodation ? [this.accommodation, this.accommodation] : undefined;
|
query.sun_hours = toMinMaxArray(this.sunHours);
|
||||||
|
query.rain_days = toMinMaxArray(this.rainDays);
|
||||||
|
query.average_per_day_costs = toMinMaxArray(this.costPerDay);
|
||||||
|
query.accommodation_costs = toMinMaxArray(this.accommodation);
|
||||||
|
query.entertainment_costs = toMinMaxArray(this.entertainment);
|
||||||
|
query.local_transportation_costs = toMinMaxArray(this.localTransport);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
@ -150,7 +162,12 @@ export class SearchInputComponent implements OnInit {
|
|||||||
textFiler: this.textFilter,
|
textFiler: this.textFilter,
|
||||||
tempMeanMax: this.temperatureMeanMax,
|
tempMeanMax: this.temperatureMeanMax,
|
||||||
precipitation: this.precipitation,
|
precipitation: this.precipitation,
|
||||||
|
rain_days: this.rainDays,
|
||||||
|
sun_hours: this.sunHours,
|
||||||
|
average_per_day_costs: this.costPerDay,
|
||||||
accommodation: this.accommodation,
|
accommodation: this.accommodation,
|
||||||
|
entertainment_costs: this.entertainment,
|
||||||
|
local_transportation_costs: this.localTransport,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +185,12 @@ export class SearchInputComponent implements OnInit {
|
|||||||
this.selectedTab = prevInput.wasAdvanced ? 1 : 0;
|
this.selectedTab = prevInput.wasAdvanced ? 1 : 0;
|
||||||
this.temperatureMeanMax = prevInput.tempMeanMax;
|
this.temperatureMeanMax = prevInput.tempMeanMax;
|
||||||
this.precipitation = prevInput.precipitation;
|
this.precipitation = prevInput.precipitation;
|
||||||
|
this.rainDays = prevInput.rain_days;
|
||||||
|
this.sunHours = prevInput.sun_hours;
|
||||||
|
this.costPerDay = prevInput.average_per_day_costs;
|
||||||
this.accommodation = prevInput.accommodation;
|
this.accommodation = prevInput.accommodation;
|
||||||
|
this.entertainment = prevInput.entertainment_costs;
|
||||||
|
this.localTransport = prevInput.local_transportation_costs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,8 @@
|
|||||||
<mat-tab-group>
|
<mat-tab-group>
|
||||||
<mat-tab *ngIf="region.avg_price_relative" label="Price Deviation">
|
<mat-tab *ngIf="region.avg_price_relative" label="Price Deviation">
|
||||||
<ng-template matTabContent>
|
<ng-template matTabContent>
|
||||||
<app-graph [monthlyDatas]="[region.avg_price_relative]" class="graph" formatSting="##,##%" graphType="column">
|
<app-graph [monthlyDatas]="[region.avg_price_relative]" class="graph" formatSting="##0.##'%'"
|
||||||
|
graphType="column">
|
||||||
</app-graph>
|
</app-graph>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
@ -35,25 +36,27 @@
|
|||||||
<ng-template matTabContent>
|
<ng-template matTabContent>
|
||||||
<app-graph [colors]="['blue', 'red']" [labels]="['Min', 'Max']"
|
<app-graph [colors]="['blue', 'red']" [labels]="['Min', 'Max']"
|
||||||
[monthlyDatas]="[region.temperature_mean_min, region.temperature_mean_max]" class="graph"
|
[monthlyDatas]="[region.temperature_mean_min, region.temperature_mean_max]" class="graph"
|
||||||
formatSting="##,##°C">
|
[minMax]="[-25, 50]" formatSting="##,##°C">
|
||||||
</app-graph>
|
</app-graph>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab *ngIf="region.precipitation" label="Precipitation">
|
<mat-tab *ngIf="region.precipitation" label="Precipitation">
|
||||||
<ng-template matTabContent>
|
<ng-template matTabContent>
|
||||||
<app-graph [monthlyDatas]="[region.precipitation]" class="graph" formatSting="####mm">
|
<app-graph [minMax]="[0, 1200]" [monthlyDatas]="[region.precipitation]" class="graph" formatSting="####'mm'">
|
||||||
</app-graph>
|
</app-graph>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab *ngIf="region.rain_days" label="Rain days">
|
<mat-tab *ngIf="region.rain_days" label="Rain days">
|
||||||
<ng-template matTabContent>
|
<ng-template matTabContent>
|
||||||
<app-graph [monthlyDatas]="[region.rain_days]" class="graph" formatSting="####" graphType="column">
|
<app-graph [minMax]="[0, 31]" [monthlyDatas]="[region.rain_days]" class="graph" formatSting="####"
|
||||||
|
graphType="column">
|
||||||
</app-graph>
|
</app-graph>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab *ngIf="region.sun_hours" label="Sun hours">
|
<mat-tab *ngIf="region.sun_hours" label="Sun hours">
|
||||||
<ng-template matTabContent>
|
<ng-template matTabContent>
|
||||||
<app-graph [monthlyDatas]="[region.sun_hours]" class="graph" formatSting="####" graphType="column">
|
<app-graph [minMax]="[0, 450]" [monthlyDatas]="[region.sun_hours]" class="graph" formatSting="####"
|
||||||
|
graphType="column">
|
||||||
</app-graph>
|
</app-graph>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|||||||
@ -84,6 +84,7 @@
|
|||||||
|
|
||||||
app-place {
|
app-place {
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,12 +61,16 @@ export class SearchComponent implements OnInit {
|
|||||||
{name: 'Price', property: 'average_per_day_costs'}
|
{name: 'Price', property: 'average_per_day_costs'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.sortBy = 'score';
|
||||||
|
this.sortDes = true;
|
||||||
|
|
||||||
if (this.results.length > 0) {
|
if (this.results.length > 0) {
|
||||||
this.results[0].scores.forEach(({type}) => {
|
const tags = await this.ss.getAvailableTags();
|
||||||
|
for (const {type} of this.results[0].scores) {
|
||||||
if (!this.sortOptions.find(i => i.property === type)) {
|
if (!this.sortOptions.find(i => i.property === type)) {
|
||||||
this.sortOptions.push({name: type, property: type, isScore: true});
|
this.sortOptions.push({name: type, property: type, isScore: true, descending: tags.includes(type)});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate duration
|
// Calculate duration
|
||||||
|
|||||||
@ -13,7 +13,12 @@ export interface SearchInput {
|
|||||||
fullText: boolean;
|
fullText: boolean;
|
||||||
tempMeanMax: number;
|
tempMeanMax: number;
|
||||||
precipitation: number;
|
precipitation: number;
|
||||||
|
rain_days: number;
|
||||||
|
sun_hours: number;
|
||||||
|
average_per_day_costs: number;
|
||||||
accommodation: number;
|
accommodation: number;
|
||||||
|
entertainment_costs: number;
|
||||||
|
local_transportation_costs: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
|||||||
7
frontend/src/app/utils/toMinMaxArray.ts
Normal file
7
frontend/src/app/utils/toMinMaxArray.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Transforms a value into a min max array.
|
||||||
|
* @param value The value
|
||||||
|
*/
|
||||||
|
export function toMinMaxArray(value: number): number[] {
|
||||||
|
return value ? [value, value] : undefined;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user