Skip to content

Commit

Permalink
Merge pull request #1869 from dubinc/sortby
Browse files Browse the repository at this point in the history
Add sortBy saleAmount
  • Loading branch information
steven-tey authored Jan 8, 2025
2 parents edefbd4 + 1f63ace commit 101a5ad
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 80 deletions.
2 changes: 1 addition & 1 deletion apps/web/app/api/customers/[id]/activity/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const GET = withWorkspace(async ({ workspace, params }) => {
getEvents({
customerId: customer.id,
event: "sales",
order: "desc",
sortOrder: "desc",
sortBy: "timestamp",
interval: "1y",
page: 1,
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/api/links/export/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export const GET = withWorkspace(
}),
...(userId && { userId }),
},

// TODO: orderBy is not currently supported
orderBy: {
[sort]: "desc",
},
Expand Down
39 changes: 4 additions & 35 deletions apps/web/app/api/links/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,15 @@ import { NextResponse } from "next/server";
export const GET = withWorkspace(
async ({ req, headers, workspace }) => {
const searchParams = getSearchParamsWithArray(req.url);
const params = getLinksQuerySchemaExtended.parse(searchParams);

const {
domain,
tagId,
tagIds,
search,
sort,
page,
pageSize,
userId,
showArchived,
withTags,
includeUser,
includeWebhooks,
includeDashboard,
linkIds,
tenantId,
} = getLinksQuerySchemaExtended.parse(searchParams);

if (domain) {
await getDomainOrThrow({ workspace, domain });
if (params.domain) {
await getDomainOrThrow({ workspace, domain: params.domain });
}

const response = await getLinksForWorkspace({
...params,
workspaceId: workspace.id,
domain,
tagId,
tagIds,
search,
sort,
page,
pageSize,
userId,
showArchived,
withTags,
includeUser,
includeWebhooks,
includeDashboard,
linkIds,
tenantId,
});

return NextResponse.json(response, {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/lib/actions/partners/backfill-link-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const backfillLinkData = async ({
interval: "all",
page: 1,
limit: 5000,
order: "desc",
sortOrder: "desc",
sortBy: "timestamp",
});

Expand Down
8 changes: 8 additions & 0 deletions apps/web/lib/analytics/get-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export const getEvents = async (params: EventsFilters) => {
region,
country,
isDemo,
order,
sortOrder,
} = params;

const { startDate, endDate } = getStartEndDates({
Expand All @@ -57,6 +59,11 @@ export const getEvents = async (params: EventsFilters) => {
region = split[1];
}

// support legacy order param
if (order && order !== "desc") {
sortOrder = order;
}

const pipe = (isDemo ? tbDemo : tb).buildPipe({
pipe: "v2_events",
parameters: eventsFilterTB,
Expand All @@ -75,6 +82,7 @@ export const getEvents = async (params: EventsFilters) => {
qr,
country,
region,
order: sortOrder,
offset: (params.page - 1) * params.limit,
start: startDate.toISOString().replace("T", " ").replace("Z", ""),
end: endDate.toISOString().replace("T", " ").replace("Z", ""),
Expand Down
1 change: 1 addition & 0 deletions apps/web/lib/analytics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const partnerEventsSchema = eventsQuerySchema
page: true,
limit: true,
order: true,
sortOrder: true,
sortBy: true,
})
.partial();
Expand Down
11 changes: 9 additions & 2 deletions apps/web/lib/api/links/get-links-for-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export async function getLinksForWorkspace({
tagIds,
tagNames,
search,
sort = "createdAt",
sort, // Deprecated
sortBy,
sortOrder,
page,
pageSize,
userId,
Expand All @@ -27,6 +29,11 @@ export async function getLinksForWorkspace({
}) {
const combinedTagIds = combineTagIds({ tagId, tagIds });

// support legacy sort param
if (sort && sort !== "createdAt") {
sortBy = sort;
}

const links = await prisma.link.findMany({
where: {
projectId: workspaceId,
Expand Down Expand Up @@ -85,7 +92,7 @@ export async function getLinksForWorkspace({
dashboard: includeDashboard,
},
orderBy: {
[sort]: "desc",
[sortBy]: sortOrder,
},
take: pageSize,
skip: (page - 1) * pageSize,
Expand Down
4 changes: 2 additions & 2 deletions apps/web/lib/openapi/links/get-links.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { openApiErrorResponses } from "@/lib/openapi/responses";
import z from "@/lib/zod";
import { getLinksQuerySchema, LinkSchema } from "@/lib/zod/schemas/links";
import { getLinksQuerySchemaBase, LinkSchema } from "@/lib/zod/schemas/links";
import { ZodOpenApiOperationObject } from "zod-openapi";

export const getLinks: ZodOpenApiOperationObject = {
Expand Down Expand Up @@ -28,7 +28,7 @@ export const getLinks: ZodOpenApiOperationObject = {
description:
"Retrieve a paginated list of links for the authenticated workspace.",
requestParams: {
query: getLinksQuerySchema,
query: getLinksQuerySchemaBase,
},
responses: {
"200": {
Expand Down
17 changes: 15 additions & 2 deletions apps/web/lib/zod/schemas/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ export const eventsFilterTB = analyticsFilterTB
}),
);

const sortOrder = z
.enum(["asc", "desc"])
.default("desc")
.optional()
.describe("The sort order. The default is `desc`.");

export const eventsQuerySchema = analyticsQuerySchema
.omit({ groupBy: true })
.extend({
Expand All @@ -259,6 +265,13 @@ export const eventsQuerySchema = analyticsQuerySchema
),
page: z.coerce.number().default(1),
limit: z.coerce.number().default(PAGINATION_LIMIT),
order: z.enum(["asc", "desc"]).default("desc"),
sortBy: z.enum(["timestamp"]).default("timestamp"),
sortOrder,
sortBy: z
.enum(["timestamp"])
.optional()
.default("timestamp")
.describe("The field to sort the events by. The default is `timestamp`."),
order: sortOrder
.describe("DEPRECATED. Use `sortOrder` instead.")
.openapi({ deprecated: true }),
});
26 changes: 17 additions & 9 deletions apps/web/lib/zod/schemas/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,23 @@ const LinksQuerySchema = z.object({
.openapi({ deprecated: true }),
});

export const getLinksQuerySchema = LinksQuerySchema.merge(
const sortBy = z
.enum(["createdAt", "clicks", "saleAmount", "lastClicked"])
.optional()
.default("createdAt")
.describe("The field to sort the links by. The default is `createdAt`.");

export const getLinksQuerySchemaBase = LinksQuerySchema.merge(
z.object({
sort: z
.enum(["createdAt", "clicks", "lastClicked"])
sortBy,
sortOrder: z
.enum(["asc", "desc"])
.optional()
.default("createdAt")
.describe(
"The field to sort the links by. The default is `createdAt`, and sort order is always descending.",
),
.default("desc")
.describe("The sort order. The default is `desc`."),
sort: sortBy
.openapi({ deprecated: true })
.describe("DEPRECATED. Use `sortBy` instead."),
}),
).merge(getPaginationQuerySchema({ pageSize: 100 }));

Expand All @@ -99,7 +107,7 @@ export const getLinksCountQuerySchema = LinksQuerySchema.merge(
}),
);

export const linksExportQuerySchema = getLinksQuerySchema
export const linksExportQuerySchema = getLinksQuerySchemaBase
.omit({ page: true, pageSize: true })
.merge(
z.object({
Expand Down Expand Up @@ -603,7 +611,7 @@ export const getLinkInfoQuerySchema = domainKeySchema.partial().merge(
}),
);

export const getLinksQuerySchemaExtended = getLinksQuerySchema.merge(
export const getLinksQuerySchemaExtended = getLinksQuerySchemaBase.merge(
z.object({
// Only Dub UI uses the following query parameters
includeUser: booleanQuerySchema.default("false"),
Expand Down
2 changes: 1 addition & 1 deletion apps/web/scripts/backfill-missing-sales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async function main() {
interval: "all",
page: 1,
limit: 1000,
order: "desc",
sortOrder: "desc",
sortBy: "timestamp",
})) as unknown as SaleEvent[];

Expand Down
2 changes: 1 addition & 1 deletion apps/web/scripts/backfill-sales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async function main() {
interval: "all",
page: 1,
limit: 5000,
order: "desc",
sortOrder: "desc",
sortBy: "timestamp",
});

Expand Down
16 changes: 8 additions & 8 deletions apps/web/ui/analytics/events/events-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export default function EventsTable({

const { columnVisibility, setColumnVisibility } = useColumnVisibility();

const sortBy = searchParams.get("sort") || "timestamp";
const order = searchParams.get("order") === "asc" ? "asc" : "desc";
const sortBy = searchParams.get("sortBy") || "timestamp";
const sortOrder = searchParams.get("sortOrder") === "asc" ? "asc" : "desc";

const columns = useMemo<ColumnDef<EventDatum, any>[]>(
() =>
Expand Down Expand Up @@ -440,9 +440,9 @@ export default function EventsTable({
event: tab,
page: pagination.pageIndex.toString(),
sortBy,
order,
sortOrder,
}).toString(),
[originalQueryString, tab, pagination, sortBy, order],
[originalQueryString, tab, pagination, sortBy, sortOrder],
);

// Update export query string
Expand Down Expand Up @@ -482,13 +482,13 @@ export default function EventsTable({
columnVisibility: columnVisibility[tab],
onColumnVisibilityChange: (args) => setColumnVisibility(tab, args),
sortableColumns: ["timestamp"],
sortBy: sortBy,
sortOrder: order,
sortBy,
sortOrder,
onSortChange: ({ sortBy, sortOrder }) =>
queryParams({
set: {
...(sortBy && { sort: sortBy }),
...(sortOrder && { order: sortOrder }),
...(sortBy && { sortBy }),
...(sortOrder && { sortOrder }),
},
}),
columnPinning: { right: ["menu"] },
Expand Down
4 changes: 3 additions & 1 deletion apps/web/ui/layout/sidebar/app-sidebar-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ export function AppSidebarNav({
currentArea={currentArea}
data={{
slug: slug || "",
queryString: getQueryString(),
queryString: getQueryString(undefined, {
ignore: ["sortBy", "sortOrder"],
}),
flags,
programs,
session: session || undefined,
Expand Down
6 changes: 3 additions & 3 deletions apps/web/ui/links/link-sort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export default function LinkSort() {

const [openPopover, setOpenPopover] = useState(false);

const { sort: sortSlug, setSort } = useContext(LinksDisplayContext);
const { sortBy, setSort } = useContext(LinksDisplayContext);
const selectedSort =
sortOptions.find((s) => s.slug === sortSlug) ?? sortOptions[0];
sortOptions.find((s) => s.slug === sortBy) ?? sortOptions[0];

return (
<Popover
Expand All @@ -36,7 +36,7 @@ export default function LinkSort() {
text={display}
icon={<SortDesc className="h-4 w-4" />}
/>
{sortSlug === slug && (
{sortBy === slug && (
<Tick className="h-4 w-4" aria-hidden="true" />
)}
</button>
Expand Down
4 changes: 2 additions & 2 deletions apps/web/ui/links/links-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export default function LinksContainer({
}: {
CreateLinkButton: () => JSX.Element;
}) {
const { viewMode, sort, showArchived } = useContext(LinksDisplayContext);
const { viewMode, sortBy, showArchived } = useContext(LinksDisplayContext);

const { links, isValidating } = useLinks({ sort, showArchived });
const { links, isValidating } = useLinks({ sortBy, showArchived });
const { data: count } = useLinksCount<number>({ showArchived });

return (
Expand Down
Loading

0 comments on commit 101a5ad

Please sign in to comment.