Skip to content

Commit d66d3ce

Browse files
tefkah3mcd
andauthored
feat: sorting/filtering on all pubs page (#1338)
* fix: initial search improvement * feat: pretty good first pass at filtering * feat: nice popups * refactor: cache pubfields * feat: add cacheskip fn to autocache * refactor: optimize some pages a bit * feat: skip caching for large items * refactor: progress * fix: make filter buttons work * fix: make pubtypelabel and stagemovebutton work and accessible * fix: pubcard slightly more accessible * fix: pubcard slightly more accessible * fix: make pub details page header look nicer for long titles * feat: add react scan debugging * fix: fix pub tests * fix: fix test commonnnn * fix: fix test * fix: also stale the footer on navigation * fix: fix unrelated issue where edit stage button didn't go to the manage page --------- Co-authored-by: Eric McDaniel <[email protected]>
1 parent d099898 commit d66d3ce

30 files changed

+1254
-451
lines changed

core/app/c/[communitySlug]/CommunitySwitcher.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ const CommunitySwitcher: React.FC<Props> = async function ({ community, availabl
3030
const communityRedirectUrls = await Promise.all(
3131
availableCommunities.map(async (option) => ({
3232
communityId: option.id,
33-
redirectUrl: await constructRedirectToBaseCommunityPage({ communitySlug: option.slug }),
33+
redirectUrl: await constructRedirectToBaseCommunityPage({
34+
communitySlug: community.slug === option.slug ? undefined : option.slug,
35+
}),
3436
}))
3537
);
3638

core/app/c/[communitySlug]/layout.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ export default async function MainLayout(props: Props) {
3636

3737
const { children } = props;
3838

39-
const { user } = await getPageLoginData();
39+
const [{ user }, community] = await Promise.all([
40+
getPageLoginData(),
41+
findCommunityBySlug(params.communitySlug),
42+
]);
4043

41-
const community = await findCommunityBySlug(params.communitySlug);
4244
if (!community) {
4345
return notFound();
4446
}

core/app/c/[communitySlug]/pubs/PubList.tsx

Lines changed: 87 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ import type { CommunitiesId, UsersId } from "db/public";
55
import { Skeleton } from "ui/skeleton";
66
import { cn } from "utils";
77

8-
import { searchParamsCache } from "~/app/components/DataTable/PubsDataTable/validations";
9-
import { FooterPagination } from "~/app/components/Pagination";
10-
import { PubCard } from "~/app/components/PubCard";
8+
import type { AutoReturnType } from "~/lib/types";
9+
import { PubCard } from "~/app/components/pubs/PubCard/PubCard";
1110
import {
1211
userCanArchiveAllPubs,
1312
userCanEditAllPubs,
1413
userCanMoveAllPubs,
1514
userCanRunActionsAllPubs,
1615
userCanViewAllStages,
1716
} from "~/lib/authorization/capabilities";
18-
import { getPubsCount, getPubsWithRelatedValues } from "~/lib/server";
17+
import { getPubsCount, getPubsWithRelatedValues, getPubTypesForCommunity } from "~/lib/server";
1918
import { getCommunitySlug } from "~/lib/server/cache/getCommunitySlug";
2019
import { getStages } from "~/lib/server/stages";
20+
import { getPubFilterParamsFromSearch, pubSearchParamsCache } from "./pubQuery";
21+
import { PubSearchFooter } from "./PubSearchFooter";
2122
import { PubSearch } from "./PubSearchInput";
23+
import { PubSearchProvider } from "./PubSearchProvider";
2224
import { PubsSelectedProvider } from "./PubsSelectedContext";
2325
import { PubsSelectedCounter } from "./PubsSelectedCounter";
2426

@@ -45,6 +47,7 @@ const PaginatedPubListInner = async (
4547
props: PaginatedPubListProps & {
4648
communitySlug: string;
4749
pubsPromise: Promise<PubListProcessedPub[]>;
50+
stagesPromise: Promise<AutoReturnType<typeof getStages>["execute"]>;
4851
}
4952
) => {
5053
const [
@@ -57,10 +60,7 @@ const PaginatedPubListInner = async (
5760
canViewAllStages,
5861
] = await Promise.all([
5962
props.pubsPromise,
60-
getStages(
61-
{ communityId: props.communityId, userId: props.userId },
62-
{ withActionInstances: "full" }
63-
).execute(),
63+
props.stagesPromise,
6464
userCanEditAllPubs(),
6565
userCanArchiveAllPubs(),
6666
userCanRunActionsAllPubs(),
@@ -87,6 +87,7 @@ const PaginatedPubListInner = async (
8787
canRunActionsAllPubs={canRunActionsAllPubs}
8888
canMoveAllPubs={canMoveAllPubs}
8989
canViewAllStages={canViewAllStages}
90+
canFilter={true}
9091
/>
9192
);
9293
})}
@@ -120,83 +121,120 @@ const PubListFooterPagination = async (props: {
120121
pubsPromise: Promise<ProcessedPub[]>;
121122
userId: UsersId;
122123
}) => {
123-
const perPage = searchParamsCache.get("perPage");
124-
const query = searchParamsCache.get("query");
124+
const search = pubSearchParamsCache.all();
125+
126+
const filterParams = getPubFilterParamsFromSearch(search);
125127

126128
const count = await getPubsCount(
127-
{ communityId: props.communityId, userId: props.userId },
128129
{
129-
search: query,
130+
communityId: props.communityId,
131+
userId: props.userId,
132+
133+
pubTypeId: filterParams.pubTypes,
134+
stageId: filterParams.stages,
135+
},
136+
{
137+
search: search.query,
138+
filters: filterParams.filters,
130139
}
131140
);
132141

133142
const paginationProps = {
134143
mode: "total" as const,
135-
totalPages: Math.ceil((count ?? 0) / perPage),
144+
totalPages: Math.ceil((count ?? 0) / search.perPage),
136145
};
137146

138147
return (
139-
<FooterPagination {...props} {...paginationProps} className="z-20">
148+
<PubSearchFooter {...props} {...paginationProps} className="z-20">
140149
{props.children}
141-
<PubsSelectedCounter pageSize={Math.min(perPage, count)} />
142-
</FooterPagination>
150+
<PubsSelectedCounter pageSize={Math.min(search.perPage, count)} />
151+
</PubSearchFooter>
143152
);
144153
};
145154

146155
export const PaginatedPubList: React.FC<PaginatedPubListProps> = async (props) => {
147-
const search = searchParamsCache.parse(props.searchParams);
156+
const search = pubSearchParamsCache.parse(props.searchParams);
157+
const filterParams = getPubFilterParamsFromSearch(search);
148158

149159
const communitySlug = await getCommunitySlug();
150160

151161
const basePath = props.basePath ?? `/c/${communitySlug}/pubs`;
152162

153163
// we do one more than the total amount of pubs to know if there is a next page
154-
const limit = search.query ? search.perPage + 1 : search.perPage;
164+
// const limit = search.query ? filterParams.perPage + 1 : filterParams.perPage;
155165

156166
const pubsPromise = getPubsWithRelatedValues(
157-
{ communityId: props.communityId, userId: props.userId },
158167
{
159-
limit,
160-
offset: (search.page - 1) * search.perPage,
161-
orderBy: "updatedAt",
168+
communityId: props.communityId,
169+
userId: props.userId,
170+
pubTypeId: filterParams.pubTypes,
171+
stageId: filterParams.stages,
172+
},
173+
{
174+
limit: filterParams.limit,
175+
offset: filterParams.offset,
176+
orderBy: filterParams.orderBy,
162177
withPubType: true,
163178
withRelatedPubs: false,
164179
withStage: true,
165180
withValues: false,
166181
withRelatedCounts: true,
167182
search: search.query,
183+
orderDirection: filterParams.orderDirection,
184+
filters: filterParams.filters,
168185
}
169186
);
170187

188+
const [pubTypes, stages] = await Promise.all([
189+
getPubTypesForCommunity(props.communityId, {
190+
limit: 0,
191+
}),
192+
getStages(
193+
{ communityId: props.communityId, userId: props.userId },
194+
{ withActionInstances: "full" }
195+
).execute(),
196+
]);
197+
// const stagesPromise = getStages(
198+
// { communityId: props.communityId, userId: props.userId },
199+
// { withActionInstances: "full" }
200+
// ).execute();
201+
202+
// const pubTypesPromise = getPubTypesForCommunity(props.communityId, {
203+
// limit: 0,
204+
// });
205+
171206
return (
172207
<div className="relative flex h-full flex-col">
173-
<PubsSelectedProvider pubIds={[]}>
174-
<div
175-
className={cn(
176-
"mb-4 flex h-full w-full flex-col gap-3 overflow-y-scroll p-4 pb-16"
177-
)}
178-
>
179-
<PubSearch>
180-
<Suspense fallback={<PubListSkeleton />}>
181-
<PaginatedPubListInner
182-
{...props}
183-
communitySlug={communitySlug}
184-
pubsPromise={pubsPromise}
185-
/>
186-
</Suspense>
187-
</PubSearch>
188-
</div>
189-
<Suspense fallback={null}>
190-
<PubListFooterPagination
191-
basePath={basePath}
192-
searchParams={props.searchParams}
193-
userId={props.userId}
194-
page={search.page}
195-
communityId={props.communityId}
196-
pubsPromise={pubsPromise}
197-
></PubListFooterPagination>
198-
</Suspense>
199-
</PubsSelectedProvider>
208+
<PubSearchProvider availablePubTypes={pubTypes} availableStages={stages}>
209+
<PubsSelectedProvider pubIds={[]}>
210+
<div
211+
className={cn(
212+
"mb-4 flex h-full w-full flex-col gap-3 overflow-y-scroll pb-16"
213+
)}
214+
>
215+
<PubSearch>
216+
<Suspense fallback={<PubListSkeleton />}>
217+
<PaginatedPubListInner
218+
{...props}
219+
communitySlug={communitySlug}
220+
pubsPromise={pubsPromise}
221+
stagesPromise={Promise.resolve(stages)}
222+
/>
223+
</Suspense>
224+
</PubSearch>
225+
</div>
226+
<Suspense fallback={null}>
227+
<PubListFooterPagination
228+
basePath={basePath}
229+
searchParams={props.searchParams}
230+
userId={props.userId}
231+
page={search.page}
232+
communityId={props.communityId}
233+
pubsPromise={pubsPromise}
234+
></PubListFooterPagination>
235+
</Suspense>
236+
</PubsSelectedProvider>
237+
</PubSearchProvider>
200238
</div>
201239
);
202240
};

0 commit comments

Comments
 (0)