Skip to content

Commit 60f9db9

Browse files
[dashboard] Onboarding: new video onboarding for new workspace (#19987)
* [dashboard] Onboarding: new video onboarding for new workspace * New button and copy text updates * Update YT Video
1 parent 2cc42e2 commit 60f9db9

File tree

2 files changed

+86
-24
lines changed

2 files changed

+86
-24
lines changed

components/dashboard/src/Analytics.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export type Event =
2222
| "modal_dismiss"
2323
| "ide_configuration_changed"
2424
| "status_rendered"
25-
| "error_rendered";
25+
| "error_rendered"
26+
| "video_clicked";
2627
type InternalEvent = Event | "path_changed" | "dashboard_clicked";
2728

2829
export type EventProperties =
@@ -36,7 +37,8 @@ export type EventProperties =
3637
| TrackIDEConfigurationChanged
3738
| TrackWorkspaceClassChanged
3839
| TrackStatusRendered
39-
| TrackErrorRendered;
40+
| TrackErrorRendered
41+
| TrackVideoClicked;
4042
type InternalEventProperties = EventProperties | TrackDashboardClick | TrackPathChanged;
4143

4244
export interface TrackErrorRendered {
@@ -105,6 +107,11 @@ export interface TrackBrowserExtensionPromotionInteraction {
105107
action: "chrome_navigation" | "firefox_navigation" | "manually_dismissed";
106108
}
107109

110+
export interface TrackVideoClicked {
111+
context: string;
112+
path: string;
113+
}
114+
108115
interface TrackDashboardClick {
109116
dnt?: boolean;
110117
path: string;
@@ -140,6 +147,7 @@ export function trackEvent(event: "modal_dismiss", properties: TrackModalDismiss
140147
export function trackEvent(event: "ide_configuration_changed", properties: TrackIDEConfigurationChanged): void;
141148
export function trackEvent(event: "status_rendered", properties: TrackStatusRendered): void;
142149
export function trackEvent(event: "error_rendered", properties: TrackErrorRendered): void;
150+
export function trackEvent(event: "video_clicked", properties: TrackVideoClicked): void;
143151
export function trackEvent(event: Event, properties: EventProperties): void {
144152
trackEventInternal(event, properties);
145153
}
@@ -157,6 +165,13 @@ export function sendTrackEvent(message: RemoteTrackMessage): void {
157165
sendAnalytics("trackEvent", message);
158166
}
159167

168+
export function trackVideoClick(context: string) {
169+
trackEvent("video_clicked", {
170+
context: context,
171+
path: window.location.pathname,
172+
});
173+
}
174+
160175
export const trackButtonOrAnchor = (target: HTMLAnchorElement | HTMLButtonElement | HTMLDivElement) => {
161176
//read manually passed analytics props from 'data-analytics' attribute of event target
162177
let passedProps: TrackDashboardClick | undefined;

components/dashboard/src/workspaces/EmptyWorkspacesContent.tsx

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,81 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7+
import React, { useEffect } from "react";
78
import { StartWorkspaceModalKeyBinding } from "../App";
89
import { LinkButton } from "@podkit/buttons/LinkButton";
9-
import { Heading2, Subheading } from "@podkit/typography/Headings";
10+
import { Heading1, Heading2, Subheading } from "@podkit/typography/Headings";
11+
import { trackVideoClick } from "../Analytics";
12+
13+
declare global {
14+
interface Window {
15+
onYouTubeIframeAPIReady: () => void;
16+
YT: any;
17+
}
18+
}
1019

1120
export const EmptyWorkspacesContent = () => {
21+
useEffect(() => {
22+
// Load the YouTube IFrame Player API code asynchronously
23+
const tag = document.createElement("script");
24+
tag.src = "https://www.youtube.com/iframe_api";
25+
const firstScriptTag = document.getElementsByTagName("script")[0];
26+
firstScriptTag.parentNode?.insertBefore(tag, firstScriptTag);
27+
28+
// Create YouTube player when API is ready
29+
window.onYouTubeIframeAPIReady = () => {
30+
new window.YT.Player("gitpod-video", {
31+
events: {
32+
onStateChange: onPlayerStateChange,
33+
},
34+
});
35+
};
36+
}, []);
37+
38+
const onPlayerStateChange = (event: any) => {
39+
if (event.data === window.YT.PlayerState.PLAYING) {
40+
trackVideoClick("create-new-workspace");
41+
}
42+
};
43+
1244
return (
1345
<div className="app-container flex flex-col space-y-2">
14-
<div className="px-6 py-3 flex flex-col">
15-
<div className="flex flex-col items-center justify-center h-96 w-96 mx-auto">
16-
<Heading2 className="text-center pb-3">No Workspaces</Heading2>
17-
<Subheading className="text-center pb-6">
18-
Prefix any Git repository URL with {window.location.host}/# or create a new workspace for a
19-
recently used project.{" "}
20-
<a
21-
className="gp-link"
22-
target="_blank"
23-
rel="noreferrer"
24-
href="https://www.gitpod.io/docs/getting-started/"
25-
>
26-
Learn more
27-
</a>
28-
</Subheading>
29-
<span>
30-
<LinkButton href={"/new"} className="gap-1.5">
31-
New Workspace{" "}
32-
<span className="opacity-60 hidden md:inline">{StartWorkspaceModalKeyBinding}</span>
33-
</LinkButton>
34-
</span>
46+
<div className="px-6 mt-12 flex flex-row justify-center space-x-8">
47+
<div>
48+
<iframe
49+
id="gitpod-video"
50+
width="535"
51+
height="307"
52+
src="https://www.youtube.com/embed/1ZBN-b2cIB8?enablejsapi=1&modestbranding=1&rel=0&controls=1&showinfo=0&fs=1"
53+
title="YouTube - Gitpod in 120 seconds"
54+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
55+
allowFullScreen
56+
className="rounded-xl"
57+
></iframe>
58+
</div>
59+
<div>
60+
<div className="flex flex-col items-left h-96 w-96">
61+
<Heading1 className="text-left mb-4 !font-semibold !text-2xl">Welcome to Gitpod</Heading1>
62+
<Heading2 className="text-left !mb-0 !font-semibold !text-lg">
63+
Create your first workspace
64+
</Heading2>
65+
<Subheading className="text-left max-w-xs">
66+
A workspace is a cloud development environment
67+
</Subheading>
68+
<span className="flex flex-col space-y-4 w-fit">
69+
<LinkButton
70+
variant="secondary"
71+
className="mt-4 border border-pk-content-secondary text-pk-content-secondary bg-pk-surface-secondary"
72+
href={"/new?showExamples=true"}
73+
>
74+
Try a configured demo repo
75+
</LinkButton>
76+
<LinkButton href={"/new"} className="gap-1.5">
77+
Open your repository{" "}
78+
<span className="opacity-60 hidden md:inline">{StartWorkspaceModalKeyBinding}</span>
79+
</LinkButton>
80+
</span>
81+
</div>
3582
</div>
3683
</div>
3784
</div>

0 commit comments

Comments
 (0)