mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
acknowledge_tasks endpoint & basic UI
Update tasks.service.ts
This commit is contained in:
parent
4bbaf5f89c
commit
0a06c291e2
@ -5,7 +5,7 @@
|
|||||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||||
</svg> <ng-container i18n>Clear selection</ng-container>
|
</svg> <ng-container i18n>Clear selection</ng-container>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-sm btn-outline-primary me-4" (click)="dismissMany()" [disabled]="tasksService.total == 0">
|
<button class="btn btn-sm btn-outline-primary me-4" (click)="dismissTasks()" [disabled]="tasksService.total == 0">
|
||||||
<svg class="sidebaricon" fill="currentColor">
|
<svg class="sidebaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#check2-all"/>
|
<use xlink:href="assets/bootstrap-icons.svg#check2-all"/>
|
||||||
</svg> <ng-container i18n>{{dismissButtonText}}</ng-container>
|
</svg> <ng-container i18n>{{dismissButtonText}}</ng-container>
|
||||||
|
@ -30,11 +30,13 @@ export class TasksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismissTask(task: PaperlessTask) {
|
dismissTask(task: PaperlessTask) {
|
||||||
throw new Error('Not implemented' + task)
|
this.dismissTasks(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissMany() {
|
dismissTasks(task: PaperlessTask = undefined) {
|
||||||
throw new Error('Not implemented')
|
this.tasksService.dismissTasks(
|
||||||
|
task ? new Set([task.id]) : this.selectedTasks
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSelected(task: PaperlessTask) {
|
toggleSelected(task: PaperlessTask) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { HttpClient } from '@angular/common/http'
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Observable } from 'rxjs'
|
|
||||||
import { first, map } from 'rxjs/operators'
|
import { first, map } from 'rxjs/operators'
|
||||||
import { PaperlessTask } from 'src/app/data/paperless-task'
|
import { PaperlessTask } from 'src/app/data/paperless-task'
|
||||||
import { environment } from 'src/environments/environment'
|
import { environment } from 'src/environments/environment'
|
||||||
@ -43,7 +42,7 @@ export class TasksService {
|
|||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
this.http
|
this.http
|
||||||
.get<TasksAPIResponse>(`${this.baseUrl}consumption_tasks/`)
|
.get<TasksAPIResponse>(`${this.baseUrl}tasks/`)
|
||||||
.pipe(first())
|
.pipe(first())
|
||||||
.subscribe((r) => {
|
.subscribe((r) => {
|
||||||
this.total = r.total
|
this.total = r.total
|
||||||
@ -55,35 +54,14 @@ export class TasksService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// private savedViews: PaperlessSavedView[] = []
|
public dismissTasks(task_ids: Set<number>) {
|
||||||
|
this.http
|
||||||
// get allViews() {
|
.post(`${this.baseUrl}acknowledge_tasks/`, {
|
||||||
// return this.savedViews
|
tasks: [...task_ids],
|
||||||
// }
|
})
|
||||||
|
.pipe(first())
|
||||||
// get sidebarViews() {
|
.subscribe((r) => {
|
||||||
// return this.savedViews.filter((v) => v.show_in_sidebar)
|
this.reload()
|
||||||
// }
|
})
|
||||||
|
}
|
||||||
// get dashboardViews() {
|
|
||||||
// return this.savedViews.filter((v) => v.show_on_dashboard)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// create(o: PaperlessSavedView) {
|
|
||||||
// return super.create(o).pipe(tap(() => this.reload()))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// update(o: PaperlessSavedView) {
|
|
||||||
// return super.update(o).pipe(tap(() => this.reload()))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// patchMany(objects: PaperlessSavedView[]): Observable<PaperlessSavedView[]> {
|
|
||||||
// return combineLatest(objects.map((o) => super.patch(o))).pipe(
|
|
||||||
// tap(() => this.reload())
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// delete(o: PaperlessSavedView) {
|
|
||||||
// return super.delete(o).pipe(tap(() => this.reload()))
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ from .models import Correspondent
|
|||||||
from .models import Document
|
from .models import Document
|
||||||
from .models import DocumentType
|
from .models import DocumentType
|
||||||
from .models import MatchingModel
|
from .models import MatchingModel
|
||||||
|
from .models import PaperlessTask
|
||||||
from .models import SavedView
|
from .models import SavedView
|
||||||
from .models import SavedViewFilterRule
|
from .models import SavedViewFilterRule
|
||||||
from .models import StoragePath
|
from .models import StoragePath
|
||||||
@ -597,9 +598,35 @@ class UiSettingsViewSerializer(serializers.ModelSerializer):
|
|||||||
return ui_settings
|
return ui_settings
|
||||||
|
|
||||||
|
|
||||||
class ConsupmtionTasksViewSerializer(serializers.Serializer):
|
class TasksViewSerializer(serializers.Serializer):
|
||||||
|
|
||||||
type = serializers.ChoiceField(
|
type = serializers.ChoiceField(
|
||||||
choices=["all", "incomplete", "complete", "failed"],
|
choices=["all", "incomplete", "complete", "failed"],
|
||||||
default="all",
|
default="all",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AcknowledgeTasksViewSerializer(serializers.Serializer):
|
||||||
|
|
||||||
|
tasks = serializers.ListField(
|
||||||
|
required=True,
|
||||||
|
label="Tasks",
|
||||||
|
write_only=True,
|
||||||
|
child=serializers.IntegerField(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _validate_task_id_list(self, tasks, name="tasks"):
|
||||||
|
pass
|
||||||
|
if not type(tasks) == list:
|
||||||
|
raise serializers.ValidationError(f"{name} must be a list")
|
||||||
|
if not all([type(i) == int for i in tasks]):
|
||||||
|
raise serializers.ValidationError(f"{name} must be a list of integers")
|
||||||
|
count = PaperlessTask.objects.filter(id__in=tasks).count()
|
||||||
|
if not count == len(tasks):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
f"Some tasks in {name} don't exist or were " f"specified twice.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate_tasks(self, tasks):
|
||||||
|
self._validate_task_id_list(tasks)
|
||||||
|
return tasks
|
||||||
|
@ -69,9 +69,9 @@ from .models import SavedView
|
|||||||
from .models import StoragePath
|
from .models import StoragePath
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
from .parsers import get_parser_class_for_mime_type
|
from .parsers import get_parser_class_for_mime_type
|
||||||
|
from .serialisers import AcknowledgeTasksViewSerializer
|
||||||
from .serialisers import BulkDownloadSerializer
|
from .serialisers import BulkDownloadSerializer
|
||||||
from .serialisers import BulkEditSerializer
|
from .serialisers import BulkEditSerializer
|
||||||
from .serialisers import ConsupmtionTasksViewSerializer
|
|
||||||
from .serialisers import CorrespondentSerializer
|
from .serialisers import CorrespondentSerializer
|
||||||
from .serialisers import DocumentListSerializer
|
from .serialisers import DocumentListSerializer
|
||||||
from .serialisers import DocumentSerializer
|
from .serialisers import DocumentSerializer
|
||||||
@ -81,6 +81,7 @@ from .serialisers import SavedViewSerializer
|
|||||||
from .serialisers import StoragePathSerializer
|
from .serialisers import StoragePathSerializer
|
||||||
from .serialisers import TagSerializer
|
from .serialisers import TagSerializer
|
||||||
from .serialisers import TagSerializerVersion1
|
from .serialisers import TagSerializerVersion1
|
||||||
|
from .serialisers import TasksViewSerializer
|
||||||
from .serialisers import UiSettingsViewSerializer
|
from .serialisers import UiSettingsViewSerializer
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.api")
|
logger = logging.getLogger("paperless.api")
|
||||||
@ -799,37 +800,37 @@ class UiSettingsView(GenericAPIView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConsupmtionTasksView(GenericAPIView):
|
class TasksView(GenericAPIView):
|
||||||
|
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
serializer_class = ConsupmtionTasksViewSerializer
|
serializer_class = TasksViewSerializer
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
consumption_tasks = (
|
tasks = (
|
||||||
PaperlessTask.objects.filter(
|
PaperlessTask.objects.filter(
|
||||||
acknowledged=False,
|
acknowledged=False,
|
||||||
)
|
)
|
||||||
.order_by("attempted_task__started")
|
.order_by("attempted_task__started")
|
||||||
.reverse()
|
.reverse()
|
||||||
)
|
)
|
||||||
incomplete_tasks = consumption_tasks.filter(task=None).values(
|
incomplete_tasks = tasks.filter(attempted_task=None).values(
|
||||||
"id",
|
"id",
|
||||||
"task_id",
|
"task_id",
|
||||||
"name",
|
"name",
|
||||||
"created",
|
"created",
|
||||||
"acknowledged",
|
"acknowledged",
|
||||||
)
|
)
|
||||||
failed_tasks = consumption_tasks.filter(attempted_task__success=0).values(
|
failed_tasks = tasks.filter(attempted_task__success=0).values(
|
||||||
"id",
|
"id",
|
||||||
"task_id",
|
"task_id",
|
||||||
"name",
|
"name",
|
||||||
"created",
|
"created",
|
||||||
"acknowledged",
|
"acknowledged",
|
||||||
)
|
)
|
||||||
completed_tasks = consumption_tasks.filter(attempted_task__success=1).values(
|
completed_tasks = tasks.filter(attempted_task__success=1).values(
|
||||||
"id",
|
"id",
|
||||||
"task_id",
|
"task_id",
|
||||||
"name",
|
"name",
|
||||||
@ -838,9 +839,31 @@ class ConsupmtionTasksView(GenericAPIView):
|
|||||||
)
|
)
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
"total": consumption_tasks.count(),
|
"total": tasks.count(),
|
||||||
"incomplete": incomplete_tasks,
|
"incomplete": incomplete_tasks,
|
||||||
"failed": failed_tasks,
|
"failed": failed_tasks,
|
||||||
"completed": completed_tasks,
|
"completed": completed_tasks,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AcknowledgeTasksView(GenericAPIView):
|
||||||
|
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
serializer_class = AcknowledgeTasksViewSerializer
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
tasks = serializer.validated_data.get("tasks")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.debug(tasks)
|
||||||
|
result = PaperlessTask.objects.filter(id__in=tasks).update(
|
||||||
|
acknowledged=True,
|
||||||
|
)
|
||||||
|
return Response({"result": result})
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return HttpResponseBadRequest(str(e))
|
||||||
|
@ -7,9 +7,9 @@ from django.urls import re_path
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
from documents.views import AcknowledgeTasksView
|
||||||
from documents.views import BulkDownloadView
|
from documents.views import BulkDownloadView
|
||||||
from documents.views import BulkEditView
|
from documents.views import BulkEditView
|
||||||
from documents.views import ConsupmtionTasksView
|
|
||||||
from documents.views import CorrespondentViewSet
|
from documents.views import CorrespondentViewSet
|
||||||
from documents.views import DocumentTypeViewSet
|
from documents.views import DocumentTypeViewSet
|
||||||
from documents.views import IndexView
|
from documents.views import IndexView
|
||||||
@ -22,6 +22,7 @@ from documents.views import SelectionDataView
|
|||||||
from documents.views import StatisticsView
|
from documents.views import StatisticsView
|
||||||
from documents.views import StoragePathViewSet
|
from documents.views import StoragePathViewSet
|
||||||
from documents.views import TagViewSet
|
from documents.views import TagViewSet
|
||||||
|
from documents.views import TasksView
|
||||||
from documents.views import UiSettingsView
|
from documents.views import UiSettingsView
|
||||||
from documents.views import UnifiedSearchViewSet
|
from documents.views import UnifiedSearchViewSet
|
||||||
from paperless.consumers import StatusConsumer
|
from paperless.consumers import StatusConsumer
|
||||||
@ -88,9 +89,14 @@ urlpatterns = [
|
|||||||
name="ui_settings",
|
name="ui_settings",
|
||||||
),
|
),
|
||||||
re_path(
|
re_path(
|
||||||
r"^consumption_tasks/",
|
r"^tasks/",
|
||||||
ConsupmtionTasksView.as_view(),
|
TasksView.as_view(),
|
||||||
name="consumption_tasks",
|
name="tasks",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r"^acknowledge_tasks/",
|
||||||
|
AcknowledgeTasksView.as_view(),
|
||||||
|
name="acknowledge_tasks",
|
||||||
),
|
),
|
||||||
path("token/", views.obtain_auth_token),
|
path("token/", views.obtain_auth_token),
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user