Skip to content

Commit b280398

Browse files
authored
Merge pull request #8342 from sagemathinc/next-tweak-contact-links
next/support: streamline video call booking
2 parents e272d9a + b267c87 commit b280398

File tree

16 files changed

+239
-130
lines changed

16 files changed

+239
-130
lines changed

src/packages/database/settings/customize.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export default async function getCustomize(
7777
imprint: settings.imprint,
7878
policies: settings.policies,
7979
support: settings.support,
80+
supportVideoCall: settings.support_video_call,
8081

8182
// Is important for invite emails, password reset, etc. (e.g., so we can construct a url to our site).
8283
// This *can* start with http:// to explicitly use http instead of https, and can end

src/packages/next/components/auth/sign-up.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { Alert, Button, Checkbox, Input } from "antd";
6+
import { Alert, Button, Checkbox, Divider, Input } from "antd";
77
import { CSSProperties, useEffect, useRef, useState } from "react";
88
import {
99
GoogleReCaptchaProvider,
1010
useGoogleReCaptcha,
1111
} from "react-google-recaptcha-v3";
12+
1213
import Markdown from "@cocalc/frontend/editors/slate/static-markdown";
1314
import {
1415
CONTACT_TAG,
@@ -22,6 +23,7 @@ import {
2223
} from "@cocalc/util/misc";
2324
import { COLORS } from "@cocalc/util/theme";
2425
import { Strategy } from "@cocalc/util/types/sso";
26+
import { Paragraph } from "components/misc";
2527
import A from "components/misc/A";
2628
import Loading from "components/share/loading";
2729
import apiPost from "lib/api/post";
@@ -99,7 +101,7 @@ function SignUp0({
99101

100102
const submittable = useRef<boolean>(false);
101103
const { executeRecaptcha } = useGoogleReCaptcha();
102-
const { strategies } = useCustomize();
104+
const { strategies, supportVideoCall } = useCustomize();
103105

104106
// Sometimes the user if this component knows requiresToken and sometimes they don't.
105107
// If they don't, we have to make an API call to figure it out.
@@ -263,13 +265,21 @@ function SignUp0({
263265
minimal={minimal}
264266
title={`Create a free account with ${siteName}`}
265267
>
266-
<div>
268+
<Paragraph>
267269
By creating an account, you agree to the{" "}
268270
<A external={true} href="/policies/terms">
269271
Terms of Service
270272
</A>
271273
.
272-
</div>
274+
</Paragraph>
275+
{onCoCalcCom && supportVideoCall ? (
276+
<Paragraph>
277+
Do you need more information how {siteName} can be useful for you?{" "}
278+
<A href={supportVideoCall}>Book a video call</A> and we'll help you
279+
decide.
280+
</Paragraph>
281+
) : undefined}
282+
<Divider />
273283
{!minimal && onCoCalcCom ? (
274284
<Tags
275285
setTags={setTags}

src/packages/next/components/landing/content.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export default function Content(props: Props) {
224224
}
225225
/>
226226
</div>
227-
<SignIn startup={startup ?? title} hideFree={true} />
227+
<SignIn startup={startup ?? title} hideFree={true} emphasize />
228228
</Space>
229229
</Col>
230230
<Col sm={14} xs={24}>

src/packages/next/components/landing/footer.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default function Footer() {
6262
organizationURL,
6363
enabledPages,
6464
termsOfServiceURL,
65-
account,
65+
supportVideoCall,
6666
} = useCustomize();
6767

6868
const footerColumns: Array<FooterColumn> = [
@@ -140,8 +140,13 @@ export default function Footer() {
140140
},
141141
{
142142
text: "Get a Live Demo",
143+
url: supportVideoCall ?? "",
144+
hide: !enabledPages?.liveDemo || !supportVideoCall,
145+
},
146+
{
147+
text: "Contact Us",
143148
url: liveDemoUrl("footer"),
144-
hide: !account || !enabledPages?.liveDemo,
149+
hide: !enabledPages?.support,
145150
},
146151
],
147152
},

src/packages/next/components/landing/header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default function Header(props: Props) {
7272
}}
7373
>
7474
{true || account ? (
75-
<LiveDemo context="header" type="primary" />
75+
<LiveDemo context="header" btnType="primary" />
7676
) : (
7777
<Button
7878
type="primary"

src/packages/next/components/landing/index-list.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,27 @@ import { MAX_WIDTH } from "lib/config";
1515
import useCustomize, { CustomizeType } from "lib/use-customize";
1616

1717
export interface Item {
18-
link: string;
18+
link: string | ((customize: CustomizeType) => string | undefined);
1919
linkText?: ReactNode;
2020
title: ReactNode;
2121
logo: IconName | StaticImageData;
2222
logoBackground?: string; // #color
2323
image?: StaticImageData;
2424
imageWidth?: string;
25-
description: ReactNode;
25+
description: ReactNode | ((customize: CustomizeType) => ReactNode);
2626
shareServer?: boolean; // only show if the share server is enabled
2727
landingPages?: boolean; // only show if landing pages are enabled.
2828
hide?: (customize: CustomizeType) => boolean; // if returns true, then this item will be hidden.
2929
}
3030

3131
export type DataSource = Item[];
3232

33+
// replaces the description attribute by {description: ReactNode}
34+
type ItemProcessed = Omit<Item, "description" | "link"> & {
35+
description: ReactNode;
36+
link: string;
37+
};
38+
3339
interface Props {
3440
title: ReactNode;
3541
description: ReactNode;
@@ -41,13 +47,27 @@ interface Props {
4147
export default function IndexList({ title, description, dataSource }: Props) {
4248
const customize = useCustomize();
4349
const { shareServer, landingPages } = customize;
44-
const filteredDataSource = useMemo(() => {
45-
return dataSource.filter((item) => {
46-
if (item.shareServer && !shareServer) return false;
47-
if (item.landingPages && !landingPages) return false;
48-
if (item.hide?.(customize)) return false;
49-
return true;
50-
});
50+
const filteredDataSource: ItemProcessed[] = useMemo(() => {
51+
return dataSource
52+
.filter((item) => {
53+
if (item.shareServer && !shareServer) return false;
54+
if (item.landingPages && !landingPages) return false;
55+
if (item.hide?.(customize)) return false;
56+
return true;
57+
})
58+
.map((item) => {
59+
return {
60+
...item,
61+
description:
62+
typeof item.description === "function"
63+
? item.description(customize)
64+
: item.description,
65+
link:
66+
typeof item.link === "function"
67+
? item.link(customize) ?? ""
68+
: item.link,
69+
};
70+
});
5171
}, [shareServer, landingPages, dataSource]);
5272
return (
5373
<Layout.Content
@@ -80,8 +100,8 @@ export default function IndexList({ title, description, dataSource }: Props) {
80100
);
81101
}
82102

83-
function DataList({ dataSource }: { dataSource: Item[] }) {
84-
function renderItem(item): ReactNode {
103+
function DataList({ dataSource }: { dataSource: ItemProcessed[] }) {
104+
function renderItem(item: ItemProcessed): ReactNode {
85105
const icon = (
86106
<div>
87107
{isValidElement(item.logo) ? (
Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import getSupportUrl from "@cocalc/frontend/support/url";
21
import { Button } from "antd";
2+
import type { ButtonType } from "antd/es/button";
3+
import type { ReactNode } from "react";
4+
35
import { Icon } from "@cocalc/frontend/components/icon";
4-
import { useEffect, useState } from "react";
6+
import getSupportUrl from "@cocalc/frontend/support/url";
7+
import { useCustomize } from "lib/customize";
58

69
export function liveDemoUrl(context) {
710
return getSupportUrl({
@@ -14,18 +17,20 @@ export function liveDemoUrl(context) {
1417

1518
interface Props {
1619
context: string;
17-
label?;
18-
type?;
20+
label?: string | ReactNode;
21+
btnType?: ButtonType;
1922
}
2023

21-
export default function LiveDemo({ context, label, type }: Props) {
22-
const [href, setHref] = useState<string | undefined>(undefined);
23-
useEffect(() => {
24-
setHref(liveDemoUrl(context));
25-
}, []);
24+
export default function LiveDemo({ label, btnType }: Props) {
25+
const { supportVideoCall } = useCustomize();
26+
27+
if (!supportVideoCall) {
28+
return null;
29+
}
30+
2631
return (
27-
<Button href={href} type={type}>
28-
<Icon name="users" /> {label ?? "Contact Us!"}
32+
<Button href={supportVideoCall} type={btnType}>
33+
<Icon name="video-camera" /> {label ?? "Book a Demo!"}
2934
</Button>
3035
);
3136
}

src/packages/next/components/landing/sign-in.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useRouter } from "next/router";
88
import { join } from "path";
99
import { CSSProperties, ReactNode } from "react";
1010

11+
import { Icon } from "@cocalc/frontend/components/icon";
1112
import SSO from "components/auth/sso";
1213
import { Paragraph } from "components/misc";
1314
import basePath from "lib/base-path";
@@ -17,6 +18,7 @@ interface Props {
1718
startup?: ReactNode; // customize the button, e.g. "Start Jupyter Now".
1819
hideFree?: boolean;
1920
style?: React.CSSProperties;
21+
emphasize?: boolean;
2022
}
2123

2224
const STYLE: CSSProperties = {
@@ -25,7 +27,7 @@ const STYLE: CSSProperties = {
2527
marginBottom: "0",
2628
} as const;
2729

28-
export default function SignIn({ startup, hideFree, style }: Props) {
30+
export default function SignIn({ startup, hideFree, style, emphasize }: Props) {
2931
const { anonymousSignup, siteName, account, emailSignup } = useCustomize();
3032
style = { ...STYLE, ...style };
3133
const router = useRouter();
@@ -38,6 +40,7 @@ export default function SignIn({ startup, hideFree, style }: Props) {
3840
onClick={() => (window.location.href = join(basePath, "projects"))}
3941
title={`Open the ${siteName} app and view your projects.`}
4042
type="primary"
43+
icon={<Icon name="edit" />}
4144
>
4245
Your {siteName} Projects
4346
</Button>
@@ -55,6 +58,7 @@ export default function SignIn({ startup, hideFree, style }: Props) {
5558
style={{ margin: "10px" }}
5659
title={"Create a new account."}
5760
onClick={() => router.push("/auth/sign-up")}
61+
type={emphasize ? "primary" : undefined}
5862
>
5963
Sign Up
6064
</Button>
@@ -65,6 +69,7 @@ export default function SignIn({ startup, hideFree, style }: Props) {
6569
"Either create a new account or sign into an existing account."
6670
}
6771
onClick={() => router.push("/auth/sign-in")}
72+
type={emphasize ? "primary" : undefined}
6873
>
6974
Sign In
7075
</Button>

src/packages/next/components/store/overview.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import { Divider } from "antd";
77
import { useRouter } from "next/router";
88
import { useEffect } from "react";
9+
910
import { Icon, PAYASYOUGO_ICON } from "@cocalc/frontend/components/icon";
1011
import { Paragraph } from "components/misc";
1112
import A from "components/misc/A";
1213
import SiteName from "components/share/site-name";
14+
import { useCustomize } from "lib/customize";
1315
import {
1416
OVERVIEW_LARGE_ICON,
1517
OVERVIEW_STYLE,
@@ -19,6 +21,7 @@ import {
1921

2022
export default function Overview() {
2123
const router = useRouter();
24+
const { supportVideoCall } = useCustomize();
2225

2326
// most likely, user will go to the cart next
2427
useEffect(() => {
@@ -31,11 +34,18 @@ export default function Overview() {
3134
<h2 style={{ marginBottom: "30px" }}>
3235
Welcome to the <SiteName /> Store!
3336
</h2>
34-
<div style={{ fontSize: "13pt" }}>
37+
<Paragraph style={{ fontSize: "13pt" }}>
3538
Shop below for <A href="/store/site-license">licenses</A> and{" "}
3639
<A href="/store/vouchers">vouchers</A> or explore{" "}
3740
<A href="/pricing">all available products and pricing</A>.
38-
</div>
41+
</Paragraph>
42+
{supportVideoCall ? (
43+
<Paragraph>
44+
Not sure what you need?{" "}
45+
<A href={supportVideoCall}>Book a video call</A> and we'll help you
46+
decide.
47+
</Paragraph>
48+
) : undefined}
3949
<OverviewRow>
4050
<Product icon="key" title="Licenses" href="/store/site-license">
4151
Buy a license to upgrade projects, get internet access, more CPU, disk

0 commit comments

Comments
 (0)