From 4066abb255068f80cdfb12635104d7aa203faddb Mon Sep 17 00:00:00 2001 From: tomchukk Date: Sat, 15 Mar 2025 18:28:52 +0200 Subject: [PATCH] uploaded base code --- app.py | 136 +++++++++++++++++++++++++++++++++++++ config.json | 15 ++++ database/init.sql | 10 +++ docker/Dockerfile | 0 docker/docker-compose.yaml | 0 requirements.txt | 5 ++ static/script.js | 53 +++++++++++++++ static/styles.css | 41 +++++++++++ templates/index.html | 42 ++++++++++++ translations.json | 0 10 files changed, 302 insertions(+) create mode 100644 app.py create mode 100644 config.json create mode 100644 database/init.sql create mode 100644 docker/Dockerfile create mode 100644 docker/docker-compose.yaml create mode 100644 requirements.txt create mode 100644 static/script.js create mode 100644 static/styles.css create mode 100644 templates/index.html create mode 100644 translations.json diff --git a/app.py b/app.py new file mode 100644 index 0000000..46b0cc9 --- /dev/null +++ b/app.py @@ -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) diff --git a/config.json b/config.json new file mode 100644 index 0000000..49c3137 --- /dev/null +++ b/config.json @@ -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" +} \ No newline at end of file diff --git a/database/init.sql b/database/init.sql new file mode 100644 index 0000000..b431a79 --- /dev/null +++ b/database/init.sql @@ -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 +); \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c71c022 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Flask +mysql-connector-python +flask-socketio +gevent +gevent-websocket \ No newline at end of file diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..ae891e0 --- /dev/null +++ b/static/script.js @@ -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); + }); +}); diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..5e98971 --- /dev/null +++ b/static/styles.css @@ -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; +} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..d569122 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,42 @@ + + + + + + שמירת חפצים + + + + + +
+

שמירת חפצים

+ +
+ + + + +
+ +

חיפוש חפצים

+ + + +

הגדרות

+
+ + + + + + + + + + + +
+
+ + diff --git a/translations.json b/translations.json new file mode 100644 index 0000000..e69de29