Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e464628ab7 | |||
| a5a6f89f18 |
+31
@@ -2063,6 +2063,11 @@ def _upload_excel_items(scope='inventory'):
|
||||
validation_warnings = []
|
||||
reserved_codes = set()
|
||||
known_locations = set(it.get_predefined_locations())
|
||||
known_filters = {
|
||||
1: set(it.get_predefined_filter_values(1)),
|
||||
2: set(it.get_predefined_filter_values(2)),
|
||||
3: set(it.get_predefined_filter_values(3))
|
||||
}
|
||||
|
||||
def is_code_available(candidate_code):
|
||||
return candidate_code not in reserved_codes and it.is_code_unique(candidate_code)
|
||||
@@ -2114,8 +2119,19 @@ def _upload_excel_items(scope='inventory'):
|
||||
validation_warnings.append((row_number, f'Ort "{ort}" wird neu angelegt'))
|
||||
|
||||
filter1 = expand_filter_selection(_excel_list(val('filter1')), 1)
|
||||
for f in filter1:
|
||||
if f and f not in known_filters[1]:
|
||||
validation_warnings.append((row_number, f'Kategorie 1 "{f}" wird neu angelegt'))
|
||||
|
||||
filter2 = expand_filter_selection(_excel_list(val('filter2')), 2)
|
||||
for f in filter2:
|
||||
if f and f not in known_filters[2]:
|
||||
validation_warnings.append((row_number, f'Kategorie 2 "{f}" wird neu angelegt'))
|
||||
|
||||
filter3 = _excel_list(val('filter3'))
|
||||
for f in filter3:
|
||||
if f and f not in known_filters[3]:
|
||||
validation_warnings.append((row_number, f'Kategorie 3 "{f}" wird neu angelegt'))
|
||||
|
||||
anschaffungsjahr = _excel_int(val('anschaffungsjahr'))
|
||||
raw_year = val('anschaffungsjahr')
|
||||
@@ -2217,6 +2233,21 @@ def _upload_excel_items(scope='inventory'):
|
||||
it.add_predefined_location(row['ort'])
|
||||
known_locations.add(row['ort'])
|
||||
|
||||
for f in row.get('filter1', []):
|
||||
if f and f not in known_filters[1]:
|
||||
it.add_predefined_filter_value(1, f)
|
||||
known_filters[1].add(f)
|
||||
|
||||
for f in row.get('filter2', []):
|
||||
if f and f not in known_filters[2]:
|
||||
it.add_predefined_filter_value(2, f)
|
||||
known_filters[2].add(f)
|
||||
|
||||
for f in row.get('filter3', []):
|
||||
if f and f not in known_filters[3]:
|
||||
it.add_predefined_filter_value(3, f)
|
||||
known_filters[3].add(f)
|
||||
|
||||
series_group_id = str(uuid.uuid4()) if row['count'] > 1 else None
|
||||
row_created_ids = []
|
||||
|
||||
|
||||
+83
-13
@@ -321,7 +321,7 @@
|
||||
border: 1px solid #dc3545 !important;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<div class="container admin-content-container">
|
||||
<!-- Conflict warning banner (populated by JS) -->
|
||||
<div id="conflict-banner" style="display:none; background:#fff3cd; border:1px solid #ffc107; border-left:4px solid #fd7e14; color:#856404; padding:12px 16px; border-radius:4px; margin-bottom:16px; position:relative;">
|
||||
<strong>⚠ Reservierungskonflikt</strong>
|
||||
@@ -904,7 +904,7 @@
|
||||
const filter2More = filter2Array.length > 1 ? ` (+${filter2Array.length - 1} mehr)` : '';
|
||||
const filter3More = filter3Array.length > 1 ? ` (+${filter3Array.length - 1} mehr)` : '';
|
||||
|
||||
const imagesHtml = item.Images ? item.Images.map((file, index) => {
|
||||
const imagesHtml = item.Images && item.Images.length > 0 ? item.Images.slice(0, 1).map((file, index) => {
|
||||
// Get file with correct case handling
|
||||
const image = file;
|
||||
|
||||
@@ -1005,14 +1005,14 @@
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="card-content" data-item-id="${item._id}">
|
||||
<h3 class="item-name-cell">${item.Name}</h3>
|
||||
<p class="item-ort-cell"><strong>Ort:</strong> ${item.Ort || '-'}</p>
|
||||
<p class="item-filter1-cell"><strong>Unterrichtsfach:</strong> ${filter1Display}${filter1More}</p>
|
||||
<p class="item-filter2-cell"><strong>Jahrgangsstufe:</strong> ${filter2Display}${filter2More}</p>
|
||||
<p class="item-filter3-cell"><strong>Thema:</strong> ${filter3Display}${filter3More}</p>
|
||||
<p class="item-code-cell"><strong>Barcode:</strong> ${item.Code_4 || '-'}</p>
|
||||
<p class="item-count-cell"><strong>Anzahl:</strong> ${groupedCount}</p>
|
||||
${isGroupedItem ? `<p class="item-count-cell"><strong>Verfügbar:</strong> ${availableGroupedCount}</p>` : ''}
|
||||
<h3 class="item-col-name">${item.Name}</h3>
|
||||
<p class="item-col-location"><strong>Ort:</strong> ${item.Ort || '-'}</p>
|
||||
<p class="item-col-filter1"><strong>Unterrichtsfach:</strong> ${filter1Display}${filter1More}</p>
|
||||
<p class="item-col-filter2"><strong>Jahrgangsstufe:</strong> ${filter2Display}${filter2More}</p>
|
||||
<p class="item-col-filter3"><strong>Thema:</strong> ${filter3Display}${filter3More}</p>
|
||||
<p class="item-col-code"><strong>Barcode:</strong> ${item.Code_4 || '-'}</p>
|
||||
<p class="item-col-count"><strong>Anzahl:</strong> ${groupedCount}</p>
|
||||
${isGroupedItem ? `<p class="item-col-count"><strong>Verfügbar:</strong> ${availableGroupedCount}</p>` : ''}
|
||||
<div class="image-container">
|
||||
${imagesHtml}
|
||||
</div>
|
||||
@@ -1631,7 +1631,7 @@
|
||||
|
||||
<div class="detail-group">
|
||||
<div class="detail-label">Anschaffungskosten:</div>
|
||||
<div class="detail-value">${item.Anschaffungskosten || '-'}</div>
|
||||
<div class="detail-value">${item.Anschaffungskosten ? item.Anschaffungskosten + ' €' : '-'}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-group full-width">
|
||||
@@ -4174,7 +4174,7 @@
|
||||
overflow-wrap: break-word !important;
|
||||
}
|
||||
|
||||
body.table-view .item-card .card-content .item-name-cell {
|
||||
body.table-view .item-card .card-content .item-col-name {
|
||||
font-size: 0.95rem !important;
|
||||
}
|
||||
|
||||
@@ -4598,4 +4598,74 @@ function openItemQuick(id){
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
<style>
|
||||
/* Admin/Main Content Container align */
|
||||
.admin-content-container {
|
||||
--table-columns: minmax(190px, 2fr) repeat(6, minmax(110px, 1fr));
|
||||
}
|
||||
@media screen and (min-width: 769px) and (max-width: 1024px) {
|
||||
.admin-content-container {
|
||||
width: 90% !important;
|
||||
}
|
||||
.items-container {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
gap: 20px !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
.admin-content-container {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 12px 12px 18px !important;
|
||||
box-sizing: border-box !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
.item-card .item-image {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
max-height: 300px !important;
|
||||
display: block !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
.item-card .image-container {
|
||||
height: 200px !important;
|
||||
overflow: hidden !important;
|
||||
position: relative !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
.actions {
|
||||
gap: 8px !important;
|
||||
border-top: none !important;
|
||||
padding-top: 8px !important;
|
||||
flex-direction: column !important;
|
||||
align-items: stretch !important;
|
||||
}
|
||||
.actions form,
|
||||
.actions button,
|
||||
.actions a {
|
||||
width: 100% !important;
|
||||
}
|
||||
.items-container, .item-card, .image-container, .item-image {
|
||||
touch-action: pan-y !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
.admin-content-container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 12px 12px 18px;
|
||||
box-sizing: border-box;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2584,7 +2584,7 @@ document.addEventListener('DOMContentLoaded', ()=>{
|
||||
<input type="date" id="edit-year" name="anschaffungsjahr">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit-cost">Anschaffungskosten:</label>
|
||||
<label for="edit-cost">Anschaffungskosten (€):</label>
|
||||
<input id="edit-cost" name="anschaffungskosten">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -3530,7 +3530,7 @@ document.addEventListener('DOMContentLoaded', ()=>{
|
||||
const filter2More = filter2Array.length > 1 ? ` (+${filter2Array.length - 1} mehr)` : '';
|
||||
const filter3More = filter3Array.length > 1 ? ` (+${filter3Array.length - 1} mehr)` : '';
|
||||
|
||||
const imagesHtml = item.Images ? item.Images.map((image, index) => {
|
||||
const imagesHtml = item.Images && item.Images.length > 0 ? item.Images.slice(0, 1).map((image, index) => {
|
||||
// Check if the image already has a full URL path or just the filename
|
||||
const imageSrc = image.startsWith('/uploads/') || image.startsWith('http') ?
|
||||
image :
|
||||
@@ -4441,7 +4441,7 @@ document.addEventListener('DOMContentLoaded', ()=>{
|
||||
|
||||
<div class="detail-group">
|
||||
<div class="detail-label">Anschaffungskosten:</div>
|
||||
<div class="detail-value">${item.Anschaffungskosten || '-'}</div>
|
||||
<div class="detail-value">${item.Anschaffungskosten ? item.Anschaffungskosten + ' €' : '-'}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-group full-width">
|
||||
|
||||
@@ -863,7 +863,7 @@
|
||||
<input type="date" id="anschaffungsjahr" name="anschaffungsjahr">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="anschaffungskosten">Anschaffungskosten</label>
|
||||
<label for="anschaffungskosten">Anschaffungskosten (€)</label>
|
||||
<input id="anschaffungskosten" name="anschaffungskosten">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
Reference in New Issue
Block a user