Create IndexDB and add NewEntryWindow with func && Show Data of month in Aktivitäten

sortierung
Samuel Zielke 1 year ago
parent 07c88d9164
commit b7755949c8

@ -0,0 +1,204 @@
// IndexedDB Funktionen
const dbName = 'myDB';
const dbVersion = 1;
let db;
// IndexedDB initialisieren
function initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, dbVersion);
request.onupgradeneeded = function (event) {
db = event.target.result;
const store = db.createObjectStore('hours', {
keyPath: 'id',
autoIncrement: true,
});
// Spalten definieren
store.createIndex('createdate', 'createdate', { unique: false });
store.createIndex('date', 'date', { unique: false });
store.createIndex('duration', 'duration', { unique: false });
store.createIndex('type', 'type', { unique: false });
store.createIndex('status', 'status', { unique: false });
store.createIndex('sondertext', 'sondertext', { unique: false });
};
request.onsuccess = function (event) {
db = event.target.result;
resolve(db);
};
request.onerror = function (event) {
console.error('IndexedDB Fehler:', event.target.errorCode);
reject(event.target.errorCode);
};
});
}
// Neuer Eintrag in die IndexedDB
function addEntry(data) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readwrite');
const store = transaction.objectStore('hours');
data.createdate = new Date();
const request = store.add(data);
request.onsuccess = function () {
resolve(request.result);
};
request.onerror = function (event) {
reject('Fehler beim Hinzufügen des Eintrags:', event.target.error);
};
});
}
// Eintrag aktualisieren
function updateEntry(id, updatedData) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readwrite');
const store = transaction.objectStore('hours');
const getRequest = store.get(id);
getRequest.onsuccess = function (event) {
const data = event.target.result;
Object.assign(data, updatedData);
data.createdate = new Date(); // Aktualisiere das Änderungsdatum
const updateRequest = store.put(data);
updateRequest.onsuccess = function () {
resolve(data);
};
updateRequest.onerror = function (event) {
reject('Fehler beim Aktualisieren des Eintrags:', event.target.error);
};
};
getRequest.onerror = function (event) {
reject('Fehler beim Abrufen des Eintrags:', event.target.error);
};
});
}
// Eintrag löschen
function deleteEntry(id) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readwrite');
const store = transaction.objectStore('hours');
const request = store.delete(id);
request.onsuccess = function () {
resolve(`Eintrag mit ID ${id} gelöscht.`);
};
request.onerror = function (event) {
reject('Fehler beim Löschen des Eintrags:', event.target.error);
};
});
}
// Einträge abrufen
function getAllEntries() {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readonly');
const store = transaction.objectStore('hours');
const request = store.getAll();
request.onsuccess = function () {
resolve(request.result);
};
request.onerror = function (event) {
reject('Fehler beim Abrufen der Einträge:', event.target.error);
};
});
}
// Einträge nach Monat und/oder Jahr filtern
function filterEntriesByMonthYear(month, year) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readonly');
const store = transaction.objectStore('hours');
const request = store.getAll();
request.onsuccess = function () {
const allEntries = request.result;
// Filter nach Monat und Jahr
const filteredEntries = allEntries.filter(entry => {
const entryDate = new Date(entry.date); // Konvertiere das date-Feld in ein Date-Objekt
const matchesMonth = month ? entryDate.getMonth() + 1 === month : true; // +1 da getMonth() 0-basiert ist
const matchesYear = year ? entryDate.getFullYear() === year : true;
return matchesMonth && matchesYear;
});
resolve(filteredEntries);
};
request.onerror = function (event) {
reject('Fehler beim Abrufen der Einträge:', event.target.error);
};
});
}
// Neuen Eintrag verschlüsselt speichern
async function addEncryptedEntry(data) {
const key = await generateKey();
const { iv, encryptedData } = await encryptData(key, JSON.stringify(data));
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readwrite');
const store = transaction.objectStore('hours');
const request = store.add({
iv: Array.from(iv), // IV muss auch gespeichert werden
encryptedData: Array.from(new Uint8Array(encryptedData)), // Encrypted data als Uint8Array speichern
});
request.onsuccess = function () {
resolve(request.result);
};
request.onerror = function (event) {
reject('Fehler beim Hinzufügen des verschlüsselten Eintrags:', event.target.error);
};
});
}
// Verschlüsselten Eintrag entschlüsseln
async function getDecryptedEntry(id) {
const key = await generateKey();
return new Promise((resolve, reject) => {
const transaction = db.transaction(['hours'], 'readonly');
const store = transaction.objectStore('hours');
const request = store.get(id);
request.onsuccess = async function () {
const entry = request.result;
if (entry) {
const iv = new Uint8Array(entry.iv);
const encryptedData = new Uint8Array(entry.encryptedData);
const decryptedData = await decryptData(key, iv, encryptedData);
resolve(JSON.parse(decryptedData));
} else {
reject('Eintrag nicht gefunden');
}
};
request.onerror = function (event) {
reject('Fehler beim Abrufen des verschlüsselten Eintrags:', event.target.error);
};
});
}

@ -13,6 +13,7 @@ var filesToCache = [
// ) // )
// }); // });
// Clear cache on activate // Clear cache on activate
self.addEventListener('activate', event => { self.addEventListener('activate', event => {
event.waitUntil( event.waitUntil(

@ -8,6 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static 'app/css/bootstrap.css' %}"> <link rel="stylesheet" href="{% static 'app/css/bootstrap.css' %}">
<link rel="stylesheet" href="{% static 'app/css/custom.css' %}"> <link rel="stylesheet" href="{% static 'app/css/custom.css' %}">
<script src="{% static 'app/js/dbcontrol.js' %}"></script>
{% progressive_web_app_meta %} {% progressive_web_app_meta %}
@ -39,10 +40,6 @@
Dauer-Hippi Dauer-Hippi
<button class="badge btn btn-secondary">Off</button> <button class="badge btn btn-secondary">Off</button>
</li> </li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Stunden-Schnitt berechnung
<button class="badge btn btn-success">On</button>
</li>
</ul> </ul>
<h5 class="pt-4">Account</h5> <h5 class="pt-4">Account</h5>
<ul class="list-group" style="color: black;"> <ul class="list-group" style="color: black;">

@ -9,6 +9,18 @@
document.getElementById('maincontainer').classList.replace('align-items-center', 'align-items-top') document.getElementById('maincontainer').classList.replace('align-items-center', 'align-items-top')
</script> </script>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
initDB().then(() => {
console.log('IndexedDB erfolgreich initialisiert.');
// Hier kannst du die App weiter initialisieren, z.B. Daten laden oder die UI aufbauen
//loadInitialData();
}).catch((error) => {
console.error('Fehler bei der Initialisierung der IndexedDB:', error);
});
});
</script>
<div class="container" id="welcome_content"> <!-- d-none muss entfernt werden für richtige Funktion --> <div class="container" id="welcome_content"> <!-- d-none muss entfernt werden für richtige Funktion -->
<h1>Wilkommen!</h1> <h1>Wilkommen!</h1>
<p>Schön das du hier bist! <p>Schön das du hier bist!
@ -63,8 +75,8 @@
</div> </div>
</div> </div>
<div class="row justify-content-around" style="width: 95vw; color: black; padding-top: 2rem;"></div> <div class="row justify-content-around" style="width: 95vw; color: black; padding-top: 2rem;"></div>
<div class="col-12" style="height: 40vh; padding: 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray"> <div class="col-12" style="height: 40vh; padding: 0rem 1rem 1rem 1rem; border-radius:1rem; box-shadow: 0 0 0.5rem gray; overflow-y: auto;">
<div class="row justify-content-between align-items-center m-0" style="width: 100%;"> <div class="row justify-content-between align-items-center m-0" style="width: 100%;position: sticky; top: 0; background-color: white; padding-top: 1rem;">
<p class="col-5" style="font-size: 1.2rem; margin: 0 1rem 0 -1rem;" ><b>Aktivitäten</b></p> <p class="col-5" style="font-size: 1.2rem; margin: 0 1rem 0 -1rem;" ><b>Aktivitäten</b></p>
<!-- <span class="col-2" style="margin-left: 32%; padding: 0;"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid" style="height: 35px"></span> --> <!-- <span class="col-2" style="margin-left: 32%; padding: 0;"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid" style="height: 35px"></span> -->
<button type="button" class="offset-2 col-2 btn btn-light" data-bs-toggle="modal" data-bs-target="#newEntryModal"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid"></button> <button type="button" class="offset-2 col-2 btn btn-light" data-bs-toggle="modal" data-bs-target="#newEntryModal"><img id="resetTimer" src="{% static 'app/images/addcircle.png' %}" alt="add" class="img-fluid"></button>
@ -72,35 +84,16 @@
</div> </div>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead style="position: sticky; top: 3.5rem; background-color: white;">
<tr> <tr>
<th scope="col">Dauer</th> <th scope="col">Dauer</th>
<th scope="col">Datum</th> <th scope="col">Datum</th>
<th scope="col">Typ</th> <th scope="col">Beschreibung</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody id="entriesTableBody" style="overflow-y: auto; max-height: 70%;">
<tr>
<td>01:30</td>
<td>12.09.24</td>
<td>Dienst</td>
</tr>
<tr>
<td>03:30</td>
<td>13.09.24</td>
<td>LDC</td>
</tr>
<tr>
<td>03:00</td>
<td>08.09.24</td>
<td>Dienst</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
@ -116,15 +109,52 @@
<div class="modal-body"> <div class="modal-body">
<form method="POST" action=""> <form method="POST" action="">
{% csrf_token %} {% csrf_token %}
<div class="mb-3"> <!-- Dauer in Stunden und Minuten -->
<label for="inputName" class="form-label">Name</label> <div class="form-row">
<input type="text" class="form-control" id="inputName" name="name" required> <div class="form-group col-7">
<label for="stunden"><b>Dauer</b></label>
<div class="input-group">
<input type="number" class="form-control" id="stunden" placeholder="00" min="0" max="99" maxlength="2" required>
<div class="input-group-append">
<span class="input-group-text">h</span>
</div>
<input type="number" class="form-control" id="minuten" placeholder="00" min="0" max="59" maxlength="2" required>
<div class="input-group-append">
<span class="input-group-text">min</span>
</div>
</div>
</div>
</div> </div>
<div class="mb-3">
<label for="inputEmail" class="form-label">E-Mail</label> <!-- Datum -->
<input type="email" class="form-control" id="inputEmail" name="email" required> <div class="form-group">
<label for="datum"><b>Datum</b></label>
<input type="date" class="form-control" id="datum" required>
</div> </div>
<button type="submit" class="btn btn-primary">Absenden</button>
<!-- Auswahl LDC oder Sonstiges (Checkboxen) -->
<div class="form-group">
<label for="optionen"><b>Optionen:</b></label>
<div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="ldcCheck" name="optionen" value="LDC">
<label class="form-check-label" for="ldcCheck">LDC</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="sonstigesCheck" name="optionen" value="Sonstiges">
<label class="form-check-label" for="sonstigesCheck">Sonstiges</label>
</div>
</div>
</div>
<!-- Textfeld für Sonstiges (versteckt, wenn Sonstiges nicht gewählt ist) -->
<div class="form-group" id="sonstiges-text" style="display:none;">
<!--
<label for="sonstigesInput">Beschreibung:</label>
-->
<input type="text" class="form-control" id="sonstigesInput" placeholder="Beschreibung">
</div>
<button type="button" class="btn btn-light disabled" id="newEntrySubmitButton" data-bs-dismiss="modal">Hinzufügen</button>
</form> </form>
</div> </div>
</div> </div>
@ -134,6 +164,192 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script> <script>
function formatDuration(minutes) {
const hours = Math.floor(minutes / 60); // Ganze Stunden berechnen
const mins = minutes % 60; // Verbleibende Minuten berechnen
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`; // Stunden und Minuten formatieren
}
function formatDate(dateString) {
const date = new Date(dateString); // Konvertiere in ein Date-Objekt
const day = String(date.getDate()).padStart(2, '0'); // Tag
const month = String(date.getMonth() + 1).padStart(2, '0'); // Monat (getMonth() ist 0-basiert)
const year = String(date.getFullYear()).slice(-2); // Die letzten 2 Ziffern des Jahres
return `${day}.${month}.${year}`; // Format tt.mm.yy
}
function fillTableWithEntries(entries) {
const tableBody = document.getElementById('entriesTableBody');
// Zuerst den Inhalt der Tabelle löschen (falls schon Daten da sind)
tableBody.innerHTML = '';
// Iteriere durch die Einträge und füge Zeilen hinzu
entries.forEach(entry => {
const row = document.createElement('tr');
// Spalte für die Dauer (duration)
const durationCell = document.createElement('td');
durationCell.textContent = formatDuration(entry.duration); // Dauer im hh:mm-Format
row.appendChild(durationCell);
// Spalte für das Datum (date)
const dateCell = document.createElement('td');
const entryDate = new Date(entry.date); // Konvertiere in ein Date-Objekt
dateCell.textContent = formatDate(entry.date); // Datum im tt.mm.yy-Format
row.appendChild(dateCell);
// Spalte für den Typ (type) - wenn 3, dann zeige "Beschreibung" an
const typeCell = document.createElement('td');
if (entry.type === 3) {
typeCell.textContent = 'Beschreibung'; // Bei Type 3 zeige "Beschreibung" an
} else if (entry.type === 2) {
typeCell.textContent = 'LDC'; // Ansonsten zeige den Type-Wert
} else if (entry.type === 1) {
typeCell.textContent = 'Dienst'; // Ansonsten zeige den Type-Wert
}
row.appendChild(typeCell);
// Füge die erstellte Zeile dem Tabellenkörper hinzu
tableBody.appendChild(row);
});
}
async function initAndTestFilter() {
try {
// IndexedDB initialisieren
await initDB();
console.log('IndexedDB erfolgreich initialisiert.');
// Filterfunktion aufrufen
const filteredEntries = await filterEntriesByMonthYear(9, 2024);
fillTableWithEntries(filteredEntries)
console.log('Gefilterte Einträge für September 2024:', filteredEntries);
} catch (error) {
console.error('Fehler bei der Initialisierung oder Filterung:', error);
}
}
// Initialisierungsfunktion nach dem DOM laden aufrufen
document.addEventListener('DOMContentLoaded', (event) => {
initAndTestFilter();
});
// Absende Formular Verwalten
const hours = document.getElementById('stunden');
const mins = document.getElementById('minuten');
const NewEntryButton = document.getElementById('newEntrySubmitButton')
var allowToSend = false;
function checkInput() {
if (hours.value && mins.value) {
if (!allowToSend) {
allowToSend = true;
NewEntryButton.classList.remove('disabled');
NewEntryButton.classList.replace('btn-light', 'btn-primary');
}
} else {
if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
}
if(sonstigesCheck.checked){
if(sonstigesInput.value) {
if (!allowToSend) {
allowToSend = true;
NewEntryButton.classList.remove('disabled');
NewEntryButton.classList.replace('btn-light', 'btn-primary');
}
} else {
if (allowToSend) {
allowToSend = false;
NewEntryButton.classList.add('disabled');
NewEntryButton.classList.replace('btn-primary', 'btn-light');
}
}
}
}
// Änderungen überwachen damit die das Formular nicht zu früh abgesendet wird
hours.addEventListener('input', () => {
checkInput();
})
mins.addEventListener('input', () => {
checkInput();
})
document.getElementById('sonstigesInput').addEventListener('input', () => {
checkInput();
})
// Einstellungen wenn Neuer Eintrag erstellt wird
NewEntryButton.addEventListener('click', () => {
if (allowToSend === true) {
var type = 1
// Abfragen der Checkboxen
const ldcCheck = document.getElementById('ldcCheck').checked
if (ldcCheck) {
type = 2
document.getElementById('ldcCheck').checked = false
} else if (document.getElementById('sonstigesCheck').checked) {
type = 3;
document.getElementById('sonstigesCheck').checked = false;
sonstigesText.style.display = 'none';
}
// Berechnen der Duration
const duration = (parseInt(hours.value)*60) + parseInt(mins.value)
const newEntryData = {
date: document.getElementById('datum').value,
duration: duration,
type: type,
status: 1,
sondertext: document.getElementById('sonstigesInput').value,
}
addEntry(newEntryData).then((id) => {
console.log('Eintrag hinzugefügt mit ID:', id);
});
hours.value = null
mins.value = null
document.getElementById('sonstigesInput').value = null
checkInput()
}
})
// Setze das heutige Datum als Standardwert
document.getElementById('datum').value = new Date().toISOString().split('T')[0];
// Checkboxen-Verhalten: Nur eine Checkbox kann ausgewählt werden
var ldcCheck = document.getElementById('ldcCheck');
var sonstigesCheck = document.getElementById('sonstigesCheck');
var sonstigesText = document.getElementById('sonstiges-text');
var sonstigesInput = document.getElementById('sonstigesInput');
ldcCheck.addEventListener('change', function() {
if (ldcCheck.checked) {
sonstigesCheck.checked = false;
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
sonstigesCheck.addEventListener('change', function() {
checkInput();
if (sonstigesCheck.checked) {
ldcCheck.checked = false;
sonstigesText.style.display = 'block';
sonstigesInput.setAttribute('required', 'required'); // Setze required, wenn "Sonstiges" ausgewählt ist
} else {
sonstigesText.style.display = 'none';
sonstigesInput.removeAttribute('required'); // Entferne required, wenn "Sonstiges" abgewählt ist
}
});
/* ALLES RUND UM DIE WILLKOMMENSMELDUNG */ /* ALLES RUND UM DIE WILLKOMMENSMELDUNG */

Loading…
Cancel
Save

Powered by TurnKey Linux.