deleted some useless stuff and backend integration
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const FtpDeploy = require("ftp-deploy");
|
||||
const ftpDeploy = new FtpDeploy();
|
||||
|
||||
const ftp = new FtpDeploy();
|
||||
|
||||
const config = {
|
||||
user: process.env.FTP_USER,
|
||||
@@ -8,9 +9,7 @@ const config = {
|
||||
port: process.env.FTP_PORT,
|
||||
localRoot: __dirname + "/../frontend",
|
||||
remoteRoot: "/public_html/car/",
|
||||
// include: ["*", "**/*"], // this would upload everything except dot files
|
||||
include: ["build/**"],
|
||||
// e.g. exclude sourcemaps, and ALL files in node_modules (including dot files)
|
||||
exclude: ["build/**/*.map", "node_modules/**", "node_modules/**/.*", ".git/**"],
|
||||
// delete ALL existing files at destination before uploading, if true
|
||||
deleteRemote: false,
|
||||
@@ -18,9 +17,9 @@ const config = {
|
||||
forcePasv: true
|
||||
};
|
||||
|
||||
ftpDeploy
|
||||
ftp
|
||||
.deploy(config)
|
||||
.then(res => {
|
||||
.then(() => {
|
||||
console.log("Deployment to FTP finished");
|
||||
return;
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "5.13.0",
|
||||
"@reduxjs/toolkit": "1.3.6",
|
||||
"@reduxjs/toolkit": "^1.3.6",
|
||||
"core-js": "3.6.5",
|
||||
"react": "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'
|
||||
? process.env.API_BASE_PATH
|
||||
: 'http://localhost:4000';
|
||||
|
||||
export const getPlateRecognized = async (image) => {
|
||||
export const getPlateRecognized = (image) => async (dispatch) => {
|
||||
console.log(image);
|
||||
dispatch(alprFetchStart());
|
||||
const body = new FormData();
|
||||
body.append('upload', image);
|
||||
try {
|
||||
@@ -12,6 +18,7 @@ export const getPlateRecognized = async (image) => {
|
||||
});
|
||||
console.log(response);
|
||||
const data = await response.json();
|
||||
dispatch(alprFetchSuccess(data));
|
||||
console.log(data);
|
||||
} catch (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, {
|
||||
useState, useEffect, useRef, useCallback,
|
||||
useState, useEffect, useRef, useCallback, useContext,
|
||||
} from 'react';
|
||||
import Webcam from 'react-webcam';
|
||||
import FacingMode from '@constant/FacingMode';
|
||||
import Loader from '@components/Loader';
|
||||
import Loader from '@components/common/Loader';
|
||||
import '@style/RootContainer.scss';
|
||||
import RootContext from '@context/RootContext';
|
||||
import { resetResults } from '@slice/RecognitionSlice';
|
||||
import CameraOptions from './CameraOptions';
|
||||
import Capture from './Capture';
|
||||
|
||||
@@ -17,6 +19,7 @@ const CAMERA_OPTIONS = {
|
||||
};
|
||||
|
||||
const CameraContainer = () => {
|
||||
const { dispatch } = useContext(RootContext);
|
||||
const ref = useRef(null);
|
||||
const [imgSrc, setImgSrc] = useState(null);
|
||||
const [captureError, setCaptureError] = useState(null);
|
||||
@@ -71,7 +74,10 @@ const CameraContainer = () => {
|
||||
}
|
||||
}, [ref, setImgSrc]);
|
||||
|
||||
const onBackClick = () => setImgSrc(null);
|
||||
const onBackClick = () => {
|
||||
setImgSrc(null);
|
||||
dispatch(resetResults());
|
||||
};
|
||||
|
||||
const cameraView = () => (
|
||||
<>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import Button from '@components/Button';
|
||||
import Button from '@components/common/Button';
|
||||
|
||||
const CameraOptions = ({ capture, changeCameraView }) => (
|
||||
<div className="row button-container">
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
import React from 'react';
|
||||
import Loader from '@components/Loader';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import Loader from '@components/common/Loader';
|
||||
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 [hasFetched, setHasFetched] = useState(false);
|
||||
const { state: { alpr: { isFetchingALPR } }, dispatch } = useContext(RootContext);
|
||||
const onUploadClick = () => {
|
||||
getPlateRecognized(imgSrc);
|
||||
getPlateRecognized(imgSrc)(dispatch);
|
||||
setHasFetched(true);
|
||||
};
|
||||
return (
|
||||
<div className="container">
|
||||
{isFetchingALPR ? <Loader /> : (
|
||||
<div className="row">
|
||||
<img src={imgSrc} alt="captured" />
|
||||
</div>
|
||||
)}
|
||||
{hasFetched && !isFetchingALPR && (<RecognitionResults />)}
|
||||
<div className="row button-container">
|
||||
<Button text="Back" onClick={onBackClick} />
|
||||
<Button text="Upload" onClick={onUploadClick} />
|
||||
{!hasFetched && <Button text="Upload" onClick={onUploadClick} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import '@style/spinner.scss';
|
||||
import './Loader.scss';
|
||||
|
||||
const Loader = () => (<div className="loader">Loading...</div>);
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import React, { useReducer, useContext } from 'react';
|
||||
import { usePersistedContext, usePersistedReducer } from '@hook/usePersist';
|
||||
|
||||
import RootContainer from '@container/RootContainer';
|
||||
import RootContext from '@context/RootContext';
|
||||
import RootReducer from '@slice/RootSlice';
|
||||
import Properties from '@constant/Properties';
|
||||
|
||||
const App = () => {
|
||||
const globalStore = usePersistedContext(
|
||||
useContext(RootContext),
|
||||
Properties.STORE_KEY,
|
||||
);
|
||||
const globalStore = useContext(RootContext);
|
||||
|
||||
const [state, dispatch] = usePersistedReducer(
|
||||
useReducer(RootReducer, globalStore),
|
||||
Properties.STORE_KEY,
|
||||
);
|
||||
const [state, dispatch] = useReducer(RootReducer, globalStore);
|
||||
|
||||
return (
|
||||
<RootContext.Provider value={{ state, dispatch }}>
|
||||
|
||||
@@ -2,14 +2,11 @@ import React from 'react';
|
||||
import CameraContainer from '@components/camera/CameraContainer';
|
||||
import '@style/RootContainer.scss';
|
||||
|
||||
const RootContainer = () => {
|
||||
console.log('Hello wlrld');
|
||||
return (
|
||||
const RootContainer = () => (
|
||||
<div className="container root-container">
|
||||
<div className="header" />
|
||||
<CameraContainer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RootContainer;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
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 alpr from '@slice/RecognitionSlice';
|
||||
|
||||
export default combineReducers({}); // include slices here
|
||||
export default combineReducers({
|
||||
alpr,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@import 'camphor.scss';
|
||||
@import 'palette.scss';
|
||||
@import 'constants.scss';
|
||||
@import './common/font/camphor.scss';
|
||||
@import './common/palette.scss';
|
||||
@import './common/constants.scss';
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
|
||||
Reference in New Issue
Block a user