Basic data retrieval

This commit is contained in:
Michael Shamoon 2022-11-08 03:39:54 -08:00
parent ea38eb01b2
commit c3331086d5
9 changed files with 431 additions and 9 deletions

View File

@ -216,6 +216,37 @@
</ng-template>
</li>
<li [ngbNavItem]="4">
<a ngbNavLink i18n>Paperless Mail</a>
<ng-template ngbNavContent>
<h4 i18n>Mail accounts</h4>
<div formGroupName="mailAccounts">
<div *ngFor="let account of mailAccounts" [formGroupName]="account.id" class="row">
<div class="mb-3 col">
{{account.name}}
</div>
</div>
<div *ngIf="mailAccounts.length == 0" i18n>No mail accounts defined.</div>
</div>
<h4 i18n>Mail rules</h4>
<div formGroupName="mailRules">
<div *ngFor="let rule of mailRules" [formGroupName]="rule.id" class="row">
<div class="mb-3 col">
{{rule.name}}
</div>
</div>
<div *ngIf="mailRules.length == 0" i18n>No mail rules defined.</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>

View File

@ -29,6 +29,10 @@ import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
import { ActivatedRoute } from '@angular/router'
import { ViewportScroller } from '@angular/common'
import { TourService } from 'ngx-ui-tour-ng-bootstrap'
import { PaperlessMailAccount } from 'src/app/data/paperless-mail-account'
import { PaperlessMailRule } from 'src/app/data/paperless-mail-rule'
import { MailAccountService as MailAccountService } from 'src/app/services/rest/mail-account.service'
import { MailRuleService } from 'src/app/services/rest/mail-rule.service'
@Component({
selector: 'app-settings',
@ -40,6 +44,9 @@ export class SettingsComponent
{
savedViewGroup = new FormGroup({})
mailAccountGroup = new FormGroup({})
mailRuleGroup = new FormGroup({})
settingsForm = new FormGroup({
bulkEditConfirmationDialogs: new FormControl(null),
bulkEditApplyOnClose: new FormControl(null),
@ -50,20 +57,28 @@ export class SettingsComponent
darkModeInvertThumbs: new FormControl(null),
themeColor: new FormControl(null),
useNativePdfViewer: new FormControl(null),
savedViews: this.savedViewGroup,
displayLanguage: new FormControl(null),
dateLocale: new FormControl(null),
dateFormat: new FormControl(null),
commentsEnabled: new FormControl(null),
updateCheckingEnabled: new FormControl(null),
notificationsConsumerNewDocument: new FormControl(null),
notificationsConsumerSuccess: new FormControl(null),
notificationsConsumerFailed: new FormControl(null),
notificationsConsumerSuppressOnDashboard: new FormControl(null),
commentsEnabled: new FormControl(null),
updateCheckingEnabled: new FormControl(null),
savedViews: this.savedViewGroup,
mailAccounts: this.mailAccountGroup,
mailRules: this.mailRuleGroup,
})
savedViews: PaperlessSavedView[]
mailAccounts: PaperlessMailAccount[]
mailRules: PaperlessMailRule[]
store: BehaviorSubject<any>
storeSub: Subscription
isDirty$: Observable<boolean>
@ -81,6 +96,8 @@ export class SettingsComponent
constructor(
public savedViewService: SavedViewService,
public mailAccountService: MailAccountService,
public mailRuleService: MailRuleService,
private documentListViewService: DocumentListViewService,
private toastService: ToastService,
private settings: SettingsService,
@ -123,10 +140,13 @@ export class SettingsComponent
useNativePdfViewer: this.settings.get(
SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER
),
savedViews: {},
displayLanguage: this.settings.getLanguage(),
dateLocale: this.settings.get(SETTINGS_KEYS.DATE_LOCALE),
dateFormat: this.settings.get(SETTINGS_KEYS.DATE_FORMAT),
commentsEnabled: this.settings.get(SETTINGS_KEYS.COMMENTS_ENABLED),
updateCheckingEnabled: this.settings.get(
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED
),
notificationsConsumerNewDocument: this.settings.get(
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT
),
@ -139,17 +159,25 @@ export class SettingsComponent
notificationsConsumerSuppressOnDashboard: this.settings.get(
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD
),
commentsEnabled: this.settings.get(SETTINGS_KEYS.COMMENTS_ENABLED),
updateCheckingEnabled: this.settings.get(
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED
),
savedViews: {},
mailAccounts: {},
mailRules: {},
}
}
ngOnInit() {
this.savedViewService.listAll().subscribe((r) => {
this.savedViews = r.results
this.initialize()
this.mailAccountService.listAll().subscribe((r) => {
this.mailAccounts = r.results
this.mailRuleService.listAll().subscribe((r) => {
this.mailRules = r.results
this.initialize()
})
})
})
}
@ -176,6 +204,76 @@ export class SettingsComponent
)
}
for (let account of this.mailAccounts) {
storeData.mailAccounts[account.id.toString()] = {
id: account.id,
name: account.name,
imap_server: account.imap_server,
imap_port: account.imap_port,
imap_security: account.imap_security,
username: account.username,
password: account.password,
character_set: account.character_set,
}
this.mailAccountGroup.addControl(
account.id.toString(),
new FormGroup({
id: new FormControl(null),
name: new FormControl(null),
imap_server: new FormControl(null),
imap_port: new FormControl(null),
imap_security: new FormControl(null),
username: new FormControl(null),
password: new FormControl(null),
character_set: new FormControl(null),
})
)
}
for (let rule of this.mailRules) {
storeData.mailRules[rule.id.toString()] = {
name: rule.name,
order: rule.order,
account: rule.account,
folder: rule.folder,
filter_from: rule.filter_from,
filter_subject: rule.filter_subject,
filter_body: rule.filter_body,
filter_attachment_filename: rule.filter_attachment_filename,
maximum_age: rule.maximum_age,
attachment_type: rule.attachment_type,
action: rule.action,
action_parameter: rule.action_parameter,
assign_title_from: rule.assign_title_from,
assign_tags: rule.assign_tags,
assign_document_type: rule.assign_document_type,
assign_correspondent_from: rule.assign_correspondent_from,
assign_correspondent: rule.assign_correspondent,
}
this.mailRuleGroup.addControl(
rule.id.toString(),
new FormGroup({
name: new FormControl(null),
order: new FormControl(null),
account: new FormControl(null),
folder: new FormControl(null),
filter_from: new FormControl(null),
filter_subject: new FormControl(null),
filter_body: new FormControl(null),
filter_attachment_filename: new FormControl(null),
maximum_age: new FormControl(null),
attachment_type: new FormControl(null),
action: new FormControl(null),
action_parameter: new FormControl(null),
assign_title_from: new FormControl(null),
assign_tags: new FormControl(null),
assign_document_type: new FormControl(null),
assign_correspondent_from: new FormControl(null),
assign_correspondent: new FormControl(null),
})
)
}
this.store = new BehaviorSubject(storeData)
this.storeSub = this.store.asObservable().subscribe((state) => {

View File

@ -0,0 +1,23 @@
import { ObjectWithId } from './object-with-id'
export enum IMAPSecurity {
None = 0,
SSL = 1,
STARTTLS = 2,
}
export interface PaperlessMailAccount extends ObjectWithId {
name: string
imap_server: string
imap_port: number
imap_security: IMAPSecurity
username: string
password: string
character_set?: string
}

View File

@ -0,0 +1,66 @@
import { ObjectWithId } from './object-with-id'
import { PaperlessCorrespondent } from './paperless-correspondent'
import { PaperlessDocumentType } from './paperless-document-type'
import { PaperlessMailAccount } from './paperless-mail-account'
import { PaperlessTag } from './paperless-tag'
export enum MailFilterAttachmentType {
Attachments = 1,
Everything = 2,
}
export enum MailAction {
Delete = 1,
Move = 2,
MarkRead = 3,
Flag = 4,
Tag = 5,
}
export enum MailMetadataTitleOption {
FromSubject = 1,
FromFilename = 2,
}
export enum MailMetadataCorrespondentOption {
FromNothing = 1,
FromEmail = 2,
FromName = 3,
FromCustom = 4,
}
export interface PaperlessMailRule extends ObjectWithId {
name: string
order: number
account: PaperlessMailAccount
folder: string
filter_from: string
filter_subject: string
filter_body: string
filter_attachment_filename: string
maximum_age: number
attachment_type: MailFilterAttachmentType
action: MailAction
action_parameter?: string
assign_title_from: MailMetadataTitleOption
assign_tags?: PaperlessTag[]
assign_document_type?: PaperlessDocumentType
assign_correspondent_from?: MailMetadataCorrespondentOption
assign_correspondent?: PaperlessCorrespondent
}

View File

@ -0,0 +1,52 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { combineLatest, Observable } from 'rxjs'
import { tap } from 'rxjs/operators'
import { PaperlessMailAccount } from 'src/app/data/paperless-mail-account'
import { AbstractPaperlessService } from './abstract-paperless-service'
@Injectable({
providedIn: 'root',
})
export class MailAccountService extends AbstractPaperlessService<PaperlessMailAccount> {
loading: boolean
constructor(http: HttpClient) {
super(http, 'mail_accounts')
this.reload()
}
private reload() {
this.loading = true
this.listAll().subscribe((r) => {
this.mailAccounts = r.results
this.loading = false
})
}
private mailAccounts: PaperlessMailAccount[] = []
get allAccounts() {
return this.mailAccounts
}
create(o: PaperlessMailAccount) {
return super.create(o).pipe(tap(() => this.reload()))
}
update(o: PaperlessMailAccount) {
return super.update(o).pipe(tap(() => this.reload()))
}
patchMany(
objects: PaperlessMailAccount[]
): Observable<PaperlessMailAccount[]> {
return combineLatest(objects.map((o) => super.patch(o))).pipe(
tap(() => this.reload())
)
}
delete(o: PaperlessMailAccount) {
return super.delete(o).pipe(tap(() => this.reload()))
}
}

View File

@ -0,0 +1,50 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { combineLatest, Observable } from 'rxjs'
import { tap } from 'rxjs/operators'
import { PaperlessMailRule } from 'src/app/data/paperless-mail-rule'
import { AbstractPaperlessService } from './abstract-paperless-service'
@Injectable({
providedIn: 'root',
})
export class MailRuleService extends AbstractPaperlessService<PaperlessMailRule> {
loading: boolean
constructor(http: HttpClient) {
super(http, 'mail_rules')
this.reload()
}
private reload() {
this.loading = true
this.listAll().subscribe((r) => {
this.mailRules = r.results
this.loading = false
})
}
private mailRules: PaperlessMailRule[] = []
get allRules() {
return this.mailRules
}
create(o: PaperlessMailRule) {
return super.create(o).pipe(tap(() => this.reload()))
}
update(o: PaperlessMailRule) {
return super.update(o).pipe(tap(() => this.reload()))
}
patchMany(objects: PaperlessMailRule[]): Observable<PaperlessMailRule[]> {
return combineLatest(objects.map((o) => super.patch(o))).pipe(
tap(() => this.reload())
)
}
delete(o: PaperlessMailRule) {
return super.delete(o).pipe(tap(() => this.reload()))
}
}

View File

@ -28,6 +28,8 @@ from .models import UiSettings
from .models import PaperlessTask
from .parsers import is_mime_type_supported
from paperless_mail.models import MailAccount, MailRule
# https://www.django-rest-framework.org/api-guide/serializers/#example
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
@ -688,3 +690,61 @@ class AcknowledgeTasksViewSerializer(serializers.Serializer):
def validate_tasks(self, tasks):
self._validate_task_id_list(tasks)
return tasks
class MailAccountSerializer(serializers.ModelSerializer):
class Meta:
model = MailAccount
depth = 1
fields = [
"id",
"name",
"imap_server",
"imap_port",
"imap_security",
"username",
"password",
"character_set",
]
def update(self, instance, validated_data):
super().update(instance, validated_data)
return instance
def create(self, validated_data):
mail_account = MailAccount.objects.create(**validated_data)
return mail_account
class MailRuleSerializer(serializers.ModelSerializer):
class Meta:
model = MailRule
depth = 1
fields = [
"id",
"name",
"account",
"folder",
"filter_from",
"filter_subject",
"filter_body",
"filter_attachment_filename",
"maximum_age",
"action",
"action_parameter",
"assign_title_from",
"assign_tags",
"assign_correspondent_from",
"assign_correspondent",
"assign_document_type",
"order",
"attachment_type",
]
def update(self, instance, validated_data):
super().update(instance, validated_data)
return instance
def create(self, validated_data):
mail_rule = MailRule.objects.create(**validated_data)
return mail_rule

View File

@ -33,6 +33,8 @@ from packaging import version as packaging_version
from paperless import version
from paperless.db import GnuPG
from paperless.views import StandardPagination
from paperless_mail.models import MailAccount
from paperless_mail.models import MailRule
from rest_framework import parsers
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
@ -81,6 +83,8 @@ from .serialisers import CorrespondentSerializer
from .serialisers import DocumentListSerializer
from .serialisers import DocumentSerializer
from .serialisers import DocumentTypeSerializer
from .serialisers import MailAccountSerializer
from .serialisers import MailRuleSerializer
from .serialisers import PostDocumentSerializer
from .serialisers import SavedViewSerializer
from .serialisers import StoragePathSerializer
@ -910,3 +914,37 @@ class AcknowledgeTasksView(GenericAPIView):
return Response({"result": result})
except Exception:
return HttpResponseBadRequest()
class MailAccountViewSet(ModelViewSet):
model = MailAccount
queryset = MailAccount.objects.all()
serializer_class = MailAccountSerializer
pagination_class = StandardPagination
permission_classes = (IsAuthenticated,)
# TODO: user-scoped
# def get_queryset(self):
# user = self.request.user
# return MailAccount.objects.filter(user=user)
# def perform_create(self, serializer):
# serializer.save(user=self.request.user)
class MailRuleViewSet(ModelViewSet):
model = MailRule
queryset = MailRule.objects.all()
serializer_class = MailRuleSerializer
pagination_class = StandardPagination
permission_classes = (IsAuthenticated,)
# TODO: user-scoped
# def get_queryset(self):
# user = self.request.user
# return MailRule.objects.filter(user=user)
# def perform_create(self, serializer):
# serializer.save(user=self.request.user)

View File

@ -14,6 +14,8 @@ from documents.views import CorrespondentViewSet
from documents.views import DocumentTypeViewSet
from documents.views import IndexView
from documents.views import LogViewSet
from documents.views import MailAccountViewSet
from documents.views import MailRuleViewSet
from documents.views import PostDocumentView
from documents.views import RemoteVersionView
from documents.views import SavedViewViewSet
@ -39,6 +41,8 @@ api_router.register(r"tags", TagViewSet)
api_router.register(r"saved_views", SavedViewViewSet)
api_router.register(r"storage_paths", StoragePathViewSet)
api_router.register(r"tasks", TasksViewSet, basename="tasks")
api_router.register(r"mail_accounts", MailAccountViewSet)
api_router.register(r"mail_rules", MailRuleViewSet)
urlpatterns = [