@@ -19,6 +19,16 @@ import type { PlainMessage } from "@bufbuild/protobuf";
1919import { InputField } from "../components/forms/InputField" ;
2020import { TextInput } from "../components/forms/TextInputField" ;
2121import { LoadingButton } from "@podkit/buttons/LoadingButton" ;
22+ import MDEditor from "@uiw/react-md-editor" ;
23+ import { Textarea } from "@podkit/forms/TextArea" ;
24+ import Modal , { ModalFooter , ModalBody , ModalHeader } from "../components/Modal" ;
25+ import { Button } from "@podkit/buttons/Button" ;
26+ import { SwitchInputField } from "@podkit/switch/Switch" ;
27+
28+ const sampleMarkdown = `“With Gitpod, you'll boost your productivity and streamline your workflow, giving you the freedom to work how you want while helping our team meet its efficiency goals.”
29+
30+ **Hannah Cole** - CTO Acme, Inc.
31+ ` ;
2232
2333export default function TeamOnboardingPage ( ) {
2434 useDocumentTitle ( "Organization Settings - Onboarding" ) ;
@@ -30,7 +40,9 @@ export default function TeamOnboardingPage() {
3040 const updateTeamSettings = useUpdateOrgSettingsMutation ( ) ;
3141
3242 const [ internalLink , setInternalLink ] = useState < string | undefined > ( undefined ) ;
33-
43+ const [ welcomeMessage , setWelcomeMessage ] = useState < string > ( sampleMarkdown ) ;
44+ const [ showWelcomeMessage , setShowWelcomeMessage ] = useState < boolean > ( true ) ;
45+ const [ welcomeMessageEditorOpen , setWelcomeMessageEditorOpen ] = useState < boolean > ( false ) ;
3446 const handleUpdateTeamSettings = useCallback (
3547 async ( newSettings : Partial < PlainMessage < OrganizationSettings > > , options ?: { throwMutateError ?: boolean } ) => {
3648 if ( ! org ?. id ) {
@@ -99,7 +111,100 @@ export default function TeamOnboardingPage() {
99111 </ LoadingButton >
100112 </ form >
101113 </ ConfigurationSettingsField >
114+
115+ < ConfigurationSettingsField >
116+ < Heading3 > Welcome message</ Heading3 >
117+ < Subheading >
118+ A welcome message to your organization members. This message will be shown to your organization
119+ members once they sign up and join your organization.
120+ </ Subheading >
121+
122+ < span className = "text-pk-content-secondary text-sm" >
123+ Here's a preview of the welcome message that will be shown to your organization members:
124+ </ span >
125+ < WelcomeMessagePreview
126+ welcomeMessage = { welcomeMessage }
127+ setWelcomeMessageEditorOpen = { setWelcomeMessageEditorOpen }
128+ />
129+
130+ < Modal onClose = { ( ) => setWelcomeMessageEditorOpen ( false ) } visible = { welcomeMessageEditorOpen } >
131+ < ModalHeader > Edit welcome message</ ModalHeader >
132+ < ModalBody >
133+ < InputField
134+ label = "Enabled"
135+ hint = { < > Enable showing the message to new organization members.</ > }
136+ id = "show-welcome-message"
137+ >
138+ < SwitchInputField
139+ id = "show-welcome-message"
140+ checked = { showWelcomeMessage }
141+ disabled = { ! isOwner || updateTeamSettings . isLoading }
142+ onCheckedChange = { setShowWelcomeMessage }
143+ label = ""
144+ />
145+ </ InputField >
146+ < WelcomeMessageEditor
147+ welcomeMessage = { welcomeMessage }
148+ setWelcomeMessage = { setWelcomeMessage }
149+ disabled = { ! showWelcomeMessage }
150+ />
151+ </ ModalBody >
152+ < ModalFooter >
153+ < Button variant = "secondary" onClick = { ( ) => setWelcomeMessageEditorOpen ( false ) } >
154+ Cancel
155+ </ Button >
156+ < LoadingButton type = "submit" loading = { updateTeamSettings . isLoading } disabled = { ! isOwner } >
157+ Save
158+ </ LoadingButton >
159+ </ ModalFooter >
160+ </ Modal >
161+ </ ConfigurationSettingsField >
102162 </ div >
103163 </ OrgSettingsPage >
104164 ) ;
105165}
166+
167+ type WelcomeMessagePreviewProps = {
168+ welcomeMessage : string ;
169+ setWelcomeMessageEditorOpen : ( open : boolean ) => void ;
170+ } ;
171+ const WelcomeMessagePreview = ( { welcomeMessage, setWelcomeMessageEditorOpen } : WelcomeMessagePreviewProps ) => {
172+ return (
173+ < div className = "max-w-2xl mx-auto" >
174+ < div className = "flex justify-between gap-2 items-center" >
175+ < Heading2 className = "py-6" > Welcome to Gitpod</ Heading2 >
176+ < Button variant = "secondary" onClick = { ( ) => setWelcomeMessageEditorOpen ( true ) } >
177+ Edit
178+ </ Button >
179+ </ div >
180+ < Subheading >
181+ Gitpod’s sandboxed, ephemeral development environments enable you to use your existing tools without
182+ worrying about vulnerabilities impacting their local machines.
183+ </ Subheading >
184+ { /* todo: sanitize md */ }
185+ < MDEditor . Markdown
186+ source = { welcomeMessage }
187+ className = "md-preview space-y-4 p-8 my-4 bg-pk-surface-secondary text-pk-content-primary rounded-xl text-center"
188+ />
189+ </ div >
190+ ) ;
191+ } ;
192+
193+ type WelcomeMessageEditorProps = {
194+ welcomeMessage : string ;
195+ setWelcomeMessage : ( welcomeMessage : string ) => void ;
196+ disabled ?: boolean ;
197+ } ;
198+ const WelcomeMessageEditor = ( { welcomeMessage, setWelcomeMessage, disabled } : WelcomeMessageEditorProps ) => {
199+ return (
200+ < InputField label = "Welcome message" error = { undefined } className = "mb-4" >
201+ < Textarea
202+ className = "bg-pk-surface-secondary text-pk-content-primary w-full p-4 rounded-xl min-h-[400px]"
203+ value = { welcomeMessage }
204+ placeholder = "Write a welcome message to your organization members. Markdown formatting is supported."
205+ onChange = { ( e ) => setWelcomeMessage ( e . target . value ) }
206+ disabled = { disabled }
207+ />
208+ </ InputField >
209+ ) ;
210+ } ;
0 commit comments