deleted some useless stuff and backend integration
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
const FtpDeploy = require("ftp-deploy");
|
const FtpDeploy = require("ftp-deploy");
|
||||||
const ftpDeploy = new FtpDeploy();
|
|
||||||
|
const ftp = new FtpDeploy();
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
user: process.env.FTP_USER,
|
user: process.env.FTP_USER,
|
||||||
@@ -8,9 +9,7 @@ const config = {
|
|||||||
port: process.env.FTP_PORT,
|
port: process.env.FTP_PORT,
|
||||||
localRoot: __dirname + "/../frontend",
|
localRoot: __dirname + "/../frontend",
|
||||||
remoteRoot: "/public_html/car/",
|
remoteRoot: "/public_html/car/",
|
||||||
// include: ["*", "**/*"], // this would upload everything except dot files
|
|
||||||
include: ["build/**"],
|
include: ["build/**"],
|
||||||
// e.g. exclude sourcemaps, and ALL files in node_modules (including dot files)
|
|
||||||
exclude: ["build/**/*.map", "node_modules/**", "node_modules/**/.*", ".git/**"],
|
exclude: ["build/**/*.map", "node_modules/**", "node_modules/**/.*", ".git/**"],
|
||||||
// delete ALL existing files at destination before uploading, if true
|
// delete ALL existing files at destination before uploading, if true
|
||||||
deleteRemote: false,
|
deleteRemote: false,
|
||||||
@@ -18,9 +17,9 @@ const config = {
|
|||||||
forcePasv: true
|
forcePasv: true
|
||||||
};
|
};
|
||||||
|
|
||||||
ftpDeploy
|
ftp
|
||||||
.deploy(config)
|
.deploy(config)
|
||||||
.then(res => {
|
.then(() => {
|
||||||
console.log("Deployment to FTP finished");
|
console.log("Deployment to FTP finished");
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "5.13.0",
|
"@fortawesome/fontawesome-free": "5.13.0",
|
||||||
"@reduxjs/toolkit": "1.3.6",
|
"@reduxjs/toolkit": "^1.3.6",
|
||||||
"core-js": "3.6.5",
|
"core-js": "3.6.5",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1",
|
"react-dom": "16.13.1",
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
|
import {
|
||||||
|
alprFetchSuccess, alprFetchStart,
|
||||||
|
} from '@slice/RecognitionSlice';
|
||||||
|
|
||||||
const API_BASE_PATH = process.env.NODE_ENV === 'production'
|
const API_BASE_PATH = process.env.NODE_ENV === 'production'
|
||||||
? process.env.API_BASE_PATH
|
? process.env.API_BASE_PATH
|
||||||
: 'http://localhost:4000';
|
: 'http://localhost:4000';
|
||||||
|
|
||||||
export const getPlateRecognized = async (image) => {
|
export const getPlateRecognized = (image) => async (dispatch) => {
|
||||||
|
console.log(image);
|
||||||
|
dispatch(alprFetchStart());
|
||||||
const body = new FormData();
|
const body = new FormData();
|
||||||
body.append('upload', image);
|
body.append('upload', image);
|
||||||
try {
|
try {
|
||||||
@@ -12,6 +18,7 @@ export const getPlateRecognized = async (image) => {
|
|||||||
});
|
});
|
||||||
console.log(response);
|
console.log(response);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
dispatch(alprFetchSuccess(data));
|
||||||
console.log(data);
|
console.log(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|||||||
37
frontend/src/components/alpr/RecognitionResults.jsx
Normal file
37
frontend/src/components/alpr/RecognitionResults.jsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import RootContext from '@context/RootContext';
|
||||||
|
import Button from '@components/common/Button';
|
||||||
|
|
||||||
|
const RecognitionResults = () => {
|
||||||
|
const { state: { alpr: { results } } } = useContext(RootContext);
|
||||||
|
|
||||||
|
const getPlate = () => {
|
||||||
|
if (results.length === 0) {
|
||||||
|
return (<h2>No plate detected</h2>);
|
||||||
|
}
|
||||||
|
console.log(results);
|
||||||
|
const { score, plate } = results[0];
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="row">
|
||||||
|
<h2>{plate.toUpperCase()}</h2>
|
||||||
|
<h3>
|
||||||
|
Confidence
|
||||||
|
{' '}
|
||||||
|
{score}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<Button text="Fetch data" />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
{getPlate()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RecognitionResults;
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useState, useEffect, useRef, useCallback,
|
useState, useEffect, useRef, useCallback, useContext,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import Webcam from 'react-webcam';
|
import Webcam from 'react-webcam';
|
||||||
import FacingMode from '@constant/FacingMode';
|
import FacingMode from '@constant/FacingMode';
|
||||||
import Loader from '@components/Loader';
|
import Loader from '@components/common/Loader';
|
||||||
import '@style/RootContainer.scss';
|
import '@style/RootContainer.scss';
|
||||||
|
import RootContext from '@context/RootContext';
|
||||||
|
import { resetResults } from '@slice/RecognitionSlice';
|
||||||
import CameraOptions from './CameraOptions';
|
import CameraOptions from './CameraOptions';
|
||||||
import Capture from './Capture';
|
import Capture from './Capture';
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ const CAMERA_OPTIONS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CameraContainer = () => {
|
const CameraContainer = () => {
|
||||||
|
const { dispatch } = useContext(RootContext);
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
const [imgSrc, setImgSrc] = useState(null);
|
const [imgSrc, setImgSrc] = useState(null);
|
||||||
const [captureError, setCaptureError] = useState(null);
|
const [captureError, setCaptureError] = useState(null);
|
||||||
@@ -71,7 +74,10 @@ const CameraContainer = () => {
|
|||||||
}
|
}
|
||||||
}, [ref, setImgSrc]);
|
}, [ref, setImgSrc]);
|
||||||
|
|
||||||
const onBackClick = () => setImgSrc(null);
|
const onBackClick = () => {
|
||||||
|
setImgSrc(null);
|
||||||
|
dispatch(resetResults());
|
||||||
|
};
|
||||||
|
|
||||||
const cameraView = () => (
|
const cameraView = () => (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Button from '@components/Button';
|
import Button from '@components/common/Button';
|
||||||
|
|
||||||
const CameraOptions = ({ capture, changeCameraView }) => (
|
const CameraOptions = ({ capture, changeCameraView }) => (
|
||||||
<div className="row button-container">
|
<div className="row button-container">
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
import React from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import Loader from '@components/Loader';
|
import Loader from '@components/common/Loader';
|
||||||
import { getPlateRecognized } from '@actions/CaptureActions';
|
import { getPlateRecognized } from '@actions/CaptureActions';
|
||||||
import Button from '@components/Button';
|
import Button from '@components/common/Button';
|
||||||
|
import RootContext from '@context/RootContext';
|
||||||
|
import RecognitionResults from '@components/alpr/RecognitionResults';
|
||||||
|
|
||||||
const UploadCapture = ({ imgSrc, onBackClick }) => {
|
const UploadCapture = ({ imgSrc, onBackClick }) => {
|
||||||
|
const [hasFetched, setHasFetched] = useState(false);
|
||||||
|
const { state: { alpr: { isFetchingALPR } }, dispatch } = useContext(RootContext);
|
||||||
const onUploadClick = () => {
|
const onUploadClick = () => {
|
||||||
getPlateRecognized(imgSrc);
|
getPlateRecognized(imgSrc)(dispatch);
|
||||||
|
setHasFetched(true);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
|
{isFetchingALPR ? <Loader /> : (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<img src={imgSrc} alt="captured" />
|
<img src={imgSrc} alt="captured" />
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{hasFetched && !isFetchingALPR && (<RecognitionResults />)}
|
||||||
<div className="row button-container">
|
<div className="row button-container">
|
||||||
<Button text="Back" onClick={onBackClick} />
|
<Button text="Back" onClick={onBackClick} />
|
||||||
<Button text="Upload" onClick={onUploadClick} />
|
{!hasFetched && <Button text="Upload" onClick={onUploadClick} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import '@style/spinner.scss';
|
import './Loader.scss';
|
||||||
|
|
||||||
const Loader = () => (<div className="loader">Loading...</div>);
|
const Loader = () => (<div className="loader">Loading...</div>);
|
||||||
|
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
import React, { useReducer, useContext } from 'react';
|
import React, { useReducer, useContext } from 'react';
|
||||||
import { usePersistedContext, usePersistedReducer } from '@hook/usePersist';
|
|
||||||
|
|
||||||
import RootContainer from '@container/RootContainer';
|
import RootContainer from '@container/RootContainer';
|
||||||
import RootContext from '@context/RootContext';
|
import RootContext from '@context/RootContext';
|
||||||
import RootReducer from '@slice/RootSlice';
|
import RootReducer from '@slice/RootSlice';
|
||||||
import Properties from '@constant/Properties';
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const globalStore = usePersistedContext(
|
const globalStore = useContext(RootContext);
|
||||||
useContext(RootContext),
|
|
||||||
Properties.STORE_KEY,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [state, dispatch] = usePersistedReducer(
|
const [state, dispatch] = useReducer(RootReducer, globalStore);
|
||||||
useReducer(RootReducer, globalStore),
|
|
||||||
Properties.STORE_KEY,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RootContext.Provider value={{ state, dispatch }}>
|
<RootContext.Provider value={{ state, dispatch }}>
|
||||||
|
|||||||
@@ -2,14 +2,11 @@ import React from 'react';
|
|||||||
import CameraContainer from '@components/camera/CameraContainer';
|
import CameraContainer from '@components/camera/CameraContainer';
|
||||||
import '@style/RootContainer.scss';
|
import '@style/RootContainer.scss';
|
||||||
|
|
||||||
const RootContainer = () => {
|
const RootContainer = () => (
|
||||||
console.log('Hello wlrld');
|
|
||||||
return (
|
|
||||||
<div className="container root-container">
|
<div className="container root-container">
|
||||||
<div className="header" />
|
<div className="header" />
|
||||||
<CameraContainer />
|
<CameraContainer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
export default RootContainer;
|
export default RootContainer;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
import { initialState as alpr } from '@slice/RecognitionSlice';
|
||||||
|
|
||||||
export default createContext({}); // include initialStates here
|
export default createContext({
|
||||||
|
alpr,
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
// Path2D for a Heart SVG
|
|
||||||
const heartSVG = 'M0 200 v-200 h200 a100,100 90 0,1 0,200 a100,100 90 0,1 -200,0 z';
|
|
||||||
const SVG_PATH = new Path2D(heartSVG);
|
|
||||||
|
|
||||||
// Scaling Constants for Canvas
|
|
||||||
const SCALE = 0.1;
|
|
||||||
const OFFSET = 80;
|
|
||||||
export const canvasWidth = window.innerWidth * 0.7;
|
|
||||||
export const canvasHeight = window.innerHeight * 0.7;
|
|
||||||
|
|
||||||
export function draw(ctx, location) {
|
|
||||||
console.log('attempting to draw');
|
|
||||||
ctx.fillStyle = 'red';
|
|
||||||
ctx.shadowColor = 'blue';
|
|
||||||
ctx.shadowBlur = 15;
|
|
||||||
ctx.save();
|
|
||||||
ctx.scale(SCALE, SCALE);
|
|
||||||
ctx.translate(location.x / SCALE - OFFSET, location.y / SCALE - OFFSET);
|
|
||||||
ctx.rotate(225 * Math.PI / 180);
|
|
||||||
ctx.fill(SVG_PATH);
|
|
||||||
// .restore(): Canvas 2D API restores the most recently saved canvas state
|
|
||||||
ctx.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCanvas() {
|
|
||||||
const canvasRef = useRef(null);
|
|
||||||
const [coordinates, setCoordinates] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const canvasObj = canvasRef.current;
|
|
||||||
const ctx = canvasObj.getContext('2d');
|
|
||||||
// clear the canvas area before rendering the coordinates held in state
|
|
||||||
ctx.clearRect(0, 0, canvasObj.parentNode.clientWidth, canvasObj.parentNode.clientHeight);
|
|
||||||
|
|
||||||
// draw all coordinates held in state
|
|
||||||
coordinates.forEach((coordinate) => { draw(ctx, coordinate); });
|
|
||||||
});
|
|
||||||
|
|
||||||
return [coordinates, setCoordinates, canvasRef, canvasWidth, canvasHeight];
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
// https://overreacted.io/making-setinterval-declarative-with-react-hooks/
|
|
||||||
const useInterval = (callback, delay) => {
|
|
||||||
const savedCallback = useRef();
|
|
||||||
|
|
||||||
// Remember the latest callback.
|
|
||||||
useEffect(() => {
|
|
||||||
savedCallback.current = callback;
|
|
||||||
}, [callback]);
|
|
||||||
|
|
||||||
// Set up the interval.
|
|
||||||
useEffect(() => {
|
|
||||||
const tick = () => savedCallback.current();
|
|
||||||
if (delay !== null) {
|
|
||||||
const id = setInterval(tick, delay);
|
|
||||||
return () => clearInterval(id);
|
|
||||||
}
|
|
||||||
return () => {};
|
|
||||||
}, [delay]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useInterval;
|
|
||||||
32
frontend/src/slice/RecognitionSlice.js
Normal file
32
frontend/src/slice/RecognitionSlice.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export const initialState = {
|
||||||
|
isFetchingALPR: false,
|
||||||
|
results: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const recognitionSlice = createSlice({
|
||||||
|
name: 'alpr',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
alprFetchStart(state) {
|
||||||
|
state.isFetchingALPR = true;
|
||||||
|
},
|
||||||
|
alprFetchSuccess(state, { payload }) {
|
||||||
|
state.isFetchingALPR = false;
|
||||||
|
state.results = payload.results;
|
||||||
|
},
|
||||||
|
resetResults(state) {
|
||||||
|
state.results = [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {
|
||||||
|
alprFetchStart,
|
||||||
|
alprFetchSuccess,
|
||||||
|
resetResults,
|
||||||
|
} = recognitionSlice.actions;
|
||||||
|
|
||||||
|
export default recognitionSlice.reducer;
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
import { combineReducers } from '@reduxjs/toolkit';
|
import { combineReducers } from '@reduxjs/toolkit';
|
||||||
|
import alpr from '@slice/RecognitionSlice';
|
||||||
|
|
||||||
export default combineReducers({}); // include slices here
|
export default combineReducers({
|
||||||
|
alpr,
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@import 'camphor.scss';
|
@import './common/font/camphor.scss';
|
||||||
@import 'palette.scss';
|
@import './common/palette.scss';
|
||||||
@import 'constants.scss';
|
@import './common/constants.scss';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user