@@ -33,6 +33,11 @@ import { VideoSection } from "../onboarding/VideoSection";
3333import { trackVideoClick } from "../Analytics" ;
3434import { cn } from "@podkit/lib/cn" ;
3535import { useInstallationConfiguration } from "../data/installation/default-workspace-image-query" ;
36+ import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutation" ;
37+ import { useUserLoader } from "../hooks/use-user-loader" ;
38+ import Tooltip from "../components/Tooltip" ;
39+
40+ export const GETTING_STARTED_DISMISSAL_KEY = "workspace-list-getting-started" ;
3641
3742const WorkspacesPage : FunctionComponent = ( ) => {
3843 const [ limit , setLimit ] = useState ( 50 ) ;
@@ -47,6 +52,9 @@ const WorkspacesPage: FunctionComponent = () => {
4752 const { data : org } = useCurrentOrg ( ) ;
4853 const { data : orgSettings } = useOrgSettingsQuery ( ) ;
4954
55+ const { user } = useUserLoader ( ) ;
56+ const { mutate : mutateUser } = useUpdateCurrentUserMutation ( ) ;
57+
5058 const { toast } = useToast ( ) ;
5159
5260 // Sort workspaces into active/inactive groups
@@ -108,6 +116,29 @@ const WorkspacesPage: FunctionComponent = () => {
108116 } catch ( e ) { }
109117 } , [ deleteInactiveWorkspaces , inactiveWorkspaces , toast ] ) ;
110118
119+ const [ showGettingStarted , setShowGettingStarted ] = useState ( true ) ;
120+ const dismissGettingStarted = useCallback ( ( ) => {
121+ setShowGettingStarted ( false ) ;
122+
123+ mutateUser (
124+ {
125+ additionalData : {
126+ profile : {
127+ coachmarksDismissals : {
128+ [ GETTING_STARTED_DISMISSAL_KEY ] : new Date ( ) . toISOString ( ) ,
129+ } ,
130+ } ,
131+ } ,
132+ } ,
133+ {
134+ onError : ( e ) => {
135+ toast ( "Failed to dismiss getting started" ) ;
136+ setShowGettingStarted ( true ) ;
137+ } ,
138+ } ,
139+ ) ;
140+ } , [ mutateUser , toast ] ) ;
141+
111142 const [ isVideoModalVisible , setVideoModalVisible ] = useState ( false ) ;
112143 const handleVideoModalClose = useCallback ( ( ) => {
113144 setVideoModalVisible ( false ) ;
@@ -120,81 +151,88 @@ const WorkspacesPage: FunctionComponent = () => {
120151 subtitle = "Manage, start and stop your personal development environments in the cloud."
121152 />
122153
123- { isDedicatedInstallation && (
124- < >
125- < Subheading className = "font-semibold text-pk-content-primary mt-4 mb-2 lg:px-28 px-4" >
126- Getting started
127- </ Subheading >
128-
129- < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 lg:px-28 px-4" >
130- < Card onClick = { ( ) => setVideoModalVisible ( true ) } >
131- < GraduationCap className = "flex-shrink-0" size = { 24 } />
132- < div className = "min-w-0" >
133- < CardTitle > Learn how Gitpod works</ CardTitle >
134- < CardDescription >
135- We've put together resources for you to get the most our of Gitpod.
136- </ CardDescription >
137- </ div >
138- </ Card >
154+ { isDedicatedInstallation &&
155+ showGettingStarted &&
156+ ! user ?. profile ?. coachmarksDismissals [ GETTING_STARTED_DISMISSAL_KEY ] && (
157+ < >
158+ < div className = "app-container flex flex-row items-center justify-between mt-4 mb-2" >
159+ < Subheading className = "font-semibold text-pk-content-primary" > Getting started</ Subheading >
160+ < Tooltip content = { `Hide "Getting started" - can be restored in your user preferences` } >
161+ < Button variant = { "ghost" } onClick = { dismissGettingStarted } >
162+ Hide
163+ </ Button >
164+ </ Tooltip >
165+ </ div >
139166
140- { orgSettings ?. onboardingSettings ?. internalLink ? (
141- < Card href = { orgSettings . onboardingSettings . internalLink } isLinkExternal >
142- < Building className = "flex-shrink-0" size = { 24 } />
167+ < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 lg:px-28 px-4" >
168+ < Card onClick = { ( ) => setVideoModalVisible ( true ) } >
169+ < GraduationCap className = "flex-shrink-0" size = { 24 } />
143170 < div className = "min-w-0" >
144- < CardTitle > Learn more about Gitpod at { org ?. name } </ CardTitle >
171+ < CardTitle > Learn how Gitpod works </ CardTitle >
145172 < CardDescription >
146- Read through the internal Gitpod landing page of your organization .
173+ We've put together resources for you to get the most our of Gitpod .
147174 </ CardDescription >
148175 </ div >
149176 </ Card >
150- ) : (
151- < Card href = { "/new?showExamples=true" } >
152- < Code className = "flex-shrink-0" size = { 24 } />
177+
178+ { orgSettings ?. onboardingSettings ?. internalLink ? (
179+ < Card href = { orgSettings . onboardingSettings . internalLink } isLinkExternal >
180+ < Building className = "flex-shrink-0" size = { 24 } />
181+ < div className = "min-w-0" >
182+ < CardTitle > Learn more about Gitpod at { org ?. name } </ CardTitle >
183+ < CardDescription >
184+ Read through the internal Gitpod landing page of your organization.
185+ </ CardDescription >
186+ </ div >
187+ </ Card >
188+ ) : (
189+ < Card href = { "/new?showExamples=true" } >
190+ < Code className = "flex-shrink-0" size = { 24 } />
191+ < div className = "min-w-0" >
192+ < CardTitle > Open a sample repository</ CardTitle >
193+ < CardDescription >
194+ Explore a sample repository to quickly experience Gitpod.
195+ </ CardDescription >
196+ </ div >
197+ </ Card >
198+ ) }
199+
200+ < Card href = "https://www.gitpod.io/docs/introduction" isLinkExternal >
201+ < Book className = "flex-shrink-0" size = { 24 } />
153202 < div className = "min-w-0" >
154- < CardTitle > Open a sample repository </ CardTitle >
203+ < CardTitle > Visit the docs </ CardTitle >
155204 < CardDescription >
156- Explore a sample repository to quickly experience Gitpod .
205+ We have extensive documentation to help if you get stuck .
157206 </ CardDescription >
158207 </ div >
159208 </ Card >
160- ) }
161-
162- < Card href = "https://www.gitpod.io/docs/introduction" isLinkExternal >
163- < Book className = "flex-shrink-0" size = { 24 } />
164- < div className = "min-w-0" >
165- < CardTitle > Visit the docs</ CardTitle >
166- < CardDescription >
167- We have extensive documentation to help if you get stuck.
168- </ CardDescription >
169- </ div >
170- </ Card >
171- </ div >
172-
173- < Modal
174- visible = { isVideoModalVisible }
175- onClose = { handleVideoModalClose }
176- containerClassName = "min-[576px]:max-w-[600px]"
177- >
178- < ModalHeader > Demo video</ ModalHeader >
179- < ModalBody >
180- < div className = "flex flex-row items-center justify-center" >
181- < VideoSection
182- metadataVideoTitle = "Gitpod demo"
183- playbackId = "m01BUvCkTz7HzQKFoIcQmK00Rx5laLLoMViWBstetmvLs"
184- poster = "https://i.ytimg.com/vi_webp/1ZBN-b2cIB8/maxresdefault.webp"
185- playerProps = { { onPlay : handlePlay , defaultHiddenCaptions : true } }
186- className = "w-[535px] rounded-xl"
187- />
188- </ div >
189- </ ModalBody >
190- < ModalBaseFooter >
191- < Button variant = "secondary" onClick = { handleVideoModalClose } >
192- Close
193- </ Button >
194- </ ModalBaseFooter >
195- </ Modal >
196- </ >
197- ) }
209+ </ div >
210+
211+ < Modal
212+ visible = { isVideoModalVisible }
213+ onClose = { handleVideoModalClose }
214+ containerClassName = "min-[576px]:max-w-[600px]"
215+ >
216+ < ModalHeader > Demo video</ ModalHeader >
217+ < ModalBody >
218+ < div className = "flex flex-row items-center justify-center" >
219+ < VideoSection
220+ metadataVideoTitle = "Gitpod demo"
221+ playbackId = "m01BUvCkTz7HzQKFoIcQmK00Rx5laLLoMViWBstetmvLs"
222+ poster = "https://i.ytimg.com/vi_webp/1ZBN-b2cIB8/maxresdefault.webp"
223+ playerProps = { { onPlay : handlePlay , defaultHiddenCaptions : true } }
224+ className = "w-[535px] rounded-xl"
225+ />
226+ </ div >
227+ </ ModalBody >
228+ < ModalBaseFooter >
229+ < Button variant = "secondary" onClick = { handleVideoModalClose } >
230+ Close
231+ </ Button >
232+ </ ModalBaseFooter >
233+ </ Modal >
234+ </ >
235+ ) }
198236
199237 { deleteModalVisible && (
200238 < ConfirmationModal
0 commit comments