Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73cf63a56d | |||
| fdcd26326b | |||
| 1fd9e230ac | |||
| cc0c4e28b7 | |||
| ea73b98549 | |||
| d6dda0f25a | |||
| 46176c1741 |
+57
@@ -6627,6 +6627,63 @@ def edit_item(id):
|
||||
return redirect(url_for('home_admin'))
|
||||
|
||||
|
||||
@app.route('/update_group', methods=['POST'])
|
||||
def update_group():
|
||||
data = request.get_json()
|
||||
series_group_id = data.get('series_group_id')
|
||||
|
||||
if not series_group_id:
|
||||
return jsonify({'success': False, 'message': 'Keine Gruppen-ID'}), 400
|
||||
|
||||
# 1. Shared Fields (Group Logic)
|
||||
# These apply to every item in the group
|
||||
shared_update = {
|
||||
'Name': data.get('name'),
|
||||
'Ort': data.get('ort'),
|
||||
'Beschreibung': data.get('beschreibung'),
|
||||
'Anschaffungsjahr': data.get('ansch_jahr'),
|
||||
'Anschaffungskosten': data.get('ansch_kost'),
|
||||
'Reservierbar': data.get('reservierbar'),
|
||||
'ISBN': data.get('isbn'),
|
||||
'ItemType': data.get('item_type'),
|
||||
'LastUpdated': datetime.datetime.now()
|
||||
}
|
||||
|
||||
# 2. Individual Updates (Specific Code Logic)
|
||||
# Expected format: [{'id': '...', 'code_4': '...'}, ...]
|
||||
individual_items = data.get('items', [])
|
||||
|
||||
try:
|
||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||
db = client[cfg.MONGODB_DB]
|
||||
items_col = db['items']
|
||||
|
||||
# A. Apply Shared Attributes to the whole group
|
||||
items_col.update_many(
|
||||
{'SeriesGroupId': series_group_id},
|
||||
{'$set': shared_update}
|
||||
)
|
||||
|
||||
# B. Apply Unique Codes to specific items
|
||||
# We iterate through the provided list to update the specific code for each ID
|
||||
for item in individual_items:
|
||||
item_id = item.get('id')
|
||||
new_code = item.get('code_4')
|
||||
|
||||
if item_id:
|
||||
items_col.update_one(
|
||||
{'_id': ObjectId(item_id), 'SeriesGroupId': series_group_id},
|
||||
{'$set': {'Code_4': new_code}}
|
||||
)
|
||||
|
||||
client.close()
|
||||
return jsonify({'success': True, 'message': 'Gruppe und individuelle Codes aktualisiert'})
|
||||
|
||||
except Exception as e:
|
||||
app.logger.error(f"Error updating group {series_group_id}: {e}")
|
||||
return jsonify({'success': False, 'message': 'Systemfehler beim Update'}), 500
|
||||
|
||||
|
||||
@app.route('/report_damage/<id>', methods=['POST'])
|
||||
def report_damage(id):
|
||||
"""Register a damage report entry for an item (admin only)."""
|
||||
|
||||
@@ -1200,7 +1200,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Felder befüllen
|
||||
// 1. Felder befüllen
|
||||
document.getElementById('editLibraryItemId').value = item._id || '';
|
||||
document.getElementById('editLibraryName').value = item.Name || '';
|
||||
document.getElementById('editLibraryType').value = item.ItemType || 'book';
|
||||
@@ -1209,29 +1209,32 @@
|
||||
document.getElementById('editLibraryLocation').value = item.Ort || '';
|
||||
document.getElementById('editLibraryDescription').value = item.Beschreibung || '';
|
||||
|
||||
// Gruppen-Logik für die Anzeige der gesamten Range
|
||||
// 2. Gruppen-Logik (Codes anzeigen)
|
||||
const warningDiv = document.getElementById('editLibraryGroupWarning');
|
||||
const codesContainer = document.getElementById('editLibraryAllCodes');
|
||||
|
||||
if (item.SeriesGroupId) {
|
||||
// Alle Mitglieder der Gruppe finden (sortiert nach SeriesPosition)
|
||||
const groupMembers = libraryItems
|
||||
.filter(i => i.SeriesGroupId === item.SeriesGroupId)
|
||||
.sort((a, b) => a.SeriesPosition - b.SeriesPosition);
|
||||
|
||||
// Codes für die Anzeige formatieren
|
||||
const codesHtml = groupMembers.map(member => {
|
||||
const isCurrent = member._id === itemId;
|
||||
return `<span style="background: ${isCurrent ? '#0ea5e9' : '#e0e0e0'};
|
||||
color: ${isCurrent ? '#fff' : '#333'};
|
||||
padding: 2px 8px; border-radius: 4px; margin-right: 5px; font-size: 12px;">
|
||||
${member.Code_4 || 'n/a'}
|
||||
</span>`;
|
||||
}).join('');
|
||||
|
||||
// DEBUG: Schau in der Konsole, wie viele Items gefunden werden
|
||||
console.log("Suche Items mit SeriesGroupId:", item.SeriesGroupId);
|
||||
|
||||
const groupMembers = libraryItems.filter(i => {
|
||||
// Debug: Prüfen, ob die IDs matchen
|
||||
const match = i.SeriesGroupId === item.SeriesGroupId;
|
||||
if(match) console.log("Gefundenes Item:", i.Code_4);
|
||||
return match;
|
||||
});
|
||||
|
||||
console.log("Anzahl gefundener Gruppenmitglieder:", groupMembers.length);
|
||||
|
||||
// Sortierung und Extraktion
|
||||
const codeList = groupMembers
|
||||
.sort((a, b) => (a.SeriesPosition || 0) - (b.SeriesPosition || 0))
|
||||
.map(member => member.Code_4 || "---")
|
||||
.join(', ');
|
||||
|
||||
document.getElementById('editLibraryGroupCount').textContent = groupMembers.length;
|
||||
codesContainer.innerHTML = codesHtml;
|
||||
|
||||
document.getElementById('editLibraryAllCodes').textContent = codeList;
|
||||
|
||||
warningDiv.style.display = 'block';
|
||||
} else {
|
||||
warningDiv.style.display = 'none';
|
||||
@@ -1244,90 +1247,161 @@
|
||||
document.getElementById('editLibraryModal').style.display = 'none';
|
||||
}
|
||||
|
||||
document.getElementById('editLibraryForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const itemId = document.getElementById('editLibraryItemId').value;
|
||||
|
||||
// Daten sammeln
|
||||
const updateData = {
|
||||
id: itemId,
|
||||
name: document.getElementById('editLibraryName').value,
|
||||
item_type: document.getElementById('editLibraryType').value,
|
||||
isbn: document.getElementById('editLibraryIsbn').value,
|
||||
code_4: document.getElementById('editLibraryCode4').value,
|
||||
ort: document.getElementById('editLibraryLocation').value,
|
||||
beschreibung: document.getElementById('editLibraryDescription').value
|
||||
};
|
||||
|
||||
// Fetch zum Backend
|
||||
const response = await fetch('/api/update-item', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(updateData)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Lokale Synchronisierung im Array (für sofortiges UI-Update)
|
||||
const editedItem = libraryItems.find(i => i._id === itemId);
|
||||
if (editedItem && editedItem.SeriesGroupId) {
|
||||
libraryItems.forEach(item => {
|
||||
if (item.SeriesGroupId === editedItem.SeriesGroupId) {
|
||||
// Alle Felder synchronisieren
|
||||
item.Name = updateData.name;
|
||||
item.ItemType = updateData.item_type;
|
||||
item.ISBN = updateData.isbn;
|
||||
item.Ort = updateData.ort;
|
||||
item.Beschreibung = updateData.beschreibung;
|
||||
|
||||
// Code nur für das aktive Item setzen
|
||||
if (item._id === itemId) {
|
||||
item.Code_4 = updateData.code_4;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Event-Listener für das Formular (Initialisierung)
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editForm = document.getElementById('editLibraryForm');
|
||||
|
||||
if (editForm) {
|
||||
editForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const itemId = document.getElementById('editLibraryItemId').value;
|
||||
const currentItem = libraryItems.find(i => i._id === itemId);
|
||||
|
||||
if (!currentItem) return;
|
||||
|
||||
// 1. Payload für die /update_group Route zusammenstellen
|
||||
// Wir sammeln alle Gruppenmitglieder, um die individuellen Codes zu senden
|
||||
const groupMembers = libraryItems.filter(i => i.SeriesGroupId === currentItem.SeriesGroupId);
|
||||
const individualItems = groupMembers.map(member => {
|
||||
return {
|
||||
id: member._id,
|
||||
// Wenn es das aktive Item ist, nimm den neuen Wert aus dem Input
|
||||
code_4: (member._id === itemId) ? document.getElementById('editLibraryCode4').value : member.Code_4
|
||||
};
|
||||
});
|
||||
} else if (editedItem) {
|
||||
// Einzel-Update
|
||||
Object.assign(editedItem, updateData);
|
||||
}
|
||||
|
||||
closeEditLibraryModal();
|
||||
// Hier ggf. deine Render-Funktion aufrufen, um die Tabelle zu aktualisieren
|
||||
renderLibraryTable();
|
||||
|
||||
const payload = {
|
||||
series_group_id: currentItem.SeriesGroupId,
|
||||
name: document.getElementById('editLibraryName').value,
|
||||
ort: document.getElementById('editLibraryLocation').value,
|
||||
beschreibung: document.getElementById('editLibraryDescription').value,
|
||||
isbn: document.getElementById('editLibraryIsbn').value,
|
||||
item_type: document.getElementById('editLibraryType').value,
|
||||
items: individualItems
|
||||
};
|
||||
|
||||
// 2. Request an Backend
|
||||
try {
|
||||
const response = await fetch('/update_group', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// 3. UI-Synchronisierung (lokal im Browser)
|
||||
libraryItems.forEach(item => {
|
||||
if (item.SeriesGroupId === currentItem.SeriesGroupId) {
|
||||
item.Name = payload.name;
|
||||
item.Ort = payload.ort;
|
||||
item.Beschreibung = payload.beschreibung;
|
||||
item.ISBN = payload.isbn;
|
||||
item.ItemType = payload.item_type;
|
||||
|
||||
// Nur den Code des aktiven Items lokal updaten
|
||||
if (item._id === itemId) item.Code_4 = document.getElementById('editLibraryCode4').value;
|
||||
}
|
||||
});
|
||||
|
||||
closeEditLibraryModal();
|
||||
// Falls du eine Funktion zum Neuzeichnen der Tabelle hast, rufe sie hier auf:
|
||||
// renderTable();
|
||||
alert("Erfolgreich synchronisiert.");
|
||||
} else {
|
||||
alert('Fehler: ' + result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fetch error:', error);
|
||||
alert('Netzwerkfehler beim Speichern.');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="editLibraryModal" class="modal" style="display:none;">
|
||||
<div class="modal-content" style="max-width: 760px;">
|
||||
<span class="close" onclick="closeEditLibraryModal()">×</span>
|
||||
<div class="modal-content" style="max-width: 760px; padding: 25px; border-radius: 8px;">
|
||||
<span class="close" onclick="closeEditLibraryModal()" style="cursor: pointer; float: right; font-size: 24px;">×</span>
|
||||
<h3 style="margin-top:0;">Bibliotheksmedium bearbeiten</h3>
|
||||
|
||||
<!-- Bereich für Gruppen-Informationen (Range) -->
|
||||
<div id="editLibraryGroupWarning" style="display:none; background-color: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 20px; border: 1px solid #dee2e6;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||||
<strong style="color: #0ea5e9;">Gruppen-Synchronisierung aktiv</strong>
|
||||
<span style="font-size: 12px; color: #666;">Gesamt: <span id="editLibraryGroupCount"></span> Exemplare</span>
|
||||
<!-- Bereich für Gruppen-Informationen (Hier konsolidiert!) -->
|
||||
<div id="editLibraryGroupWarning" style="display:none; background-color: #fff; padding: 15px; border-radius: 6px; margin-bottom: 20px; border: 1px solid #0ea5e9;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; border-bottom: 1px solid #eee; padding-bottom: 10px;">
|
||||
<strong style="color: #0ea5e9;">Gruppen-Range (Total: <span id="editLibraryGroupCount"></span>)</strong>
|
||||
</div>
|
||||
|
||||
<p style="margin: 0 0 10px 0; font-size: 13px;">Verfügbare Codes in dieser Range:</p>
|
||||
<div id="editLibraryAllCodes" style="display: flex; flex-wrap: wrap; gap: 5px;">
|
||||
<!-- Codes werden hier per JS eingefügt -->
|
||||
</div>
|
||||
|
||||
<p style="margin-top: 15px; font-size: 12px; color: #555; border-top: 1px solid #eee; pt: 10px;">
|
||||
<em>Änderungen an allgemeinen Daten (Titel, Ort, etc.) betreffen <strong>alle</strong> oben aufgeführten Codes.</em>
|
||||
<p style="margin: 5px 0; font-size: 12px; color: #555;">
|
||||
Alle aufgeführten Codes gehören zu diesem Datensatz:
|
||||
</p>
|
||||
|
||||
<!-- Hier werden die Codes per JS eingefügt -->
|
||||
<div id="editLibraryAllCodes" style="display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px;"></div>
|
||||
|
||||
<div style="margin-top: 15px; font-size: 11px; background: #e0f2fe; padding: 8px; border-radius: 4px;">
|
||||
<strong>Hinweis:</strong> Änderungen an Titel/Ort/Beschreibung werden auf <strong>alle</strong> Exemplare der Range übertragen.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="editLibraryForm">
|
||||
<!-- Formularfelder wie gehabt... -->
|
||||
<input type="hidden" id="editLibraryItemId">
|
||||
<div class="edit-grid">
|
||||
<!-- ... (Dein restliches Formular) ... -->
|
||||
<div class="full">
|
||||
<label for="editLibraryName">Titel</label>
|
||||
<input id="editLibraryName" required style="width: 100%;">
|
||||
</div>
|
||||
<div>
|
||||
<label for="editLibraryType">Medientyp</label>
|
||||
<select id="editLibraryType" style="width: 100%;">
|
||||
<option value="book">Buch</option>
|
||||
<option value="schulbuch">Schulbuch</option>
|
||||
<option value="cd">CD</option>
|
||||
<option value="dvd">DVD</option>
|
||||
<option value="media">Sonstige Medien</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="editLibraryIsbn">ISBN</label>
|
||||
<input id="editLibraryIsbn" placeholder="optional ISBN-10/13" style="width: 100%;">
|
||||
</div>
|
||||
<div>
|
||||
<label for="editLibraryCode4">Code</label>
|
||||
<input id="editLibraryCode4" placeholder="optional Mediencode" style="width: 100%;">
|
||||
</div>
|
||||
<div class="full">
|
||||
<label for="editLibraryLocation">Ort</label>
|
||||
<input id="editLibraryLocation" required style="width: 100%;">
|
||||
</div>
|
||||
<div class="full">
|
||||
<label for="editLibraryDescription">Beschreibung</label>
|
||||
<textarea id="editLibraryDescription" rows="4" required style="width: 100%;"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit-actions" style="margin-top:20px;">
|
||||
<button type="submit" class="button" style="background:#0ea5e9;color:#fff;">Speichern & Synchronisieren</button>
|
||||
<button type="button" class="button" onclick="closeEditLibraryModal()">Abbrechen</button>
|
||||
</div>
|
||||
<!-- ... -->
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="editLibraryGroupWarning" style="display:none; background-color: #fff; padding: 15px; border-radius: 6px; margin-bottom: 20px; border: 1px solid #0ea5e9;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; border-bottom: 1px solid #eee; padding-bottom: 10px;">
|
||||
<strong style="color: #0ea5e9;">Gruppen-Range (Total: <span id="editLibraryGroupCount"></span>)</strong>
|
||||
</div>
|
||||
|
||||
<p style="margin: 5px 0; font-size: 12px; color: #555;">
|
||||
Alle Codes in dieser Gruppe:
|
||||
</p>
|
||||
|
||||
<!-- Hier wird die Liste als Komma-Text eingefügt -->
|
||||
<div id="editLibraryAllCodes" style="font-family: monospace; font-size: 14px; font-weight: bold; color: #333; margin-top: 5px;"></div>
|
||||
|
||||
<div style="margin-top: 15px; font-size: 11px; background: #e0f2fe; padding: 8px; border-radius: 4px;">
|
||||
<strong>Hinweis:</strong> Änderungen an Titel/Ort/Beschreibung werden auf <strong>alle</strong> Exemplare der Range übertragen.
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user