Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9697801
D7344.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Subscribers
None
D7344.diff
View Options
diff --git a/swh/web/api/views/add_forge_now.py b/swh/web/api/views/add_forge_now.py
--- a/swh/web/api/views/add_forge_now.py
+++ b/swh/web/api/views/add_forge_now.py
@@ -4,11 +4,12 @@
# See top-level LICENSE file for more information
import json
-from typing import Union
+from typing import Any, Dict, Union
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator
from django.db import transaction
+from django.db.models import Q
from django.forms import CharField, ModelForm
from django.http import HttpResponseBadRequest
from django.http.request import HttpRequest
@@ -269,7 +270,45 @@
:statuscode 200: always
"""
- add_forge_requests = AddForgeRequest.objects.order_by("-id")
+ datatables = int(request.GET.get("draw", 0))
+
+ if datatables:
+ # datatables request handling
+ add_forge_requests = AddForgeRequest.objects.all()
+
+ table_data: Dict[str, Any] = {}
+ table_data["recordsTotal"] = add_forge_requests.count()
+ table_data["draw"] = int(request.GET["draw"])
+
+ search_value = request.GET.get("search[value]")
+
+ column_order = request.GET.get("order[0][column]")
+ field_order = request.GET.get(f"columns[{column_order}][name]")
+ order_dir = request.GET.get("order[0][dir]")
+
+ if field_order:
+ if order_dir == "desc":
+ field_order = "-" + field_order
+ add_forge_requests = add_forge_requests.order_by(field_order)
+ else:
+ add_forge_requests = add_forge_requests.order_by("-id")
+
+ per_page = int(request.GET["length"])
+ page_num = int(request.GET["start"]) // per_page + 1
+
+ if search_value:
+ add_forge_requests = add_forge_requests.filter(
+ Q(forge_type__icontains=search_value)
+ | Q(forge_url__icontains=search_value)
+ | Q(status__icontains=search_value)
+ )
+ else:
+ # standard Web API request handling
+ add_forge_requests = AddForgeRequest.objects.order_by("-id")
+
+ page_num = int(request.GET.get("page", 1))
+ per_page = int(request.GET.get("per_page", 10))
+ per_page = min(per_page, 1000)
if (
int(request.GET.get("user_requests_only", "0"))
@@ -279,35 +318,43 @@
submitter_name=request.user.username
)
- page_num = int(request.GET.get("page", 1))
- per_page = int(request.GET.get("per_page", 10))
- per_page = min(per_page, 1000)
-
paginator = Paginator(add_forge_requests, per_page)
page = paginator.page(page_num)
if request.user.has_perm(MODERATOR_ROLE):
- results = AddForgeNowRequestSerializer(page.object_list, many=True).data
+ requests = AddForgeNowRequestSerializer(page.object_list, many=True).data
else:
- results = AddForgeNowRequestPublicSerializer(page.object_list, many=True).data
+ requests = AddForgeNowRequestPublicSerializer(page.object_list, many=True).data
- response = {"results": results, "headers": {}}
+ results = [dict(request) for request in requests]
- if page.has_previous():
- response["headers"]["link-prev"] = reverse(
- "api-1-add-forge-request-list",
- query_params={"page": page.previous_page_number(), "per_page": per_page},
- request=request,
- )
+ if datatables:
+ # datatables response
+ table_data["recordsFiltered"] = add_forge_requests.count()
+ table_data["data"] = results
+ return table_data
+ else:
+ # standard Web API response
+ response: Dict[str, Any] = {"results": results, "headers": {}}
+
+ if page.has_previous():
+ response["headers"]["link-prev"] = reverse(
+ "api-1-add-forge-request-list",
+ query_params={
+ "page": page.previous_page_number(),
+ "per_page": per_page,
+ },
+ request=request,
+ )
- if page.has_next():
- response["headers"]["link-next"] = reverse(
- "api-1-add-forge-request-list",
- query_params={"page": page.next_page_number(), "per_page": per_page},
- request=request,
- )
+ if page.has_next():
+ response["headers"]["link-next"] = reverse(
+ "api-1-add-forge-request-list",
+ query_params={"page": page.next_page_number(), "per_page": per_page},
+ request=request,
+ )
- return response
+ return response
@api_route(
diff --git a/swh/web/tests/api/views/test_add_forge_now.py b/swh/web/tests/api/views/test_add_forge_now.py
--- a/swh/web/tests/api/views/test_add_forge_now.py
+++ b/swh/web/tests/api/views/test_add_forge_now.py
@@ -387,6 +387,150 @@
assert len(resp.data) == 1
+NB_FORGE_TYPE = 2
+NB_FORGES_PER_TYPE = 20
+
+
+def _create_add_forge_requests(api_client, regular_user, regular_user2):
+ requests = []
+ for i in range(NB_FORGES_PER_TYPE):
+ request = {
+ "forge_type": "gitlab",
+ "forge_url": f"https://gitlab.example{i:02d}.org",
+ "forge_contact_email": f"admin@gitlab.example{i:02d}.org",
+ "forge_contact_name": f"gitlab.example{i:02d}.org admin",
+ "forge_contact_comment": "user marked as owner in forge members",
+ }
+ _create_add_forge_request(
+ api_client, regular_user, data=request,
+ )
+ requests.append(request)
+
+ request = {
+ "forge_type": "gitea",
+ "forge_url": f"https://gitea.example{i:02d}.org",
+ "forge_contact_email": f"admin@gitea.example{i:02d}.org",
+ "forge_contact_name": f"gitea.example{i:02d}.org admin",
+ "forge_contact_comment": "user marked as owner in forge members",
+ }
+ _create_add_forge_request(
+ api_client, regular_user2, data=request,
+ )
+ requests.append(request)
+ return requests
+
+
+@pytest.mark.django_db(transaction=True, reset_sequences=True)
+def test_add_forge_request_list_datatables(
+ api_client, regular_user, regular_user2, moderator_user
+):
+ _create_add_forge_requests(api_client, regular_user, regular_user2)
+
+ length = 10
+
+ url = reverse(
+ "api-1-add-forge-request-list",
+ query_params={"draw": 1, "length": length, "start": 0},
+ )
+
+ api_client.force_login(regular_user)
+ resp = check_api_get_responses(api_client, url, status_code=200)
+
+ assert resp.data["draw"] == 1
+ assert resp.data["recordsFiltered"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert resp.data["recordsTotal"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert len(resp.data["data"]) == length
+ # default ordering is by descending id
+ assert resp.data["data"][0]["id"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert (
+ resp.data["data"][-1]["id"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE - length + 1
+ )
+ assert "submitter_name" not in resp.data["data"][0]
+
+ api_client.force_login(moderator_user)
+ resp = check_api_get_responses(api_client, url, status_code=200)
+
+ assert resp.data["draw"] == 1
+ assert resp.data["recordsFiltered"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert resp.data["recordsTotal"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert len(resp.data["data"]) == length
+ # default ordering is by descending id
+ assert resp.data["data"][0]["id"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert (
+ resp.data["data"][-1]["id"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE - length + 1
+ )
+ assert "submitter_name" in resp.data["data"][0]
+
+
+@pytest.mark.django_db(transaction=True, reset_sequences=True)
+def test_add_forge_request_list_datatables_ordering(
+ api_client, regular_user, regular_user2, moderator_user
+):
+ requests = _create_add_forge_requests(api_client, regular_user, regular_user2)
+ requests_sorted = list(sorted(requests, key=lambda d: d["forge_url"]))
+ forge_urls_asc = [request["forge_url"] for request in requests_sorted]
+ forge_urls_desc = list(reversed(forge_urls_asc))
+
+ length = 10
+
+ for direction in ("asc", "desc"):
+ for i in range(4):
+ url = reverse(
+ "api-1-add-forge-request-list",
+ query_params={
+ "draw": 1,
+ "length": length,
+ "start": i * length,
+ "order[0][column]": 2,
+ "order[0][dir]": direction,
+ "columns[2][name]": "forge_url",
+ },
+ )
+
+ api_client.force_login(regular_user)
+ resp = check_api_get_responses(api_client, url, status_code=200)
+
+ assert resp.data["draw"] == 1
+ assert resp.data["recordsFiltered"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert resp.data["recordsTotal"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert len(resp.data["data"]) == length
+
+ page_forge_urls = [request["forge_url"] for request in resp.data["data"]]
+ if direction == "asc":
+ expected_forge_urls = forge_urls_asc[i * length : (i + 1) * length]
+ else:
+ expected_forge_urls = forge_urls_desc[i * length : (i + 1) * length]
+ assert page_forge_urls == expected_forge_urls
+
+
+@pytest.mark.django_db(transaction=True, reset_sequences=True)
+def test_add_forge_request_list_datatables_search(
+ api_client, regular_user, regular_user2, moderator_user
+):
+ _create_add_forge_requests(api_client, regular_user, regular_user2)
+
+ url = reverse(
+ "api-1-add-forge-request-list",
+ query_params={
+ "draw": 1,
+ "length": NB_FORGES_PER_TYPE,
+ "start": 0,
+ "search[value]": "gitlab",
+ },
+ )
+
+ api_client.force_login(regular_user)
+ resp = check_api_get_responses(api_client, url, status_code=200)
+
+ assert resp.data["draw"] == 1
+ assert resp.data["recordsFiltered"] == NB_FORGES_PER_TYPE
+ assert resp.data["recordsTotal"] == NB_FORGE_TYPE * NB_FORGES_PER_TYPE
+ assert len(resp.data["data"]) == NB_FORGES_PER_TYPE
+
+ page_forge_type = [request["forge_type"] for request in resp.data["data"]]
+ assert page_forge_type == ["gitlab"] * NB_FORGES_PER_TYPE
+
+
@pytest.mark.django_db(transaction=True, reset_sequences=True)
def test_add_forge_request_get(api_client, regular_user, moderator_user):
resp = _create_add_forge_request(api_client, regular_user)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Aug 18, 12:58 AM (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3218339
Attached To
D7344: api/add_forge_now: Allow to use requests list endpoint with datatables
Event Timeline
Log In to Comment