From f592a13be4a4c983fe29bf5a250fd66c49224b28 Mon Sep 17 00:00:00 2001 From: Atilla Date: Tue, 5 Mar 2024 11:10:23 +0100 Subject: [PATCH] Up to date --- app.js | 58 ++- script/DUMMY.json | 123 ++++++ script/__pycache__/db_connect.cpython-311.pyc | Bin 941 -> 941 bytes script/battery_voltage_events.py | 405 ++++++++++++++---- script/main.js | 27 -- src/css/style.css | 163 ++++++- src/css/style.css.map | 2 +- src/css/style.scss | 376 ++++++++++++---- src/images/logo.png | Bin 0 -> 20646 bytes src/index.html | 6 +- src/js/main.js | 124 ++++++ src/kas_informatie.html | 120 +++++- src/py/calculate.py | 7 + 13 files changed, 1167 insertions(+), 244 deletions(-) create mode 100644 script/DUMMY.json delete mode 100644 script/main.js create mode 100644 src/images/logo.png create mode 100644 src/js/main.js create mode 100644 src/py/calculate.py diff --git a/app.js b/app.js index 6c0eae4..7c74b7f 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow } = require('electron'); /* TYPE IN TERMINAL: "npm install electron" */ +const { app, BrowserWindow,ipcMain } = require('electron'); /* TYPE IN TERMINAL: "npm install electron" */ const express = require('express'); /* TYPE IN TERMINAL: "npm install express" */ const bodyParser = require('body-parser'); /* TYPE IN TERMINAL: "npm install body-parser" */ const { PythonShell } = require('python-shell'); /* TYPE IN TERMINAL: "npm install python-shell" */ @@ -16,19 +16,31 @@ server.post('/submit-form', (req, res) => { let options = { mode: 'text', - args: [plant_naam, plantensoort, plant_geteelt] // Zet hier een variable bij om de data toe te voegen aan de database + args: [plant_naam, plantensoort, plant_geteelt], // Zet hier een variable bij om de data toe te voegen aan de databas }; - // Voer Python script uit met de plant_naam als argument - PythonShell.run('./script/db_connect_form.py', options, (err, results) => { - if (err) { - console.error(err); - res.send('Er is een fout opgetreden'); - } else { - console.log('Python script uitvoering resultaten:', results); - res.send('Formulier succesvol verwerkt'); - } - }); +/*Om python te gebruiken*/ +// ipcMain.on('request-update-temp', (event, args) => { +// let options = { +// mode: 'text', +// scriptPath: 'path/to/your/python/script', +// args: args +// }; + +// PythonShell.run('calculate.py', options, (err, results) => { +// if (err) { +// console.error('Error running python script', err); +// event.reply('update-temp-result', 'error'); +// } else { +// console.log('Python script results:', results); +// event.reply('update-temp-result', results[0]); // Verstuur het resultaat terug naar de renderer proces +// } +// }); +// }); + +// En dan in je renderer proces, stuur je een bericht om de update te verzoeken +ipcRenderer.send('request-update-temp', [/* hier kunnen argumenten komen die je Python script nodig heeft */]); + }); // Start de server voor verbinding met de database @@ -42,6 +54,7 @@ function createWindow() { const mainWindow = new BrowserWindow({ width: 1280, height: 800, + frame: false, webPreferences: { nodeIntegration: true, contextIsolation: false @@ -49,6 +62,27 @@ function createWindow() { }); mainWindow.loadURL(urlElectron); + + /*Is om het Python script te kunnen gebruiken*/ + ipcMain.on('run-python-script', (event, args) => { + let options = { + mode: 'text', + args: args + }; + + PythonShell.run('../src/py/calculate.py', options, (err, results) => { + if (err) + { + console.error('Error running python script', err); + event.reply('python-script-response', 'error'); + } + else + { + console.log('Python script results:', results); + event.reply('python-script-response', results); + } + }); +}); } app.whenReady().then(createWindow); diff --git a/script/DUMMY.json b/script/DUMMY.json new file mode 100644 index 0000000..98acdaf --- /dev/null +++ b/script/DUMMY.json @@ -0,0 +1,123 @@ + + // Deze spanningswaarden zijn relatief hoog, wat suggereert dat de batterijen van de sensoren goed opgeladen zijn. De meeste sensorapparaten gebruiken batterijen die een nominale spanning van ongeveer 3,7 volt hebben (typisch voor lithium-ion batterijen) en kunnen worden beschouwd als "volledig opgeladen" wanneer ze een spanning dicht bij of iets boven 4,1 volt bereiken + "battery_voltage_events": [ + { + "timestamp": 1707825721, + "gateway_receive_time": "2024-02-13T12:02:01Z", + "device": 256, + "value": 4.098901271820068 + // Volledig opgeladen: Rond 4.2 volt. + // Nominale spanning: Ongeveer 3.7 volt. + // Kritiek laag: Minder dan 3.0 volt. + }, + { + "timestamp": 1707837460, + "gateway_receive_time": "2024-02-13T15:17:40Z", + "device": 322, + "value": 4.105006217956543 + } + ], + + + + + "devices": [ + { + "id": 256, + "serial_number": "0033889B1BAB1169", + "name": "firefly2_0051", + "label": "The Field", + "last_seen": 1707765066, + "last_battery_voltage": 4.09768009185791 + }, + { + "id": 322, + "serial_number": "006FE1FC316ED7D8", + "name": "firefly2_0111", + "label": "The Field", + "last_seen": 1707764966, + "last_battery_voltage": 4.107448101043701 + } + ], + + + + + + // Fotosyntese??? (zonlicht) + "par_events": [ + { + "timestamp": 1707844638, + "gateway_receive_time": "2024-02-13T17:17:18Z", + "device": 322, + "value": 0.0 + }, + { + "timestamp": 1707851099, + "gateway_receive_time": "2024-02-13T19:04:59Z", + "device": 256, + "value": 0.0 + } + ], + + + + + // Luchtvochtigheid + "relative_humidity_events": [ + { + "timestamp": 1707844638, + "gateway_receive_time": "2024-02-13T17:17:18Z", + "device": 322, + "value": 71.08984375 + }, + { + "timestamp": 1707851099, + "gateway_receive_time": "2024-02-13T19:04:59Z", + "device": 256, + "value": 66.7294921875 + } + ], + + + + + + // De "soil_electric_conductivity_events" gegevens wijzen op metingen van de elektrische geleidbaarheid (EC) van de bodem, een indicator van de hoeveelheid oplosbare zouten of voedingsstoffen in de bodem. EC wordt gemeten in Siemens per meter (S/m) of, voor bodemmetingen, vaak in milliSiemens per centimeter (mS/cm). Een hogere EC-waarde duidt op een hogere concentratie van opgeloste zouten, wat belangrijk is voor het bepalen van de voedingsstatus van de bodem en het beheren van de bemesting voor optimale plantengroei. + "soil_electric_conductivity_events": [ + { + "timestamp": 1707851215, + "gateway_receive_time": "2024-02-13T19:06:55Z", + "device": 322, + "value": 0.0 + } + ], + + + + + + // In de context van bodemmetingen, geeft deze waarde inzicht in het vochtgehalte van de bodem, omdat water een relatief hoge diëlektrische constante heeft in vergelijking met droge bodem of lucht. + "soil_relative_permittivity_events": [ + { + "timestamp": 1707851215, + "gateway_receive_time": "2024-02-13T19:06:55Z", + "device": 322, + "value": 1.52 + // Een waarde van 1.52 is relatief laag en suggereert dat de bodem droog kan zijn op het moment van meting. Ter referentie, de diëlektrische constante van lucht is ongeveer 1, terwijl water een diëlektrische constante heeft van ongeveer 80 bij kamertemperatuur. + } + ], + + + + //De "soil_temperature_events" gegevens bevatten informatie over de temperatuur van de bodem op een specifiek tijdstip. De waarde geeft de temperatuur van de bodem aan in graden Celsius (°C). + "soil_temperature_events": [ + { + "timestamp": 1707851215, + "gateway_receive_time": "2024-02-13T19:06:55Z", + "device": 322, + "value": 12.06 + } + ] + } + \ No newline at end of file diff --git a/script/__pycache__/db_connect.cpython-311.pyc b/script/__pycache__/db_connect.cpython-311.pyc index 9938e4f2221b414b508f484518cf17d2ae4a168b..89c2567a41e2281ad8e40dd3e036b7fd82fe77f6 100644 GIT binary patch delta 19 ZcmZ3>zLuS9IWI340}!-!Z{%9c3;-^`1g`)9 delta 19 ZcmZ3>zLuS9IWI340}w24*vPe*82~R;1jYaW diff --git a/script/battery_voltage_events.py b/script/battery_voltage_events.py index cc61544..ee63266 100644 --- a/script/battery_voltage_events.py +++ b/script/battery_voltage_events.py @@ -1,178 +1,415 @@ -import requests #** TYPE IN TERMINAL: "pip install requests" +# import requests #** TYPE IN TERMINAL: "pip install requests" +# import time +# import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python" + +# # Import python db_connect.py script +# from db_connect import database_connect + +# # Functie voor het aanmaken van gegevens in de database +# def create_data(url, access_token, repeat_count=5): +# for _ in range(repeat_count): +# try: +# headers = { +# "Authorization": f"Token {access_token}" +# } +# response = requests.get(url, headers=headers) +# response.raise_for_status() + +# data = response.json() + +# # print(f"Data from {url}:") +# print(data) +# insert_data(data) + +# except requests.exceptions.RequestException as e: +# print(f"Error fetching data from {url}: {e}") + +# print("Waiting for the next create action...") +# time.sleep(10) +# # time.sleep(300) + +# # Functie voor het invoegen van gegevens in de database +# def insert_data(data): +# mydb = database_connect() +# if mydb.is_connected(): +# mycursor = mydb.cursor() + +# insert_query = """ +# INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value) +# VALUES (%s, %s, %s, %s) +# """ + +# for record in data['results']: # Pas dit aan op basis van de werkelijke structuur van de JSON + +# timestamp = record.get('timestamp', '') +# gateway_receive_time = record.get('gateway_receive_time', '') +# device = record.get('device', '') +# value = record.get('value', '') + +# print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}") + +# # Voer de query uit +# mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value)) + +# # Bevestig de wijzigingen +# mydb.commit() + +# # Sluit cursor en verbinding +# mycursor.close() +# mydb.close() + +# # Functie voor het lezen van gegevens uit de database +# def read_data(url, access_token, repeat_count=5): +# for _ in range(repeat_count): +# try: +# headers = { +# "Authorization": f"Token {access_token}" +# } +# response = requests.get(url, headers=headers) +# response.raise_for_status() + +# data = response.json() +# print(f"Data from {url}:") +# print(data) + +# except requests.exceptions.RequestException as e: +# print(f"Error fetching data from {url}: {e}") + +# # Wacht een bepaalde tijd in secondes +# print("Waiting for the next read action...") +# time.sleep(300) + +# # Functie voor het bijwerken van gegevens in de database +# def update_data(record_id, new_value): +# try: +# mydb = database_connect() + +# if mydb.is_connected(): +# mycursor = mydb.cursor() + +# # Controleer of het record bestaat voordat je het bijwerkt +# mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,)) +# existing_record = mycursor.fetchone() + +# if not existing_record: +# print(f"Record with ID {record_id} not found. Update operation aborted.") +# return + +# # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database +# update_query = """ +# UPDATE goodgarden.battery_voltage_events +# SET value = %s +# WHERE id = %s +# """ + +# # Voer de query uit +# print(f"Executing update query: {update_query}") +# print(f"Updating record with ID {record_id} to new value: {new_value}") + +# mycursor.execute(update_query, (new_value, record_id)) # Provide the tuple with values here + +# # Bevestig de wijzigingen +# mydb.commit() + +# print(f"Update executed. Rowcount: {mycursor.rowcount}") + +# except mysql.connector.Error as update_err: +# print(f"Error updating data: {update_err}") +# finally: +# # Zorg ervoor dat je altijd de cursor en de databaseverbinding sluit +# if 'mycursor' in locals() and mycursor is not None: +# mycursor.close() +# if 'mydb' in locals() and mydb.is_connected(): +# mydb.close() + + +# # Functie voor het verwijderen van gegevens uit de database +# def delete_data(record_id): +# mydb = database_connect() +# if mydb.is_connected(): +# mycursor = mydb.cursor() + +# # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database +# delete_query = """ +# DELETE FROM goodgarden.battery_voltage_events +# WHERE id = %s +# """ + +# # Voer de query uit +# mycursor.execute(delete_query, (record_id,)) + +# # Bevestig de wijzigingen +# mydb.commit() + +# # Sluit cursor en verbinding +# mycursor.close() +# mydb.close() + +# print(f"Data with ID {record_id} deleted.") + +# if __name__ == "__main__": +# url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json" +# access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" + +# repeat_count = 10 + +# operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper() + +# # Maak gegevens aan +# if operation_choice == "C": +# create_data(url, access_token, repeat_count) + +# # Lees gegevens +# elif operation_choice == "R": +# read_data(url, access_token, repeat_count) + +# # Update gegevens +# elif operation_choice == "U": +# record_id = int(input("Enter record ID to update: ")) +# new_value = input("Enter new value: ") +# update_data(record_id, new_value) + +# # Verwijder gegevens +# elif operation_choice == "D": +# record_id = int(input("Enter record ID to delete: ")) +# delete_data(record_id) + +# else: +# print("Invalid operation choice. Please choose C, R, U, or D.") + +import mysql.connector +import requests +from datetime import datetime, timezone, timedelta import time -import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python" - -# Import python db_connect.py script -from db_connect import database_connect - + +# Functie om verbinding te maken met de database +def database_connect(): + return mysql.connector.connect( + host="localhost", + user="root", + password="", + database="goodgarden" + ) + +def calculate_timestamp(gateway_receive_time): + # Converteer de stringrepresentatie naar een datetime-object in UTC + datetime_obj_utc = datetime.strptime(gateway_receive_time, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc) + + # Voeg het tijdsverschil van 1 uur toe voor de Nederlandse tijdzone (UTC+1) + datetime_obj_nl = datetime_obj_utc + timedelta(hours=0) + + # Formateer het datetime-object als een leesbare datumstring + formatted_date = datetime_obj_nl.strftime("%Y-%m-%d %H:%M:%S") + return formatted_date + # Functie voor het aanmaken van gegevens in de database def create_data(url, access_token, repeat_count=5): for _ in range(repeat_count): try: - headers = { - "Authorization": f"Token {access_token}" - } + headers = {"Authorization": f"Token {access_token}"} response = requests.get(url, headers=headers) response.raise_for_status() - + data = response.json() - - # print(f"Data from {url}:") - print(data) - insert_data(data) - + print(f"Data from {url}:\n") + + # Check if data is a list (records directly under the root) + if isinstance(data, list): + records = data + elif isinstance(data, dict) and 'results' in data: + records = data['results'] + else: + print(f"Unexpected data format received: {data}") + continue + + for record in records: + # Now, record is assumed to be a dictionary + timestamp = record.get('timestamp', '') + gateway_receive_time = record.get('gateway_receive_time', '') + device = record.get('device', '') + value = record.get('value', '') + + # Voeg de timestamp-berekening toe + calculated_timestamp = calculate_timestamp(gateway_receive_time) + + print(f"\nInserted data: Timestamp: {calculated_timestamp}, Device: {device}, Battery Voltage: {value}V") + if float(value) < 3.0: + print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n") + # Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding + elif float(value) > 4.2: + print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n") + else: + print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n") + + # Insert data into the database + insert_data(record) + except requests.exceptions.RequestException as e: print(f"Error fetching data from {url}: {e}") - - print("Waiting for the next create action...") - time.sleep(10) - # time.sleep(300) - + + print("Waiting for the next create action...\n") + time.sleep(2) + # Functie voor het invoegen van gegevens in de database -def insert_data(data): +def insert_data(record): mydb = database_connect() if mydb.is_connected(): mycursor = mydb.cursor() - + + # Hier moet je de juiste kolomnamen en gegevensindeling aanpassen op basis van de API-respons insert_query = """ INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value) VALUES (%s, %s, %s, %s) """ - - for record in data['results']: # Pas dit aan op basis van de werkelijke structuur van de JSON - - timestamp = record.get('timestamp', '') - gateway_receive_time = record.get('gateway_receive_time', '') - device = record.get('device', '') - value = record.get('value', '') - - print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}") - - # Voer de query uit - mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value)) - + # Pas dit aan op basis van de werkelijke structuur van de JSON + timestamp = calculate_timestamp(record.get('gateway_receive_time', '')) + gateway_receive_time = record.get('gateway_receive_time', '') + device = record.get('device', '') + value = record.get('value', '') + + print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}\n\n") # Print de ingevoerde gegevens + + # Voer de query uit + mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value)) + # Bevestig de wijzigingen mydb.commit() - + # Sluit cursor en verbinding mycursor.close() mydb.close() - + + print("Data inserted into the database.") + # Functie voor het lezen van gegevens uit de database def read_data(url, access_token, repeat_count=5): for _ in range(repeat_count): try: - headers = { - "Authorization": f"Token {access_token}" - } + headers = {"Authorization": f"Token {access_token}"} response = requests.get(url, headers=headers) response.raise_for_status() - + data = response.json() - print(f"Data from {url}:") - print(data) - + print(f"Data from {url}:\n") + + for record in data['results']: + timestamp = record.get('timestamp', '') + device = record.get('device', '') + value = record.get('value', '') + print(f"Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n") + + if float(value) < 3.0: + print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n") + # Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding + elif float(value) > 4.2: + print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n") + else: + print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n") + except requests.exceptions.RequestException as e: print(f"Error fetching data from {url}: {e}") - - # Wacht een bepaalde tijd in secondes - print("Waiting for the next read action...") + + print("Waiting for the next read action...\n") time.sleep(300) - + # Functie voor het bijwerken van gegevens in de database -def update_data(record_id, new_value): +def update_data(record_id): try: mydb = database_connect() - + if mydb.is_connected(): mycursor = mydb.cursor() - + # Controleer of het record bestaat voordat je het bijwerkt mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,)) existing_record = mycursor.fetchone() - + if not existing_record: print(f"Record with ID {record_id} not found. Update operation aborted.") return - + + # Vraag de gebruiker om nieuwe waarden voor de andere velden + new_timestamp = input("Enter new timestamp: ") + new_gateway_receive_time = input("Enter new gateway_receive_time: ") + new_device = input("Enter new device: ") + new_value = input("Enter new value: ") + # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database update_query = """ UPDATE goodgarden.battery_voltage_events - SET value = %s + SET timestamp = %s, gateway_receive_time = %s, device = %s, value = %s WHERE id = %s """ - + # Voer de query uit print(f"Executing update query: {update_query}") - print(f"Updating record with ID {record_id} to new value: {new_value}") - - mycursor.execute(update_query, (new_value, record_id)) # Provide the tuple with values here - + print(f"Updating record with ID {record_id} to new values - timestamp: {new_timestamp}, gateway_receive_time: {new_gateway_receive_time}, device: {new_device}, value: {new_value}") + + mycursor.execute(update_query, (new_timestamp, new_gateway_receive_time, new_device, new_value, record_id)) + # Bevestig de wijzigingen mydb.commit() - + print(f"Update executed. Rowcount: {mycursor.rowcount}") - + except mysql.connector.Error as update_err: - print(f"Error updating data: {update_err}") + print(f"Error updating data: {update_err}") finally: # Zorg ervoor dat je altijd de cursor en de databaseverbinding sluit if 'mycursor' in locals() and mycursor is not None: mycursor.close() if 'mydb' in locals() and mydb.is_connected(): mydb.close() - - + # Functie voor het verwijderen van gegevens uit de database def delete_data(record_id): mydb = database_connect() if mydb.is_connected(): mycursor = mydb.cursor() - + # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database delete_query = """ DELETE FROM goodgarden.battery_voltage_events WHERE id = %s """ - + # Voer de query uit mycursor.execute(delete_query, (record_id,)) - + # Bevestig de wijzigingen mydb.commit() - + # Sluit cursor en verbinding mycursor.close() mydb.close() - + print(f"Data with ID {record_id} deleted.") - + +# Functie voor het aanmaken van gegevens in de database op basis van batterijspanningsinformatie if __name__ == "__main__": url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json" - access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" - + access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit door je werkelijke toegangstoken + + # Je kunt repeat_count wijzigen om te bepalen hoe vaak je de bewerking wilt herhalen repeat_count = 10 - + + # Keuze voor de bewerking operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper() - - # Maak gegevens aan + if operation_choice == "C": + # Maak gegevens aan create_data(url, access_token, repeat_count) - - # Lees gegevens elif operation_choice == "R": + # Lees gegevens read_data(url, access_token, repeat_count) - - # Update gegevens elif operation_choice == "U": + # Update gegevens record_id = int(input("Enter record ID to update: ")) - new_value = input("Enter new value: ") - update_data(record_id, new_value) - - # Verwijder gegevens + # Call the update_data function without additional arguments + update_data(record_id) elif operation_choice == "D": + # Verwijder gegevens record_id = int(input("Enter record ID to delete: ")) delete_data(record_id) - else: print("Invalid operation choice. Please choose C, R, U, or D.") \ No newline at end of file diff --git a/script/main.js b/script/main.js deleted file mode 100644 index 1717c8c..0000000 --- a/script/main.js +++ /dev/null @@ -1,27 +0,0 @@ -function openModal() -{ - const modal = document.getElementById("myModal"); - const button = document.getElementById("modalButton"); - const close = document.getElementsByClassName("close")[0]; - - // Toon de modal wanneer op de knop wordt geklikt - button.onclick = function() - { - modal.style.display = "block"; - } - - // Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt - close.onclick = function() - { - modal.style.display = "none"; - } - - // Sluit de modal wanneer buiten de modal wordt geklikt - window.onclick = function(event) - { - if (event.target == modal) - { - modal.style.display = "none"; - } - } -} \ No newline at end of file diff --git a/src/css/style.css b/src/css/style.css index d4e140e..8e26c88 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -1,40 +1,118 @@ /*default colors*/ @import url("https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap"); -/* The Main container and border*/ +h1, h2, h3, h4, h5 { + font-family: "Akaya Kanadaka", system-ui; + margin: 0; +} + +p, td { + font-family: "Afacad", sans-serif; +} + body { background-image: url("../images/achtergrond.png"); background-repeat: no-repeat; background-size: cover; - font-family: "Afacad", sans-serif; + background-position: center; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; } - -.mainContainer { - margin: 2rem; - height: 37rem; +body .mainContainer { + width: 85vw; + height: 38rem; background-color: rgba(255, 255, 255, 0.95); border-radius: 40px; padding: 2rem; } -.mainContainer .mainBorder { - padding: 1rem 0; +body .mainContainer .goodgarden-logo { + position: absolute; + width: 10vw; + left: 50%; + top: 2.5rem; + transform: translateX(-50%); +} +body .mainContainer .informatie-kas-main-container { + display: grid; + grid-template-columns: 5fr 7fr; +} +body .mainContainer .mainBorder { + padding: 1.25rem 1.5rem; height: 35rem; border: solid 5px rgb(171, 211, 174); border-radius: 40px; } -.mainContainer .mainBorder .content { +body .mainContainer .mainBorder .pagina-titel { + font-size: 2rem; + margin-left: 1.5rem; +} +body .mainContainer .mainBorder #sectie-1 { + display: flex; + flex-direction: column; + gap: 1rem; + padding: 0 2.5rem 0 1rem; + position: relative; +} +body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht { + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); + border-radius: 40px; + padding: 1rem; + margin-top: 1rem; +} +body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht { + border: solid 2px rgb(171, 211, 174); + border-radius: 35px; + font-size: 1.25rem; + padding: 0.5rem 1rem; +} +body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas { + width: 100%; +} +body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas .tr-informatie-kas { + display: flex; + justify-content: space-between; + text-align: left; +} +body .mainContainer .mainBorder #sectie-1 .grafiek { + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); + border-radius: 40px; + padding: 1rem; + position: relative; +} +body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox { + border: solid 2px rgb(171, 211, 174); + border-radius: 35px; + font-size: 1.25rem; + padding: 0 1rem 2.5rem; + height: 225px; +} +body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox h2 { + position: absolute; + left: 50%; + transform: translateX(-50%); +} +body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox canvas { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +body .mainContainer .mainBorder #sectie-1 .content { display: grid; grid-template-columns: 3fr 1fr 3fr; height: 100%; } -.mainContainer .mainBorder .content .kant-links { +body .mainContainer .mainBorder #sectie-1 .content .kant-links { grid-column: 1; } -.mainContainer .mainBorder .content .kant-links #planten { +body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten { width: 100%; border-collapse: collapse; } -.mainContainer .mainBorder .content .kant-links #planten td article { +body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article { height: 7rem; width: 10rem; padding: 0.6rem; @@ -48,35 +126,76 @@ body { border-radius: 40px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } -.mainContainer .mainBorder .content .kant-links #planten td article #toevoegen { +body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article #toevoegen { height: 5rem; width: 5rem; } -.mainContainer .mainBorder .content .kant-links #planten td article h2 { +body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article h2 { color: gray; } -.mainContainer .mainBorder .content .kant-links #planten td article:hover { +body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article:hover { background-color: lightgray; } -.mainContainer .mainBorder .content .kant-rechts { +body .mainContainer .mainBorder #sectie-1 .content .kant-rechts { grid-column: 3; - margin-right: 2rem; } -.mainContainer .mainBorder .content .kant-rechts #metingen { +body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen { border: solid 3px rgb(171, 211, 174); border-radius: 40px; } -.mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes { +body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen #main-waardes { display: flex; justify-content: space-evenly; padding: 0.5rem; padding-bottom: 0; width: 100%; } -.mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes table { +body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen #main-waardes table { display: flex; justify-content: space-around; } +body .mainContainer .mainBorder .grid-column-2 { + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); + border-radius: 40px; + padding: 1rem; + margin: 3.25rem 1rem 1.25rem 1rem; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child { + border: solid 2px rgb(171, 211, 174); + border-radius: 35px; + height: 100%; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table { + padding: 1.5rem 2rem; + display: flex; + flex-direction: column; + justify-content: space-around; + height: 90%; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table table tr td { + font-size: 1.05rem; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-1 tr td { + font-size: 1.25rem; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2 { + position: relative; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after, body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before { + content: ""; + position: absolute; + left: 0; + right: 0; + height: 1px; + width: 90%; + background: black; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after { + bottom: -20px; +} +body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before { + top: -20px; +} /* Divider */ .divider { @@ -97,7 +216,7 @@ body { top: 50%; transform: translate(-50%, -50%); background: white; - padding: 20px; + padding: 1.25rem; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); width: 30vw; height: auto; @@ -107,7 +226,7 @@ body { .modal .close { color: #aaa; float: right; - font-size: 28px; + font-size: 1.75rem; font-weight: bold; } .modal .close:hover, .modal .close:active { diff --git a/src/css/style.css.map b/src/css/style.css.map index ae223fa..d300b9e 100644 --- a/src/css/style.css.map +++ b/src/css/style.css.map @@ -1 +1 @@ -{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"AAAA,iBAAA;AAKQ,mFAAA;AACA,2GAAA;AAMR,iCAAA;AACA;EAEI,kDAAA;EACA,4BAAA;EACA,sBAAA;EACA,iCARQ;ACDZ;;ADYA;EAEI,YAAA;EACA,aAAA;EACA,2CAAA;EACA,mBAAA;EACA,aAAA;ACVJ;ADYI;EAEI,eAAA;EACA,aAAA;EACA,oCAAA;EACA,mBAAA;ACXR;ADaQ;EAEI,aAAA;EACA,kCAAA;EACA,YAAA;ACZZ;ADgBgB;EAEI,cAAA;ACfpB;ADiBoB;EAEI,WAAA;EACA,yBAAA;AChBxB;ADoB4B;EAEI,YAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,oCAAA;EACA,mBAAA;EACA,wCAAA;ACnBhC;ADqBgC;EAEI,YAAA;EACA,WAAA;ACpBpC;ADuBgC;EAEI,WAAA;ACtBpC;ADyBgC;EAEI,2BAAA;ACxBpC;ADgCgB;EAEI,cAAA;EACA,kBAAA;AC/BpB;ADiCoB;EAGI,oCAAA;EACA,mBAAA;ACjCxB;ADmCwB;EAEA,aAAA;EACA,6BAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;AClCxB;ADoC4B;EAEI,aAAA;EACA,6BAAA;ACnChC;;AD8CA,YAAA;AACA;EACI,aAAA;EACA,uBAAA;EACA,oCAAA;EACA,kBAAA;EACA,UAAA;EACA,cAAA;AC3CJ;;AD8CA,2BAAA;AAEA;EAEI,aAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,gCAAA;EACA,iBAAA;EACA,aAAA;EACA,wCAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;AC7CJ;AD+CI;EAEI,WAAA;EACA,YAAA;EACA,eAAA;EACA,iBAAA;AC9CR;ADgDQ;EAGI,YAAA;EACA,qBAAA;EACA,eAAA;AChDZ","file":"style.css"} \ No newline at end of file +{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file diff --git a/src/css/style.scss b/src/css/style.scss index 3655136..24bade7 100644 --- a/src/css/style.scss +++ b/src/css/style.scss @@ -7,122 +7,340 @@ $secondary-color: rgb(143, 188, 143); @import url('https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap'); $font-titels: "Akaya Kanadaka", system-ui; -; + $font-text: "Afacad", sans-serif; -/* The Main container and border*/ +@mixin flexbox +{ + display: flex; + justify-content: space-around; +} + +@mixin groene-border +{ + border: solid 2px $primary-color; +} + +@mixin box-shadow +{ + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); +} + +@mixin border-radius +{ + border-radius: 40px; +} + +@mixin inner-border-radius +{ + border-radius: 35px; +} + +h1, h2, h3, h4, h5 +{ + font-family: $font-titels; + margin: 0; +} + +p, td +{ + font-family: $font-text; +} + body { background-image: url("../images/achtergrond.png"); background-repeat: no-repeat; background-size: cover; - font-family: $font-text; -} + background-position: center; + // font-family: $font-text; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; -.mainContainer -{ - margin: 2rem; - height: 37rem; - background-color: rgb(255, 255, 255, 95%); - border-radius: 40px; - padding: 2rem; - - .mainBorder + .mainContainer { - padding: 1rem 0; - height: 35rem; - border: solid 5px $primary-color; + width: 85vw; + height: 38rem; + background-color: rgb(255, 255, 255, 95%); border-radius: 40px; + padding: 2rem; - .content + .goodgarden-logo + { + // z-index: inherit; + position: absolute; + width: 10vw; + left: 50%; + top: 2.5rem; + transform: translateX(-50%); + } + + .informatie-kas-main-container { display: grid; - grid-template-columns: 3fr 1fr 3fr; - height: 100%; - - .kant + grid-template-columns: 5fr 7fr; + } + + .mainBorder + { + padding: 1.25rem 1.5rem; + height: 35rem; + border: solid 5px $primary-color; + border-radius: 40px; + + .pagina-titel { - &-links + font-size: 2rem; + margin-left: 1.5rem; + } + + #sectie-1 + { + display: flex; + flex-direction: column; + gap: 1rem; + padding: 0 2.5rem 0 1rem; + position: relative; + + .parent-algemeen-overzicht { - grid-column: 1; + @include box-shadow; + @include border-radius; + padding: 1rem; + margin-top: 1rem; - #planten + + .algemeen-overzicht { - width: 100%; - border-collapse: collapse; + @include groene-border; + @include inner-border-radius; + font-size: 1.25rem; + padding: .5rem 1rem; + // background-color: red; - td + .table-informatie-kas { - article + width: 100%; + + .tr-informatie-kas { - height: 7rem; - width: 10rem; - padding: .6rem; - margin: .1rem; - margin-left: 2rem; display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border: solid 3px $primary-color; - border-radius: 40px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - - #toevoegen - { - height: 5rem; - width: 5rem; - } - - h2 - { - color: gray; - } - - &:hover - { - background-color: lightgray; - } - - + justify-content: space-between; + text-align: left; } + + + } + } + } + + .grafiek + { + @include box-shadow; + @include border-radius; + padding: 1rem; + position: relative; + + .grafiek-innerbox + { + @include groene-border; + @include inner-border-radius; + font-size: 1.25rem; + padding: 0 1rem 2.5rem; + height: 225px; + // position: relative; + + h2 + { + position: absolute; + left: 50%; + transform: translateX(-50%); + } + + canvas + { + // Zorgt ervoor dat de grafiek precies in eht midden komt + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } } } - &-rechts + + .content { - grid-column: 3; - margin-right: 2rem; - - #metingen + display: grid; + grid-template-columns: 3fr 1fr 3fr; + height: 100%; + + .kant { - - border: solid 3px $primary-color; - border-radius: 40px; - - #main-waardes + &-links { - display: flex; - justify-content: space-evenly; - padding: .5rem; - padding-bottom: 0; - width: 100%; + grid-column: 1; - table + #planten { + width: 100%; + border-collapse: collapse; + + td + { + article + { + height: 7rem; + width: 10rem; + padding: .6rem; + margin: .1rem; + margin-left: 2rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border: solid 3px $primary-color; + border-radius: 40px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + + #toevoegen + { + height: 5rem; + width: 5rem; + } + + h2 + { + color: gray; + } + + &:hover + { + background-color: lightgray; + } + + + } + } + } + } + + &-rechts + { + grid-column: 3; + // margin-right: 2rem; + + #metingen + { + + border: solid 3px $primary-color; + border-radius: 40px; + + #main-waardes + { display: flex; - justify-content: space-around; - // width: 100%; + justify-content: space-evenly; + padding: .5rem; + padding-bottom: 0; + width: 100%; + + table + { + display: flex; + justify-content: space-around; + // width: 100%; + } + } } } } } } + + .grid-column-2 + { + @include box-shadow; + @include border-radius; + padding: 1rem; + margin: 3.25rem 1rem 1.25rem 1rem; + + .grid-2-child + { + @include groene-border; + @include inner-border-radius; + height: 100%; + + + .parent-table + { + padding: 1.5rem 2rem; + display: flex; + flex-direction: column; + // align-items: stretch; + // gap: 2.5rem; + justify-content: space-around; + height: 90%; + + table + { + tr + { + td + { + font-size: 1.05rem; + } + } + } + + .kas-table-1 + { + tr + { + td + { + font-size: 1.25rem; + } + } + } + + .kas-table-2 + { + position: relative; + + &::after, + &::before + { + content: ""; + position: absolute; + left: 0; + right: 0; + height: 1px; + width: 90%; + background: black; + } + + &::after + { + bottom: -20px; + } + + &::before + { + top: -20px; + } + } + + } + } + } + } - } + } } -/* Divider */ + /* Divider */ .divider { display: flex; justify-content: center; @@ -143,7 +361,7 @@ body top: 50%; transform: translate(-50%, -50%); background: white; - padding: 20px; + padding: 1.25rem; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); width: 30vw; height: auto; @@ -154,7 +372,7 @@ body { color: #aaa; float: right; - font-size: 28px; + font-size: 1.75rem; font-weight: bold; &:hover, diff --git a/src/images/logo.png b/src/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b46eaa6a436948490679a0f787dec36612c77a3d GIT binary patch literal 20646 zcmdR#W=#=hm=?3Wri9u=UZehqlx;uuDmagac`!Ajs zFudRc`|Pv!UTa;~cSWgwlzoLshWX!r|GkozlT!chzZaCi&x7cw!1tMBUJc*_!$}U} z`rm)-bpO6yctOD)|NW<`BQGVc>6LTT0db<3%UZh?e%Dmi+v%wP!RdRmd?AwpVQGhZ z({bm@(b7@lcbI(y-JgKW%!tf)zNT-5cA=D9TpqthL*I#*B*2bV+x-1cjymzB)ry;A zbmi1GUnf!5B>jrl<-W+_!GWLz(|;)Z@RI4vtp*c1AxrtknV|=SXXg>R88#Oe*9a1L zlnklZb!(ZtE2amx>`OsZTj+o+IntE=c^X4an4~g9H0@_;rPa6P%5GQuO-O>;uR;QX zI=`DglMw^xzjcukJJFG+SjNo0svEy=Z`t>)+57biBnw{=BFLmhjm0G?iVE$;WeMZP ztdx9DR`hDv%1&>y`L%*|EEkE{Zv`{VYM!0Nyd!t^(2NId^q+R*Beh=cGkW7nex?&q zQQiZ7-dmwuU%1GilC>sjwdeF{_Q}sk;lXlD_3;55`ZL!Y@;tY76GF9GN`EtYjNQ%( zx!)n{q)9^{(doLYUN&b@((f2Qr{x@on09|_U{rl!ILVNB%82s8Iu3KD_&<{5Kz-)= z*$Y-|tk5k10gQ+hdq+6r-@o=g7IZ&~#BfI^aa$E)W>qm+;$!6CW|_Wzq%S$m(0wDJ z4w67m8bWSEG;c>szxxbveK>e0V=Zl7K!S_Pv0=Kvhs&miDTap`fM=f;XThB>5FcWp zcvTVboe5aecR8`HfNA7{1U|Bm@COAy7g0l<2yp#}eEkF@iO~}>eRMT+y=@pHV{T03 zeGPWc;~JJ^+(YCwc*;(OIrP6*>I%3ov7)}xo}{#&WFX@*`sia~1$~g~+5TPPYmXd+ ziLM#1incd|C;d|GG!C8StGemJ8};Z1L=^I`jNk-5-DAR>DlU}-3y2p+`U0x&RR4IM3Pp7{V zOj{H53G43kr^HH6*UeU)hfm*n{CM*=w%^tyqbzP(>U0iMV^GE9+T>aPaF{YV$S+#1t`_kzSl2ozcVQ! zE)MfEqn44i8d5{WBQc2+df9tWTXO0|CImg`0DY6V>O8F9rhNwEt;7f{%!lt7uDz0mJShlX`lB4-q{L7sp zNj~AA40Bi=Ba}0FVUp8gwPaa8j~H|39S+ad`GMx#cNw{${7Z~Jr@V+Jw@4`&soa?o zLNwHZ-A~v5A%*l|Cw$&NZt0T}is42Dqn|xeuWcF+*J^wr#2>*IXbd?N(nY5TK?lq(=B zO83KzEF&WN{P<rwce#`1e6S3p(K+gCqME+g1KS#4@xm`Cp6Cxfc$Uus;&@c-O-Ry(; z_5gll(s=s~v<>s|yd5cTX~DL|E9HQKUXnh9sI1awkvb6gRNt9`e5tY7 z(=p}vNu1r_aCdY;5qp_@EPGHX?;A=W+|P`Wtx!(0o-ZZc+itBrJdV=dt-_`dTKbw9 zMQ|<9fig2K#VfCGUMFkG|GIg?Kb>RTV8ch7W0>$kAQ1=gL;>eWcGcc9itWJH0r0uS&cM>q_Lf}nMu|}rJt6UOV`o}w>g^RkCt0)W^YH5=tUCpI@|nwZyDDN zJNtLwZ)ISU0`a*gGqs$w7xb9#TyR-H7)PvR3oY(!db8DqX6`&Pw!zeX4z$J+A80qY z`0_T?E%_0hhuaVR>lH+rfJtF(bKif~hv#eInfUxhtgs?*SJ z8Z55Q*$zZ;RT1ZN964SUVBSmZL5M{o=f!@FDtr6z$D&hYZ73DK#Dr9}rNkG`q7@s& ziH(tJs%49`#Mg8&e02%z4Wp_J#4-?z#)&dJhsx=yjoi<@Gx;Ljfm=u{=ujZpRAZQ_ za>&Bpri^vIu_ZTGPk6r5nK#}ZFI2JZCj?!bHZx;cO~TLT>}2%9Zig@@cA;W?zq;D# zygWv~Z8e4}oL;1w9+YLue1rO_e!9+IL-_vM4qDoo#kof9*P^=j#wvDqNzs7fd6PE1 z+MVY;w-_mgz6}#}==Oy>FOl6JD~l6Wj-TFrES!o>VKyKkZ>a#iS41pTt9x7PXLb7R zJ~2^I6jge6X=BNpUrx~G(~2ugJyYmdPf0Qw0$9k|?fLImg4=G7@*DZ~luX>e% zkgqxV(a@{@4x7j%V4=a^Rrut{H!5x5;0H~+t`Gm~IahE0v9|H*Jsox0Vsk6=*bv!q zm-CU4*!b^>-ZZ)&t<2CR!w%;w936MjPL4kx9Wa7MXtC2*lN2$7EFi@^g7BQS;hrL+ zDIQLAsW*p{omwK1G{Xl(FLkpIy*y7o8m`WYLx$=VfE zYq%I`pMLBz;%*1LD?ztS^49@ZMB+c34J-}U>WmGfIyuf%)hvHK+U@LlDqQ1TSg4{_1{nI&KD%T{C|GNiy7AwSaLt zc%tULzb7h&BoW(f@hHbqzP-cOt@%)eixHKsZ_me^U1yJTR<>3BIKfG;D~W3_(;J|4 z&=0zA@^hck@&g|Pk*;N!6dCjU)i3|Lr)&-BTI zdK%gEVNr#w>c;g0*N=YtFGI-&U{kT*>tf?9o1NPdI)h9cmJei!hCzAaSphG`-7^Nw zZ%?N(XS0+qpL%W?p?4DPrMq(m8{kBa-$l%+*pVrM;6a6xy)T7IW zxj!}X{$A9P)Kf$%4VBfhh}P^KBes#5t+ii5XD*_YlL$MxXR`l|I!T&8QG>y~@MWn3 z>F-}0=PeJg+1A3K&)E1%-6>dlLbxY=&Ctx;E_m&s$JS22jn?K-uWZhBTK|Rf%{fOL z``P7#{?FnMaxp3ifqmm*V*PtMsB`{4eN{irlhmo{-_Om}+M5Ye9x1=)*GxVY8CHK= zTFmc#owJy<8RYUDflRM!D9z}D8y>4-K4|VAF3Z?Fzat`af4 zwqms0n6`F15m3gW5#zHdBaA86dDocS^|Z7FtlC6)R>P=b;LD_q3#ne7!fEfo3~-m3 zNh^w$rpQ7j8B(Jw$ayWSMOre~Qbd~>5$xa!rdq~{Mb1R{SNKh=vibgg8!W86>E_sl zct4gZmmtFuf02IxH#9nYQ6b=7d(C)hzylXLCn2eeU-`b;qdiK%=aR0DkV35=_f`rS zEg^RcxI{jSB=eZ;ZK$rsCm&&aX+zT z^{FKoJiI=5!{dB~W{~#0u zn|qlD|0_6lZa+G#9@FKXooIK189J#{HMHR1$CYcy+C-WPz28B)|7SVo3Ec~ck(l{S z(q(4FsKGxe6ap@3Mie5_LWkgnb!72K+~9#$77sf}pDl-DNlPc$QoPR+P``*azZE#J zJ{d-Zj+$%Aql>d78ec{uv+CJ++m3$%4r8i@kzsM0<5xGn2!xPprvMhwES(vF@q2XJ zo~B2f6w-OiB7kb`Q77+6^fBs*jgCdP@cVTy~sD))Fjp6SUh^oFu6Tl_xN)n z4oyN+?5oMtvW~Ku0Yi01dlZ(oqwDrI|8lcvH&7GB+k>_K>uI!~%+%jTBMi2DaL&u> zmB}z`QL~$KO;bLhU_EIU_WDZ!e!d}G$Vs>$^u)8r26n_iZQyFm)(a7rTj5YX&L0^4 z#E)f8PiBUGaj7AJK0Jcoet+lTak4xZHQu!|y}-Ks=k0&Vjydlm=9<`IN?L93F+6*C z(!wGaBmEv%+@BsS^SMOwyvtfb_Kr`y*_Zel>P}{ey-fO8K#EGbFR+LzS(iVo2P}-m zvz0HjIureign7i8b4^{g-E4x-pV2eX0~^-TGLUbYWZ(dLz1sXDzZ`SApZK@Ych{7H zx39p$PDvG1BB={x;h0G6_4aJ{hTcKMd{w=TpkSvnI^+Qo%~him1p&X4-1LPScQzQ@ z4^}g^#`PY!{}!boq5~upbD!O9C7+tZ9=}#?Io;~w1U@#sBOy~Z1NR$%54K5umNi5@ z`Zk^~j%3R*>IYNX{A|o1eDG0=q3@|WI{f!2@qx}kbnnKeW?a#h8ezUmqT0;;&N zEZ7dt5%mM!$5g2%2)tXOuCtCgNLNWJQbgBo8>@kw?N#U7%2ycU7F*$3Se?lchx5w^ zEhB3W=K`XS*M;a46x!d#ag$E#VH~ zZ)mK!Y>tLKY}E-z#6^(}Hu23So!Tiy&CM*}LYXXi7W&_g@Yx9iE4{(d#s2R=i z7hqf)zX^*gzkSliuU8uttj4<9z8AWH3v)&fo@^r*!B}b} zp;W#g?h@!7JAR=L%S^`6W)33^eyr~7##vpEc9nb;fD0FPq%3sZInhfZ$Jm*5a1W1OOTan}BD-pYqr9K-Ks zT0H23w@~l1F)2R8me3ntqXj8FThYMFiz5Bb)sUfxO-l*uvFKeNo3ar_U1Jp716+)s zZI8-{ay~I4#hZ!Tn63d{+pL{!E?6*jc!C-=I$_n;Y2UTS#dYALGSCqY-YP0Om29HX zsAFCoFOGumhJ@WJ>}b(vVriU0dXkdj4nJ*=(C-GuhPfmVSaxm|jdw~!wuC)OLK9ya zF4W`&J}jNoIJjdi?j^D9d*K(TGuiLy%=`l13WD6pj4kM@chPMA!U zKmI8L22RM_VtIGdtWchHMo`K7lug|V?GkI z!5zQZ3Y!hjz=tg>$89m>22r=7MvzpB7zWSmQ0&&y#q~*OoYq;fzXQdxnuE!2U=1FV~|aqUBy@ z;<7JjRhlDNU6>1&@&!>-L3BngN1r(`#@X(8Qzq#}vWZ+g26TRNV!^6jSB%KfVATru!j8#NED&1a2^X zA2;k#By`NRrp(;=7wnEFD{mX}bxMLYy04LdHu$!Z>KIB#C6ib2jyrtpP&-+v`C?Ua zp_cy9Q%2D34~5B(nBxcnhDBz>)y_1k_O=+QUiOyZ8%t#p7K(o>>H75~x^&Kfa_hmY zJEdc!tnBVRbS)J;$nE>V?W)RGrP<-^Q=bH&dxS`u`MEq$Eaf(0C-W;T#c{(c3}$*&0_yV{ON3rRIZ^fJN?HoYmTD0*@2JCo(?Lb~6#OJCIY^uS zYd}gd9$4$Y7xh)a2f63`P0mY`A9BrnYk~I`eD3uH^;zvE({oztkVJ`e-J?E9bb^K^ zFY{S{a7MDE2hCU7=uf$Vo~h;hJ~34zQ6Cq-q&HS=taRuVy&PjOP7-5{{OTpSL<#Az#&9D#h1r;nSYz+hEY9$gsEa6G~N5@apPBBYyHc=7=&EG5aeZ_Cf+ukE*+0lAi( z@zyK8fQODbCPnWAft@_Gdah6w^J{oqd)o_!`6 zPvqIBs;dD>-0tvSvbHY^U`M>BR(-*$cX+eWR=wWx#+_HI!p>TU`{f@wgxbVH*O~UO zy1j|>3Oos8WD2lrP{Bl0VPy@crlwYjm+uLmZnjN6d7Yn7N_1_?b=Td?Y@tOfqZtVc z3mZfKm+@wgdO>;+^lx6`7zhm~}SxxG%3dYQyG?RwdvZkG0{q zjOY@;Hs1EMwVjGs)?Rk|QA5p5X-Blz^v%4?bEFaj`lvPS44Z-<+l;zvx09SQ;O`V{ z_2)jHRE;ekbSQd5Fe}r;p=RUsLJHENhRPU%C3Z`@^ZSmZWRx7OKKiy}WwWSPCkrw^ z-gGIn0}1C#W%j3{u?L6s-FZGs4t<2FrRRH3X&pfYTNZVUfSs}Q(o$w4?vcoU3(F!e zv$pvmQwlxHMMugz5^Ze{mYA!XgqT9owvT@^A=p>x)3IXCcdRO%?S_2s4U4O)4qCbt z#bVX7ZtF)Y+c^+zBTXa}Z&`&nWSRT(()sI5ln-lFY?;y|UhJrw$jEYcKfR(#nU;07 z&*p#|n5-L4vwAiXl6`m7ZAzllTjaXCy+i@MiMMyHYs+^fuG%7mJW?Uk*ef@*-)*8M z$s<~#-^0_OpBu>g{uXL{BjhVcR_Dwca&D=Ma1+wjRQtw-3TyNZTvMb^cCgz4ajK)g zgzmR5z*c%D3e)<--g32h*codbPDa6hiD2;5?V&R((7GK9@#Px$FCTa4xiz|xur%5` zSX$^A4Ds{n#_Kfpcl6-F^G-lM5F%t6Am$coER;L@twaJxLadXJu;$a^USAess+e10 zup4wpuXP)%;jx-^*Zi+YjXvK_`k@GkUnZs4@p$ei^a~x3`gFDH&Z@Jp`18*QMIQfW z5dxM9o2+u(i#B8soO`5}9?+Kd_sOLqH-C*^`#0L@kCmm}c|jV`<(P+d{MZfJl;Jor zE?%ewg#}g7_SuVxwSTXiqBF_EG>m1YOca+szTkAb%&Q>)DF|!8JoZRQwg--$Xe%i~ zz9!jceNiz~7c0ljdF&Vi9;YRI{zwyPWV+XUSK-UuIFF5k`T^5e-YzJF$Y~z@Y zRgA1{-%+P8uzu#Up=9-}-Ef=5tTL`&pWqS%xs2h!(Z-HfB6MG6f|fEV*0{Ug2fK5{ zLP#(*1j|{yuZNqEC8YGs=CP(+VM$37XYWP*L*yVi1d})tz<)Cvi%vr{%2+z%Sy}8I zx5&bAq7_i5Wi&J(0|O2Ap=Y&T5N_Lxjkt!Bm=4=D0vXZ@+L+7TU<>KOsTI%aAA=FI zS?0YKT0qOU-Rnq3OduE}3BBDlMVR;9FBr#)W6Ent63q}<)NoiX;2j|uxmnpf58(VF zKU^htwdR6gr!kPer9|u=Jrzpq=#tx%4O?65ljTmQu`c9{|CVe0VZ&~QT?IHDD+(Kk2a;hcl#Z`r3s}*=auXuP%|qmq@|*Xd&OH{Z4;IIH6|37^F4QumypJ^ z^8lbbPSmtooL^^HNIa3HnTB&mE^y|XSkWN2`T zz8#;Jdd(Zb=2t#E0%*VRzDQGrAX3}v&wYNnc)@bhjFT_=GX!Q3#>4VVg{~=IF{6_Ud?}`}xp|=IW-e!TRjqzMmMX#kIvvG{-Az z_4hi&k-O$gc(tFvam9aRROZ^miYxTo@!AVC66uwW#P5mxgyv-L=``|Id(tw~3$A_l zTz5#c2Vq-aBF;u3Vd_Pcg}got^2bEv z?F(Je>=r$AkXmpdfrTZ>L1WRv&gu;jtKl5j)1$3_Q90> zpOBD7!82Cs7zt@5Li%&e-WxTbw!cznG{1Fug!qDbM#c0UKIkTC*1qS%BD@uC6%%=2 zh=|Y6otlMVg{fyLQ;t3KoII1I?pVYmYg!jhrmN#x(jccXv^X8{JzoQ=QsYsIou29% z&V0QC(esVx>i340MmN_f#tS!djOf>ik^;#?Z(8WNolGn+V|Wpf2HR5t4kA4B<=*K!ndY*Fm_b-fvr1i8KE!#E*@@iB!|FJaCK z@IYFrQhk}JiwaoDD>dTdLNwFJv;injkm>L*c0%E)tdR`b)pbmK=}Zhj}Ue zrn(=$jQmHj(YfYCa#5^ISYq0n&}qBk`GmUOUE{Z*fZpxi&A?1ADNZv6{v=2;i#n#e z(GyQ_m+qOx^<2m3rS*&W7UvxL)TR(~bB%`!vRB)QRCwFj(}aGj0Lj<9`!*}2ppcz! z(m$GHdd-sWVvKh-oBKV=Zf%?6$9W?BoxuYh5o-$j^;|$*Jm-&X6 zX5_;rEYp&`zrW7Y(m?u6Nn_&k{cKczNjwW+%*Y#RBBO-8v z-55utTIV&RGN8enE)Ka!Smy7d9rZZ%X!GOam|Y6!fwN9XkhwfLq^ILxC0Pa%mu86? zZ2M~&_65)qFCTlWxkk{L8RV<~?Aufu8eQiJIByXokHBFr1I8FmAadyEH4WhQJBxb1 z(t%{B+xF7nC5n!MZLcaG`+B%@SnOhd_kS4UeaZp}CHLSL_Sg_3Y5r{dL7(3P+X!WL z9kE#433%&>vKthaz5;o6>WyD(-iTjhJfGUx+Hj)`yZdThgCJulb@oMzuOo6zKtB(a z_8G}=GQ0bXg_lZdqKH8cd~_Tug*F-M%~2r{zFlcdjVtb#S*Ifz{w2PuU$xtXb9gQB zKqqdO6}t@^>r)ETRJyn+s>Wkc<|77m&4MI;`p>YxNLa9Q6fHna&ebUU*0@V)CP z)Q+!7;7tNoJ>Q)3@uq#sY@N+E!#S^Klg}}JC`%X8;HJJ8qvM9%(r@RPEEUhLb1h8Ezp3w#g>)x+lxf3Ni zjZPxoh5f>jtXkgd8Ak!t>ap)axTTe-ge%`UzU6-B5MVkWGjQsPr8iaFP*N)*uV-ej zR;Xc>=YA=J^XM7=^GHC=seo(1ST6|>rZOeVKlQAi3V5Q*Zt0g>44X;Ik}I=!2w0#f zSPzdR0YMPV%)SO}dTZ;+#ELJ@yEnNgunZ=SB4{ZpjF}zNLVjrdH^d{VDxnV_uuI8f)~qN$ZS|+YTb$n zZ^Q>@$o*sEEPg6{^S2(YTYr-0+=^v^z7Z8<#U`{LyR5Ia`-Ky&w<;Jv257Fom%#78 z^O16?02Ri0Eiy;v&(};2ilo-^4%aJNy)%0AAMK7n{3S%WMcS{^qz0)qvlb69KQ-`D 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 Document - - + +
@@ -16,10 +16,12 @@
+

Tomaat

+
diff --git a/src/js/main.js b/src/js/main.js new file mode 100644 index 0000000..4ce0a61 --- /dev/null +++ b/src/js/main.js @@ -0,0 +1,124 @@ +const { ipcRenderer } = require("electron"); + +document.addEventListener('DOMContentLoaded', () => +{ + // Stuur een bericht naar de main process om het Python script uit te voeren +// In je renderer.js (geladen met defer in je HTML) + ipcRenderer.send('request-update-temp', ['some', 'arguments']); + + ipcRenderer.on('update-temp-result', (event, newTemperature) => { + if (newTemperature === 'error') { + console.error('Er is een fout opgetreden bij het ophalen van de nieuwe temperatuur'); + } else { + document.getElementById('bodem-temperatuur').textContent = newTemperature; + } + }); + +}); + +// function dataTablePython() +// { +// document.getElementById("") +// } + +function openModal() +{ + const modal = document.getElementById("myModal"); + const button = document.getElementById("modalButton"); + const close = document.getElementsByClassName("close")[0]; + + // Toon de modal wanneer op de knop wordt geklikt + button.onclick = function() + { + modal.style.display = "block"; + } + + // Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt + close.onclick = function() + { + modal.style.display = "none"; + } + + // Sluit de modal wanneer buiten de modal wordt geklikt + window.onclick = function(event) + { + if (event.target == modal) + { + modal.style.display = "none"; + } + } +} + +/** + * --- Functie om de grafiek te tekenen. Enigste belangrijke is de eerste 2 "const" arrays "data" & "xLabels". + */ +function drawLineChart() +{ + /*Dit is de data die getoond wordt als "punt" op de grafiek. 20 = y20 / x20, 50 = y50 / x50 enzovoort... De array "data" & "xLabels" moeten beide evenveel array items hebben!!*/ + const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0]; + const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12]; + + // Define Y-axis labels here. The number of labels should match your scale. + const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/ + + const canvas = document.getElementById("myCanvas"); + const ctx = canvas.getContext("2d"); + + ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas + + const padding = 35; // Increased padding for Y labels + const graphWidth = canvas.width - padding * 2; + const graphHeight = canvas.height - padding * 2; + + // Draw the axes + ctx.beginPath(); + ctx.moveTo(padding, padding); + ctx.lineTo(padding, canvas.height - padding); + ctx.lineTo(canvas.width - padding, canvas.height - padding); + ctx.stroke(); + + // Set the color of the line + ctx.strokeStyle = "#008000"; // This sets the line color to green + + const xIncrement = graphWidth / (xLabels.length - 1); + const yIncrement = graphHeight / (yLabels.length - 1); // Assuming you have labels for each increment + + // Plot the data + ctx.beginPath(); + ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight); + + for (let i = 1; i < data.length; i++) + { + const xPos = padding + i * xIncrement; + const yPos = canvas.height - padding - (data[i] / 100) * graphHeight; + ctx.lineTo(xPos, yPos); + } + ctx.stroke(); // Apply the stroke to the line + + // Draw Y labels + ctx.fillStyle = "black"; + ctx.textAlign = "right"; // Align text to the right + ctx.textBaseline = "middle"; // Center vertically + + for (let i = 0; i < yLabels.length; i++) + { + if (yLabels[i] !== "") + { + const yPos = canvas.height - padding - i * yIncrement; + ctx.fillText(yLabels[i], padding - 10, yPos); + } + } + + // Draw X labels + ctx.textAlign = "center"; // Center horizontally for X labels + for (let i = 0; i < xLabels.length; i++) + { + if (xLabels[i] !== "") + { + const xPos = padding + i * xIncrement; + ctx.fillText(xLabels[i], xPos, canvas.height - padding + 20); + } + } +} + +drawLineChart(); \ No newline at end of file diff --git a/src/kas_informatie.html b/src/kas_informatie.html index e23678f..fad704a 100644 --- a/src/kas_informatie.html +++ b/src/kas_informatie.html @@ -1,25 +1,111 @@ - - - + + + + + + Informatie Kas - - -
+ + +
+
+ +
+
-
- +

Informatie Kas

+
+
+
+ + + + + + + + + + + + + + + + + +
Dagen tot Oogst12
Dagen in Kas2
Tevredenheid80%
Aandachtspunten1
+
-
-
-
- +
+
+

Zonlicht

+ +
+
+
+
+
+
+ + + + + + + + + + + + + +
Aantal geplant:2
Succesvolle Oogst:2
Gefaalde Oogst:2
+ + + + + + + + + + + + + + + + + +
Warmste Maand:n.v.t.
koudste Maand:December
Gemiddelde Bodemtemp.:2˚C
Gemiddelde Uren Zonlicht:2u
+ + + + + + + + + + + + + + + + + +
Laatste Irrigatie:2u
Aankomende Irrigatie:2u
Laatste Bemesting2d
Aankomende Bemesting:2w
+
+
+
+ -
- -
- - \ No newline at end of file + + diff --git a/src/py/calculate.py b/src/py/calculate.py new file mode 100644 index 0000000..5a4f5f5 --- /dev/null +++ b/src/py/calculate.py @@ -0,0 +1,7 @@ +# In calculate.py + +# Doe je berekeningen hier, vervang 42 door je berekende waarde +calculated_value = 42 + +# Print het resultaat, dat zal worden gelezen door de PythonShell.run callback +print(calculated_value)