Add image attachments to feedback form (JPEG/PNG)
- File input in feedback modal (max 3 images, 5 MB each) - Frontend validation for file count and size - Backend: multipart/form-data with UploadFile, MIME attachments - Images attached to feedback email as base64-encoded attachments - Only JPEG and PNG allowed (validated server-side) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -551,6 +551,11 @@
|
||||
<textarea id="fb-message" required aria-required="true" minlength="10" maxlength="5000" rows="6" placeholder="Beschreibe dein Anliegen (mind. 10 Zeichen)..."></textarea>
|
||||
<div class="form-hint"><span id="fb-char-count">0</span> / 5.000 Zeichen</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="fb-files">Bilder anhaengen (optional)</label>
|
||||
<input type="file" id="fb-files" accept="image/jpeg,image/png" multiple style="font-size:13px;">
|
||||
<div class="form-hint">Max. 3 Bilder (JPEG/PNG, je max. 5 MB)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeModal('modal-feedback')">Abbrechen</button>
|
||||
|
||||
@@ -197,6 +197,23 @@ const API = {
|
||||
return this._request('POST', '/feedback', data);
|
||||
},
|
||||
|
||||
async sendFeedbackForm(formData) {
|
||||
const token = localStorage.getItem('osint_token');
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 60000);
|
||||
const resp = await fetch(this.baseUrl + '/feedback', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': token ? 'Bearer ' + token : '' },
|
||||
body: formData,
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(timeout);
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json().catch(() => ({}));
|
||||
throw new Error(err.detail || 'Fehler ' + resp.status);
|
||||
}
|
||||
},
|
||||
|
||||
// Export
|
||||
exportIncident(id, format, scope) {
|
||||
const token = localStorage.getItem('osint_token');
|
||||
|
||||
@@ -2168,10 +2168,30 @@ const App = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Dateien pruefen
|
||||
const fileInput = document.getElementById('fb-files');
|
||||
const files = fileInput ? Array.from(fileInput.files) : [];
|
||||
if (files.length > 3) {
|
||||
UI.showToast('Maximal 3 Bilder erlaubt.', 'error');
|
||||
return;
|
||||
}
|
||||
for (const f of files) {
|
||||
if (f.size > 5 * 1024 * 1024) {
|
||||
UI.showToast('Datei "' + f.name + '" ist groesser als 5 MB.', 'error');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Wird gesendet...';
|
||||
try {
|
||||
await API.sendFeedback({ category, message });
|
||||
const formData = new FormData();
|
||||
formData.append('category', category);
|
||||
formData.append('message', message);
|
||||
for (const f of files) {
|
||||
formData.append('files', f);
|
||||
}
|
||||
await API.sendFeedbackForm(formData);
|
||||
closeModal('modal-feedback');
|
||||
UI.showToast('Feedback gesendet. Vielen Dank!', 'success');
|
||||
} catch (err) {
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren