diff --git a/docs/setup-development.md b/docs/setup-development.md index 965b29dc8..ae7f824f3 100644 --- a/docs/setup-development.md +++ b/docs/setup-development.md @@ -111,7 +111,7 @@ Most of these environment variables have reasonable default settings. - `GARMIN_CONFIG`, `GARMIN_MKGMAP` absolute paths to garmin JARs - `OVERPASS_API_URL` url of Overpass api endpoint -- `RAW_DATA_API_URL` url of Galaxy api endpoint +- `RAW_DATA_API_URL` url of Raw data api endpoint - `DATABASE_URL` Database URL. Defaults to `postgres:///exports` - `DEBUG` Whether to enable debug mode. Defaults to `False` (production). diff --git a/requirements.txt b/requirements.txt index b32183eac..9a7faec3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ mercantile~=0.10.0 psycopg2 python3-openid==3.2.0 social-auth-app-django==5.4.0 -social-auth-core==4.4.2 ### Upgrade this to include oauth2 +social-auth-core @ git+https://github.com/kshitijrajsharma/social-core.git ### Upgrade this to include osm oauth2 when released pytz pyyaml>=5.3 raven diff --git a/ui/app/actions/exports.js b/ui/app/actions/exports.js index 0512af16c..d583ba5f9 100644 --- a/ui/app/actions/exports.js +++ b/ui/app/actions/exports.js @@ -170,8 +170,8 @@ export const getOverpassTimestamp = () => (dispatch, getState) => { export const getGalaxyTimestamp = () => (dispatch, getState) => { return axios({ - baseURL: "https://api-prod.raw-data.hotosm.org/v1", - url: "/status/" + baseURL: window.RAW_DATA_API_URL, + url: "v1/status/" }) .then(response => dispatch({ diff --git a/ui/app/actions/meta.js b/ui/app/actions/meta.js index 3025d07fa..ab5ad30a8 100644 --- a/ui/app/actions/meta.js +++ b/ui/app/actions/meta.js @@ -10,6 +10,10 @@ if (window.location.port) { hostname += `:${window.location.port}`; } +if (window.RAW_DATA_API_URL == null) { + window.RAW_DATA_API_URL = process.env.RAW_DATA_API_URL; +} + if (window.EXPORTS_API_URL == null) { window.EXPORTS_API_URL = process.env.EXPORTS_API_URL; diff --git a/ui/app/app.js b/ui/app/app.js index c350ffa4f..4ed34b0c0 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -25,6 +25,7 @@ import Home from "./components/Home"; import NavBar from "./components/NavBar"; import Stats from "./components/Stats"; import Banner from "./components/Banner"; +import Message from "./components/Message.js"; import { requireAuth } from "./components/utils"; import "@blueprintjs/core/dist/blueprint.css"; @@ -49,6 +50,7 @@ export default ({ history }) => {
+ diff --git a/ui/app/components/ExportForm.js b/ui/app/components/ExportForm.js index d46fe020e..0e4e623b2 100644 --- a/ui/app/components/ExportForm.js +++ b/ui/app/components/ExportForm.js @@ -1,4 +1,5 @@ import area from "@turf/area"; +import axios from "axios"; import bbox from "@turf/bbox"; import React, { Component } from "react"; import { Col, Nav, Panel, Row } from "react-bootstrap"; @@ -8,7 +9,6 @@ import { Redirect, Route, Switch } from "react-router"; import { NavLink } from "react-router-dom"; import { Fields, formValueSelector, reduxForm } from "redux-form"; import { pointToTile } from "tilebelt"; - import ChooseFormats from "./ChooseFormats"; import DescribeExport from "./DescribeExport"; import ExportAOIField from "./ExportAOIField"; @@ -128,6 +128,86 @@ export class ExportForm extends Component { }; } + async fetchData(geometry) { + const url = window.RAW_DATA_API_URL + "v1/stats/polygon/"; + try { + const response = await axios.post(url, { + geometry: geometry + }, { + headers: {"Content-Type": "application/json"} + }); + + if (response.data) { + + this.setState({ fetchedInfo: response.data }); + } + } catch (error) { + console.error("Failed to fetch summary data", error); + + } + } + + componentDidUpdate(prevProps) { + if (this.props.formValues.the_geom !== prevProps.formValues.the_geom) { + this.fetchData(this.props.formValues.the_geom); + } + } + + renderFetchedInfo() { + const { fetchedInfo } = this.state; + if (!this.props.formValues.the_geom) return null; + if (!fetchedInfo) return null; + + // Function to trigger the download of the raw data as a JSON file + const downloadRawData = () => { + const filename = "raw_region_summary.json"; + const jsonStr = JSON.stringify(fetchedInfo, null, 4); + const element = document.createElement('a'); + element.setAttribute('href', 'data:text/json;charset=utf-8,' + encodeURIComponent(jsonStr)); + element.setAttribute('download', filename); + element.style.display = 'none'; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + }; + + return ( + +
+
+ Buildings: +

+ +

+
+
+ Roads: +

+ +

+
+
+ More info: + Download, + Indicators, + Metrics +
+
+
+ ); + } + + + + componentWillMount() { const { getConfigurations, getOverpassTimestamp, getGalaxyTimestamp} = this.props; @@ -281,10 +361,11 @@ export class ExportForm extends Component { />} />
+ {this.renderFetchedInfo()} diff --git a/ui/app/components/Message.js b/ui/app/components/Message.js new file mode 100644 index 000000000..9fb51f7e9 --- /dev/null +++ b/ui/app/components/Message.js @@ -0,0 +1,34 @@ +import React, { Component } from "react"; + +class Message extends Component { + constructor(props) { + super(props); + // Use "messageClosed" as the key to check if the message was previously closed + const messageClosed = localStorage.getItem("messageClosed") === "true"; + this.state = { + isVisible: !messageClosed, + }; + } + + handleClose = () => { + this.setState({ isVisible: false }); + // When closing, set "messageClosed" in localStorage to "true" + localStorage.setItem("messageClosed", "true"); + }; + + render() { + if (!this.state.isVisible) { + return null; + } + return ( +
+

We have recently upgraded from OAuth 1.0 to 2.0. Please Logout and Login again before use!

+ +
+ ); + } +} + +export default Message; diff --git a/ui/app/components/utils.js b/ui/app/components/utils.js index 58fbcb9b0..4fcd6e892 100644 --- a/ui/app/components/utils.js +++ b/ui/app/components/utils.js @@ -58,6 +58,11 @@ export const AVAILABLE_EXPORT_FORMATS = { SQL .sql ), + mbtiles: ( + + MBTiles .mbtiles + + ), garmin_img: ( Garmin .img @@ -83,11 +88,6 @@ export const AVAILABLE_EXPORT_FORMATS = { OsmAnd .obf ), - mbtiles: ( - - MBTiles .mbtiles - - ), bundle: ( POSM bundle diff --git a/ui/templates/ui/v3.html b/ui/templates/ui/v3.html index 7f9fcfd17..1649f8f67 100644 --- a/ui/templates/ui/v3.html +++ b/ui/templates/ui/v3.html @@ -30,6 +30,7 @@ diff --git a/ui/views.py b/ui/views.py index a5496b931..2cfd4b98e 100644 --- a/ui/views.py +++ b/ui/views.py @@ -56,7 +56,9 @@ def v3(request, *args, **kwargs): skip_authorization=True, ) - context = dict(client_id=ui_app.client_id) + context = dict( + client_id=ui_app.client_id, RAW_DATA_API_URL=settings.RAW_DATA_API_URL + ) if settings.MATOMO_URL is not None and settings.MATOMO_SITEID is not None: context.update( {"MATOMO_URL": settings.MATOMO_URL, "MATOMO_SITEID": settings.MATOMO_SITEID} diff --git a/ui/webpack.config.js b/ui/webpack.config.js index 858b0313e..ed8ec9e2b 100644 --- a/ui/webpack.config.js +++ b/ui/webpack.config.js @@ -93,7 +93,8 @@ const config = { plugins: [new webpack.DefinePlugin({ "process.env": { CLIENT_ID: JSON.stringify(process.env.CLIENT_ID), - EXPORTS_API_URL: JSON.stringify(process.env.EXPORTS_API_URL) + EXPORTS_API_URL: JSON.stringify(process.env.EXPORTS_API_URL), + RAW_DATA_API_URL: JSON.stringify(process.env.RAW_DATA_API_URL) } }), new webpack.NamedModulesPlugin(), new WriteFilePlugin()], resolve: { @@ -110,6 +111,7 @@ if (process.env.NODE_ENV === "production") { "process.env": { CLIENT_ID: JSON.stringify(process.env.CLIENT_ID), EXPORTS_API_URL: JSON.stringify(process.env.EXPORTS_API_URL), + RAW_DATA_API_URL: JSON.stringify(process.env.RAW_DATA_API_URL), NODE_ENV: JSON.stringify("production") } }),