expanded log activity
This commit is contained in:
@ -92,3 +92,11 @@ export function apiDownloadUrl(endpoint) {
|
||||
const cleanEndpoint = endpoint.replace(/\.php(\?|$)/, '$1');
|
||||
return `${API_BASE}/${cleanEndpoint}${cleanEndpoint.includes('?') ? '&' : '?'}token=${encodeURIComponent(token)}`;
|
||||
}
|
||||
|
||||
/** Authenticated file/download fetch (marks request as website for activity logging). */
|
||||
export async function apiDownloadFetch(url, options = {}) {
|
||||
const token = getToken();
|
||||
const headers = { ...(options.headers || {}), 'X-QDB-Client': 'web' };
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||
return fetch(url, { ...options, headers });
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { apiGet, apiPost } from '../api.js';
|
||||
import { apiGet, apiPost, apiDownloadFetch } from '../api.js';
|
||||
import { getRole, pageHeaderHTML, showToast } from '../app.js';
|
||||
import { navigate } from '../router.js';
|
||||
|
||||
@ -6,6 +6,7 @@ const ACTIVITY_LABELS = {
|
||||
app_sync: 'App sync',
|
||||
app_change: 'App change',
|
||||
web_change: 'Website change',
|
||||
web_export: 'Website export',
|
||||
};
|
||||
|
||||
export function devPage() {
|
||||
@ -61,8 +62,8 @@ export function devPage() {
|
||||
<div class="card activity-log-card" style="margin-top:16px">
|
||||
<h2 style="margin:0 0 8px;font-size:1.1rem">API activity log</h2>
|
||||
<p class="field-hint" style="margin:0 0 14px">
|
||||
App syncs (<code>GET /app_questionnaires</code>) and data changes
|
||||
(POST, PUT, PATCH, DELETE). Routine website page loads are not logged.
|
||||
App syncs, website edits (translations, users, questionnaires, …),
|
||||
and exports/downloads. Routine page loads (lists, dashboards) are not logged.
|
||||
</p>
|
||||
<div class="filter-bar" style="margin-bottom:12px">
|
||||
<label style="font-size:.85rem;font-weight:500">Date</label>
|
||||
@ -73,6 +74,7 @@ export function devPage() {
|
||||
<option value="app_sync">App sync</option>
|
||||
<option value="app_change">App change</option>
|
||||
<option value="web_change">Website change</option>
|
||||
<option value="web_export">Website export</option>
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm" id="activityLogRefresh">Refresh</button>
|
||||
</div>
|
||||
@ -405,13 +407,7 @@ function filenameFromContentDisposition(res, fallback) {
|
||||
}
|
||||
|
||||
async function downloadExportZip(url, defaultFilename) {
|
||||
const token = localStorage.getItem('qdb_token');
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'X-QDB-Client': 'web',
|
||||
},
|
||||
});
|
||||
const res = await apiDownloadFetch(url);
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ error: 'Download failed' }));
|
||||
throw new Error(err.error?.message || err.error || 'Download failed');
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { apiGet } from '../api.js';
|
||||
import { apiGet, apiDownloadFetch } from '../api.js';
|
||||
import { canEdit, pageHeaderHTML, showToast } from '../app.js';
|
||||
let questionnairesList = [];
|
||||
let filterSearch = '';
|
||||
@ -153,10 +153,7 @@ function wireExportActions() {
|
||||
const prev = btn.textContent;
|
||||
btn.textContent = 'Preparing…';
|
||||
try {
|
||||
const token = localStorage.getItem('qdb_token');
|
||||
const res = await fetch('../api/export?bundle=1', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const res = await apiDownloadFetch('../api/export?bundle=1');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err.error?.message || err.error || 'Export failed');
|
||||
@ -180,10 +177,7 @@ function wireExportActions() {
|
||||
}
|
||||
|
||||
async function downloadExportCsv(btn, url, filename) {
|
||||
const token = localStorage.getItem('qdb_token');
|
||||
const res = await fetch(url, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const res = await apiDownloadFetch(url);
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ error: 'Download failed' }));
|
||||
throw new Error(err.error?.message || err.error || 'Download failed');
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { apiGet, apiPost, apiPut, apiDelete } from '../api.js';
|
||||
import { apiGet, apiPost, apiPut, apiDelete, apiDownloadFetch } from '../api.js';
|
||||
import { canEdit, pageHeaderHTML, showToast } from '../app.js';
|
||||
import {
|
||||
SOURCE_LANG,
|
||||
@ -406,10 +406,7 @@ function bindTranslationBundleActions() {
|
||||
const prev = exportBtn.textContent;
|
||||
exportBtn.textContent = 'Preparing…';
|
||||
try {
|
||||
const token = localStorage.getItem('qdb_token');
|
||||
const res = await fetch('../api/translations?exportBundle=1', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const res = await apiDownloadFetch('../api/translations?exportBundle=1');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err.error?.message || err.error || 'Export failed');
|
||||
|
||||
Reference in New Issue
Block a user