Skip to content

Commit cf003e5

Browse files
committed
Merge branch 'main' into feat/1544
2 parents 0820d9d + b1d8317 commit cf003e5

File tree

40 files changed

+3346
-1434
lines changed

40 files changed

+3346
-1434
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"search.exclude": {
1919
"apps/api/src/assets/js": true,
2020
"**/monaco/vs/**": true,
21+
"**/node_modules/**": true,
2122
"dist": true,
2223
"logs": true,
2324
"tmp": true

apps/landing/components/ErrorQueryParamErrorBanner.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ interface ErrorQueryParamErrorBannerProps {
1313
}
1414

1515
export function ErrorQueryParamErrorBanner({ error, message, success }: ErrorQueryParamErrorBannerProps) {
16-
const params = useSearchParams();
16+
const searchParams = useSearchParams();
1717

18-
error = error ?? params.get('error');
19-
message = message ?? params.get('message');
20-
success = success ?? params.get('success');
18+
error = error ?? searchParams?.get('error');
19+
message = message ?? searchParams?.get('message');
20+
success = success ?? searchParams?.get('success');
2121

2222
if (error) {
2323
return (

apps/landing/components/Navigation.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,15 @@ export const Navigation = ({ className, inverse, omitLinks = [], userProfile }:
142142
</div>
143143
<div className="hidden md:flex md:items-center md:space-x-6">
144144
{userProfile?.isLoggedIn && !userProfile?.pendingVerifications ? (
145-
<>
146-
<a
147-
href={ENVIRONMENT.CLIENT_URL}
148-
className={classNames('inline-flex items-center px-4 py-2 border border-transparent text-base font-medium rounded-md', {
149-
'text-white bg-gray-600 hover:bg-gray-700': inverse,
150-
'bg-linear-to-r from-teal-500 to-cyan-600 text-white font-medium hover:from-teal-600 hover:to-cyan-700': !inverse,
151-
})}
152-
>
153-
Go to Jetstream
154-
</a>
155-
</>
145+
<a
146+
href={ENVIRONMENT.CLIENT_URL}
147+
className={classNames('inline-flex items-center px-4 py-2 border border-transparent text-base font-medium rounded-md', {
148+
'text-white bg-gray-600 hover:bg-gray-700': inverse,
149+
'bg-linear-to-r from-teal-500 to-cyan-600 text-white font-medium hover:from-teal-600 hover:to-cyan-700': !inverse,
150+
})}
151+
>
152+
Go to Jetstream
153+
</a>
156154
) : (
157155
<>
158156
{' '}

apps/landing/components/auth/LoginOrSignUp.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ export function LoginOrSignUp({ action, providers, csrfToken }: LoginOrSignUpPro
8585
const searchParams = useSearchParams();
8686
const [{ lastUsedLogin, rememberedEmail }] = useState(getLastUsedLoginMethod);
8787

88-
const emailHint = searchParams.get('email') || (action === 'login' ? rememberedEmail : null);
89-
const returnUrl = searchParams.get('returnUrl');
88+
const emailHint = searchParams?.get('email') || (action === 'login' ? rememberedEmail : null);
89+
const returnUrl = searchParams?.get('returnUrl');
9090

9191
const {
9292
register,
@@ -268,12 +268,10 @@ export function LoginOrSignUp({ action, providers, csrfToken }: LoginOrSignUpPro
268268
}}
269269
>
270270
{action !== 'register' && (
271-
<>
272-
<div className="flex items-center justify-between">
273-
<Checkbox inputProps={{ ...register('rememberMe') }}>Remember Me</Checkbox>
274-
<ShowPasswordButton isActive={showPasswordActive} onClick={() => setShowPasswordActive(!showPasswordActive)} />
275-
</div>
276-
</>
271+
<div className="flex items-center justify-between">
272+
<Checkbox inputProps={{ ...register('rememberMe') }}>Remember Me</Checkbox>
273+
<ShowPasswordButton isActive={showPasswordActive} onClick={() => setShowPasswordActive(!showPasswordActive)} />
274+
</div>
277275
)}
278276
</Input>
279277

apps/landing/components/auth/LoginOrSignUpOAuthButton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import type { Provider, Providers } from '@jetstream/auth/types';
2+
import { Maybe } from '@jetstream/types';
23
import classNames from 'classnames';
34
import { useMemo } from 'react';
45

56
interface LoginOrSignUpOAuthButtonProps {
67
action: 'login' | 'register';
78
provider: Provider;
89
csrfToken: string;
9-
returnUrl: string | null;
10+
returnUrl?: Maybe<string>;
1011
lastUsedLogin: keyof Providers | null;
1112
setLastUsed: (data: { lastUsedLogin?: keyof Providers | null; rememberedEmail?: string | null }) => void;
1213
}

apps/landing/components/auth/PasswordResetInit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function PasswordResetInit({ csrfToken }: PasswordResetInitProps) {
4040
const captchaRef = useRef<{ reset: () => void }>(null);
4141
const [{ rememberedEmail }] = useState(getLastUsedLoginMethod);
4242

43-
const emailHint = searchParams.get('email') || rememberedEmail || '';
43+
const emailHint = searchParams?.get('email') || rememberedEmail || '';
4444

4545
const {
4646
register,

apps/landing/components/auth/VerifyEmailOr2fa.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function VerifyEmailOr2fa({ csrfToken, email, pendingVerifications }: Ver
6363
} = useForm({
6464
resolver: zodResolver(FormSchema),
6565
defaultValues: {
66-
code: searchParams.get('code') || '',
66+
code: searchParams?.get('code') || '',
6767
csrfToken,
6868
captchaToken: '',
6969
type: activeFactor,
Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,39 @@
11
import Head from 'next/head';
2+
import { useRouter } from 'next/router';
3+
4+
const DESCRIPTION =
5+
'Jetstream is a powerful suite of Salesforce administration tools built for Salesforce admins, developers, and power users. Manage, query, and update Salesforce data faster with an advanced SOQL query builder, a high-performance data loader, and productivity features designed for real-world Salesforce workflows.';
6+
7+
const OG_IMAGE = 'https://res.cloudinary.com/getjetstream/image/upload/v1771094335/public/jetstream-og-image_chejpi.png';
8+
const SITE_URL = 'https://getjetstream.app';
9+
10+
export default function LayoutHead({ title = 'Jetstream', url }: { title?: string; url?: string }) {
11+
const router = useRouter();
12+
const fullTitle = title === 'Jetstream' ? title : `${title} | Jetstream`;
13+
// Automatically construct the canonical URL from the current route if not provided
14+
const canonicalUrl = url || `${SITE_URL}${router.asPath}`;
215

3-
export default function LayoutHead({ title = 'Jetstream' }: { title?: string }) {
416
return (
517
<Head>
6-
<title>{title}</title>
7-
<meta
8-
name="description"
9-
content="Jetstream is a set of tools that supercharge your administration of Salesforce.com. Jetstream is built for administrators, developers, quality assurance, or power users that want to speed up your management of Salesforce. Jetstream comes with an advanced query builder for viewing records, a powerful data loader for making changes to your record data, and many more features!"
10-
/>
11-
<meta
12-
name="og:description"
13-
content="Jetstream is a set of tools that supercharge your administration of Salesforce.com. Jetstream is built for administrators, developers, quality assurance, or power users that want to speed up your management of Salesforce. Jetstream comes with an advanced query builder for viewing records, a powerful data loader for making changes to your record data, and many more features!"
14-
/>
18+
<title>{fullTitle}</title>
19+
<meta name="description" content={DESCRIPTION} />
20+
<link rel="canonical" href={canonicalUrl} />
1521

16-
<meta
17-
name="image"
18-
content="https://res.cloudinary.com/getjetstream/image/upload/b_rgb:ffffff,bo_3px_solid_rgb:ffffff,pg_1/v1634516631/public/jetstream-logo-1200w.png"
19-
/>
20-
<meta
21-
name="og:image"
22-
content="https://res.cloudinary.com/getjetstream/image/upload/b_rgb:ffffff,bo_3px_solid_rgb:ffffff,pg_1/v1634516631/public/jetstream-logo-1200w.png"
23-
/>
24-
<meta
25-
name="twitter:image"
26-
content="https://res.cloudinary.com/getjetstream/image/upload/b_rgb:ffffff,bo_3px_solid_rgb:ffffff,pg_1/v1634516631/public/jetstream-logo-1200w.png"
27-
/>
22+
{/* Open Graph */}
23+
<meta property="og:title" content={fullTitle} />
24+
<meta property="og:description" content={DESCRIPTION} />
25+
<meta property="og:type" content="website" />
26+
<meta property="og:url" content={canonicalUrl} />
27+
<meta property="og:site_name" content="Jetstream" />
28+
<meta property="og:image" content={OG_IMAGE} />
29+
<meta property="og:image:width" content="1200" />
30+
<meta property="og:image:height" content="630" />
31+
32+
{/* Twitter Card */}
33+
<meta name="twitter:card" content="summary_large_image" />
34+
<meta name="twitter:title" content={fullTitle} />
35+
<meta name="twitter:description" content={DESCRIPTION} />
36+
<meta name="twitter:image" content={OG_IMAGE} />
2837

2938
<link rel="icon" type="image/png" href="/images/favicon.ico"></link>
3039
<meta charSet="UTF-8" />
@@ -51,6 +60,27 @@ export default function LayoutHead({ title = 'Jetstream' }: { title?: string })
5160
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png" />
5261
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon-96x96.png" />
5362
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png" />
63+
64+
{/* Structured Data */}
65+
<script
66+
type="application/ld+json"
67+
dangerouslySetInnerHTML={{
68+
__html: JSON.stringify({
69+
'@context': 'https://schema.org',
70+
'@type': 'SoftwareApplication',
71+
name: 'Jetstream',
72+
description: DESCRIPTION,
73+
applicationCategory: 'BusinessApplication',
74+
operatingSystem: 'Web, Windows, macOS, Linux',
75+
offers: {
76+
'@type': 'Offer',
77+
price: '0',
78+
priceCurrency: 'USD',
79+
},
80+
url: 'https://getjetstream.app',
81+
}),
82+
}}
83+
/>
5484
</Head>
5585
);
5686
}

apps/landing/hooks/desktop-auth.hooks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ function reducer(state: State, action: Action): State {
9797

9898
export function useDesktopAuthState() {
9999
const searchParams = useSearchParams();
100-
const deviceId = searchParams.get('deviceId');
101-
const token = searchParams.get('token');
100+
const deviceId = searchParams?.get('deviceId');
101+
const token = searchParams?.get('token');
102102

103103
const [{ status, errorMessage }, dispatch] = useReducer(reducer, {
104104
status: 'loading',

apps/landing/next-env.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3+
/// <reference types="next/navigation-types/compat/navigation" />
4+
import "./.next/types/routes.d.ts";
35

46
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
7+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

0 commit comments

Comments
 (0)