aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-05-13 15:53:08 +0800
committercrupest <crupest@outlook.com>2021-05-13 15:53:08 +0800
commit5b059ad031b87fc2e3beaf1b650fc365b34b86ba (patch)
treedd56141734ad3c97ae1a6c8e8a9b4f25ebabeca3
parentaea8e41def7eab0d4e9f339ff14143f5441ae71d (diff)
downloadtimeline-5b059ad031b87fc2e3beaf1b650fc365b34b86ba.tar.gz
timeline-5b059ad031b87fc2e3beaf1b650fc365b34b86ba.tar.bz2
timeline-5b059ad031b87fc2e3beaf1b650fc365b34b86ba.zip
feat: Posts pagination.
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs18
-rw-r--r--BackEnd/Timeline/Controllers/TimelinePostController.cs6
-rw-r--r--BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs4
-rw-r--r--BackEnd/Timeline/Services/Timeline/Resource.Designer.cs18
-rw-r--r--BackEnd/Timeline/Services/Timeline/Resource.resx6
-rw-r--r--BackEnd/Timeline/Services/Timeline/TimelinePostService.cs14
6 files changed, 62 insertions, 4 deletions
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
index c918f793..097275b0 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
@@ -634,5 +634,23 @@ namespace Timeline.Tests.IntegratedTests
await client.TestDeleteAsync($"timelines/{generator(1)}/posts/{post.Id}");
}
}
+
+ [Theory]
+ [MemberData(nameof(TimelineNameGeneratorTestData))]
+ public async Task Post_List_Pagination_Test(TimelineNameGenerator generator)
+ {
+ using var client = await CreateClientAsUser();
+ var posts = new List<HttpTimelinePost>();
+ for (int i = 0; i < 50; i++)
+ {
+ var post = await client.TestPostAsync<HttpTimelinePost>($"timelines/{generator(1)}/posts", CreateTextPostRequest(i.ToString()));
+ posts.Add(post);
+ }
+
+ {
+ var p = await client.TestGetAsync<List<HttpTimelinePost>>($"timelines/{generator(1)}/posts?page=2&numberPerPage=10");
+ p.Should().BeEquivalentTo(posts.Skip(10).Take(10));
+ }
+ }
}
}
diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs
index 21d3821a..da45cbea 100644
--- a/BackEnd/Timeline/Controllers/TimelinePostController.cs
+++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs
@@ -57,12 +57,14 @@ namespace Timeline.Controllers
/// <param name="timeline">The name of the timeline.</param>
/// <param name="modifiedSince">If set, only posts modified since the time will return.</param>
/// <param name="includeDeleted">If set to true, deleted post will also return.</param>
+ /// <param name="page">Page number, starting from 0. Null to get all.</param>
+ /// <param name="numberPerPage">Post number per page. Default is 20.</param>
/// <returns>The post list.</returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task<ActionResult<List<HttpTimelinePost>>> List([FromRoute][GeneralTimelineName] string timeline, [FromQuery] DateTime? modifiedSince, [FromQuery] bool? includeDeleted)
+ public async Task<ActionResult<List<HttpTimelinePost>>> List([FromRoute][GeneralTimelineName] string timeline, [FromQuery] DateTime? modifiedSince, [FromQuery] bool? includeDeleted, [FromQuery][Range(0, int.MaxValue)] int? page, [FromQuery][Range(1, int.MaxValue)] int? numberPerPage)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
@@ -71,7 +73,7 @@ namespace Timeline.Controllers
return ForbidWithCommonResponse();
}
- var posts = await _postService.GetPostsAsync(timelineId, modifiedSince, includeDeleted ?? false);
+ var posts = await _postService.GetPostsAsync(timelineId, modifiedSince, includeDeleted ?? false, page, numberPerPage);
var result = await Map(posts);
return result;
diff --git a/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs
index 92984938..c0edf857 100644
--- a/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs
+++ b/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs
@@ -16,9 +16,11 @@ namespace Timeline.Services.Timeline
/// <param name="timelineId">The id of the timeline.</param>
/// <param name="modifiedSince">The time that posts have been modified since.</param>
/// <param name="includeDeleted">Whether include deleted posts.</param>
+ /// <param name="page">The page number. Starts from 0. If null, do not do pagination.</param>
+ /// <param name="numberPerPage">Count of entities per page. If null, 20.</param>
/// <returns>A list of all posts.</returns>
/// <exception cref="EntityNotExistException">Thrown when timeline does not exist.</exception>
- Task<List<TimelinePostEntity>> GetPostsAsync(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false);
+ Task<List<TimelinePostEntity>> GetPostsAsync(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false, int? page = null, int? numberPerPage = null);
/// <summary>
/// Get a post of a timeline.
diff --git a/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs b/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs
index 5ad03011..f5112cd9 100644
--- a/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs
+++ b/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs
@@ -106,6 +106,24 @@ namespace Timeline.Services.Timeline {
}
/// <summary>
+ /// Looks up a localized string similar to Number per page can&apos;t be zero or negative..
+ /// </summary>
+ internal static string ExceptionNumberPerPageZeroOrNegative {
+ get {
+ return ResourceManager.GetString("ExceptionNumberPerPageZeroOrNegative", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Page number can&apos;t be negative..
+ /// </summary>
+ internal static string ExceptionPageNegative {
+ get {
+ return ResourceManager.GetString("ExceptionPageNegative", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Image validation failed..
/// </summary>
internal static string ExceptionPostDataImageInvalid {
diff --git a/BackEnd/Timeline/Services/Timeline/Resource.resx b/BackEnd/Timeline/Services/Timeline/Resource.resx
index cc293d05..1d61a1bb 100644
--- a/BackEnd/Timeline/Services/Timeline/Resource.resx
+++ b/BackEnd/Timeline/Services/Timeline/Resource.resx
@@ -132,6 +132,12 @@
<data name="ExceptionGeneralTimelineNameBadFormat" xml:space="preserve">
<value>This timeline name is neither a valid personal timeline name nor a valid ordinary timeline name. {0}</value>
</data>
+ <data name="ExceptionNumberPerPageZeroOrNegative" xml:space="preserve">
+ <value>Number per page can't be zero or negative.</value>
+ </data>
+ <data name="ExceptionPageNegative" xml:space="preserve">
+ <value>Page number can't be negative.</value>
+ </data>
<data name="ExceptionPostDataImageInvalid" xml:space="preserve">
<value>Image validation failed.</value>
</data>
diff --git a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs
index a0961a8d..ee1002e0 100644
--- a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs
+++ b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs
@@ -64,8 +64,14 @@ namespace Timeline.Services.Timeline
});
}
- public async Task<List<TimelinePostEntity>> GetPostsAsync(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false)
+ public async Task<List<TimelinePostEntity>> GetPostsAsync(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false, int? page = null, int? numberPerPage = null)
{
+ if (page.HasValue && page < 0)
+ throw new ArgumentOutOfRangeException(nameof(page), Resource.ExceptionPageNegative);
+ if (numberPerPage.HasValue && numberPerPage <= 0)
+ throw new ArgumentOutOfRangeException(nameof(numberPerPage), Resource.ExceptionNumberPerPageZeroOrNegative);
+
+
await _basicTimelineService.ThrowIfTimelineNotExist(timelineId);
modifiedSince = modifiedSince?.MyToUtc();
@@ -84,6 +90,12 @@ namespace Timeline.Services.Timeline
query = query.OrderBy(p => p.Time);
+ if (page.HasValue)
+ {
+ var npp = numberPerPage.GetValueOrDefault(20);
+ query = query.Skip(npp * (page.Value - 1)).Take(npp);
+ }
+
return await query.ToListAsync();
}