Skip to content

Commit b64895b

Browse files
authored
Merge pull request #1233 from syucream/feature/filter-jobs-by-target
Enable target_id filter on the job list API v2
2 parents 0f8f02b + e2de159 commit b64895b

File tree

11 files changed

+70
-18
lines changed

11 files changed

+70
-18
lines changed

apiclient/typescript-fetch/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dmm-com/airone-apiclient-typescript-fetch",
3-
"version": "0.0.18",
3+
"version": "0.0.19",
44
"description": "AirOne APIv2 client in TypeScript",
55
"main": "src/autogenerated/index.ts",
66
"scripts": {

frontend/src/Routes.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export const topPath = () => basePath;
55
export const advancedSearchPath = () => basePath + "advanced_search";
66
export const advancedSearchResultPath = () =>
77
basePath + "advanced_search_result";
8-
export const jobsPath = () => basePath + "jobs";
8+
export const jobsPath = (targetId?: number) =>
9+
basePath + "jobs" + (targetId ? `?target_id=${targetId}` : "");
910
export const aclPath = (objectId: number | string) =>
1011
basePath + `acl/${objectId}`;
1112
export const aclHistoryPath = (objectId: number | string) =>

frontend/src/components/common/PageHeader.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import AutorenewIcon from "@mui/icons-material/Autorenew";
22
import { Box, Divider, Tooltip, Typography } from "@mui/material";
33
import { styled } from "@mui/material/styles";
44
import React, { FC } from "react";
5+
import { Link } from "react-router-dom";
6+
7+
import { jobsPath } from "Routes";
58

69
const Frame = styled(Box)({
710
width: "100%",
@@ -41,13 +44,15 @@ const ChildrenBox = styled(Box)({
4144
interface Props {
4245
title: string;
4346
description?: string;
47+
targetId?: number;
4448
hasOngoingProcess?: boolean;
4549
children?: React.ReactNode;
4650
}
4751

4852
export const PageHeader: FC<Props> = ({
4953
title,
5054
description,
55+
targetId,
5156
hasOngoingProcess,
5257
children,
5358
}) => {
@@ -63,7 +68,9 @@ export const PageHeader: FC<Props> = ({
6368
</Typography>
6469
{hasOngoingProcess && (
6570
<Tooltip title="未処理の変更があります。現在表示されているデータは最新でない可能性があります。">
66-
<AutorenewIcon />
71+
<Box component={Link} to={jobsPath(targetId)}>
72+
<AutorenewIcon />
73+
</Box>
6774
</Tooltip>
6875
)}
6976
<ChildrenBox>{children}</ChildrenBox>

frontend/src/pages/EntityEditPage.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ export const EntityEditPage: FC = () => {
199199
entity?.value != null ? entity.value.name : "新規エンティティの作成"
200200
}
201201
description={entity?.value && "エンティテイティ詳細 / 編集"}
202+
targetId={entity.value?.id}
202203
hasOngoingProcess={entity?.value?.hasOngoingChanges}
203204
>
204205
<SubmitButton

frontend/src/pages/EntryListPage.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const EntryListPage: FC<Props> = ({ canCreateEntry = true }) => {
3434
<PageHeader
3535
title={entity.value?.name ?? ""}
3636
description="エントリ一覧"
37+
targetId={entity.value?.id}
3738
hasOngoingProcess={entity.value?.hasOngoingChanges}
3839
>
3940
<Box width="50px">

frontend/src/pages/JobListPage.tsx

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import ReplayIcon from "@mui/icons-material/Replay";
22
import { Box, Button, Container, Typography } from "@mui/material";
3-
import React, { FC } from "react";
4-
import { Link } from "react-router-dom";
3+
import React, { FC, useMemo } from "react";
4+
import { Link, useLocation } from "react-router-dom";
55
import { useToggle } from "react-use";
66

77
import { useAsyncWithThrow } from "../hooks/useAsyncWithThrow";
@@ -17,13 +17,22 @@ import { aironeApiClient } from "repository/AironeApiClient";
1717
import { JobList as ConstJobList } from "services/Constants";
1818

1919
export const JobListPage: FC = () => {
20-
const [page, changePage] = usePage();
20+
const location = useLocation();
2121

22+
const [page, changePage] = usePage();
2223
const [refresh, toggleRefresh] = useToggle(false);
2324

25+
const { targetId } = useMemo(() => {
26+
const params = new URLSearchParams(location.search);
27+
const targetId = params.get("target_id");
28+
return {
29+
targetId: targetId ? Number(targetId) : undefined,
30+
};
31+
}, [location.search]);
32+
2433
const jobs = useAsyncWithThrow(async () => {
25-
return await aironeApiClient.getJobs(page);
26-
}, [page, refresh]);
34+
return await aironeApiClient.getJobs(page, targetId);
35+
}, [page, targetId, refresh]);
2736

2837
return (
2938
<Box className="container-fluid">

frontend/src/repository/AironeApiClient.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -918,10 +918,14 @@ class AironeApiClient {
918918
);
919919
}
920920

921-
async getJobs(page = 1): Promise<PaginatedJobSerializersList> {
921+
async getJobs(
922+
page: number = 1,
923+
targetId?: number
924+
): Promise<PaginatedJobSerializersList> {
922925
return await this.job.jobApiV2JobsList({
923926
offset: (page - 1) * JobList.MAX_ROW_COUNT,
924927
limit: JobList.MAX_ROW_COUNT,
928+
targetId,
925929
});
926930
}
927931

job/api_v2/views.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def download(self, request: Request, *args, **kwargs) -> Response:
7676
@extend_schema(
7777
parameters=[
7878
OpenApiParameter("created_after", OpenApiTypes.DATETIME, OpenApiParameter.QUERY),
79+
OpenApiParameter("target_id", OpenApiTypes.INT, OpenApiParameter.QUERY),
7980
],
8081
)
8182
class JobListAPI(viewsets.ModelViewSet):
@@ -84,7 +85,8 @@ class JobListAPI(viewsets.ModelViewSet):
8485

8586
def get_queryset(self) -> QuerySet:
8687
user = self.request.user
87-
created_after = self.request.query_params.get("created_after", None)
88+
created_after: str | None = self.request.query_params.get("created_after", None)
89+
target_id: str | None = self.request.query_params.get("target_id", None)
8890

8991
export_operations: list[JobOperation] = [
9092
JobOperation.EXPORT_ENTRY,
@@ -109,6 +111,8 @@ def get_queryset(self) -> QuerySet:
109111

110112
if created_after:
111113
query &= Q(created_at__gte=created_after)
114+
if target_id:
115+
query &= Q(target=target_id)
112116

113117
return Job.objects.filter(query).select_related("target").order_by("-created_at")
114118

job/tests/test_api_v2.py

+25
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,31 @@ def test_get_recent_job(self):
108108
self.assertEqual(resp.status_code, 200)
109109
self.assertEqual(resp.json()["count"], 0)
110110

111+
def test_get_jobs_with_target_id(self):
112+
user = self.guest_login()
113+
114+
entity = Entity.objects.create(name="entity", created_user=user)
115+
entry1 = Entry.objects.create(name="entry1", created_user=user, schema=entity)
116+
entry2 = Entry.objects.create(name="entry2", created_user=user, schema=entity)
117+
118+
# create three jobs for entry1
119+
[Job.new_create(user, entry1) for _ in range(0, _TEST_MAX_LIST_VIEW)]
120+
self.assertEqual(Job.objects.filter(user=user).count(), _TEST_MAX_LIST_VIEW)
121+
# create one job for entry2
122+
Job.new_create(user, entry2)
123+
124+
# checks number of the returned objects are for entry1
125+
resp = self.client.get(
126+
f"/job/api/v2/jobs?limit={_TEST_MAX_LIST_VIEW + 100}&offset=0&target_id={entry1.id}"
127+
)
128+
self.assertEqual(resp.status_code, 200)
129+
self.assertEqual(resp.json()["count"], _TEST_MAX_LIST_VIEW)
130+
131+
# checks number of the returned objects are for both entry1 and entry2
132+
resp = self.client.get(f"/job/api/v2/jobs?limit={_TEST_MAX_LIST_VIEW + 100}&offset=0")
133+
self.assertEqual(resp.status_code, 200)
134+
self.assertEqual(resp.json()["count"], _TEST_MAX_LIST_VIEW + 1)
135+
111136
def test_get_job(self):
112137
user = self.guest_login()
113138

package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"zod": "^3.22.4"
8181
},
8282
"dependencies": {
83-
"@dmm-com/airone-apiclient-typescript-fetch": "^0.0.18",
83+
"@dmm-com/airone-apiclient-typescript-fetch": "^0.0.19",
8484
"@emotion/react": "^11.10.5",
8585
"@emotion/styled": "^11.10.5",
8686
"@jest/globals": "^27.0.6",

0 commit comments

Comments
 (0)