acknowledge_tasks endpoint & basic UI

Update tasks.service.ts
This commit is contained in:
Michael Shamoon 2022-05-23 10:45:14 -07:00
parent 4bbaf5f89c
commit 0a06c291e2
6 changed files with 86 additions and 50 deletions

View File

@ -5,7 +5,7 @@
<use xlink:href="assets/bootstrap-icons.svg#x"/>
</svg>&nbsp;<ng-container i18n>Clear selection</ng-container>
</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">
<use xlink:href="assets/bootstrap-icons.svg#check2-all"/>
</svg>&nbsp;<ng-container i18n>{{dismissButtonText}}</ng-container>

View File

@ -30,11 +30,13 @@ export class TasksComponent implements OnInit, OnDestroy {
}
dismissTask(task: PaperlessTask) {
throw new Error('Not implemented' + task)
this.dismissTasks(task)
}
dismissMany() {
throw new Error('Not implemented')
dismissTasks(task: PaperlessTask = undefined) {
this.tasksService.dismissTasks(
task ? new Set([task.id]) : this.selectedTasks
)
}
toggleSelected(task: PaperlessTask) {

View File

@ -1,6 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { first, map } from 'rxjs/operators'
import { PaperlessTask } from 'src/app/data/paperless-task'
import { environment } from 'src/environments/environment'
@ -43,7 +42,7 @@ export class TasksService {
this.loading = true
this.http
.get<TasksAPIResponse>(`${this.baseUrl}consumption_tasks/`)
.get<TasksAPIResponse>(`${this.baseUrl}tasks/`)
.pipe(first())
.subscribe((r) => {
this.total = r.total
@ -55,35 +54,14 @@ export class TasksService {
})
}
// private savedViews: PaperlessSavedView[] = []
// get allViews() {
// return this.savedViews
// }
// get sidebarViews() {
// return this.savedViews.filter((v) => v.show_in_sidebar)
// }
// 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()))
// }
public dismissTasks(task_ids: Set<number>) {
this.http
.post(`${this.baseUrl}acknowledge_tasks/`, {
tasks: [...task_ids],
})
.pipe(first())
.subscribe((r) => {
this.reload()
})
}
}

View File

@ -12,6 +12,7 @@ from .models import Correspondent
from .models import Document
from .models import DocumentType
from .models import MatchingModel
from .models import PaperlessTask
from .models import SavedView
from .models import SavedViewFilterRule
from .models import StoragePath
@ -597,9 +598,35 @@ class UiSettingsViewSerializer(serializers.ModelSerializer):
return ui_settings
class ConsupmtionTasksViewSerializer(serializers.Serializer):
class TasksViewSerializer(serializers.Serializer):
type = serializers.ChoiceField(
choices=["all", "incomplete", "complete", "failed"],
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

View File

@ -69,9 +69,9 @@ from .models import SavedView
from .models import StoragePath
from .models import Tag
from .parsers import get_parser_class_for_mime_type
from .serialisers import AcknowledgeTasksViewSerializer
from .serialisers import BulkDownloadSerializer
from .serialisers import BulkEditSerializer
from .serialisers import ConsupmtionTasksViewSerializer
from .serialisers import CorrespondentSerializer
from .serialisers import DocumentListSerializer
from .serialisers import DocumentSerializer
@ -81,6 +81,7 @@ from .serialisers import SavedViewSerializer
from .serialisers import StoragePathSerializer
from .serialisers import TagSerializer
from .serialisers import TagSerializerVersion1
from .serialisers import TasksViewSerializer
from .serialisers import UiSettingsViewSerializer
logger = logging.getLogger("paperless.api")
@ -799,37 +800,37 @@ class UiSettingsView(GenericAPIView):
)
class ConsupmtionTasksView(GenericAPIView):
class TasksView(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = ConsupmtionTasksViewSerializer
serializer_class = TasksViewSerializer
def get(self, request, format=None):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
consumption_tasks = (
tasks = (
PaperlessTask.objects.filter(
acknowledged=False,
)
.order_by("attempted_task__started")
.reverse()
)
incomplete_tasks = consumption_tasks.filter(task=None).values(
incomplete_tasks = tasks.filter(attempted_task=None).values(
"id",
"task_id",
"name",
"created",
"acknowledged",
)
failed_tasks = consumption_tasks.filter(attempted_task__success=0).values(
failed_tasks = tasks.filter(attempted_task__success=0).values(
"id",
"task_id",
"name",
"created",
"acknowledged",
)
completed_tasks = consumption_tasks.filter(attempted_task__success=1).values(
completed_tasks = tasks.filter(attempted_task__success=1).values(
"id",
"task_id",
"name",
@ -838,9 +839,31 @@ class ConsupmtionTasksView(GenericAPIView):
)
return Response(
{
"total": consumption_tasks.count(),
"total": tasks.count(),
"incomplete": incomplete_tasks,
"failed": failed_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))

View File

@ -7,9 +7,9 @@ from django.urls import re_path
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import RedirectView
from documents.views import AcknowledgeTasksView
from documents.views import BulkDownloadView
from documents.views import BulkEditView
from documents.views import ConsupmtionTasksView
from documents.views import CorrespondentViewSet
from documents.views import DocumentTypeViewSet
from documents.views import IndexView
@ -22,6 +22,7 @@ from documents.views import SelectionDataView
from documents.views import StatisticsView
from documents.views import StoragePathViewSet
from documents.views import TagViewSet
from documents.views import TasksView
from documents.views import UiSettingsView
from documents.views import UnifiedSearchViewSet
from paperless.consumers import StatusConsumer
@ -88,9 +89,14 @@ urlpatterns = [
name="ui_settings",
),
re_path(
r"^consumption_tasks/",
ConsupmtionTasksView.as_view(),
name="consumption_tasks",
r"^tasks/",
TasksView.as_view(),
name="tasks",
),
re_path(
r"^acknowledge_tasks/",
AcknowledgeTasksView.as_view(),
name="acknowledge_tasks",
),
path("token/", views.obtain_auth_token),
]