diff options
author | crupest <crupest@outlook.com> | 2021-05-13 15:53:08 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-05-13 15:53:08 +0800 |
commit | c667c722ec081dfb651d3583236d7aa429c56941 (patch) | |
tree | 9e3da51562130f16234b6d00c210aa471d90eeed /BackEnd | |
parent | 6b19be9d57d06d9a079ed8f947d44628421bef18 (diff) | |
download | timeline-c667c722ec081dfb651d3583236d7aa429c56941.tar.gz timeline-c667c722ec081dfb651d3583236d7aa429c56941.tar.bz2 timeline-c667c722ec081dfb651d3583236d7aa429c56941.zip |
feat: Posts pagination.
Diffstat (limited to 'BackEnd')
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'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'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();
}
|