first commit
This commit is contained in:
commit
45da69700c
|
@ -0,0 +1,6 @@
|
|||
# config/db.config.js
|
||||
node_modules
|
||||
upload/*
|
||||
stuff-expermental
|
||||
package-lock.json
|
||||
config/db.config.js
|
|
@ -0,0 +1,20 @@
|
|||
# Terminal Diagnostic Helper
|
||||
|
||||
## Overview
|
||||
|
||||
**Terminal Diagnostic Helper** is an application designed to assist engineers in diagnosing and resolving issues with POS terminals. Users can view terminal images, select problems, record fixes, and generate reports in Excel format, while also sending data to a server for storage.
|
||||
|
||||
## Features
|
||||
|
||||
- **Terminal Image View:** Display images of POS terminals for easier diagnosis.
|
||||
- **Problem Selection:** Choose from a list of common terminal problems.
|
||||
- **Fix Logging:** Record the fixes applied to each issue.
|
||||
- **Excel Export:** Copy diagnostic and repair data to an Excel spreadsheet.
|
||||
- **Server Storage:** Automatically save diagnostic data to a server.
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Clone the Repository:**
|
||||
```bash
|
||||
git clone https://github.com/yourusername/your-repository.git
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
host: 'database or ip',
|
||||
user: 'user',
|
||||
password: 'pass',
|
||||
database: 'dbname'
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
HTML
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1">
|
||||
<title>Login</title>
|
||||
<!-- the form awesome library is used to add icons to our form -->
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
|
||||
<!-- include the stylesheet file -->
|
||||
<link href="/style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="login">
|
||||
<h1>Login</h1>
|
||||
<form action="/auth" method="post">
|
||||
<label for="username">
|
||||
<!-- font awesome icon -->
|
||||
<i class="fas fa-user"></i>
|
||||
</label>
|
||||
<input type="text" name="username" placeholder="Username" id="username" required>
|
||||
<label for="password">
|
||||
<i class="fas fa-lock"></i>
|
||||
</label>
|
||||
<input type="password" name="password" placeholder="Password" id="password" required>
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,162 @@
|
|||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const mysql = require("mysql2/promise");
|
||||
const config = require("./config/db.config.js");
|
||||
const session = require('express-session');
|
||||
|
||||
const PORT = process.env.PORT || 5000; // Default port is 5000
|
||||
|
||||
const log = {
|
||||
yellow: '\x1b[33m%s\x1b[0m', //yellow
|
||||
cyan: '\x1b[36m%s\x1b[0m',//cyan
|
||||
red: '\x1b[31m%s\x1b[0m', //red
|
||||
green: '\x1b[32m%s\x1b[0m', //green
|
||||
black: '\x1b[30m%s\x1b[0m', //black
|
||||
blue: '\x1b[34m%s\x1b[0m', //blue
|
||||
gray: '\x1b[90m%s\x1b[0m' //gray
|
||||
}
|
||||
|
||||
|
||||
// Create a connection pool
|
||||
const pool = mysql.createPool({
|
||||
host: config.host,
|
||||
user: config.user,
|
||||
password: config.password,
|
||||
database: config.database,
|
||||
waitForConnections: true,
|
||||
connectionLimit: 10,
|
||||
queueLimit: 0
|
||||
});
|
||||
|
||||
|
||||
|
||||
const app = express();
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
|
||||
app.use(session({
|
||||
secret: config.secret,
|
||||
resave: true,
|
||||
saveUninitialized: true
|
||||
}));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.static(path.join(__dirname, 'static')));
|
||||
|
||||
|
||||
|
||||
app.get('/', function(request, response) {
|
||||
if (request.session.loggedin) {
|
||||
// Output username
|
||||
// response.send('Welcome back, ' + request.session.username + '!');
|
||||
console.log(request.session.username , 'open main page');
|
||||
// Render home page with username
|
||||
response.render('home', { username: request.session.username });
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
// Not logged in
|
||||
// response.send('Please login to view this page!');
|
||||
response.redirect('/login');
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/login', function(request, response) {
|
||||
/// Render login template with any message from query parameters
|
||||
console.log('Message:', request.query.message); // Log the message
|
||||
response.render('login', { message: request.query.message || '' });
|
||||
|
||||
|
||||
|
||||
// response.sendFile(path.join(__dirname + '/login.html'));
|
||||
});
|
||||
|
||||
|
||||
app.post('/auth', async function(request, response) {
|
||||
// Capture the input fields
|
||||
const { login, password } = request.body;
|
||||
|
||||
// Ensure the input fields exist and are not empty
|
||||
if (login && password) {
|
||||
try {
|
||||
// Get a connection from the pool
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
// Execute SQL query
|
||||
// const [rows] = await connection.execute(
|
||||
// 'SELECT * FROM accounts WHERE username = ? AND password = ?',
|
||||
// [username, password]
|
||||
// );
|
||||
|
||||
const [rows] = await connection.execute(
|
||||
'SELECT * FROM accounts WHERE (username = ? OR email = ?) AND password = ?',
|
||||
[login, login, password]
|
||||
);
|
||||
|
||||
// console.log(rows);
|
||||
|
||||
|
||||
// Release the connection back to the pool
|
||||
connection.release();
|
||||
|
||||
// If the account exists
|
||||
if (rows.length > 0) {
|
||||
// Authenticate the user
|
||||
request.session.loggedin = true;
|
||||
request.session.username = rows[0].username;
|
||||
// request.session.username = username;
|
||||
// Redirect to home page
|
||||
response.redirect('/');
|
||||
} else {
|
||||
response.redirect('/login?message=Incorrect Username and/or Password!');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Database query error:', error);
|
||||
response.status(500).send('An error occurred while processing your request.');
|
||||
}
|
||||
} else {
|
||||
// response.send('Please enter Username and Password!');
|
||||
response.redirect('/login?message=Please enter Username and Password!');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// http://localhost:3000/home
|
||||
app.get('/home', function(request, response) {
|
||||
// If the user is loggedin
|
||||
if (request.session.loggedin) {
|
||||
// Output username
|
||||
// response.send('Welcome back, ' + request.session.username + '!');
|
||||
|
||||
// Render home page with username
|
||||
response.render('home', { username: request.session.username });
|
||||
|
||||
} else {
|
||||
// Not logged in
|
||||
// response.send('Please login to view this page!');
|
||||
response.redirect('/login');
|
||||
}
|
||||
response.end();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// http://localhost:3000/logout
|
||||
app.get('/logout', function(request, response) {
|
||||
request.session.destroy((err) => {
|
||||
if (err) {
|
||||
return response.status(500).send('Failed to logout');
|
||||
}
|
||||
response.redirect('/');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.info(`Listening on http://0.0.0.0:${PORT}/`);
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "Terminal Diagnostic Helper",
|
||||
"version": "1.0.0",
|
||||
"description": "POS Terminal Diagnostic Helper by Ahmed Alomairi",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node main.js test",
|
||||
"start": "node main.js",
|
||||
"clean": "rm -f /app/service-upload/upload/* && node main.js clean",
|
||||
"reset": "rm -f /app/service-upload/upload/* && node main.js",
|
||||
"dev": "npm install nodemon --save-dev && node main.js development --port 3000"
|
||||
},
|
||||
"author": "Ahmed Alomairi",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^4.18.3",
|
||||
"express-session": "^1.18.0",
|
||||
"mysql2": "^3.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Загрузчик файлов</title>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/favicon/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/images/favicon/site.webmanifest">
|
||||
<link rel="mask-icon" href="/images/favicon/safari-pinned-tab.svg" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="/images/favicon/favicon.ico">
|
||||
<meta name="msapplication-TileColor" content="#2b5797">
|
||||
<meta name="msapplication-config" content="/images/favicon/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="nav-bar flex">
|
||||
<div class="first-holder flex">
|
||||
<!-- <h1 class="logo">EasyCode</h1> -->
|
||||
<a class="logo"> <img src="/images/favicon/android-chrome-192x192.png" height="40"> СЕРВИС-ВОЛГА </a>
|
||||
|
||||
<a href="#" id="m-bar"><i class="fas fa-bars hm"></i></a>
|
||||
</div>
|
||||
|
||||
<div id="menu-links" class="hidden">
|
||||
<ul>
|
||||
<li><a onClick="window.location.reload();" class=" "><i class="fa-solid fa-arrows-rotate"></i> Обновить страницу </a>
|
||||
</li>
|
||||
<!-- <li><a href="check-serials.html"> <i class="fa-solid fa-list-check"></i> Check Serials</a></li> -->
|
||||
<!-- <li><a href="#"> <i class="fa-solid fa-upload"></i> Test</a></li> -->
|
||||
<!-- <li><a id="showStorage" class=" show"><div id="history-lable"><i class="fa-solid fa-floppy-disk"></i> Show History</div></a></li> -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- <a href="#" id="nav-btn" class="hidden">Signup</a> -->
|
||||
<a id="showStorage" class="nav-btn hidden show">
|
||||
<div id="history-lable"><i class="fa-solid fa-floppy-disk"></i>Последние файлы </div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<h2 class="title">
|
||||
Загрузчик инженерных файлов
|
||||
<div class="tooltip">
|
||||
<span> <img src="/images/info.svg" height="20" style="filter: invert(85%) sepia(89%) saturate(5847%) hue-rotate(343deg) brightness(103%) contrast(101%);" alt="" srcset=""></span> <!-- Insert symbol here (question mark) -->
|
||||
<span class="tooltiptext">Загружаемый файл Excel инженера из папка "Перевод в платные" должен содержать заголовок <br> ( Модель, Сер.номер, Заявленная неисправность, Произведенная работа ) </span>
|
||||
</div></h2>
|
||||
|
||||
<div id="dropZone" class="drop-zone">
|
||||
<p>Перетащите файлы сюда или нажмите, чтобы выбрать</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="upload-section">
|
||||
|
||||
<!-- <label for="fileInput" class="btn">
|
||||
Select files
|
||||
</label> -->
|
||||
|
||||
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||
<!-- <input type="file" name="uploaded" multiple id="fileInput"> -->
|
||||
|
||||
<input type="file" name="uploaded" multiple id="fileInput" style="display: none;">
|
||||
<input type="submit" value="Загружать" class="btn" id="fileUpload">
|
||||
</form>
|
||||
|
||||
|
||||
<button id="getFileStateBtn" class="btn" disabled>Получить состояние файлов</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="selectedFiles"></div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="filesList">
|
||||
|
||||
<div class="selected">
|
||||
<p>Selected files</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="uploaded">
|
||||
<p>Uploaded files</p>
|
||||
<div id="result"></div>
|
||||
</div>
|
||||
|
||||
<div class="state">
|
||||
<p>Files state</p>
|
||||
<div id="state"></div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js.js"></script>
|
||||
|
||||
<footer>
|
||||
|
||||
<a> Upload XLSX v0.9 © 2024 Ал Омаири Ахмед </a>
|
||||
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,288 @@
|
|||
const fileInput = document.getElementById('fileInput');
|
||||
const selectedFilesDiv = document.getElementById('selectedFiles');
|
||||
|
||||
let repeatedList = []
|
||||
fileInput.addEventListener('change', function () {
|
||||
|
||||
populateFileTable(Array.from(fileInput.files));
|
||||
console.log('fileInput.files on change', fileInput.files); getFileListFromServer(fileInput.files);
|
||||
});
|
||||
|
||||
async function getFileListFromServer(fileInput) {
|
||||
|
||||
const fileUpload = document.getElementById('fileUpload');
|
||||
fileUpload.style.color = 'white';
|
||||
|
||||
await fetch('/getfilenames')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Call populateFileTable() with the retrieved file list
|
||||
compareFilelist(fileInput , data);
|
||||
})
|
||||
.catch(error => console.error('Error getting file list from server:', error));
|
||||
}
|
||||
function compareFilelist(fileInput , data) {
|
||||
// console.log("resultes :");
|
||||
console.log(fileInput);
|
||||
// console.log(data); //array
|
||||
|
||||
Array.from(fileInput).forEach(selectedfile => {
|
||||
console.log(selectedfile.name);
|
||||
data.forEach(filename => {
|
||||
if (filename === selectedfile.name){
|
||||
const repeatedFileName = selectedfile.name
|
||||
console.log( repeatedFileName, 'is repeated ');
|
||||
repeatedList.push(repeatedFileName);
|
||||
|
||||
Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => {
|
||||
const fileNameCell = row.cells[0];
|
||||
const fileStateCell = row.cells[2];
|
||||
|
||||
const fileName = fileNameCell.textContent;
|
||||
if (fileName == repeatedFileName) {
|
||||
row.style.backgroundColor = 'rgb(254 255 82)';
|
||||
fileStateCell.innerText = 'Repeated file!';
|
||||
}
|
||||
});
|
||||
|
||||
} // repeat function
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function handleFormSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const getFileStateBtn = document.getElementById('getFileStateBtn');
|
||||
getFileStateBtn.disabled = false;
|
||||
|
||||
const fileUpload = document.getElementById('fileUpload');
|
||||
fileUpload.style.color = 'grey';
|
||||
|
||||
const formData = new FormData(this);
|
||||
|
||||
// Get the file input element
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
const fileList = fileInput.files;
|
||||
|
||||
|
||||
|
||||
// Filter out files based on repeatedList before upload
|
||||
const filteredFiles = Array.from(fileList).filter(file => {
|
||||
return !repeatedList.includes(file.name);
|
||||
});
|
||||
|
||||
if (filteredFiles.length > 0) {
|
||||
|
||||
// Replace the original files with the modified file list
|
||||
formData.delete('uploaded'); // Delete the existing files
|
||||
filteredFiles.forEach(file => formData.append('uploaded', file)); // Add modified files
|
||||
|
||||
|
||||
try {
|
||||
const response = await fetch('/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
// Handle response as needed
|
||||
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
const fileStates = data.states;
|
||||
const filelist = data.files;
|
||||
const fileErrors = data.errors;
|
||||
|
||||
const resultDiv = document.getElementById('result');
|
||||
// createTable(resultDiv, data.files);
|
||||
|
||||
|
||||
Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => {
|
||||
const fileNameCell = row.cells[0];
|
||||
const fileSizeCell = row.cells[1];
|
||||
const fileStateCell = row.cells[2];
|
||||
|
||||
const fileName = fileNameCell.textContent;
|
||||
const fileSize = fileSizeCell.textContent;
|
||||
|
||||
filelist.forEach(element => {
|
||||
if (element.originalFilename === fileName) {
|
||||
console.log('found file name similar');
|
||||
console.log('element.size', element.size);
|
||||
console.log('fileName', fileSize);
|
||||
|
||||
if (element.size == fileSize) {
|
||||
row.style.fontWeight = 'bold';
|
||||
row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, skyblue, transparent)';
|
||||
fileStateCell.innerText = 'uploaded';
|
||||
} else {
|
||||
row.style.backgroundColor = 'pink';
|
||||
fileStateCell.innerText = 'error upload';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
// const fileState = filelist.find(file => file.originalFilename === fileName);
|
||||
// if (fileState) {
|
||||
// fileSizeCell.textContent = fileState.size;
|
||||
// if (fileState.size === 'Bad') {
|
||||
// row.style.backgroundColor = 'red';
|
||||
// } else {
|
||||
// row.style.backgroundColor = 'transparent';
|
||||
// }
|
||||
// }
|
||||
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error uploading files:', error);
|
||||
// Handle errors during upload
|
||||
alert('Error uploading files:', error);
|
||||
}
|
||||
} else {
|
||||
console.log("No valid files selected for upload.");
|
||||
alert('Допустимые файлы не выбраны или уже загружены.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function to populate the file table with selected files
|
||||
function populateFileTable(fileList) {
|
||||
const table = document.createElement('table');
|
||||
|
||||
const headerRow = table.insertRow();
|
||||
// headerRow.style.background = '#121212';
|
||||
headerRow.style.background = ' linear-gradient(90deg, rgba(28,28,28,0.8379726890756303) 0%, rgba(24,23,23,0.9556197478991597) 51%, rgba(29,29,29,0.8715861344537815) 100%)';
|
||||
headerRow.style.color = 'white';
|
||||
const filenameHeader = headerRow.insertCell();
|
||||
filenameHeader.textContent = 'Filename';
|
||||
const sizeHeader = headerRow.insertCell();
|
||||
sizeHeader.textContent = 'Size';
|
||||
const stateHeader = headerRow.insertCell();
|
||||
stateHeader.textContent = 'State';
|
||||
|
||||
|
||||
fileList.forEach(fileData => {
|
||||
const row = table.insertRow();
|
||||
const filenameCell = row.insertCell();
|
||||
if (fileData.originalFilename) {
|
||||
filenameCell.textContent = fileData.originalFilename;
|
||||
} else if (fileData.name) {
|
||||
filenameCell.textContent = fileData.name;
|
||||
}
|
||||
|
||||
const sizeCell = row.insertCell();
|
||||
sizeCell.textContent = fileData.size;
|
||||
const stateCell = row.insertCell();
|
||||
stateCell.textContent = '---';
|
||||
});
|
||||
|
||||
// Replace the existing content with the new table
|
||||
selectedFilesDiv.innerHTML = '';
|
||||
selectedFilesDiv.appendChild(table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
document.querySelector('form').addEventListener('submit', handleFormSubmit);
|
||||
|
||||
document.getElementById("getFileStateBtn").addEventListener("click", async function () {
|
||||
|
||||
const getFileStateBtn = document.getElementById('getFileStateBtn');
|
||||
getFileStateBtn.disabled = true; // Disable the button
|
||||
const fileUpload = document.getElementById('fileUpload');
|
||||
fileUpload.style.color = 'white';
|
||||
|
||||
const response = await fetch('/getState');
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
// const stateDiv = document.getElementById('state');
|
||||
// createTable(stateDiv, data.states);
|
||||
|
||||
const fileStates = data.states;
|
||||
const fileErrors = data.errors;
|
||||
|
||||
// const resultDiv = document.getElementById('result');
|
||||
// createTable(resultDiv, data.files);
|
||||
|
||||
|
||||
Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => {
|
||||
const fileNameCell = row.cells[0];
|
||||
const fileSizeCell = row.cells[1];
|
||||
const fileStateCell = row.cells[2];
|
||||
|
||||
const fileName = fileNameCell.textContent;
|
||||
|
||||
const fileState = fileStates.find(file => file.name === fileName);
|
||||
if (fileState) {
|
||||
fileStateCell.innerText = fileState.size;
|
||||
if (fileState.size === 'Bad') {
|
||||
row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, orangered, transparent)';
|
||||
} else {
|
||||
row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, lightgreen, transparent)';
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
const dropZone = document.getElementById('dropZone');
|
||||
|
||||
// Prevent default behavior for drag events
|
||||
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
||||
dropZone.addEventListener(eventName, preventDefault, false);
|
||||
});
|
||||
|
||||
function preventDefault(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// Handle file drop event
|
||||
dropZone.addEventListener('drop', handleDrop, false);
|
||||
|
||||
function handleDrop(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const fileList = event.dataTransfer.files;
|
||||
|
||||
// const repeatedList = ['avoid_uploading_this_file.txt', 'another_filename_to_avoid.txt']; // Example repeatedList
|
||||
|
||||
// Filter out files based on repeatedList before upload
|
||||
const filteredFiles = Array.from(fileList).filter(file => {
|
||||
return !repeatedList.includes(file.name);
|
||||
});
|
||||
|
||||
// Replace the original files with the modified file list
|
||||
const formData = new FormData();
|
||||
filteredFiles.forEach(file => formData.append('uploaded', file)); // Add modified files
|
||||
|
||||
// Update the file input field with dropped files
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
fileInput.files = fileList;
|
||||
|
||||
// Submit the form or call handleFormSubmit function here with formData
|
||||
|
||||
populateFileTable(Array.from(fileInput.files));
|
||||
console.log('dragdrop', fileInput.files);
|
||||
getFileListFromServer(fileInput.files);
|
||||
|
||||
}
|
||||
|
||||
// Allow users to trigger file selection by clicking the drop zone
|
||||
dropZone.addEventListener('click', () => {
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
fileInput.click();
|
||||
});
|
|
@ -0,0 +1,320 @@
|
|||
body {
|
||||
background-color: #262626;
|
||||
}
|
||||
|
||||
/* .title {
|
||||
color: #6dabf1;
|
||||
text-align: center;
|
||||
} */
|
||||
|
||||
.filesList {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
table {
|
||||
display: table;
|
||||
width: 68vw;
|
||||
max-width: 1140px;
|
||||
border-collapse: separate;
|
||||
box-sizing: border-box;
|
||||
text-indent: initial;
|
||||
/* border-spacing: 2px; */
|
||||
border-spacing: initial;
|
||||
/* border-color: gray; */
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px;
|
||||
border-bottom: solid;
|
||||
/* border-style: solid; */
|
||||
}
|
||||
|
||||
td:first-child{
|
||||
border-top: solid;
|
||||
border-top-style: none !important;
|
||||
border-top-left-radius: 15px;
|
||||
}
|
||||
td:last-child{
|
||||
border-top: solid;
|
||||
border-top-style: none !important;
|
||||
border-top-right-radius: 15px;
|
||||
}
|
||||
|
||||
tr:last-child td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
margin: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#selectedFiles {
|
||||
|
||||
text-align: -webkit-center;
|
||||
max-width: 1140px;
|
||||
background-color: lavender;
|
||||
border-radius: 20px;
|
||||
/* padding-bottom: 10px; */
|
||||
border-style: outset;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
/* color: #fff; */
|
||||
font-family: 'Rubik', sans-serif;
|
||||
/* margin:0; */
|
||||
max-width: 1140px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
padding: 3px 10px 3px 20px;
|
||||
background-color: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
.nav-bar a {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-bar .hm {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#m-bar {
|
||||
display: none;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#menu-links ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#menu-links ul li {
|
||||
display: inline-block;
|
||||
margin: 0 35px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#menu-links a {
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
padding: 3px 15px;
|
||||
background-color: #868686;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
border-radius: 35px;
|
||||
}
|
||||
|
||||
.nav-btn:hover {
|
||||
background-color: #6791e0 !important;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #2d6cdf !important;
|
||||
}
|
||||
|
||||
#menu-links a:hover {
|
||||
color: #6dabf1 !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
#btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 880px) {
|
||||
.nav-bar {
|
||||
display: block;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
#menu-links ul li {
|
||||
display: block;
|
||||
margin: 25px 0;
|
||||
}
|
||||
|
||||
#btn {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#m-bar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.not-hidden {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.bg-tarakan {
|
||||
display: none;
|
||||
position: absolute;
|
||||
max-width: 1140px;
|
||||
width: -webkit-fill-available;
|
||||
}
|
||||
|
||||
.show-tarakan {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.control {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin: auto;
|
||||
text-align-last: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* #getFileStateBtn {
|
||||
padding: 10px;
|
||||
} */
|
||||
.btn {
|
||||
padding: 12px;
|
||||
border-radius: 10px;
|
||||
color: #f5f5f5;
|
||||
/* background-color: #2d6cdf; */
|
||||
background: linear-gradient(40deg, #000000, #698ed1);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
align-self: center;
|
||||
box-shadow: 0 4px 7px rgb(99 139 255 / 40%);
|
||||
border-style: hidden;
|
||||
}
|
||||
|
||||
.upload-section {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#fileInput {
|
||||
opacity: 0;
|
||||
width: 0.1px;
|
||||
height: 0.1px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.upload-section input[type=submit] {
|
||||
/* padding: 12px 30px; */
|
||||
border: none;
|
||||
/* background-color: #333333; */
|
||||
/* color: #ffffff; */
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn:hover ,
|
||||
.btn:focus {
|
||||
transform: scale(1.09);
|
||||
}
|
||||
|
||||
form {
|
||||
/* width: 50%; */
|
||||
/* margin: auto; */
|
||||
/* background-color: #f5f5f5; */
|
||||
/* padding: 30px; */
|
||||
/* font-size: 20px; */
|
||||
/* padding: 10px; */
|
||||
/* border-radius: 10px; */
|
||||
/* color: #f5f5f5; */
|
||||
/* background-color: #2d6cdf; */
|
||||
}
|
||||
|
||||
#dropZone {
|
||||
background: repeating-linear-gradient(45deg, black, transparent 100px);
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Add a style for the disabled button */
|
||||
#getFileStateBtn[disabled] {
|
||||
color: #ccc; /* Grey text color */
|
||||
cursor: not-allowed; /* Change cursor to 'not-allowed' */
|
||||
}
|
||||
|
||||
|
||||
|
||||
.title {
|
||||
color: #6dabf1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: help; /* Change cursor to pointer on hover */
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 327px;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 9px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: -87px;
|
||||
/* left: 50%; */
|
||||
margin-left: -60px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #000000;
|
||||
color: lightgray;
|
||||
font-family: sans-serif;
|
||||
text-decoration: none !important;
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
@import url('https://fonts.googleapis.com/css?family=Raleway:400,700');
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Raleway, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(90deg, #C7C5F4, #776BCC);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.screen {
|
||||
background: linear-gradient(90deg, #5D54A4, #7C78B8);
|
||||
position: relative;
|
||||
height: 600px;
|
||||
width: 360px;
|
||||
box-shadow: 0px 0px 24px #5C5696;
|
||||
}
|
||||
|
||||
.screen__content {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.screen__background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
-webkit-clip-path: inset(0 0 0 0);
|
||||
clip-path: inset(0 0 0 0);
|
||||
}
|
||||
|
||||
.screen__background__shape {
|
||||
transform: rotate(45deg);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.screen__background__shape1 {
|
||||
height: 520px;
|
||||
width: 520px;
|
||||
background: #FFF;
|
||||
top: -50px;
|
||||
right: 120px;
|
||||
border-radius: 0 72px 0 0;
|
||||
}
|
||||
|
||||
.screen__background__shape2 {
|
||||
height: 220px;
|
||||
width: 220px;
|
||||
background: #6C63AC;
|
||||
top: -172px;
|
||||
right: 0;
|
||||
border-radius: 32px;
|
||||
}
|
||||
|
||||
.screen__background__shape3 {
|
||||
height: 540px;
|
||||
width: 190px;
|
||||
background: linear-gradient(270deg, #5D54A4, #6A679E);
|
||||
top: -24px;
|
||||
right: 0;
|
||||
border-radius: 32px;
|
||||
}
|
||||
|
||||
.screen__background__shape4 {
|
||||
height: 400px;
|
||||
width: 200px;
|
||||
background: #7E7BB9;
|
||||
top: 420px;
|
||||
right: 50px;
|
||||
border-radius: 60px;
|
||||
}
|
||||
|
||||
.login {
|
||||
width: 360px;
|
||||
padding: 30px;
|
||||
padding-top: 64px;
|
||||
}
|
||||
|
||||
.login__field {
|
||||
padding: 20px 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login__icon {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
color: #7875B5;
|
||||
}
|
||||
|
||||
.login__input {
|
||||
border: none;
|
||||
border-bottom: 2px solid #D1D1D4;
|
||||
background: none;
|
||||
padding: 10px;
|
||||
padding-left: 24px;
|
||||
font-weight: 700;
|
||||
width: 75%;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
.login__input:active,
|
||||
.login__input:focus,
|
||||
.login__input:hover {
|
||||
outline: none;
|
||||
border-bottom-color: #6A679E;
|
||||
}
|
||||
|
||||
.login__submit {
|
||||
background: #fff;
|
||||
font-size: 14px;
|
||||
margin-top: 30px;
|
||||
padding: 16px 20px;
|
||||
border-radius: 26px;
|
||||
border: 1px solid #D4D3E8;
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
color: #4C489D;
|
||||
box-shadow: 0px 2px 2px #5C5696;
|
||||
cursor: pointer;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
.login__submit:active,
|
||||
.login__submit:focus,
|
||||
.login__submit:hover {
|
||||
border-color: #6A679E;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.button__icon {
|
||||
font-size: 24px;
|
||||
margin-left: auto;
|
||||
color: #7875B5;
|
||||
}
|
||||
|
||||
.social-login {
|
||||
position: absolute;
|
||||
height: 140px;
|
||||
width: 160px;
|
||||
text-align: center;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.social-login__icon {
|
||||
padding: 20px 10px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 0px 8px #7875B5;
|
||||
}
|
||||
|
||||
.social-login__icon:hover {
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.login-title{
|
||||
font-size: large;
|
||||
padding-left: 30px;
|
||||
padding-top: 30px;
|
||||
}
|
||||
.error-message{
|
||||
font-size: small;
|
||||
/* text-align: center; */
|
||||
color: coral;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo{
|
||||
width: 64px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,71 @@
|
|||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
nav ul li {
|
||||
display: inline;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, ubuntu, cantarell, "fira sans", "droid sans", "helvetica neue", Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
body {
|
||||
background-color: #435165;
|
||||
}
|
||||
.login {
|
||||
width: 400px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.3);
|
||||
margin: 100px auto;
|
||||
}
|
||||
.login h1 {
|
||||
text-align: center;
|
||||
color: #5b6574;
|
||||
font-size: 24px;
|
||||
padding: 20px 0 20px 0;
|
||||
border-bottom: 1px solid #dee0e4;
|
||||
}
|
||||
.login form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.login form label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #3274d6;
|
||||
color: #ffffff;
|
||||
}
|
||||
.login form input[type="password"], .login form input[type="text"] {
|
||||
width: 310px;
|
||||
height: 50px;
|
||||
border: 1px solid #dee0e4;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
.login form input[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin-top: 20px;
|
||||
background-color: #3274d6;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.login form input[type="submit"]:hover {
|
||||
background-color: #2868c7;
|
||||
transition: background-color 0.2s;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Home</title>
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/home">Home</a></li>
|
||||
<li><a href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
Welcome, <%= username %>!
|
||||
</div>
|
||||
</nav>
|
||||
<h1>Welcome to the Home Page!</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login</title>
|
||||
<link rel="stylesheet" href="/login-style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="screen">
|
||||
<div class="screen__content">
|
||||
<div class="login-title">
|
||||
<h3>Terminal Diagnostic Helper</h2>
|
||||
<span>v1.0.0</span>
|
||||
<!-- <p class="login-title"> <br> </p> -->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<form class="login" action="/auth" method="post">
|
||||
<% if (message) { %>
|
||||
<div class="error-message"><%= message %></div>
|
||||
<% } %>
|
||||
<div class="login__field">
|
||||
<i class="login__icon fas fa-user"></i>
|
||||
<input type="text" class="login__input" id="login" name="login" placeholder="User name / Email">
|
||||
</div>
|
||||
<div class="login__field">
|
||||
<i class="login__icon fas fa-lock"></i>
|
||||
<input type="password" class="login__input" id="password" name="password" placeholder="Password">
|
||||
</div>
|
||||
<input class="button login__submit" type="submit" value="Login">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<div class="social-login">
|
||||
|
||||
<img class="logo" src="/logo.png" alt="" sizes="20px" >
|
||||
<h3>SERVICE VOLGA</h3>
|
||||
<div class="social-icons">
|
||||
<a href="#" class="social-login__icon fab fa-instagram"></a>
|
||||
<a href="#" class="social-login__icon fab fa-facebook"></a>
|
||||
<a href="#" class="social-login__icon fab fa-twitter"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screen__background">
|
||||
<span class="screen__background__shape screen__background__shape4"></span>
|
||||
<span class="screen__background__shape screen__background__shape3"></span>
|
||||
<span class="screen__background__shape screen__background__shape2"></span>
|
||||
<span class="screen__background__shape screen__background__shape1"></span>
|
||||
</div>
|
||||
<p> © 2024 Ал Омаири Ахмед </p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue