diff --git a/app/package-lock.json b/app/package-lock.json index 5c1dcbe8..ae4377c3 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -32,6 +32,7 @@ "tailwindcss": "^3.4.1", "tailwindscss": "^0.3.0", "util": "^0.12.5", + "uuid": "^9.0.1", "web-vitals": "^2.1.4" }, "devDependencies": { diff --git a/app/package.json b/app/package.json index ed175aeb..3bb1c63b 100644 --- a/app/package.json +++ b/app/package.json @@ -28,6 +28,7 @@ "tailwindcss": "^3.4.1", "tailwindscss": "^0.3.0", "util": "^0.12.5", + "uuid": "^9.0.1", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/app/src/App.js b/app/src/App.js index 458ec93d..fb5a62a4 100644 --- a/app/src/App.js +++ b/app/src/App.js @@ -12,7 +12,6 @@ import SearchAddress from './components/EmailSearch' function App() { const [aboutOpen, setAboutOpen] = useState(false); const [contactOpen, setContactOpen] = useState(false); - const [emailOpen, setEmailOpen] = useState(false); const navigate = useNavigate(); const handleAboutOpen = () => { diff --git a/app/src/components/CSVUploadComponent.js b/app/src/components/CSVUploadComponent.js index 06182573..77e09435 100644 --- a/app/src/components/CSVUploadComponent.js +++ b/app/src/components/CSVUploadComponent.js @@ -14,6 +14,8 @@ function CSVUploadComponent({ onDataProcessed }) { header: true, complete: (result) => { console.log('Parsed CSV data:', result.data); + // Post the parsed CSV data to your server + postCSVDataToServer(result.data); onDataProcessed(result.data); }, error: (error) => { @@ -25,6 +27,27 @@ function CSVUploadComponent({ onDataProcessed }) { } }; + const postCSVDataToServer = async (csvData) => { + try { + const response = await fetch('http://localhost:4000/api/csv_scan', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ csvData }) + }); + + if (!response.ok) { + throw new Error('Failed to upload CSV data'); + } + + const responseData = await response.json(); + console.log('Server response:', responseData); + } catch (error) { + console.error('Error posting CSV data to server:', error); + } + }; + return (
@@ -33,4 +56,4 @@ function CSVUploadComponent({ onDataProcessed }) { ); } -export default CSVUploadComponent; \ No newline at end of file +export default CSVUploadComponent; diff --git a/app/src/components/DataTable.js b/app/src/components/DataTable.js index 9962c4bf..c4ab8a6b 100644 --- a/app/src/components/DataTable.js +++ b/app/src/components/DataTable.js @@ -3,6 +3,9 @@ import { DataGrid } from '@mui/x-data-grid'; import '../styles/DataGrid.css'; function DataTable({ data = [] }) { // Default data to an empty array if not provided + // Generate unique IDs for each row + const rowsWithIds = data.map((row, index) => ({ ...row, id: index + 1 })); + const columns = [ { field: 'id', headerName: 'ID', width: 70 }, { field: 'scanName', headerName: 'Scan Name', width: 200 }, @@ -17,7 +20,7 @@ function DataTable({ data = [] }) { // Default data to an empty array if not pro
); - } export default DataTable; + diff --git a/app/src/components/DatabaseFetch.js b/app/src/components/DatabaseFetch.js index e8108ef5..754f499a 100644 --- a/app/src/components/DatabaseFetch.js +++ b/app/src/components/DatabaseFetch.js @@ -36,7 +36,8 @@ function DataFetchComponent() { setIsLoading(true); try { const response = await axios.get('http://localhost:4000/api/analysis_results'); - setData(response.data); + const dataWithIds = response.data.map((item, index) => ({ ...item, id: index })); + setData(dataWithIds); } catch (error) { console.error("Error fetching data:", error); setError('Error fetching data'); diff --git a/app/src/components/EmailSearch.js b/app/src/components/EmailSearch.js index 2042c94e..9f58f4ef 100644 --- a/app/src/components/EmailSearch.js +++ b/app/src/components/EmailSearch.js @@ -1,4 +1,5 @@ import React, { useState } from 'react'; + export default function SearchAddress() { const api_key = process.env.REACT_APP_EMAIL_API_KEY const [site, setSite] = useState(''); diff --git a/app/src/components/SearchComponent.js b/app/src/components/SearchComponent.js index 1d2a21fd..6076703c 100644 --- a/app/src/components/SearchComponent.js +++ b/app/src/components/SearchComponent.js @@ -56,12 +56,16 @@ function SearchComponent() { const [searchResults, setSearchResults] = useState(null); const [searchButtonPressed, setSearchButtonPressed] = useState(false); const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); const handleWebSearch = async () => { setIsLoading(true); setSearchButtonPressed(true); + if (!searchTerm) { + alert('You must enter a URL to perform a search.'); + setIsLoading(false); + return; + } try { const response = await axios.post('http://localhost:4000/api/url', { url: searchTerm @@ -75,30 +79,36 @@ function SearchComponent() { } catch (error) { console.error(`Error making POST request: ${error}`); if (error.response) { - setError('There was a problem with the server response.'); + alert('There was a problem with the server response.'); } else if (error.request) { - setError('The server did not respond. Please check your internet connection and try again.'); + alert('The server did not respond. Please check your internet connection and try again.'); } else { - setError('There was a problem sending your request.'); + alert('There was a problem sending your request.'); } } setIsLoading(false); } // Function to handle the processed CSV data - const handleCSVData = (csvData) => { - // Convert parsed CSV (array of objects) to the expected object format + const handleCSVData = async (csvData) => { const formattedData = csvData.map((item, index) => ({ - id: index + 1, // Assigning a unique ID - scanName: item['Scan Name'], // Make sure the keys match the CSV header names + id: index + 1, + scanName: item['Scan Name'], type: item['Type'], module: item['Module'], source: item['Source'], - 'f/p': item['F/P'], // If F/P is a column name in your CSV, ensure it's written exactly as in the CSV - data: item['Data'], // Same as above, ensure it matches the CSV header name + 'f/p': item['F/P'], + data: item['Data'], })); - setData(formattedData); // Update the state with the formatted data - setShowData(true); // Set the flag to show the data table + setData(formattedData); + setShowData(true); + + // Send a POST request with the CSV data to your server + try { + await axios.post('http://localhost:4000/api/csv_scan', formattedData); + } catch (error) { + console.error(`Error sending CSV data to server: ${error}`); + } }; const handleToggle = () => { @@ -153,7 +163,6 @@ function SearchComponent() {
- {error &&
{error}
} {showData && }
diff --git a/docker-compose.yml b/docker-compose.yml index bfbaa1f8..e73bbd67 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,7 @@ services: - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} + - REACT_APP_EMAIL_API_KEY=${REACT_APP_EMAIL_API_KEY} command: ["sh", "-c", "node src/server.js && npx knex migrate:latest"] db: diff --git a/server/migrations/20240211072255_create_tbl_scan.js b/server/migrations/20240211072255_create_tbl_scan.js index ed13e2e5..27ff7bb9 100644 --- a/server/migrations/20240211072255_create_tbl_scan.js +++ b/server/migrations/20240211072255_create_tbl_scan.js @@ -1,12 +1,13 @@ exports.up = function(knex) { return knex.schema.createTable('csv_scan', function(table) { table.increments('id').primary(); - table.text('data'); - table.string('f/p'); - table.string('module'); - table.string('scanName'); - table.string('source'); - table.string('type'); + table.text('Scan Name'); + table.text('Updated'); + table.text('Type'); + table.text('Module'); + table.text('Source'); + table.text('F/P'); + table.text('Data', 'longtext'); }); }; diff --git a/server/src/server.js b/server/src/server.js index 0c2eb583..7b3cf46c 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -15,7 +15,6 @@ const cors = require('cors'); const puppeteer = require("puppeteer"); const dotenv = require('dotenv'); const fs = require('fs'); -const csv = require('csv-parser'); const pgp = require('pg-promise')(); const stream = require('stream'); dotenv.config(); @@ -112,41 +111,19 @@ function startServer() { } }); -// CSV upload for database insertion -app.post('/api/csv_scan', async (req, res) => { - const csvDataString = req.body.data; // Changed from req.data to req.body.data - - if (!csvDataString) { - return res.status(400).send('No data was uploaded.'); - } - - const csvData = []; - const csvStream = stream.Readable.from(csvDataString); - - csvStream - .pipe(csv.parse({ headers: true })) // Parse headers from the CSV file - .on('data', (row) => { - // Map the row object to match the structure of your table - const mappedRow = { - data: row.data, - 'f/p': row['f/p'], - module: row.module, - scanName: row.scanName, - source: row.source, - type: row.type, - }; - csvData.push(mappedRow); - }) - .on('end', async () => { - try { - await knex('csv_scan').insert(csvData); - res.send('CSV data has been successfully uploaded to the database.'); - } catch (error) { - console.error('Error inserting data:', error); - res.status(500).send('An error occurred while uploading CSV data to the database.'); - } - }); -}); + app.post('/api/csv_scan', async (req, res) => { + const csvData = req.body.csvData; // Extract CSV data from the request body + + try { + // Insert CSV data into the database table using Knex + await knex('csv_scan').insert(csvData); + + res.status(200).json({ message: 'CSV data inserted successfully' }); + } catch (error) { + console.error('Error inserting CSV data:', error); + res.status(500).json({ error: 'Failed to insert CSV data into the database' }); + } + }); app.post('/api/analysis_results', async (req, res) => { try {