Skip to content

Commit be522a5

Browse files
authored
Merge pull request #93 from techulus/develop
Add page screenshot
2 parents 4fa6fba + 7a55b45 commit be522a5

File tree

4 files changed

+135
-59
lines changed

4 files changed

+135
-59
lines changed

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@types/validator": "^13.15.3",
3131
"@vercel/og": "^0.0.20",
3232
"canvas-confetti": "^1.9.3",
33+
"capture-node": "^2.2.0",
3334
"chrono-node": "^2.7.6",
3435
"classnames": "^2.3.1",
3536
"easymde": "^2.18.0",

apps/web/pages/pages/index.tsx

Lines changed: 85 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { PageType, PageTypeToLabel } from "@changes-page/supabase/types/page";
22
import { PlusIcon, UserGroupIcon } from "@heroicons/react/solid";
33
import classNames from "classnames";
4-
import { InferGetServerSidePropsType } from "next";
4+
import type { InferGetServerSidePropsType } from "next";
55
import Link from "next/link";
66
import { useRouter } from "next/router";
7-
import { useEffect, type JSX } from "react";
7+
import { type JSX, useEffect } from "react";
88
import { useHotkeys } from "react-hotkeys-hook";
99
import { PrimaryRouterButton } from "../../components/core/buttons.component";
1010
import { notifyError } from "../../components/core/toast.component";
@@ -13,6 +13,7 @@ import AuthLayout from "../../components/layout/auth-layout.component";
1313
import Page from "../../components/layout/page.component";
1414
import Changelog from "../../components/marketing/changelog";
1515
import { ROUTES } from "../../data/routes.data";
16+
import { getPageScreenshotUrl } from "../../utils/capture";
1617
import { getAppBaseURL } from "../../utils/helpers";
1718
import { withSupabase } from "../../utils/supabase/withSupabase";
1819
import { useUserData } from "../../utils/useUser";
@@ -33,16 +34,28 @@ export const getServerSideProps = withSupabase(async (_, { supabase }) => {
3334
)
3435
.order("updated_at", { ascending: false });
3536

37+
const screenshots = pages.map((page) =>
38+
page
39+
? getPageScreenshotUrl(
40+
page.page_settings?.custom_domain
41+
? `https://${page.page_settings.custom_domain}`
42+
: `https://${page.url_slug}.changes.page`
43+
)
44+
: null
45+
);
46+
3647
return {
3748
props: {
3849
pages: pages ?? [],
50+
screenshots,
3951
error,
4052
},
4153
};
4254
});
4355

4456
export default function Pages({
4557
pages,
58+
screenshots,
4659
error,
4760
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
4861
const { billingDetails, user } = useUserData();
@@ -80,7 +93,7 @@ export default function Pages({
8093
message="Get started by creating your first page."
8194
buttonLink={
8295
billingDetails?.has_active_subscription
83-
? `/pages/new`
96+
? "/pages/new"
8497
: `/api/billing/redirect-to-checkout?return_url=${getAppBaseURL()}/pages`
8598
}
8699
buttonLabel={
@@ -107,69 +120,81 @@ export default function Pages({
107120
{pages.length ? (
108121
<div className="overflow-hidden shadow rounded-md bg-white dark:bg-gray-900 border dark:border-gray-800">
109122
<ul className="divide-y divide-gray-200 dark:divide-gray-800">
110-
{pages.map((page) => (
123+
{pages.map((page, idx) => (
111124
<li
112125
key={page.id}
113126
className="relative group hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-200"
114127
>
115128
<div className="flex items-center justify-between p-6">
116-
<div className="flex-1 min-w-0">
117-
<div className="flex items-center gap-3 mb-2">
118-
<span
119-
className={classNames(
120-
page.type === PageType.announcements &&
121-
"bg-blue-100 dark:bg-blue-700",
122-
page.type === PageType.changelogs &&
123-
"bg-teal-100 dark:bg-teal-700",
124-
page.type === PageType.releases &&
125-
"bg-rose-100 dark:bg-rose-700",
126-
page.type === PageType.updates &&
127-
"bg-amber-100 dark:bg-amber-700",
128-
page.type === PageType.announcements &&
129-
"text-blue-500 dark:text-blue-100",
130-
page.type === PageType.changelogs &&
131-
"text-teal-500 dark:text-teal-100",
132-
page.type === PageType.releases &&
133-
"text-rose-500 dark:text-rose-100",
134-
page.type === PageType.updates &&
135-
"text-amber-500 dark:text-amber-100",
136-
"inline-flex px-2 py-1 text-xs font-bold rounded-md"
137-
)}
138-
>
139-
{PageTypeToLabel[page.type]}
140-
</span>
141-
{page.teams && page.user_id !== user?.id && (
142-
<div className="flex items-center gap-1 text-gray-500 dark:text-gray-400">
143-
<UserGroupIcon className="h-4 w-4" />
144-
<span className="text-xs font-medium">
145-
Editor ({page.teams.name})
146-
</span>
147-
</div>
148-
)}
149-
</div>
150-
<div>
151-
<h3 className="text-lg font-bold tracking-tight text-gray-900 dark:text-white">
152-
<Link
153-
href={`${ROUTES.PAGES}/${page.id}`}
154-
className="focus:outline-none hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors duration-200"
129+
<div className="flex items-center gap-4">
130+
{screenshots[idx] ? (
131+
<div className="flex-shrink-0 hidden sm:block">
132+
<img
133+
className="w-48 h-18 object-cover rounded-md border border-gray-200 dark:border-gray-700"
134+
src={screenshots[idx]}
135+
alt={`Screenshot of ${page.title}`}
136+
loading="lazy"
137+
/>
138+
</div>
139+
) : null}
140+
<div className="flex-1 min-w-0">
141+
<div className="flex items-center gap-3 mb-2">
142+
<span
143+
className={classNames(
144+
page.type === PageType.announcements &&
145+
"bg-blue-100 dark:bg-blue-700",
146+
page.type === PageType.changelogs &&
147+
"bg-teal-100 dark:bg-teal-700",
148+
page.type === PageType.releases &&
149+
"bg-rose-100 dark:bg-rose-700",
150+
page.type === PageType.updates &&
151+
"bg-amber-100 dark:bg-amber-700",
152+
page.type === PageType.announcements &&
153+
"text-blue-500 dark:text-blue-100",
154+
page.type === PageType.changelogs &&
155+
"text-teal-500 dark:text-teal-100",
156+
page.type === PageType.releases &&
157+
"text-rose-500 dark:text-rose-100",
158+
page.type === PageType.updates &&
159+
"text-amber-500 dark:text-amber-100",
160+
"inline-flex px-2 py-1 text-xs font-bold rounded-md"
161+
)}
155162
>
156-
<span
157-
className="absolute inset-0"
158-
aria-hidden="true"
159-
/>
160-
{page.title}
161-
</Link>
162-
</h3>
163-
{page.description && (
164-
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
165-
{page.description}
163+
{PageTypeToLabel[page.type]}
164+
</span>
165+
{page.teams && page.user_id !== user?.id && (
166+
<div className="flex items-center gap-1 text-gray-500 dark:text-gray-400">
167+
<UserGroupIcon className="h-4 w-4" />
168+
<span className="text-xs font-medium">
169+
Editor ({page.teams.name})
170+
</span>
171+
</div>
172+
)}
173+
</div>
174+
<div>
175+
<h3 className="text-lg font-bold tracking-tight text-gray-900 dark:text-white">
176+
<Link
177+
href={`${ROUTES.PAGES}/${page.id}`}
178+
className="focus:outline-none hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors duration-200"
179+
>
180+
<span
181+
className="absolute inset-0"
182+
aria-hidden="true"
183+
/>
184+
{page.title}
185+
</Link>
186+
</h3>
187+
{page.description && (
188+
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
189+
{page.description}
190+
</p>
191+
)}
192+
<p className="mt-2 text-xs text-gray-400 dark:text-gray-500">
193+
{page.page_settings?.custom_domain
194+
? page.page_settings.custom_domain
195+
: `${page.url_slug}.changes.page`}
166196
</p>
167-
)}
168-
<p className="mt-2 text-xs text-gray-400 dark:text-gray-500">
169-
{page.page_settings?.custom_domain
170-
? page.page_settings.custom_domain
171-
: `${page.url_slug}.changes.page`}
172-
</p>
197+
</div>
173198
</div>
174199
</div>
175200
<div className="ml-4 flex-shrink-0">
@@ -178,6 +203,7 @@ export default function Pages({
178203
fill="currentColor"
179204
viewBox="0 0 20 20"
180205
>
206+
<title>Go to page</title>
181207
<path
182208
fillRule="evenodd"
183209
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"

apps/web/utils/capture.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Capture } from "capture-node";
2+
3+
export function getPageScreenshotUrl(url: string) {
4+
const capture = new Capture(
5+
process.env.CAPTURE_API_KEY,
6+
process.env.CAPTURE_API_SECRET
7+
);
8+
9+
return capture.buildImageUrl(url, {
10+
vw: 1280,
11+
vh: 720,
12+
scaleFactor: 1.5,
13+
});
14+
}

pnpm-lock.yaml

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)