feat: Bearbeitungssperren und Versionskonfliktschutz ergänzen
This commit is contained in:
@@ -135,12 +135,48 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
{% if object.pk %}
|
||||
const lockToken = document.getElementById('id_edit_lock_token');
|
||||
const editForm = document.querySelector('form.object-edit');
|
||||
const csrfToken = document.querySelector('input[name=csrfmiddlewaretoken]');
|
||||
const lockUrl = "{% url 'plugins:netbox_documentation:document_lock' pk=object.pk %}";
|
||||
let submitting = false;
|
||||
const heartbeat = () => {
|
||||
if (!lockToken || !lockToken.value || submitting) return;
|
||||
const data = new URLSearchParams({token: lockToken.value, action: 'heartbeat'});
|
||||
fetch(lockUrl, {
|
||||
method: 'POST', credentials: 'same-origin', body: data,
|
||||
headers: {'X-CSRFToken': csrfToken.value, 'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
}).then(response => {
|
||||
if (response.status === 409) {
|
||||
const warning = document.createElement('div');
|
||||
warning.className = 'alert alert-danger position-fixed top-0 start-50 translate-middle-x mt-3';
|
||||
warning.style.zIndex = '2000';
|
||||
warning.textContent = 'Die Bearbeitungssperre ist abgelaufen oder wurde übernommen. Bitte Inhalt sichern und die Seite neu laden.';
|
||||
document.body.appendChild(warning);
|
||||
}
|
||||
});
|
||||
};
|
||||
const heartbeatTimer = window.setInterval(heartbeat, 60000);
|
||||
if (editForm) editForm.addEventListener('submit', () => { submitting = true; window.clearInterval(heartbeatTimer); });
|
||||
window.addEventListener('beforeunload', () => {
|
||||
if (submitting || !lockToken || !lockToken.value) return;
|
||||
const data = new FormData();
|
||||
data.append('csrfmiddlewaretoken', csrfToken.value);
|
||||
data.append('token', lockToken.value);
|
||||
data.append('action', 'release');
|
||||
navigator.sendBeacon(lockUrl, data);
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock javascript %}
|
||||
|
||||
{% block pre_form_fields %}
|
||||
{% if not object.pk %}
|
||||
{% if object.pk %}
|
||||
<div class="alert alert-success py-2"><i class="mdi mdi-lock-check"></i> Diese Dokumentation ist während der Bearbeitung für dich reserviert.</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">Speichere die neue Dokumentation einmal. Danach können Bilder direkt über die Editor-Werkzeugleiste hochgeladen werden.</div>
|
||||
{% endif %}
|
||||
{% endblock pre_form_fields %}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{% extends 'base/layout.html' %}
|
||||
|
||||
{% block title %}Bearbeitungskonflikt{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="alert alert-danger">
|
||||
<h4><i class="mdi mdi-content-save-alert"></i> Neuere Version erkannt</h4>
|
||||
<p>Die Dokumentation wurde seit dem Öffnen verändert. Deine Fassung wurde nicht gespeichert und die neuere Version wurde nicht überschrieben.</p>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-6">
|
||||
<div class="card"><h5 class="card-header">Aktuelle gespeicherte Version</h5><div class="card-body">
|
||||
<a href="{{ object.get_absolute_url }}" class="btn btn-primary" target="_blank">Aktuelle Version öffnen</a>
|
||||
</div></div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card"><h5 class="card-header">Dein nicht gespeicherter Inhalt</h5><div class="card-body">
|
||||
<p><strong>Titel:</strong> {{ submitted_title }}</p>
|
||||
<textarea class="form-control font-monospace" rows="24" readonly>{{ submitted_body }}</textarea>
|
||||
<p class="text-muted mt-2">Diesen Inhalt kannst du kopieren und nach Prüfung in die aktuelle Version übernehmen.</p>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,25 @@
|
||||
{% extends 'base/layout.html' %}
|
||||
|
||||
{% block title %}Dokumentation wird bearbeitet{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center"><div class="col-lg-7">
|
||||
<div class="card border-warning">
|
||||
<h5 class="card-header"><i class="mdi mdi-lock-clock"></i> Bearbeitung derzeit gesperrt</h5>
|
||||
<div class="card-body">
|
||||
{% if lost %}
|
||||
<p>Deine Bearbeitungssperre ist nicht mehr gültig. Der Inhalt wurde nicht überschrieben.</p>
|
||||
{% elif lock.user %}
|
||||
<p><strong>{{ lock.user }}</strong> bearbeitet „{{ object.title }}“ momentan.</p>
|
||||
{% else %}
|
||||
<p>Diese Dokumentation besitzt momentan eine aktive Bearbeitungssperre.</p>
|
||||
{% endif %}
|
||||
<p class="text-muted">Ohne Heartbeat läuft eine Sperre nach {{ timeout }} Minuten automatisch ab.</p>
|
||||
<div class="btn-list">
|
||||
<a href="{{ object.get_absolute_url }}" class="btn btn-outline-secondary">Zur Dokumentation</a>
|
||||
<a href="{% url 'plugins:netbox_documentation:document_edit' pk=object.pk %}" class="btn btn-primary">Erneut versuchen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
{% endblock content %}
|
||||
Reference in New Issue
Block a user