From ee9e73da66dc0d008a4aa8c5a8901edf2ff05251 Mon Sep 17 00:00:00 2001 From: Thomas Hassenstein <2021544@stud.hs-mannheim.de> Date: Mon, 12 Jun 2023 07:26:18 +0200 Subject: [PATCH] =?UTF-8?q?Dateien=20hochladen=20nach=20=E2=80=9EREST?= =?UTF-8?q?=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aktualisierung der Oberfläche Auslagerung des Javaskript Codes Anpassung CSS (Ergänzung von Disabled Styles) REST Antworten vereinheitlichen --- REST/app.py | 47 ++++++--- REST/index.html | 152 ++++----------------------- REST/script.js | 236 ++++++++++++++++++++++++++++++++++++++++++ REST/style.css | 267 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 551 insertions(+), 151 deletions(-) create mode 100644 REST/script.js create mode 100644 REST/style.css diff --git a/REST/app.py b/REST/app.py index a830295..afbcbd9 100644 --- a/REST/app.py +++ b/REST/app.py @@ -10,54 +10,67 @@ CORS(app) initialized = False +def create_response(status_code, description): + return jsonify({ + 'status': status_code, + 'description': description + }) + @app.route('/trng/randomNum/init', methods=['GET']) def initialize_generator(): - global initialized # Zugriff auf die globale Variable + global initialized - #parameter 1 und 2 sind default values für Tests result = analyze_data(int(1), int(1), startup=True) if result is True: initialized = True - return jsonify({'message': 'successful operation; random number generator is ready and random numbers can be requested'}), 200 + return create_response(200, 'Successful operation; random number generator is ready and random numbers can be requested') + if random_numbers == 400: + return create_response(500, 'Tests failed, try again') + if random_numbers is False: + return create_response(500, 'Unable to generate random numbers. Restart/Reset System') else: - return jsonify({'error': 'Unable to initialize the random number generator within a timeout of 60 seconds.'}), 555 + return create_response(555, 'Unable to initialize the random number generator within a timeout of 60 seconds') @app.route('/trng/randomNum/getRandom', methods=['GET']) def get_random_numbers(): - global initialized # Zugriff auf die globale Variable + global initialized quantity = request.args.get('quantity') bits = request.args.get('numBits') if not quantity.isdigit() or not bits.isdigit(): - return jsonify({'error': 'Invalid input. Quantity and bits must be numeric.'}), 400 + return create_response(400, 'Invalid input. Quantity and bits must be numeric.') if int(quantity) <= 0 or int(bits) <= 0: - return jsonify({'error': 'Invalid input. Quantity and bits must be positive integers.'}), 400 + return create_response(400, 'Invalid input. Quantity and bits must be positive integers.') - # Überprüfe den Initialisierungsstatus if not initialized: - return jsonify({'error': 'system not ready; try init'}), 432 + return create_response(432, 'System not ready; try init') random_numbers = analyze_data(int(quantity), int(bits), startup=False) + if random_numbers == 400: + return create_response(500, 'Tests failed, try again') if random_numbers is False: - return jsonify({'error': 'Unable to generate random numbers.'}), 500 + return create_response(500, 'Unable to generate random numbers. Restart/Reset System') if random_numbers: - data = {'randomNumbers': random_numbers} # Erstellen des Datenobjekts mit dem JSON-String - return jsonify(data), 200 + data = { + 'status': 200, + 'description': 'Successful operation; HEX-encoded bit arrays (with leading zeros if required)', + 'randomNumbers': random_numbers + } + return jsonify(data) else: - return jsonify({'error': 'Unable to generate random numbers.'}), 500 + return create_response(500, 'Unable to generate random numbers.') @app.route('/trng/randomNum/shutdown', methods=['GET']) def shutdown_generator(): - global initialized # Zugriff auf die globale Variable + global initialized - initialized = False # Setze den Initialisierungsstatus zurück + initialized = False - # Beispielantwort - return jsonify({'message': "successful operation; random number generator has been set to 'standby mode'"}), 200 + return create_response(200, "Successful operation; random number generator has been set to 'standby mode'") if __name__ == '__main__': diff --git a/REST/index.html b/REST/index.html index f97e053..ddbda3c 100644 --- a/REST/index.html +++ b/REST/index.html @@ -1,6 +1,7 @@ + GMTROM - True Random Number Generator @@ -11,144 +12,27 @@


-

+

-

+

- + + +
+
+ + + + +
+ -
- - + + + \ No newline at end of file diff --git a/REST/script.js b/REST/script.js new file mode 100644 index 0000000..685df19 --- /dev/null +++ b/REST/script.js @@ -0,0 +1,236 @@ +// Initialisieren der Eingabefelder +var quantityInput = document.getElementById('quantity'); +var bitsInput = document.getElementById('bits'); + +// Deaktivieren der Eingabefelder +quantityInput.disabled = true; +bitsInput.disabled = true; + +/*------------------------------------------Init Button-----------------------------------------------*/ +document.getElementById('initButton').addEventListener('click', function() { + + //zurücksetzen von status und description + document.getElementById('description').innerText = ''; + document.getElementById('status').innerText = ''; + document.getElementById('result').innerText = ''; + + showLoadingSpinner('Start-up tests and system initialization in progress.'); + + fetch('https://172.16.78.57:5000/trng/randomNum/init') + .then(response => { + document.getElementById('status').innerText = 'Status: ' + response.status; + return response.json(); + }) + .then(data => { + document.getElementById('description').innerText = data.description; + console.log('Initialisierung erfolgreich'); + + // Deaktiviere Generate und Shutdown Buttons + //document.getElementById('generateButton').disabled = false; + document.getElementById('shutdownButton').disabled = false; + // Aktiviere Initialize Button + document.getElementById('initButton').disabled = true; + + // Aktivieren der Eingabefelder + quantityInput.disabled = false; + bitsInput.disabled = false; + }) + .catch(error => { + console.error('Fehler beim Initialisieren:', error); + }) + .finally(() => { + hideLoadingSpinner(); + }); +}); + +/*------------------------------------------Generate Button-----------------------------------------------*/ +document.getElementById('generateButton').addEventListener('click', function(event) { + // Zurücksetzen von status und description + document.getElementById('description').innerText = ''; + document.getElementById('status').innerText = ''; + document.getElementById('result').innerText = ''; + + showLoadingSpinner('Generating and testing random numbers.'); + + var quantity = document.getElementById('quantity').value; + var bits = document.getElementById('bits').value; + + var url = 'https://172.16.78.57:5000/trng/randomNum/getRandom'; + if (quantity && bits) { + url += '?quantity=' + quantity + '&numBits=' + bits; + } + + fetch(url) + .then(response => { + document.getElementById('status').innerText = 'Status: ' + response.status; + return response.json(); + }) + .then(data => { + document.getElementById('status').innerText = 'Status: ' + data.status; + document.getElementById('description').innerText = data.description; + + var resultDiv = document.getElementById('result'); + resultDiv.innerHTML = ''; // Clear previous results + + if (data.status !== 200) { + return; + } + + if (data.status === 200) { + var table = document.createElement('table'); + table.classList.add('table'); + var thead = document.createElement('thead'); + var tbody = document.createElement('tbody'); + var trHead = document.createElement('tr'); + var thNr = document.createElement('th'); + var thCopy = document.createElement('th'); + var thRandom = document.createElement('th'); + var copyAllButton = document.createElement('button'); + + thNr.textContent = 'ID'; + thCopy.textContent = ' '; + thRandom.textContent = 'Random Number'; + + trHead.appendChild(thNr); + trHead.appendChild(thCopy); + trHead.appendChild(thRandom); + thead.appendChild(trHead); + table.appendChild(thead); + + var hexNumbers = JSON.parse(data.randomNumbers); // JSON-Array parsen + + for (var i = 0; i < hexNumbers.length; i++) { + var tr = document.createElement('tr'); + var tdNr = document.createElement('td'); + var tdCopy = document.createElement('td'); + var tdRandom = document.createElement('td'); + var copyButton = document.createElement('button'); + + tdNr.textContent = (i + 1).toString(); + tdRandom.textContent = hexNumbers[i]; + copyButton.textContent = 'Copy'; + copyButton.classList.add('copy-button'); + + copyButton.addEventListener('click', function() { + copyToClipboard(this.parentElement.nextElementSibling.textContent); + }); + + tdCopy.appendChild(copyButton); + tr.appendChild(tdNr); + tr.appendChild(tdCopy); + tr.appendChild(tdRandom); + tbody.appendChild(tr); + } + + table.appendChild(tbody); + resultDiv.appendChild(table); + + copyAllButton.textContent = 'Copy all'; + copyAllButton.classList.add('copy-button'); + copyAllButton.style.marginBottom = '5px'; // Setze den Abstand nach unten + + copyAllButton.addEventListener('click', function() { + copyToClipboard(hexNumbers.join('\n')); + }); + + resultDiv.insertBefore(copyAllButton, table); // Füge den "Copy all" Button vor der Tabelle ein + } else { + var errorParagraph = document.createElement('p'); + errorParagraph.textContent = 'Error: ' + data.message; + resultDiv.appendChild(errorParagraph); + } + + console.log('Generierung erfolgreich'); + }) + .catch(error => { + console.error('Fehler beim Generieren:', error); + }) + .finally(() => { + hideLoadingSpinner(); + }); +}); + +/*------------------------------------------Copy to Clipboard-----------------------------------------------*/ +function copyToClipboard(text) { + var textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + + // Anzeigen eines Popups zur Bestätigung der Kopie + window.alert('The text has been copied to the clipboard!'); +} + +/*------------------------------------------Shutdown Button-----------------------------------------------*/ +document.getElementById('shutdownButton').addEventListener('click', function() { + //zurücksetzen von status und description + document.getElementById('description').innerText = ''; + document.getElementById('status').innerText = ''; + //textfelder zurücksetzen + document.getElementById('quantity').value = ''; + document.getElementById('bits').value = ''; + //result div zurücksetzen + document.getElementById('result').innerText = ''; + + showLoadingSpinner('Shutting down the system.'); // Zeigt den Lade-Spinner + + fetch('https://172.16.78.57:5000/trng/randomNum/shutdown') + .then(response => { + document.getElementById('status').innerText = 'Status: ' + response.status; + return response.json(); + }) + .then(data => { + document.getElementById('description').innerText = data.description; + console.log('Herunterfahren erfolgreich'); + + // Deaktiviere Generate und Shutdown Buttons + document.getElementById('generateButton').disabled = true; + document.getElementById('shutdownButton').disabled = true; + // Aktiviere Initialize Button + document.getElementById('initButton').disabled = false; + }) + .catch(error => { + console.error('Fehler beim Herunterfahren:', error); + }) + .finally(() => { + hideLoadingSpinner(); // Blende den Lade-Spinner aus + }); +}); + +// Überprüfungsfunktion für die Eingabefelder +function checkInputFields() { + var quantity = document.getElementById('quantity').value; + var bits = document.getElementById('bits').value; + var generateButton = document.getElementById('generateButton'); + + if (quantity && bits) { + generateButton.disabled = false; // Aktiviere den Button, wenn beide Eingabefelder einen Wert enthalten + } else { + generateButton.disabled = true; // Deaktiviere den Button, wenn mindestens eines der Eingabefelder leer ist + } +} + +// Eventlistener für die Eingabefelder, der die Überprüfungsfunktion aufruft +document.getElementById('quantity').addEventListener('input', checkInputFields); +document.getElementById('bits').addEventListener('input', checkInputFields); + +/*-----------------------------Initiale Deaktivierung von Generate und Shutdown Buttons-----------------------------*/ +document.getElementById('generateButton').disabled = true; +document.getElementById('shutdownButton').disabled = true; + +/*------------------------------------------Loading Spinner-----------------------------------------------*/ +// Zeige den Lade-Spinner an und blockiere den Inhalt +function showLoadingSpinner(loadingText) { + document.getElementById('overlay').classList.remove('hidden'); + document.getElementById('loadingSpinner').classList.remove('hidden'); + document.getElementById('loadingText').innerText = loadingText; +} + +// Blende den Lade-Spinner aus und entsperre den Inhalt +function hideLoadingSpinner() { + document.getElementById('overlay').classList.add('hidden'); + document.getElementById('loadingSpinner').classList.add('hidden'); + document.getElementById('loadingText').innerText = ''; +} \ No newline at end of file diff --git a/REST/style.css b/REST/style.css new file mode 100644 index 0000000..ec82d91 --- /dev/null +++ b/REST/style.css @@ -0,0 +1,267 @@ +body { +font-family: Arial, sans-serif; +background-color: #292C35; +color: #DCAE52; +} + +table { +font-family: monospace, Arial, sans-serif; +max-width: 100%; +width: 100%; +border-collapse: collapse; +margin-bottom: 100px; +background-color: #292C35; +color: #DCAE52; +font-size: 14px; +border: 1px solid #DCAE52; +} + +th, td { +border: 1px solid #DCAE52; +} + +td { +text-align: center; +padding: 5px; +} + +h1 { +color: #DCAE52; +text-align: center; +} + +.disabled-input { + +} + +form { +background-color: #292C35; +border-radius: 5px; +box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); +padding: 20px; +width: 50%; +margin: 0 auto; +} + +label { +display: block; +font-weight: bold; +margin-bottom: 10px; +color: #DCAE52; +} + +input[type="number"] { +width: 100%; +padding: 10px; +margin-bottom: 20px; +border: 1px solid #E9E2C9; +border-radius: 5px; +box-sizing: border-box; +background-color: #E9E2C9; +} + +.disabled-input[type="number"]:disabled { + opacity: 0.6; + cursor: not-allowed; + border-color: #cccccc; + background-color: #999999; +} + +input[type="number"]:disabled { + opacity: 0.6; + cursor: not-allowed; + border-color: #cccccc; + background-color: #999999; +} + +input[type="submit"] { +background-color: #292C35; +border: 1px solid #E9E2C9; +/* border: none; */ +color: #DCAE52; +padding: 10px 20px; +text-align: center; +text-decoration: none; +display: inline-block; +font-size: 16px; +border-radius: 5px; +cursor: pointer; +} + +input[type="submit"]:hover { +background-color: #E9E2C9; +} + +input[type="button"] { +background-color: #292C35; +border: 1px solid #E9E2C9; +/* border: none; */ +color: #DCAE52; +padding: 10px 20px; +text-align: center; +text-decoration: none; +display: inline-block; +font-size: 16px; +border-radius: 5px; +cursor: pointer; +} + +input[type="button"]:hover { +background-color: #E9E2C9; +} + +.logo { +position: absolute; +top: 10px; +left: 10px; +width: 4em; +height: 4em; +} + +@media screen and (max-width: 600px) { + form { + width: 80%; + position: relative; + } + + .logo { + width: 2em; /* Ändern Sie die Breite des Logos für kleine Bildschirme */ + height: 2em; /* Ändern Sie die Höhe des Logos für kleine Bildschirme */ + } + + h1 { + font-size: 24px; /* Ändern Sie die Schriftgröße der Überschrift für kleine Bildschirme */ + } +} + +#status { + margin-top: 15px; +} + +#result { + font-family: monospace; + font-size: 16px; +} + +.copy-button { +background-color: #292C35; +border: 1px solid #E9E2C9; +color: #DCAE52; +padding: 5px 10px; +text-align: center; +text-decoration: none; +display: inline-block; +font-size: 14px; +border-radius: 5px; +cursor: pointer; +} + +.copy-button:hover { +background-color: #E9E2C9; +} + +.copy-button-row { +background-color: #292C35; +border: 1px solid #E9E2C9; +color: #DCAE52; +padding: 5px 10px; +text-align: center; +text-decoration: none; +display: inline-block; +font-size: 12px; +border-radius: 3px; +cursor: pointer; +} + +.copy-button-row:hover { +background-color: #E9E2C9; +} + +.table th:first-child, +.table td:first-child, +.table th:nth-child(2), +.table td:nth-child(2) { +width: auto; +white-space: nowrap; +} + +.table th:nth-child(3), +.table td:nth-child(3) { +width: 100%; +} + +.table thead tr { +font-weight: bold; +font-size: 1.2em; +background-color: #DCE52; +min-height: 20px; +} + +/* Loading Spinner */ +#loadingSpinner { + width: 50px; + height: 50px; + border: 3px solid rgba(0, 0, 0, 0.1); + border-left-color: #DCAE52; + border-radius: 50%; + animation: spin 1s infinite linear; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10000; +} + +#loadingText { + color: #DCAE52; + font-size: 16px; + text-align: center; + margin-top: 20px; /* Anpassung des margin-top-Werts auf 20px */ + position: fixed; + top: calc(50% + 45px); /* Anpassung des top-Werts auf calc(50% + 45px) */ + left: 50%; + transform: translateX(-50%); + z-index: 10000; +} + +.loading-spinner { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10000; + text-align: center; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.hidden { + display: none; +} + +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 9999; +} + +input[type="submit"]:disabled, +input[type="button"]:disabled { + background-color: #999999; + border-color: #cccccc; + cursor: not-allowed; + opacity: 0.6; + color: #666666 +} +