mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
			4e0f5dff95
			...
			feature-in
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f20b224ef5 | ||
|   | 8344a6e0e3 | ||
|   | 10a8a5da19 | ||
|   | d190b50032 | ||
|   | fda29f51c3 | 
| @@ -1,4 +1,9 @@ | ||||
| <pngx-page-header [(title)]="title"> | ||||
|   @if (document?.in_process) { | ||||
|     <span class="badge bg-danger text-dark ms-2 d-flex align-items-center"> | ||||
|       <div class="spinner-border spinner-border-sm me-1" role="status"></div><span i18n>Processing...</span> | ||||
|     </span> | ||||
|   } | ||||
|   @if (archiveContentRenderType === ContentRenderType.PDF && !useNativePdfViewer) { | ||||
|     @if (previewNumPages) { | ||||
|       <div class="input-group input-group-sm d-none d-md-flex"> | ||||
| @@ -50,7 +55,7 @@ | ||||
|       <div class="d-none d-sm-inline"> <ng-container i18n>Actions</ng-container></div> | ||||
|     </button> | ||||
|     <div ngbDropdownMenu aria-labelledby="actionsDropdown" class="shadow"> | ||||
|       <button ngbDropdownItem (click)="reprocess()" [disabled]="!userCanEdit || !userIsOwner"> | ||||
|       <button ngbDropdownItem (click)="reprocess()" [disabled]="!userCanEdit || !userIsOwner || document?.in_process"> | ||||
|         <i-bs width="1em" height="1em" name="arrow-counterclockwise"></i-bs> <span i18n>Reprocess</span> | ||||
|       </button> | ||||
|  | ||||
| @@ -58,7 +63,7 @@ | ||||
|         <i-bs width="1em" height="1em" name="diagram-3"></i-bs> <span i18n>More like this</span> | ||||
|       </button> | ||||
|  | ||||
|       <button ngbDropdownItem (click)="editPdf()" [disabled]="!userIsOwner || !userCanEdit || originalContentRenderType !== ContentRenderType.PDF"> | ||||
|       <button ngbDropdownItem (click)="editPdf()" [disabled]="!userIsOwner || !userCanEdit || originalContentRenderType !== ContentRenderType.PDF || document?.in_process"> | ||||
|         <i-bs name="pencil"></i-bs> <ng-container i18n>PDF Editor</ng-container> | ||||
|       </button> | ||||
|     </div> | ||||
| @@ -90,7 +95,6 @@ | ||||
|       } | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
| </pngx-page-header> | ||||
|  | ||||
| <div class="row"> | ||||
|   | ||||
| @@ -17,6 +17,11 @@ | ||||
|     </div> | ||||
|   <div class="col col-md-10"> | ||||
|       <div class="card-body"> | ||||
|         @if (document?.in_process) { | ||||
|           <span class="badge bg-secondary text-light mb-2"> | ||||
|             <div class="spinner-border spinner-border-sm me-1" role="status"></div><span i18n>Processing...</span> | ||||
|           </span> | ||||
|         } | ||||
|         <div class="d-flex justify-content-between align-items-center"> | ||||
|           <h5 class="card-title w-100"> | ||||
|             @if (document) { | ||||
|   | ||||
| @@ -37,6 +37,11 @@ | ||||
|     } | ||||
|  | ||||
|     <div class="card-body bg-light p-2"> | ||||
|       @if (document?.in_process) { | ||||
|         <span class="badge bg-secondary text-light mb-2"> | ||||
|           <div class="spinner-border spinner-border-sm me-1" role="status"></div><span i18n>Processing...</span> | ||||
|         </span> | ||||
|       } | ||||
|       <p class="card-text"> | ||||
|         @if (document) { | ||||
|           @if (displayFields.includes(DisplayField.CORRESPONDENT) && document.correspondent) { | ||||
|   | ||||
| @@ -301,6 +301,11 @@ | ||||
|                 } | ||||
|                 @if (activeDisplayFields.includes(DisplayField.TITLE) || activeDisplayFields.includes(DisplayField.TAGS)) { | ||||
|                   <td width="30%"> | ||||
|                     @if (d.in_process) { | ||||
|                       <span class="badge bg-secondary text-light me-1"> | ||||
|                         <div class="spinner-border spinner-border-sm me-1" role="status"></div><span i18n>Processing...</span> | ||||
|                       </span> | ||||
|                     } | ||||
|                     @if (activeDisplayFields.includes(DisplayField.TITLE)) { | ||||
|                       <div class="d-inline-block" (mouseleave)="popupPreview.close()"> | ||||
|                         <a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a> | ||||
|   | ||||
| @@ -159,6 +159,8 @@ export interface Document extends ObjectWithPermissions { | ||||
|  | ||||
|   page_count?: number | ||||
|  | ||||
|   in_process?: boolean | ||||
|  | ||||
|   // Frontend only | ||||
|   __changedFields?: string[] | ||||
| } | ||||
|   | ||||
| @@ -283,6 +283,7 @@ def rotate(doc_ids: list[int], degrees: int) -> Literal["OK"]: | ||||
|         f"Attempting to rotate {len(doc_ids)} documents by {degrees} degrees.", | ||||
|     ) | ||||
|     qs = Document.objects.filter(id__in=doc_ids) | ||||
|     Document.objects.filter(pk__in=doc_ids).update(in_process=True) | ||||
|     affected_docs: list[int] = [] | ||||
|     import pikepdf | ||||
|  | ||||
| @@ -309,7 +310,9 @@ def rotate(doc_ids: list[int], degrees: int) -> Literal["OK"]: | ||||
|                     f"Rotated document {doc.id} by {degrees} degrees", | ||||
|                 ) | ||||
|                 affected_docs.append(doc.id) | ||||
|                 Document.objects.filter(pk__in=doc_ids).update(in_process=False) | ||||
|         except Exception as e: | ||||
|             Document.objects.filter(pk__in=doc_ids).update(in_process=False) | ||||
|             logger.exception(f"Error rotating document {doc.id}: {e}") | ||||
|  | ||||
|     if len(affected_docs) > 0: | ||||
| @@ -474,6 +477,7 @@ def delete_pages(doc_ids: list[int], pages: list[int]) -> Literal["OK"]: | ||||
|         f"Attempting to delete pages {pages} from {len(doc_ids)} documents", | ||||
|     ) | ||||
|     doc = Document.objects.get(id=doc_ids[0]) | ||||
|     Document.objects.filter(pk=doc.id).update(in_process=True) | ||||
|     pages = sorted(pages)  # sort pages to avoid index issues | ||||
|     import pikepdf | ||||
|  | ||||
| @@ -492,6 +496,7 @@ def delete_pages(doc_ids: list[int], pages: list[int]) -> Literal["OK"]: | ||||
|             update_document_content_maybe_archive_file.delay(document_id=doc.id) | ||||
|             logger.info(f"Deleted pages {pages} from document {doc.id}") | ||||
|     except Exception as e: | ||||
|         Document.objects.filter(pk=doc.id).update(in_process=False) | ||||
|         logger.exception(f"Error deleting pages from document {doc.id}: {e}") | ||||
|  | ||||
|     return "OK" | ||||
| @@ -518,6 +523,7 @@ def edit_pdf( | ||||
|         f"Editing PDF of document {doc_ids[0]} with {len(operations)} operations", | ||||
|     ) | ||||
|     doc = Document.objects.get(id=doc_ids[0]) | ||||
|     Document.objects.filter(pk=doc.id).update(in_process=True) | ||||
|     import pikepdf | ||||
|  | ||||
|     pdf_docs: list[pikepdf.Pdf] = [] | ||||
| @@ -587,6 +593,7 @@ def edit_pdf( | ||||
|  | ||||
|     except Exception as e: | ||||
|         logger.exception(f"Error editing document {doc.id}: {e}") | ||||
|         Document.objects.filter(pk=doc.id).update(in_process=False) | ||||
|         raise ValueError( | ||||
|             f"An error occurred while editing the document: {e}", | ||||
|         ) from e | ||||
|   | ||||
							
								
								
									
										23
									
								
								src/documents/migrations/1069_document_in_process.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/documents/migrations/1069_document_in_process.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Generated by Django 5.2.5 on 2025-08-26 07:54 | ||||
|  | ||||
| from django.db import migrations | ||||
| from django.db import models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ("documents", "1068_alter_document_created"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name="document", | ||||
|             name="in_process", | ||||
|             field=models.BooleanField( | ||||
|                 db_index=True, | ||||
|                 default=False, | ||||
|                 help_text="Whether the document is currently being processed.", | ||||
|                 verbose_name="in process", | ||||
|             ), | ||||
|         ), | ||||
|     ] | ||||
| @@ -289,6 +289,13 @@ class Document(SoftDeleteModel, ModelWithOwner): | ||||
|         ), | ||||
|     ) | ||||
|  | ||||
|     in_process = models.BooleanField( | ||||
|         _("in process"), | ||||
|         default=False, | ||||
|         db_index=True, | ||||
|         help_text=_("Whether the document is currently being processed."), | ||||
|     ) | ||||
|  | ||||
|     class Meta: | ||||
|         ordering = ("-created",) | ||||
|         verbose_name = _("document") | ||||
|   | ||||
| @@ -935,6 +935,8 @@ class DocumentSerializer( | ||||
|         required=False, | ||||
|     ) | ||||
|  | ||||
|     in_process = serializers.BooleanField(read_only=True) | ||||
|  | ||||
|     def get_page_count(self, obj) -> int | None: | ||||
|         return obj.page_count | ||||
|  | ||||
| @@ -1103,6 +1105,7 @@ class DocumentSerializer( | ||||
|             "remove_inbox_tags", | ||||
|             "page_count", | ||||
|             "mime_type", | ||||
|             "in_process", | ||||
|         ) | ||||
|         list_serializer_class = OwnedObjectListSerializer | ||||
|  | ||||
|   | ||||
| @@ -250,6 +250,7 @@ def update_document_content_maybe_archive_file(document_id): | ||||
|     it exists. | ||||
|     """ | ||||
|     document = Document.objects.get(id=document_id) | ||||
|     Document.objects.filter(pk=document_id).update(in_process=True) | ||||
|  | ||||
|     mime_type = document.mime_type | ||||
|  | ||||
| @@ -349,6 +350,7 @@ def update_document_content_maybe_archive_file(document_id): | ||||
|         ) | ||||
|     finally: | ||||
|         parser.cleanup() | ||||
|         Document.objects.filter(pk=document_id).update(in_process=False) | ||||
|  | ||||
|  | ||||
| @shared_task | ||||
|   | ||||
		Reference in New Issue
	
	Block a user