Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat document type and storage path #298

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions source/VMelnalksnis.PaperlessDotNet/DocumentTypes/DocumentType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using NodaTime;

using VMelnalksnis.PaperlessDotNet.Correspondents;

namespace VMelnalksnis.PaperlessDotNet.DocumentTypes;

/// <summary>A type of document with whom documents were exchanged with.</summary>
public sealed class DocumentType
{
/// <summary>Gets or sets the id of the document type.</summary>
public int Id { get; set; }

/// <summary>Gets or sets the normalized <see cref="Name"/> - lowercased and with whitespace replaced with '-'.</summary>
public string Slug { get; set; } = null!;

/// <summary>Gets or sets the name of the document type.</summary>
public string Name { get; set; } = null!;

/// <summary>Gets or sets the pattern by which to match the document type to documents.</summary>
public string MatchingPattern { get; set; } = null!;

/// <summary>Gets or sets the id of the matching algorithm used to match the document type to documents.</summary>
public MatchingAlgorithm MatchingAlgorithm { get; set; } = null!;

/// <summary>Gets or sets a value indicating whether to ignore case when matching the document type to documents.</summary>
public bool IsInsensitive { get; set; }

/// <summary>Gets or sets the number of documents with the document type.</summary>
public int DocumentCount { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

using VMelnalksnis.PaperlessDotNet.Serialization;

namespace VMelnalksnis.PaperlessDotNet.DocumentTypes;

/// <inheritdoc />
public sealed class DocumentTypeClient : IDocumentTypeClient
{
private readonly HttpClient _httpClient;
private readonly JsonSerializerOptions _options;

/// <summary>Initializes a new instance of the <see cref="DocumentTypeClient"/> class.</summary>
/// <param name="httpClient">Http client configured for making requests to the Paperless API.</param>
/// <param name="serializerOptions">Paperless specific instance of <see cref="JsonSerializerOptions"/>.</param>
public DocumentTypeClient(HttpClient httpClient, PaperlessJsonSerializerOptions serializerOptions)
{
_httpClient = httpClient;
_options = serializerOptions.Options;
}

/// <inheritdoc />
public IAsyncEnumerable<DocumentType> GetAll(CancellationToken cancellationToken = default)
{
return GetAllCore(Routes.DocumentTypes.Uri, cancellationToken);
}

/// <inheritdoc />
public IAsyncEnumerable<DocumentType> GetAll(int pageSize, CancellationToken cancellationToken = default)
{
return GetAllCore(Routes.DocumentTypes.PagedUri(pageSize), cancellationToken);
}

/// <inheritdoc />
public Task<DocumentType?> Get(int id, CancellationToken cancellationToken = default)
{
return _httpClient.GetFromJsonAsync(
Routes.DocumentTypes.IdUri(id),
_options.GetTypeInfo<DocumentType>(),
cancellationToken);
}

/// <inheritdoc />
public Task<DocumentType> Create(DocumentTypeCreation documentType)
{
return _httpClient.PostAsJsonAsync(
Routes.DocumentTypes.Uri,
documentType,
_options.GetTypeInfo<DocumentTypeCreation>(),
_options.GetTypeInfo<DocumentType>());
}

/// <inheritdoc />
public async Task Delete(int id)
{
using var response = await _httpClient.DeleteAsync(Routes.DocumentTypes.IdUri(id)).ConfigureAwait(false);
await response.EnsureSuccessStatusCodeAsync().ConfigureAwait(false);
}

private IAsyncEnumerable<DocumentType> GetAllCore(Uri requestUri, CancellationToken cancellationToken)
{
return _httpClient.GetPaginated(
requestUri,
_options.GetTypeInfo<PaginatedList<DocumentType>>(),
cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using VMelnalksnis.PaperlessDotNet.Correspondents;

namespace VMelnalksnis.PaperlessDotNet.DocumentTypes;

/// <summary>Information needed to create a new <see cref="DocumentType"/>.</summary>
public sealed class DocumentTypeCreation
{
/// <summary>Initializes a new instance of the <see cref="DocumentTypeCreation"/> class.</summary>
/// <param name="name">The name of the document type.</param>
public DocumentTypeCreation(string name)
{
Name = name;
}

/// <inheritdoc cref="DocumentType.Slug"/>
public string? Slug { get; set; }

/// <inheritdoc cref="DocumentType.Name"/>
public string Name { get; set; }

/// <inheritdoc cref="DocumentType.MatchingPattern"/>
public string? Match { get; set; }

/// <inheritdoc cref="DocumentType.MatchingAlgorithm"/>
public MatchingAlgorithm? MatchingAlgorithm { get; set; }

/// <inheritdoc cref="DocumentType.IsInsensitive"/>
public bool? IsInsensitive { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace VMelnalksnis.PaperlessDotNet.DocumentTypes;

/// <summary>Paperless API client for working with correspondents.</summary>
public interface IDocumentTypeClient
{
/// <summary>Gets all document types.</summary>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>A enumerable which will asynchronously iterate over all available pages of document types.</returns>
IAsyncEnumerable<DocumentType> GetAll(CancellationToken cancellationToken = default);

/// <summary>Gets all document types.</summary>
/// <param name="pageSize">The number of document types to get in a single request.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>A enumerable which will asynchronously iterate over all available pages of document types.</returns>
IAsyncEnumerable<DocumentType> GetAll(int pageSize, CancellationToken cancellationToken = default);

/// <summary>Gets the document type with the specified id.</summary>
/// <param name="id">The id of the document type to get.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>The document type with the specified id if it exists; otherwise <see langword="null"/>.</returns>
Task<DocumentType?> Get(int id, CancellationToken cancellationToken = default);

/// <summary>Creates a new document type.</summary>
/// <param name="documentType">The correspondent to create.</param>
/// <returns>The created correspondent.</returns>
Task<DocumentType> Create(DocumentTypeCreation documentType);

/// <summary>Deletes a document type.</summary>
/// <param name="id">The id of the document type to delete.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task Delete(int id);
}
11 changes: 11 additions & 0 deletions source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ public async IAsyncEnumerable<Document<TFields>> GetAll<TFields>(int pageSize, [
}
}

/// <summary>
/// Gets all documents tagged with a certain tag Id.
/// </summary>
/// <param name="tagId">Id of the tag for which to retrieve all documents.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>An enumerable which will asynchronously iterate over all retrieved documents.</returns>
public IAsyncEnumerable<Document> GetAllByTagId(int tagId, CancellationToken cancellationToken = default)
{
return GetAllCore<Document>(Routes.Documents.ByTagIdUri(tagId), cancellationToken);
}

/// <inheritdoc />
public Task<Document?> Get(int id, CancellationToken cancellationToken = default)
{
Expand Down
22 changes: 22 additions & 0 deletions source/VMelnalksnis.PaperlessDotNet/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
private const string _correspondents = "/api/correspondents/";
private const string _customFields = "/api/custom_fields/";
private const string _documents = "/api/documents/";
private const string _documenttypes = "/api/document_types/";
private const string _storagepaths = "/api/storage_paths/";
private const string _tags = "/api/tags/";
private const string _tasks = "/api/tasks/";

Expand All @@ -27,6 +29,15 @@
internal static Uri PagedUri(int pageSize) => new($"{_correspondents}?{_pageSize}={pageSize}", Relative);
}

internal static class DocumentTypes
{
internal static readonly Uri Uri = new(_documenttypes, Relative);

internal static Uri IdUri(int id) => new($"{_documenttypes}{id}/", Relative);

internal static Uri PagedUri(int pageSize) => new($"{_documenttypes}?{_pageSize}={pageSize}", Relative);
}

Check failure on line 40 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Resharper

Check failure on line 40 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Resharper

Check failure on line 40 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check failure on line 40 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Run tests

internal static class CustomFields
{
internal static readonly Uri Uri = new(_customFields, Relative);
Expand All @@ -39,6 +50,8 @@
internal static readonly Uri Uri = new(_documents, Relative);
internal static readonly Uri CreateUri = new($"{_documents}post_document/", Relative);

internal static Uri ByTagIdUri(int id) => new($"{_documents}?tags__id__all={id}", Relative);

internal static Uri IdUri(int id) => new($"{_documents}{id}/", Relative);

internal static Uri MetadataUri(int id) => new($"{_documents}{id}/metadata/", Relative);
Expand All @@ -56,6 +69,15 @@
internal static Uri PagedUri(int pageSize) => new($"{_documents}?{_pageSize}={pageSize}", Relative);
}

internal static class StoragePaths
{
internal static readonly Uri Uri = new(_storagepaths, Relative);

internal static Uri IdUri(int id) => new($"{_storagepaths}{id}/", Relative);

internal static Uri PagedUri(int pageSize) => new($"{_storagepaths}?{_pageSize}={pageSize}", Relative);
}

Check failure on line 80 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Resharper

Check failure on line 80 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Resharper

Check failure on line 80 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Run tests

Check failure on line 80 in source/VMelnalksnis.PaperlessDotNet/Routes.cs

View workflow job for this annotation

GitHub Actions / Run tests

internal static class Tags
{
internal static readonly Uri Uri = new(_tags, Relative);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

using VMelnalksnis.PaperlessDotNet.Correspondents;
using VMelnalksnis.PaperlessDotNet.Documents;
using VMelnalksnis.PaperlessDotNet.DocumentTypes;
using VMelnalksnis.PaperlessDotNet.StoragePaths;
using VMelnalksnis.PaperlessDotNet.Tags;
using VMelnalksnis.PaperlessDotNet.Tasks;

Expand All @@ -20,6 +22,8 @@ namespace VMelnalksnis.PaperlessDotNet.Serialization;
[JsonSerializable(typeof(CorrespondentCreation))]
[JsonSerializable(typeof(PaginatedList<Document>))]
[JsonSerializable(typeof(Document))]
[JsonSerializable(typeof(DocumentType))]
Copy link
Owner

Choose a reason for hiding this comment

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

Need to also add DocumentTypeCreation and StoragePathCreation

[JsonSerializable(typeof(StoragePath))]
[JsonSerializable(typeof(List<PaperlessTask>))]
[JsonSerializable(typeof(CustomFieldCreation))]
[JsonSerializable(typeof(List<CustomField>))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace VMelnalksnis.PaperlessDotNet.StoragePaths;

/// <summary>Paperless API client for working with correspondents.</summary>
public interface IStoragePathClient
{
/// <summary>Gets all storage paths.</summary>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>A enumerable which will asynchronously iterate over all available pages of storage paths.</returns>
IAsyncEnumerable<StoragePath> GetAll(CancellationToken cancellationToken = default);

/// <summary>Gets all storage paths.</summary>
/// <param name="pageSize">The number of storage paths to get in a single request.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>A enumerable which will asynchronously iterate over all available pages of storage paths.</returns>
IAsyncEnumerable<StoragePath> GetAll(int pageSize, CancellationToken cancellationToken = default);

/// <summary>Gets the storage path with the specified id.</summary>
/// <param name="id">The id of the storage path to get.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <returns>The storage path with the specified id if it exists; otherwise <see langword="null"/>.</returns>
Task<StoragePath?> Get(int id, CancellationToken cancellationToken = default);

/// <summary>Creates a new storage path.</summary>
/// <param name="storagePath">The correspondent to create.</param>
/// <returns>The created correspondent.</returns>
Task<StoragePath> Create(StoragePathCreation storagePath);

/// <summary>Deletes a storage path.</summary>
/// <param name="id">The id of the storage path to delete.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task Delete(int id);
}
37 changes: 37 additions & 0 deletions source/VMelnalksnis.PaperlessDotNet/StoragePaths/StoragePath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2022 Valters Melnalksnis
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

using NodaTime;

using VMelnalksnis.PaperlessDotNet.Correspondents;

namespace VMelnalksnis.PaperlessDotNet.StoragePaths;

/// <summary>A type of document with whom documents were exchanged with.</summary>
public sealed class StoragePath
{
/// <summary>Gets or sets the id of the storage path.</summary>
public int Id { get; set; }

/// <summary>Gets or sets the normalized <see cref="Name"/> - lowercased and with whitespace replaced with '-'.</summary>
public string Slug { get; set; } = null!;

/// <summary>Gets or sets the name of the storage path.</summary>
public string Name { get; set; } = null!;

/// <summary>Gets or sets the path of the storage path.</summary>
public string Path { get; set; } = null!;

/// <summary>Gets or sets the pattern by which to match the storage path to documents.</summary>
public string MatchingPattern { get; set; } = null!;

/// <summary>Gets or sets the id of the matching algorithm used to match the storage path to documents.</summary>
public MatchingAlgorithm MatchingAlgorithm { get; set; } = null!;

/// <summary>Gets or sets a value indicating whether to ignore case when matching the storage path to documents.</summary>
public bool IsInsensitive { get; set; }

/// <summary>Gets or sets the number of documents with the storage path.</summary>
public int DocumentCount { get; set; }
}
Loading
Loading