44 * See License.AGPL.txt in the project root for license information.
55 */
66
7- import { FunctionComponent , useCallback , useMemo , useState } from "react" ;
7+ import { FunctionComponent , useCallback , useEffect , useMemo , useState } from "react" ;
88import Header from "../components/Header" ;
99import { WorkspaceEntry } from "./WorkspaceEntry" ;
1010import { ItemsList } from "../components/ItemsList" ;
@@ -20,7 +20,7 @@ import { Workspace, WorkspacePhase_Phase } from "@gitpod/public-api/lib/gitpod/v
2020import { Button } from "@podkit/buttons/Button" ;
2121import { VideoCarousel } from "./VideoCarousel" ;
2222import { BlogBanners } from "./BlogBanners" ;
23- import { Book , BookOpen , Building , Code , GraduationCap } from "lucide-react" ;
23+ import { Book , BookOpen , Building , ChevronRight , Code , GraduationCap } from "lucide-react" ;
2424import { ReactComponent as GitpodStrokedSVG } from "../icons/gitpod-stroked.svg" ;
2525import PersonalizedContent from "./PersonalizedContent" ;
2626import { useListenToWorkspacesWSMessages as useListenToWorkspacesStatusUpdates } from "../data/workspaces/listen-to-workspace-ws-messages" ;
@@ -119,28 +119,41 @@ const WorkspacesPage: FunctionComponent = () => {
119119 } catch ( e ) { }
120120 } , [ deleteInactiveWorkspaces , inactiveWorkspaces , toast ] ) ;
121121
122- const [ showGettingStarted , setShowGettingStarted ] = useState ( true ) ;
123- const dismissGettingStarted = useCallback ( ( ) => {
124- setShowGettingStarted ( false ) ;
125-
126- mutateUser (
127- {
128- additionalData : {
129- profile : {
130- coachmarksDismissals : {
131- [ GETTING_STARTED_DISMISSAL_KEY ] : new Date ( ) . toISOString ( ) ,
122+ // initialize a state so that we can be optimistic and reactive, but also use an effect to sync the state with the user's actual profile
123+ const [ showGettingStarted , setShowGettingStarted ] = useState < boolean | undefined > ( undefined ) ;
124+ useEffect ( ( ) => {
125+ if ( ! user ?. profile ?. coachmarksDismissals [ GETTING_STARTED_DISMISSAL_KEY ] ) {
126+ setShowGettingStarted ( true ) ;
127+ } else {
128+ setShowGettingStarted ( false ) ;
129+ }
130+ } , [ user ?. profile ?. coachmarksDismissals ] ) ;
131+
132+ const toggleGettingStarted = useCallback (
133+ ( show : boolean ) => {
134+ setShowGettingStarted ( show ) ;
135+ console . log ( "toggleGettingStarted" , show ) ;
136+
137+ mutateUser (
138+ {
139+ additionalData : {
140+ profile : {
141+ coachmarksDismissals : {
142+ [ GETTING_STARTED_DISMISSAL_KEY ] : ! show ? new Date ( ) . toISOString ( ) : "" ,
143+ } ,
132144 } ,
133145 } ,
134146 } ,
135- } ,
136- {
137- onError : ( e ) => {
138- toast ( "Failed to dismiss getting started" ) ;
139- setShowGettingStarted ( true ) ;
147+ {
148+ onError : ( e ) => {
149+ toast ( "Failed to dismiss getting started" ) ;
150+ setShowGettingStarted ( true ) ;
151+ } ,
140152 } ,
141- } ,
142- ) ;
143- } , [ mutateUser , toast ] ) ;
153+ ) ;
154+ } ,
155+ [ mutateUser , toast ] ,
156+ ) ;
144157
145158 const [ isVideoModalVisible , setVideoModalVisible ] = useState ( false ) ;
146159 const handleVideoModalClose = useCallback ( ( ) => {
@@ -154,20 +167,30 @@ const WorkspacesPage: FunctionComponent = () => {
154167 subtitle = "Manage, start and stop your personal development environments in the cloud."
155168 />
156169
157- { isEnterpriseOnboardingEnabled &&
158- isDedicatedInstallation &&
159- showGettingStarted &&
160- ! user ?. profile ?. coachmarksDismissals [ GETTING_STARTED_DISMISSAL_KEY ] && (
161- < >
162- < div className = "app-container flex flex-row items-center justify-between mt-4 mb-2" >
163- < Subheading className = "font-semibold text-pk-content-primary" > Getting started</ Subheading >
164- < Tooltip content = { `Hide "Getting started" - can be restored in your user preferences` } >
165- < Button variant = { "ghost" } onClick = { dismissGettingStarted } >
166- Hide
170+ { isEnterpriseOnboardingEnabled && isDedicatedInstallation && (
171+ < >
172+ < div className = "app-container flex flex-row items-center justify-between mt-4 mb-2" >
173+ < div className = "flex flex-row items-center gap-2" >
174+ < Tooltip content = "Toggle helpful resources for getting started with Gitpod" >
175+ < Button
176+ variant = "ghost"
177+ onClick = { ( ) => toggleGettingStarted ( ! showGettingStarted ) }
178+ className = "p-2"
179+ >
180+ < ChevronRight
181+ className = { `text-gray-400 dark:text-gray-500 transform transition-transform duration-100 ${
182+ showGettingStarted ? "rotate-90" : ""
183+ } `}
184+ size = { 24 }
185+ />
167186 </ Button >
168187 </ Tooltip >
188+
189+ < Subheading className = "font-semibold text-pk-content-primary" > Getting started</ Subheading >
169190 </ div >
191+ </ div >
170192
193+ { showGettingStarted && (
171194 < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 lg:px-28 px-4" >
172195 < Card onClick = { ( ) => setVideoModalVisible ( true ) } >
173196 < GraduationCap className = "flex-shrink-0" size = { 24 } />
@@ -211,32 +234,33 @@ const WorkspacesPage: FunctionComponent = () => {
211234 </ div >
212235 </ Card >
213236 </ div >
214-
215- < Modal
216- visible = { isVideoModalVisible }
217- onClose = { handleVideoModalClose }
218- containerClassName = "min-[576px]:max-w-[600px]"
219- >
220- < ModalHeader > Demo video</ ModalHeader >
221- < ModalBody >
222- < div className = "flex flex-row items-center justify-center" >
223- < VideoSection
224- metadataVideoTitle = "Gitpod demo"
225- playbackId = "m01BUvCkTz7HzQKFoIcQmK00Rx5laLLoMViWBstetmvLs"
226- poster = "https://i.ytimg.com/vi_webp/1ZBN-b2cIB8/maxresdefault.webp"
227- playerProps = { { onPlay : handlePlay , defaultHiddenCaptions : true } }
228- className = "w-[535px] rounded-xl"
229- />
230- </ div >
231- </ ModalBody >
232- < ModalBaseFooter >
233- < Button variant = "secondary" onClick = { handleVideoModalClose } >
234- Close
235- </ Button >
236- </ ModalBaseFooter >
237- </ Modal >
238- </ >
239- ) }
237+ ) }
238+
239+ < Modal
240+ visible = { isVideoModalVisible }
241+ onClose = { handleVideoModalClose }
242+ containerClassName = "min-[576px]:max-w-[600px]"
243+ >
244+ < ModalHeader > Demo video</ ModalHeader >
245+ < ModalBody >
246+ < div className = "flex flex-row items-center justify-center" >
247+ < VideoSection
248+ metadataVideoTitle = "Gitpod demo"
249+ playbackId = "m01BUvCkTz7HzQKFoIcQmK00Rx5laLLoMViWBstetmvLs"
250+ poster = "https://i.ytimg.com/vi_webp/1ZBN-b2cIB8/maxresdefault.webp"
251+ playerProps = { { onPlay : handlePlay , defaultHiddenCaptions : true } }
252+ className = "w-[535px] rounded-xl"
253+ />
254+ </ div >
255+ </ ModalBody >
256+ < ModalBaseFooter >
257+ < Button variant = "secondary" onClick = { handleVideoModalClose } >
258+ Close
259+ </ Button >
260+ </ ModalBaseFooter >
261+ </ Modal >
262+ </ >
263+ ) }
240264
241265 { deleteModalVisible && (
242266 < ConfirmationModal
0 commit comments