From cc86d2be678066cf00310400225971bcfc3efe04 Mon Sep 17 00:00:00 2001 From: Joe Heffer Date: Fri, 26 Jul 2024 14:36:26 +0100 Subject: [PATCH] fix: Development environment proxy settings Vite should redirect API requests from port 5173 to port 5000 to reach flask. We have to manually specify each root API endpoint. --- backend/CONTRIBUTING.md | 4 +++- backend/btviewer/app.py | 1 + backend/btviewer/app_factory.py | 1 + backend/btviewer/blueprints/photo/model.py | 4 ++-- frontend/CONTRIBUTING.md | 7 +++---- frontend/src/components/CameraList.jsx | 2 +- frontend/src/components/DeviceList.jsx | 2 +- frontend/src/components/PhotoSelection.jsx | 14 +++++++------- frontend/src/components/SessionList.jsx | 2 +- frontend/src/components/Sessions.jsx | 2 +- frontend/src/components/SetList.jsx | 2 +- frontend/vite.config.js | 13 ++++++++++--- 12 files changed, 32 insertions(+), 22 deletions(-) diff --git a/backend/CONTRIBUTING.md b/backend/CONTRIBUTING.md index 3f79962..13c9a40 100644 --- a/backend/CONTRIBUTING.md +++ b/backend/CONTRIBUTING.md @@ -42,9 +42,11 @@ pip install --editable ./backend To run the app in development mode: ```bash -flask --app backend.btviewer.app --debug run +flask --app backend.btviewer.app --debug run --port 5000 ``` +We must always use port 5000 because the front-end is configured to use that port. + To run the frontend user interface in development mode, see the [frontend contribution guide](../frontend/CONTRIBUTING.md). ## Deployment diff --git a/backend/btviewer/app.py b/backend/btviewer/app.py index 0c535ff..def77ce 100644 --- a/backend/btviewer/app.py +++ b/backend/btviewer/app.py @@ -11,3 +11,4 @@ ROOT_DIRECTORY = os.getenv('ROOT_DIRECTORY', Path(__file__).parent.parent.joinpath('tests/data')) app = create_app(root_directory=ROOT_DIRECTORY) +"DEVELOPMENT Flask app" diff --git a/backend/btviewer/app_factory.py b/backend/btviewer/app_factory.py index 9912cdc..f2c5d41 100644 --- a/backend/btviewer/app_factory.py +++ b/backend/btviewer/app_factory.py @@ -6,6 +6,7 @@ from typing import Union import flask +from werkzeug.middleware.dispatcher import DispatcherMiddleware def create_app(root_directory: Union[Path, str] = None, **kwargs) -> flask.Flask: diff --git a/backend/btviewer/blueprints/photo/model.py b/backend/btviewer/blueprints/photo/model.py index 21f6bd1..2b69bb0 100644 --- a/backend/btviewer/blueprints/photo/model.py +++ b/backend/btviewer/blueprints/photo/model.py @@ -2,7 +2,7 @@ import io import json from pathlib import Path -from typing import Iterable, Mapping, Union, Generator +from typing import Iterable, Mapping, Union, Generator, Tuple import PIL.Image import flask @@ -10,7 +10,7 @@ app: flask.Flask = flask.current_app -Coordinate = tuple[int, int] +Coordinate = Tuple[int, int] "x, y position in a 2D image pixel grid" diff --git a/frontend/CONTRIBUTING.md b/frontend/CONTRIBUTING.md index de00051..cad4464 100644 --- a/frontend/CONTRIBUTING.md +++ b/frontend/CONTRIBUTING.md @@ -31,13 +31,12 @@ npm install The development environment is defined by the `dev` configuration in `package.json` and uses the [Vite](https://vitejs.dev/guide/#index-html-and-project-root) tool. ``` - # Run the development environment npm run dev ``` - - ## Vite -[Vite](https://vitejs.dev/) provides Hot Module Replacement (HMR) and some code analysis using ESLint rules. It uses `index.html` as the [home page](https://vitejs.dev/guide/#index-html-and-project-root). \ No newline at end of file +[Vite](https://vitejs.dev/) provides automatic code reloading using Hot Module Replacement (HMR) and some code analysis using ESLint rules. It uses `index.html` as the [home page](https://vitejs.dev/guide/#index-html-and-project-root). + +There is a configuration file for Vite at `frontend/vite.config.js` that specifies some proxy settings so that we can access the backend via the frontend testing app (which defaults to port 5173.) \ No newline at end of file diff --git a/frontend/src/components/CameraList.jsx b/frontend/src/components/CameraList.jsx index 80ade31..bddbab5 100644 --- a/frontend/src/components/CameraList.jsx +++ b/frontend/src/components/CameraList.jsx @@ -31,7 +31,7 @@ if (typeof(data)==="string"){ //when there is nth in the data, especially when t function changeHandler(e) { let selectedCamera = e.target.value; // Update the list of photo filenames available in that session - let url = `/api/sessions/list/?path=${subdirectory}/${selectedCamera}`; + let url = '/sessions/list/?path=${subdirectory}/${selectedCamera}'; console.log(url) fetch(url) .then((response) => response.json()) diff --git a/frontend/src/components/DeviceList.jsx b/frontend/src/components/DeviceList.jsx index e8fef44..7d1dd12 100644 --- a/frontend/src/components/DeviceList.jsx +++ b/frontend/src/components/DeviceList.jsx @@ -31,7 +31,7 @@ if (typeof(data)==="string"){ //when there is nth in the data, especially when t let selectedDevice = e.target.value; console.log(selectedDevice) // Update the list of photo filenames available in that session - let url = `/api/sessions/list/?path=${subdirectory}/${selectedDevice}`; + let url = `/sessions/list/?path=${subdirectory}/${selectedDevice}`; console.log(url) fetch(url) .then((response) => response.json()) diff --git a/frontend/src/components/PhotoSelection.jsx b/frontend/src/components/PhotoSelection.jsx index b9e95bd..69f08f5 100644 --- a/frontend/src/components/PhotoSelection.jsx +++ b/frontend/src/components/PhotoSelection.jsx @@ -46,12 +46,12 @@ function PhotoSelection({ photoFilenames, subdirectory }) { console.log('subdirectoryJoined') console.log(subdirectoryJoined) //SC:Did we fetch photo, it does not seems so, and I only submit the image source to the image.jsx - let urlJpeg = "/api/photos/" + subdirectoryJoined.replace("np", "jpeg"); + let urlJpeg = "/photos/" + subdirectoryJoined.replace("np", "jpeg"); setCurrentPhoto(urlJpeg); console.log('urlJpeg' + urlJpeg); //Get photo dimension - let urlDimension = "/api/photos/dimension?path=" + subdirectoryJoined; + let urlDimension = "/photos/dimension?path=" + subdirectoryJoined; fetch(urlDimension) .then((response) => response.json()) .then((data)=>{ @@ -63,7 +63,7 @@ function PhotoSelection({ photoFilenames, subdirectory }) { }) // Get the json for the human/retrodetect label coordinates if it exists - let urlLabel = "/api/labels/detail?path=" + subdirectoryJoined; + let urlLabel = "/labels/detail?path=" + subdirectoryJoined; console.log("urlLabel"); console.log(urlLabel); fetch(urlLabel) @@ -76,7 +76,7 @@ function PhotoSelection({ photoFilenames, subdirectory }) { function handleNextPrevPhoto(current_path, skipnumber) { const currentPath = current_path; const skip = skipnumber; - let url = `/api/photos/next?path=${currentPath}&skip=${skip}`; + let url = `/photos/next?path=${currentPath}&skip=${skip}`; console.log("urlcurret photo in next"); console.log(url); @@ -84,10 +84,10 @@ function PhotoSelection({ photoFilenames, subdirectory }) { .then((response) => response.json()) .then((data) => { setPhotoPath(data); - let urlJpeg = "/api/photos/" + data.replace("np", "jpeg"); + let urlJpeg = "/photos/" + data.replace("np", "jpeg"); setCurrentPhoto(urlJpeg); - let urlDimension = "/api/photos/dimension?path=" + data; + let urlDimension = "/photos/dimension?path=" + data; fetch(urlDimension) .then((response) => response.json()) .then((data)=>{ @@ -97,7 +97,7 @@ function PhotoSelection({ photoFilenames, subdirectory }) { }); }) - let urlLabel = "/api/labels/detail?path=" + data; + let urlLabel = "/labels/detail?path=" + data; fetch(urlLabel) .then((response) => response.json()) .then((data) => { diff --git a/frontend/src/components/SessionList.jsx b/frontend/src/components/SessionList.jsx index 975f8c9..5e52ef5 100644 --- a/frontend/src/components/SessionList.jsx +++ b/frontend/src/components/SessionList.jsx @@ -26,7 +26,7 @@ function SessionList({ data }) { setSelectedSubdirectory(selected) // Update the list of photo filenames available in that session - let url = `/api/sessions/list/?path=${selected}`; + let url = `/sessions/list/?path=${selected}`; console.log('sessionslist') console.log(url) fetch(url) diff --git a/frontend/src/components/Sessions.jsx b/frontend/src/components/Sessions.jsx index e536fb5..aa7000c 100644 --- a/frontend/src/components/Sessions.jsx +++ b/frontend/src/components/Sessions.jsx @@ -5,7 +5,7 @@ The list of bee tracking photo data capture sessions. */ function Sessions() { // TODO use global variable for backend URL - const url = "/api/sessions/list"; + const url = "/sessions/list/"; console.log('sessions') console.log(url) diff --git a/frontend/src/components/SetList.jsx b/frontend/src/components/SetList.jsx index fa92c00..3526182 100644 --- a/frontend/src/components/SetList.jsx +++ b/frontend/src/components/SetList.jsx @@ -31,7 +31,7 @@ if (typeof(data)==="string"){ //when there is nth in the data, especially when t let selectedSet = e.target.value; console.log(selectedSet) // Update the list of photo filenames available in that session - let url = `/api/sessions/list/?path=${subdirectory}/${selectedSet}`; + let url = `/sessions/list/?path=${subdirectory}/${selectedSet}`; console.log('set') console.log(url) console.log(url) diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 48d0054..ea75753 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -11,10 +11,17 @@ export default defineConfig({ server: { // Create a proxy endpoint to the backend to avoid cross-origin (CORS) issues proxy: { - '/api': { + '/sessions': { target: 'http://localhost:5000', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, ''), + changeOrigin: true + }, + '/photos': { + target: 'http://localhost:5000', + changeOrigin: true + }, + '/labels': { + target: 'http://localhost:5000', + changeOrigin: true }, }, },