uploaded base code
This commit is contained in:
136
app.py
Normal file
136
app.py
Normal file
@@ -0,0 +1,136 @@
|
||||
from flask import Flask, request, jsonify, render_template
|
||||
import mysql.connector
|
||||
import json
|
||||
import os
|
||||
from flask_socketio import SocketIO
|
||||
|
||||
# Load configuration
|
||||
CONFIG_FILE = "config.json"
|
||||
|
||||
def load_config():
|
||||
with open(CONFIG_FILE, "r", encoding="utf-8") as config_file:
|
||||
return json.load(config_file)
|
||||
|
||||
def save_config(updated_config):
|
||||
with open(CONFIG_FILE, "w", encoding="utf-8") as config_file:
|
||||
json.dump(updated_config, config_file, indent=4, ensure_ascii=False)
|
||||
|
||||
def translate(key):
|
||||
return translations.get(config.get("language", "en"), {}).get(key, key)
|
||||
|
||||
config = load_config()
|
||||
db_config = config["database"]
|
||||
matrix_size = config["matrix_size"]
|
||||
skip_n = config.get("skip_n", True)
|
||||
rtl = config.get("rtl", False)
|
||||
|
||||
# Load translations
|
||||
with open("translations.json", "r", encoding="utf-8") as trans_file:
|
||||
translations = json.load(trans_file)
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['JSON_AS_ASCII'] = False # Ensure UTF-8 support
|
||||
socketio = SocketIO(app, cors_allowed_origins="*")
|
||||
|
||||
def init_db():
|
||||
try:
|
||||
conn = mysql.connector.connect(**db_config)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''CREATE TABLE IF NOT EXISTS storage (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
phone VARCHAR(20),
|
||||
location VARCHAR(10),
|
||||
bulk BOOLEAN)''')
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
print(f"Database initialization error: {e}")
|
||||
finally:
|
||||
if 'conn' in locals() and conn.is_connected():
|
||||
conn.close()
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template("index.html", rtl=rtl)
|
||||
|
||||
@app.route('/store', methods=['POST'])
|
||||
def store_item():
|
||||
try:
|
||||
data = request.json
|
||||
name = data.get("name")
|
||||
phone = data.get("phone")
|
||||
location = data.get("location")
|
||||
bulk = data.get("bulk", 0)
|
||||
|
||||
conn = mysql.connector.connect(**db_config)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("INSERT INTO storage (name, phone, location, bulk) VALUES (%s, %s, %s, %s)", (name, phone, location, bulk))
|
||||
conn.commit()
|
||||
socketio.emit("update", {"message": translate("item_stored")})
|
||||
return jsonify({"message": translate("item_stored")})
|
||||
except Exception as e:
|
||||
print(f"Error storing item: {e}")
|
||||
return jsonify({"error": "An error occurred"}), 500
|
||||
finally:
|
||||
if 'conn' in locals() and conn.is_connected():
|
||||
conn.close()
|
||||
|
||||
@app.route('/retrieve', methods=['GET'])
|
||||
def retrieve_items():
|
||||
try:
|
||||
phone = request.args.get("phone")
|
||||
conn = mysql.connector.connect(**db_config)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM storage WHERE phone = %s", (phone,))
|
||||
items = cursor.fetchall()
|
||||
return jsonify(items)
|
||||
except Exception as e:
|
||||
print(f"Error retrieving items: {e}")
|
||||
return jsonify({"error": "An error occurred"}), 500
|
||||
finally:
|
||||
if 'conn' in locals() and conn.is_connected():
|
||||
conn.close()
|
||||
|
||||
@app.route('/remove', methods=['POST'])
|
||||
def remove_item():
|
||||
try:
|
||||
data = request.json
|
||||
item_id = data.get("id")
|
||||
conn = mysql.connector.connect(**db_config)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM storage WHERE id = %s", (item_id,))
|
||||
conn.commit()
|
||||
socketio.emit("update", {"message": translate("item_removed")})
|
||||
return jsonify({"message": translate("item_removed")})
|
||||
except Exception as e:
|
||||
print(f"Error removing item: {e}")
|
||||
return jsonify({"error": "An error occurred"}), 500
|
||||
finally:
|
||||
if 'conn' in locals() and conn.is_connected():
|
||||
conn.close()
|
||||
|
||||
@app.route('/config', methods=['GET', 'POST'])
|
||||
def configure_app():
|
||||
global config, db_config, matrix_size, skip_n, rtl # Move this line to the start of the function
|
||||
|
||||
if request.method == 'GET':
|
||||
return jsonify(config)
|
||||
try:
|
||||
new_config = request.json
|
||||
save_config(new_config)
|
||||
|
||||
# Reload configuration
|
||||
config = load_config()
|
||||
db_config = config["database"]
|
||||
matrix_size = config["matrix_size"]
|
||||
skip_n = config.get("skip_n", True)
|
||||
rtl = config.get("rtl", False)
|
||||
|
||||
return jsonify({"message": "Configuration updated successfully"})
|
||||
except Exception as e:
|
||||
print(f"Error updating config: {e}")
|
||||
return jsonify({"error": "Failed to update config"}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
init_db()
|
||||
socketio.run(app, host='0.0.0.0', port=5000, debug=True)
|
||||
15
config.json
Normal file
15
config.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"database": {
|
||||
"host": "localhost",
|
||||
"user": "root",
|
||||
"password": "password",
|
||||
"database": "storage_room"
|
||||
},
|
||||
"matrix_size": {
|
||||
"rows": 10,
|
||||
"columns": 10
|
||||
},
|
||||
"skip_n": true,
|
||||
"rtl": true,
|
||||
"language": "he"
|
||||
}
|
||||
10
database/init.sql
Normal file
10
database/init.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
CREATE DATABASE IF NOT EXISTS storage_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
USE storage_db;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS storage (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(20) NOT NULL,
|
||||
location VARCHAR(10) NOT NULL,
|
||||
bulk BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
0
docker/Dockerfile
Normal file
0
docker/Dockerfile
Normal file
0
docker/docker-compose.yaml
Normal file
0
docker/docker-compose.yaml
Normal file
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Flask
|
||||
mysql-connector-python
|
||||
flask-socketio
|
||||
gevent
|
||||
gevent-websocket
|
||||
53
static/script.js
Normal file
53
static/script.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const socket = io();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const storeForm = document.getElementById("store-form");
|
||||
const phoneInput = document.getElementById("phone-input");
|
||||
const retrieveButton = document.getElementById("retrieve-button");
|
||||
const configForm = document.getElementById("config-form");
|
||||
|
||||
if (storeForm) {
|
||||
storeForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(storeForm);
|
||||
fetch("/store", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(Object.fromEntries(formData))
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message || "Error"));
|
||||
});
|
||||
}
|
||||
|
||||
if (retrieveButton) {
|
||||
retrieveButton.addEventListener("click", function () {
|
||||
const phone = phoneInput.value;
|
||||
fetch(`/retrieve?phone=${encodeURIComponent(phone)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
alert(JSON.stringify(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (configForm) {
|
||||
configForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(configForm);
|
||||
fetch("/config", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(Object.fromEntries(formData))
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message || "Error"));
|
||||
});
|
||||
}
|
||||
|
||||
socket.on("update", function (data) {
|
||||
console.log("Live update:", data);
|
||||
alert(data.message);
|
||||
});
|
||||
});
|
||||
41
static/styles.css
Normal file
41
static/styles.css
Normal file
@@ -0,0 +1,41 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
input, button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
42
templates/index.html
Normal file
42
templates/index.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="he">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>שמירת חפצים</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
|
||||
<script src="script.js" defer></script>
|
||||
</head>
|
||||
<body class="{{ 'rtl' if rtl else '' }}">
|
||||
<div class="container">
|
||||
<h1>שמירת חפצים</h1>
|
||||
|
||||
<form id="store-form">
|
||||
<input type="text" name="name" placeholder="שם" required>
|
||||
<input type="text" name="phone" placeholder="טלפון" required>
|
||||
<input type="text" name="location" placeholder="מיקום (שורה, עמודה או X#)" required>
|
||||
<button type="submit">שמור</button>
|
||||
</form>
|
||||
|
||||
<h2>חיפוש חפצים</h2>
|
||||
<input type="text" id="phone-input" placeholder="הזן מספר טלפון">
|
||||
<button id="retrieve-button">חפש</button>
|
||||
|
||||
<h2>הגדרות</h2>
|
||||
<form id="config-form">
|
||||
<label>שפה:</label>
|
||||
<input type="text" name="language" value="{{ config['language'] }}">
|
||||
<label>רוחב מטריצה:</label>
|
||||
<input type="number" name="matrix_size[columns]" value="{{ config['matrix_size']['columns'] }}">
|
||||
<label>גובה מטריצה:</label>
|
||||
<input type="number" name="matrix_size[rows]" value="{{ config['matrix_size']['rows'] }}">
|
||||
<label>דלג על N:</label>
|
||||
<input type="checkbox" name="skip_n" {{ 'checked' if config['skip_n'] else '' }}>
|
||||
<label>RTL:</label>
|
||||
<input type="checkbox" name="rtl" {{ 'checked' if config['rtl'] else '' }}>
|
||||
<button type="submit">שמור הגדרות</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
0
translations.json
Normal file
0
translations.json
Normal file
Reference in New Issue
Block a user