Skip to content

Add OCR and sync logging overviews to settings - #67

Merged
maxi07 merged 11 commits into
mainfrom
copilot/add-logging-overview
Jul 2, 2026
Merged

maxi07 merged 11 commits into
mainfrom
copilot/add-logging-overview

Conversation

Copilot AI commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Only file naming jobs were surfaced in the web UI; OCR and sync (upload) jobs had no visibility. This adds OCR and Sync log tables mirroring the existing File Naming logs.

Persistence

  • sync_jobs table added to schema.sql; the pre-existing but unused ocr_jobs table is now populated.
  • ocr_service writes a PROCESSING row on start and finalizes with status + a human-readable error on every completion/failure branch.
  • upload_service records the sync lifecycle (including missing-OCR-file and upload-failure paths) with a success flag and error description; ProcessItem gains sync_db_id.

API

  • New GET /api/ocr-logs and GET /api/sync-logs, paginated and filterable (all/success/failed), via a shared _fetch_job_logs helper. Table/filter fragments are hardcoded constants; only pagination values are bound parameters.

Frontend

  • OCR Logs accordion in the OCR tab; Sync Logs accordion in the OneDrive tab.
  • The per-table logs JS is consolidated into a reusable createLogsTable factory (own pagination/filter state, lazy-load on expand) driving all three tables:
createLogsTable({
    endpoint: '/api/ocr-logs',
    collapseId: 'ocr-logsCollapse', tableId: 'ocr-logs-table', /* ... */
    renderRow: (log) => `<tr><td>${log.id}</td><td>${getStatusBadge(log.ocr_status)}</td>...</tr>`
});
  • Full file-name/error text is shown via a data-fulltext attribute + addEventListener rather than inline onclick string interpolation, avoiding injection from unescaped backslashes.

Tests

  • tests/test_logs_api.py covers pagination, filters, null-count handling, and error responses for both endpoints.

Note: the click-to-expand uses alert() for parity with the existing File Naming table; a more accessible modal is left as a potential follow-up.

Copilot AI linked an issue Jul 2, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add logging overview for sync and OCR processes Add OCR and sync logging overviews to settings Jul 2, 2026
Copilot AI requested a review from maxi07 July 2, 2026 07:54
Copilot finished work on behalf of maxi07 July 2, 2026 07:54
@maxi07
maxi07 requested a review from Copilot July 2, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds end-to-end visibility for OCR and OneDrive sync (upload) job activity in the Settings UI, bringing those services to parity with the existing File Naming logs by persisting job lifecycle data, exposing new paginated API endpoints, and rendering new log tables in the frontend.

Changes:

  • Added persistence for OCR and Sync job lifecycles (ocr_jobs population + new sync_jobs table) from ocr_service and upload_service.
  • Added new paginated/filterable API endpoints (/api/ocr-logs, /api/sync-logs) using a shared _fetch_job_logs helper.
  • Extended the Settings UI with OCR and Sync log accordions and refactored frontend log rendering into a reusable createLogsTable factory.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web_service/src/templates/settings-tab/settings-tab-onedrive.html Adds a Sync Logs accordion/table to the OneDrive settings tab.
web_service/src/templates/settings-tab/settings-tab-ocr.html Replaces placeholder OCR text with an OCR Logs accordion/table.
web_service/src/static/js/settings.js Introduces createLogsTable/initLogTables and shared rendering helpers for all log tables.
web_service/src/routes/api.py Adds _fetch_job_logs plus new /api/ocr-logs and /api/sync-logs endpoints.
upload_service/main.py Inserts/updates sync_jobs records across the upload lifecycle.
tests/test_logs_api.py Adds API tests for OCR/sync logs pagination and filtering.
scansynclib/scansynclib/ProcessItem.py Adds sync_db_id field to ProcessItem.
scansynclib/scansynclib/db/schema.sql Adds the new sync_jobs table schema.
ocr_service/main.py Inserts ocr_jobs rows at start and finalizes status/error on completion/failure.

Comment thread web_service/src/routes/api.py Outdated
Comment on lines +277 to +281
page = int(request.args.get('page', 1))
per_page = int(request.args.get('per_page', 20))
filter = request.args.get('filter', 'all').lower()
offset = (page - 1) * per_page

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. Both params are now parsed inside try/except (ValueError, TypeError) blocks with safe defaults. page is clamped to max(1, ...) with no upper limit, and per_page is clamped to max(1, min(100, ...)) to prevent zero/negative values and unbounded queries.

Comment thread upload_service/main.py Outdated
Comment on lines +48 to +51
logger.exception(f"Failed processing {body}.")
item.status = ProcessStatus.SYNC_FAILED
update_scanneddata_database(item, {"file_status": item.status.value})
finalize_sync_job(item, "Unexpected error during upload")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. item is now initialized to None before the try block. The except clause checks item is not None and isinstance(item, ProcessItem) before updating status/DB, and additionally checks item.sync_db_id is not None before calling finalize_sync_job.

Comment thread tests/test_logs_api.py
Comment on lines +16 to +34
# Mock Redis before any scansynclib imports, since settings.py connects at module level
import redis as _real_redis
_orig_from_url = _real_redis.Redis.from_url


def _mock_from_url(*args, **kwargs):
mock_client = MagicMock()
mock_client.get.return_value = None # No existing settings in Redis
mock_client.set.return_value = True
mock_client.publish.return_value = 0
mock_pubsub = MagicMock()
mock_pubsub.subscribe.return_value = None
mock_pubsub.listen.return_value = iter([]) # Empty iterator
mock_client.pubsub.return_value = mock_pubsub
return mock_client


_real_redis.Redis.from_url = _mock_from_url

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. The module-level assignment and the unused _orig_from_url have been removed. The patch is now applied and torn down in a @pytest.fixture(scope="session", autouse=True) fixture that saves the original, yields, and restores it—preventing any leak into other test modules.

Copilot finished work on behalf of maxi07 July 2, 2026 15:12
@maxi07

maxi07 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

@copilot I dont like your addition of the our status text within a JS file and the except blocks within ocr_service/main.py. Please, similar to the ProcessItem definition, define all the error descriptions for the OCR failures once and make them reusable, so we can display the message also to the user in the web instead of creating new error messages in the js file with getOcrStatusText.

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot I dont like your addition of the our status text within a JS file and the except blocks within ocr_service/main.py. Please, similar to the ProcessItem definition, define all the error descrip...

Done. Here's what changed:

  1. scansynclib/ProcessItem.py – OCRStatus now follows the same pattern as FileNamingStatus: each member's .value is its human-readable description (e.g. DPI_ERROR = "Image DPI too low for accurate OCR").

  2. ocr_service/main.py – All ad-hoc string literals in except blocks are replaced with OCRStatus.<STATUS>.value, with exception detail appended where available (e.g. f"{OCRStatus.DPI_ERROR.value}: {dpiex}").

  3. web_service/src/routes/api.py – The /api/ocr-logs response enriches each log entry with ocr_status_text = OCRStatus[status_name].value, so the frontend receives the server-defined description directly.

  4. settings.js – getStatusBadge accepts an optional displayText parameter; the OCR logs row passes log.ocr_status_text so the badge uses the Python-defined text instead of a JS toTitleCase conversion.

Copilot finished work on behalf of maxi07 July 2, 2026 15:56
@maxi07
maxi07 requested a review from Copilot July 2, 2026 16:08
@maxi07
maxi07 marked this pull request as ready for review July 2, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comment thread ocr_service/main.py
Comment thread scansynclib/scansynclib.egg-info/SOURCES.txt Outdated
maxi07 and others added 2 commits July 2, 2026 18:13
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@maxi07

maxi07 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Done. Merged origin/main into this branch in commit e126ae6. The only conflicts were in scansynclib/ProcessItem.py and ocr_service/main.py:

  • ProcessItem.py: Kept our string enum values for OCRStatus and added the new NO_TEXT = "No text found in OCR output" member from main.
  • ocr_service/main.py: Used main's refined structure (result=None init, if item.ocr_db_id guard, OCRStatus.NO_TEXT for the no-text-found path) and removed the duplicate DB INSERT/ocr_error declarations left by the conflict markers. Error strings match the existing test expectations in test_ocr_job_tracking.py.

Copilot finished work on behalf of maxi07 July 2, 2026 16:29
@maxi07
maxi07 merged commit 512ca42 into main Jul 2, 2026
4 checks passed
@maxi07
maxi07 deleted the copilot/add-logging-overview branch July 2, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a logging overview

3 participants