poprawki w synchronizacji produktow
This commit is contained in:
20
app.py
20
app.py
@@ -220,7 +220,7 @@ def require_system_password():
|
||||
# specjalny wyjątek dla statycznych, ale sprawdzany ręcznie niżej
|
||||
if request.endpoint == 'static_bp.serve_js':
|
||||
# tu sprawdzamy czy to JS, który ma być chroniony
|
||||
protected_js = ["live.js", "list_guest.js", "hide_list.js", "socket_reconnect.js"]
|
||||
protected_js = ["live.js", "list_guest.js", "hide_list.js", "socket_reconnect.js","sync_products.js", "expenses.js", "toggle_button.js"]
|
||||
requested_file = request.view_args.get("filename", "")
|
||||
if requested_file in protected_js:
|
||||
return redirect(url_for('system_auth', next=request.url))
|
||||
@@ -858,21 +858,23 @@ def list_products():
|
||||
suggestions_dict=suggestions_dict
|
||||
)
|
||||
|
||||
@app.route('/admin/sync_suggestion/<item_name>')
|
||||
@app.route('/admin/sync_suggestion_ajax/<int:item_id>', methods=['POST'])
|
||||
@login_required
|
||||
def sync_suggestion(item_name):
|
||||
def sync_suggestion_ajax(item_id):
|
||||
if not current_user.is_admin:
|
||||
return redirect(url_for('index_guest'))
|
||||
return jsonify({'success': False, 'message': 'Brak uprawnień'}), 403
|
||||
|
||||
existing = SuggestedProduct.query.filter(func.lower(SuggestedProduct.name) == item_name.lower()).first()
|
||||
item = Item.query.get_or_404(item_id)
|
||||
|
||||
existing = SuggestedProduct.query.filter(func.lower(SuggestedProduct.name) == item.name.lower()).first()
|
||||
if not existing:
|
||||
new_suggestion = SuggestedProduct(name=item_name)
|
||||
new_suggestion = SuggestedProduct(name=item.name)
|
||||
db.session.add(new_suggestion)
|
||||
db.session.commit()
|
||||
flash(f'Utworzono sugestię dla produktu: {item_name}', 'success')
|
||||
return jsonify({'success': True, 'message': f'Utworzono sugestię dla produktu: {item.name}'})
|
||||
else:
|
||||
flash(f'Sugestia dla produktu "{item_name}" już istnieje.', 'info')
|
||||
return redirect(url_for('list_products'))
|
||||
return jsonify({'success': True, 'message': f'Sugestia dla produktu „{item.name}” już istnieje.'})
|
||||
|
||||
|
||||
@app.route('/admin/delete_suggestion/<int:suggestion_id>')
|
||||
@login_required
|
||||
|
@@ -120,7 +120,7 @@ function setupList(listId, username) {
|
||||
|
||||
li.innerHTML = `
|
||||
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||
<input type="checkbox">
|
||||
<input class="large-checkbox" type="checkbox">
|
||||
<span id="name-${data.id}" class="text-white">${data.name} ${quantityBadge}</span>
|
||||
</div>
|
||||
<div class="mt-2 mt-md-0">
|
||||
|
65
static/js/sync_products.js
Normal file
65
static/js/sync_products.js
Normal file
@@ -0,0 +1,65 @@
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
// Usuń stare eventy
|
||||
document.querySelectorAll('.sync-btn').forEach(btn => {
|
||||
btn.replaceWith(btn.cloneNode(true));
|
||||
});
|
||||
|
||||
// Pobierz już "czyste" przyciski
|
||||
const buttons = document.querySelectorAll('.sync-btn');
|
||||
|
||||
buttons.forEach(btn => {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const itemId = this.getAttribute('data-item-id');
|
||||
const button = this;
|
||||
|
||||
button.disabled = true;
|
||||
|
||||
fetch(`/admin/sync_suggestion_ajax/${itemId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
showToast(data.message, data.success ? 'success' : 'danger');
|
||||
|
||||
if (data.success) {
|
||||
button.innerText = '✅ Zsynchronizowano';
|
||||
button.classList.remove('btn-outline-primary');
|
||||
button.classList.add('btn-success');
|
||||
} else {
|
||||
button.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showToast('Błąd synchronizacji', 'danger');
|
||||
button.disabled = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Funkcja do wyświetlania toast
|
||||
function showToast(message, type = 'success') {
|
||||
const toastContainer = document.getElementById('toast-container');
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `toast align-items-center text-white bg-${type} border-0 show`;
|
||||
toast.role = 'alert';
|
||||
toast.style.minWidth = '250px';
|
||||
toast.innerHTML = `
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
`;
|
||||
toastContainer.appendChild(toast);
|
||||
|
||||
// Automatyczne usunięcie po 3 sekundach
|
||||
setTimeout(() => {
|
||||
toast.remove();
|
||||
}, 1750);
|
||||
}
|
@@ -41,7 +41,7 @@
|
||||
✅ Istnieje (ID: {{ suggestion.id }})
|
||||
<a href="/admin/delete_suggestion/{{ suggestion.id }}" class="btn btn-sm btn-outline-danger ms-1">🗑️ Usuń</a>
|
||||
{% else %}
|
||||
<a href="/admin/sync_suggestion/{{ item.name }}" class="btn btn-sm btn-outline-primary">🔄 Synchronizuj</a>
|
||||
<button class="btn btn-sm btn-outline-primary sync-btn" data-item-id="{{ item.id }}">🔄 Synchronizuj</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
@@ -59,4 +59,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
<script src="{{ url_for('static_bp.serve_js', filename='sync_products.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
|
Reference in New Issue
Block a user