Skip to content

Commit e198fe7

Browse files
feat: add bulk (#92)
* fix: update DealTasksTable to use <span> to fix index alignment * feat: add pocoBulk code generation and execution functionality * feat: add TaskDatasetsTable component and integrate into task route * feat: add dataset type in task dataset tab * feat: enhance task page with loading and outdated state management like workerpool, app and dataset pages * feat: add DatasetTasksTable component and integrate into dataset route with loading and outdated state management * feat: add button to view tasks for deals with null dataset in buildDealDetails * feat: rename GraphQL query to TaskDatasets for clarity * feat: add VITE_POCO_BULK_SUBGRAPH_URL to environment configuration * feat: add onSeeTasks callback to buildDealDetails for task navigation * feat: add DealAssociatedDealsTable component and integrate into DealsRoute for associated deals display * feat: enhance DealTasksTable and DealAssociatedDealsTable with loading and outdated state management * fix: remove unnecessary semicolon in DatasetTasksTable component * refactor: reorder imports * refactor: remove pocoBulk graph to use it in poco * feat: implement pagination for task datasets * feat: add pagination support to deal tasks query and table * feat: enhance DealTasksTable with type definitions and improved task formatting * feat: add MetaMask Flask and simplify networks assignment * feat: update Arbitrum Sepolia poco subgraph URL to the latest version * feat: include currentPage in queryKey for dataset and deal tasks data fetching * fix: use correct Arbitrum Sepolia poco subgraph URL in config * fix: inconsistent pagination implementation * fix: streamline associated deals formatting and improve error message clarity * feat: display "Datasets bulk" instead of "No dataset" for deals with bulk * feature: add orderBy for workerpools and apps (#94) * feat: implement filter parameter synchronization and enhance workerpools query with ordering options * feat: enhance AppsPreviewTable and appsQuery with ordering options and recent usage filter * feat: improve SearcherBar layout and error handling visibility * feat: enhance pagination controls with filter key handling and stability improvements * refactor: simplify navigation logic in useFilterParam hook * fix: remove TypeScript error comments for updated query signatures in appsQuery and workerpoolsQuery * feat: add SlidersHorizontal icon to order selection in WorkerpoolsRoute * feat: replace inline recent timestamp calculation with getRecentFromTimestamp utility function * refactor: improve raw value extraction and validation logic in useFilterParam hook * feat: add bulk deals instead of task table * feat: add presence checks for associated deals and datasets in Deals and Tasks routes * fix: reorder tab labels in taskId * fix: call react hook after return * fix: revert bad merge "feature: add orderBy for workerpools and apps (#94)" * fix: filter out dealid for consistency in dataset deals tables * fix: solve page count issue in dataset deals bulk * fix: improve task datasets tab disable reason * fix: improve deal associated deals tab disable reason --------- Co-authored-by: Pierre Jeanjacquot <[email protected]>
1 parent f0667b0 commit e198fe7

21 files changed

+889
-43
lines changed

src/modules/apps/app/AppDealsTable.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ErrorAlert } from '@/modules/ErrorAlert';
99
import { columns } from '@/modules/deals/dealsTable/columns';
1010
import useUserStore from '@/stores/useUser.store';
1111
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
12+
import { getAdditionalPages } from '@/utils/format';
1213
import { appDealsQuery } from './appDealsQuery';
1314

1415
function useAppDealsData({
@@ -21,6 +22,7 @@ function useAppDealsData({
2122
const { chainId } = useUserStore();
2223
const skip = currentPage * DETAIL_TABLE_LENGTH;
2324
const nextSkip = skip + DETAIL_TABLE_LENGTH;
25+
const nextNextSkip = skip + 2 * DETAIL_TABLE_LENGTH;
2426

2527
const queryKey = [chainId, 'app', 'deals', appAddress, currentPage];
2628
const { data, isLoading, isRefetching, isError, errorUpdateCount } = useQuery(
@@ -31,6 +33,7 @@ function useAppDealsData({
3133
length: DETAIL_TABLE_LENGTH,
3234
skip,
3335
nextSkip,
36+
nextNextSkip,
3437
appAddress,
3538
}),
3639
refetchInterval: TABLE_REFETCH_INTERVAL,
@@ -39,8 +42,10 @@ function useAppDealsData({
3942
);
4043

4144
const deals = data?.app?.deals ?? [];
42-
const hasNextPage = (data?.app?.dealsHasNext?.length ?? 0) > 0;
43-
const additionalPages = hasNextPage ? 1 : 0;
45+
const additionalPages = getAdditionalPages(
46+
Boolean(data?.app?.dealsHasNext?.length),
47+
Boolean(data?.app?.dealsHasNextNext?.length)
48+
);
4449

4550
const formattedDeal =
4651
deals.map((deal) => ({

src/modules/apps/app/appDealsQuery.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const appDealsQuery = graphql(`
55
$length: Int = 20
66
$skip: Int = 0
77
$nextSkip: Int = 20
8+
$nextNextSkip: Int = 40
89
$appAddress: ID!
910
) {
1011
app(id: $appAddress) {
@@ -42,6 +43,9 @@ export const appDealsQuery = graphql(`
4243
catid: id
4344
workClockTimeRef
4445
}
46+
bulk {
47+
id
48+
}
4549
startTime
4650
appPrice
4751
datasetPrice
@@ -59,6 +63,14 @@ export const appDealsQuery = graphql(`
5963
) {
6064
id
6165
}
66+
dealsHasNextNext: usages(
67+
orderBy: timestamp
68+
orderDirection: desc
69+
first: 1
70+
skip: $nextNextSkip
71+
) {
72+
id
73+
}
6274
}
6375
}
6476
`);
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { DETAIL_TABLE_LENGTH, TABLE_REFETCH_INTERVAL } from '@/config';
2+
import { execute } from '@/graphql/poco/execute';
3+
import { useQuery } from '@tanstack/react-query';
4+
import { useEffect } from 'react';
5+
import { DataTable } from '@/components/DataTable';
6+
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
7+
import { usePageParam } from '@/hooks/usePageParam';
8+
import { ErrorAlert } from '@/modules/ErrorAlert';
9+
import { columns } from '@/modules/deals/dealsTable/columns';
10+
import useUserStore from '@/stores/useUser.store';
11+
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
12+
import { getAdditionalPages } from '@/utils/format';
13+
import { datasetBulkDealsQuery } from './datasetBulkDealsQuery';
14+
15+
function useDatasetBulkDealsData({
16+
datasetId,
17+
currentPage,
18+
}: {
19+
datasetId: string;
20+
currentPage: number;
21+
}) {
22+
const { chainId } = useUserStore();
23+
const skip = currentPage * DETAIL_TABLE_LENGTH;
24+
const nextSkip = skip + DETAIL_TABLE_LENGTH;
25+
const nextNextSkip = skip + 2 * DETAIL_TABLE_LENGTH;
26+
27+
const queryKey = [chainId, 'dataset', 'bulkDeals', datasetId, currentPage];
28+
const { data, isLoading, isRefetching, isError, errorUpdateCount } = useQuery(
29+
{
30+
queryKey,
31+
queryFn: () =>
32+
execute(datasetBulkDealsQuery, chainId, {
33+
length: DETAIL_TABLE_LENGTH,
34+
skip,
35+
nextSkip,
36+
nextNextSkip,
37+
datasetId,
38+
}),
39+
refetchInterval: TABLE_REFETCH_INTERVAL,
40+
placeholderData: createPlaceholderDataFnForQueryKey(queryKey),
41+
}
42+
);
43+
44+
const bulkDeals = data?.bulkSliceice?.map((slice) => slice.task?.deal) ?? [];
45+
// 0 = only current, 1 = next, 2 = next+1
46+
const additionalPages = getAdditionalPages(
47+
Boolean(data?.bulkSliceiceHasNext?.length),
48+
Boolean(data?.bulkSliceiceHasNextNext?.length)
49+
);
50+
51+
const formattedBulkDeal =
52+
bulkDeals
53+
?.filter((bulkDeal) => bulkDeal !== undefined)
54+
.map((bulkDeal) => ({
55+
...bulkDeal,
56+
destination: `/bulkDeal/${bulkDeal!.dealid}`,
57+
})) ?? [];
58+
59+
return {
60+
data: formattedBulkDeal,
61+
isLoading,
62+
isRefetching,
63+
isError,
64+
additionalPages,
65+
hasPastError: isError || errorUpdateCount > 0,
66+
};
67+
}
68+
69+
export function DatasetBulkDealsTable({
70+
datasetId,
71+
setLoading,
72+
setOutdated,
73+
}: {
74+
datasetId: string;
75+
setLoading: (loading: boolean) => void;
76+
setOutdated: (outdated: boolean) => void;
77+
}) {
78+
const [currentPage, setCurrentPage] = usePageParam('datasetBulkDealsPage');
79+
const {
80+
data: bulkDeals,
81+
isError,
82+
isLoading,
83+
isRefetching,
84+
additionalPages,
85+
hasPastError,
86+
} = useDatasetBulkDealsData({ datasetId, currentPage: currentPage - 1 });
87+
88+
useEffect(
89+
() => setLoading(isLoading || isRefetching),
90+
[isLoading, isRefetching, setLoading]
91+
);
92+
useEffect(
93+
() => setOutdated(bulkDeals.length > 0 && isError),
94+
[bulkDeals.length, isError, setOutdated]
95+
);
96+
97+
const filteredColumns = columns.filter((col) => col.accessorKey !== 'dealid');
98+
99+
return (
100+
<div className="space-y-6">
101+
{hasPastError && !bulkDeals.length ? (
102+
<ErrorAlert message="An error occurred during dataset bulkDeals loading." />
103+
) : (
104+
<DataTable
105+
columns={filteredColumns}
106+
data={bulkDeals}
107+
tableLength={DETAIL_TABLE_LENGTH}
108+
/>
109+
)}
110+
<PaginatedNavigation
111+
currentPage={currentPage}
112+
totalPages={currentPage + additionalPages}
113+
onPageChange={setCurrentPage}
114+
/>
115+
</div>
116+
);
117+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { graphql } from '@/graphql/poco/gql';
2+
3+
export const datasetBulkDealsQuery = graphql(`
4+
query DatasetBulkDeals(
5+
$datasetId: ID!
6+
$length: Int!
7+
$skip: Int!
8+
$nextSkip: Int!
9+
$nextNextSkip: Int!
10+
) {
11+
bulkSliceice(
12+
first: $length
13+
skip: $skip
14+
where: { datasets_: { id: $datasetId } }
15+
orderBy: task__timestamp
16+
orderDirection: desc
17+
) {
18+
task {
19+
deal {
20+
dealid: id
21+
timestamp
22+
requester {
23+
address: id
24+
}
25+
beneficiary {
26+
address: id
27+
}
28+
callback {
29+
address: id
30+
}
31+
app {
32+
address: id
33+
name
34+
}
35+
dataset {
36+
address: id
37+
name
38+
}
39+
workerpool {
40+
address: id
41+
description
42+
}
43+
category {
44+
catid: id
45+
workClockTimeRef
46+
}
47+
bulk {
48+
id
49+
}
50+
startTime
51+
appPrice
52+
datasetPrice
53+
workerpoolPrice
54+
botSize
55+
trust
56+
completedTasksCount
57+
claimedTasksCount
58+
}
59+
}
60+
}
61+
bulkSliceiceHasNext: bulkSliceice(
62+
first: 1
63+
skip: $nextSkip
64+
where: { datasets_: { id: $datasetId } }
65+
orderBy: task__timestamp
66+
orderDirection: desc
67+
) {
68+
task {
69+
deal {
70+
id
71+
}
72+
}
73+
}
74+
bulkSliceiceHasNextNext: bulkSliceice(
75+
first: 1
76+
skip: $nextNextSkip
77+
where: { datasets_: { id: $datasetId } }
78+
orderBy: task__timestamp
79+
orderDirection: desc
80+
) {
81+
task {
82+
deal {
83+
id
84+
}
85+
}
86+
}
87+
}
88+
`);

src/modules/datasets/dataset/datasetDealsQuery.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ export const datasetDealsQuery = graphql(`
4343
catid: id
4444
workClockTimeRef
4545
}
46+
bulk {
47+
id
48+
}
4649
startTime
4750
appPrice
4851
datasetPrice
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { DETAIL_TABLE_LENGTH, TABLE_REFETCH_INTERVAL } from '@/config';
2+
import { execute } from '@/graphql/poco/execute';
3+
import { useQuery } from '@tanstack/react-query';
4+
import { useEffect } from 'react';
5+
import { DataTable } from '@/components/DataTable';
6+
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
7+
import { usePageParam } from '@/hooks/usePageParam';
8+
import { ErrorAlert } from '@/modules/ErrorAlert';
9+
import { columns } from '@/modules/deals/dealsTable/columns';
10+
import useUserStore from '@/stores/useUser.store';
11+
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
12+
import { getAdditionalPages } from '@/utils/format';
13+
import { dealAssociatedDealsQuery } from './dealAssociatedDealsQuery';
14+
15+
function useDealAssociatedDealsData({
16+
dealId,
17+
currentPage,
18+
}: {
19+
dealId: string;
20+
currentPage: number;
21+
}) {
22+
const { chainId } = useUserStore();
23+
const skip = currentPage * DETAIL_TABLE_LENGTH;
24+
const nextSkip = skip + DETAIL_TABLE_LENGTH;
25+
const nextNextSkip = skip + 2 * DETAIL_TABLE_LENGTH;
26+
27+
const queryKey = [chainId, 'deal', 'associatedDeals', dealId, currentPage];
28+
const { data, isLoading, isRefetching, isError, errorUpdateCount } = useQuery(
29+
{
30+
queryKey,
31+
queryFn: () =>
32+
execute(dealAssociatedDealsQuery, chainId, {
33+
length: DETAIL_TABLE_LENGTH,
34+
skip,
35+
nextSkip,
36+
nextNextSkip,
37+
dealId,
38+
}),
39+
refetchInterval: TABLE_REFETCH_INTERVAL,
40+
placeholderData: createPlaceholderDataFnForQueryKey(queryKey),
41+
}
42+
);
43+
const associatedDeals = data?.deal?.requestorder?.deals ?? [];
44+
const additionalPages = getAdditionalPages(
45+
Boolean(data?.deal?.requestorder?.dealsHasNext?.length),
46+
Boolean(data?.deal?.requestorder?.dealsHasNextNext?.length)
47+
);
48+
49+
const formattedAssociatedDeal = associatedDeals.map((associatedDeal) => ({
50+
...associatedDeal,
51+
destination: `/deal/${associatedDeal.dealid}`,
52+
}));
53+
54+
return {
55+
data: formattedAssociatedDeal,
56+
isLoading,
57+
isRefetching,
58+
isError,
59+
additionalPages,
60+
hasPastError: isError || errorUpdateCount > 0,
61+
};
62+
}
63+
64+
export function DealAssociatedDealsTable({
65+
dealId,
66+
setLoading,
67+
setOutdated,
68+
}: {
69+
dealId: string;
70+
setLoading: (isLoading: boolean) => void;
71+
setOutdated: (isOutdated: boolean) => void;
72+
}) {
73+
const [currentPage, setCurrentPage] = usePageParam('dealAssociatedDealsPage');
74+
const {
75+
data: associatedDeals,
76+
isError,
77+
isLoading,
78+
isRefetching,
79+
additionalPages,
80+
hasPastError,
81+
} = useDealAssociatedDealsData({
82+
dealId,
83+
currentPage: currentPage - 1,
84+
});
85+
86+
useEffect(
87+
() => setLoading(isLoading || isRefetching),
88+
[isLoading, isRefetching, setLoading]
89+
);
90+
useEffect(
91+
() => setOutdated(associatedDeals.length > 0 && isError),
92+
[associatedDeals.length, isError, setOutdated]
93+
);
94+
95+
return (
96+
<div className="space-y-6">
97+
{hasPastError && !associatedDeals.length ? (
98+
<ErrorAlert message="An error occurred during associated deals loading." />
99+
) : (
100+
<DataTable columns={columns} data={associatedDeals} />
101+
)}
102+
<PaginatedNavigation
103+
currentPage={currentPage}
104+
totalPages={currentPage + additionalPages}
105+
onPageChange={setCurrentPage}
106+
/>
107+
</div>
108+
);
109+
}

0 commit comments

Comments
 (0)