import * as React from "react" ; import { Service , IFiddleFile } from "../service" ; import * as ReactModal from "react-modal" ; import { Button } from "./shared/Button" ; import { GoGear , GoFile , GoX , Icon } from "./shared/Icons" ; import { KeyboardEvent , ChangeEvent , ChangeEventHandler } from "react" ; import { ListBox , ListItem , TextInputBox } from "./Widgets" ; import fetchTemplates from "../utils/fetchTemplates" ; import getConfig from "../config" ; export interface Template { name : string ; description : string ; files : IFiddleFile [ ] ; baseUrl : URL ; icon : string ; } export class NewProjectDialog extends React . Component < { isOpen : boolean ; templatesName : string ; onCreate : ( template : Template ) => void ; onCancel : ( ) => void ; } , { description : string ; name : string ; template : Template ; templates : Template [ ] ; } > { constructor ( props ) { super ( props ) ; this . state = { template : null , description : "" , name : "" , templates : [ ] } ; } async componentDidMount ( ) { const config = await getConfig ( ) ; const templatesPath = config . templates [ this . props . templatesName ] ; const json = await fetchTemplates ( templatesPath ) ; const base = new URL ( templatesPath , location . href ) ; const templates = [ ] ; for ( const [ key , entry ] of Object . entries ( json ) as any ) { const name = entry . name || "" ; const description = entry . description || "" ; const icon = entry . icon || "" ; templates . push ( { name , description , icon , files : entry . files , baseUrl : new URL ( key + "/" , base ) } ) ; } this . setState ( { templates } ) ; this . setTemplate ( templates [ 0 ] ) ; } async setTemplate ( template ) { const description = await Service . compileMarkdownToHtml ( template . description ) ; this . setState ( { template , description } ) ; } render ( ) { return < ReactModal isOpen = { this . props . isOpen } contentLabel = "Create New Project" className = "modal show-file-icons" overlayClassName = "overlay" ariaHideApp = { false } > < div style = { { display : "flex" , flexDirection : "column" , height : "100%" } } > < div className = "modal-title-bar" > Create New Project < /div> < div > < div style = { { display : "flex" } } > < div style = { { width : 200 } } > < ListBox value = { this . state . template } height = { 240 } onSelect = { ( template ) => { this . setTemplate ( template ) ; } } > { this . state . templates . map ( ( template ) => { return < ListItem key = { template . name } value = { template } label = { template . name } icon = { template . icon } / > ; } ) } < /ListBox> < /div> < div style = { { flex : 1 } } className = "new-project-dialog-description" > < div className = "md" dangerouslySetInnerHTML = { { __html : this . state . description } } /> < /div> < /div> < /div> < div style = { { flex : 1 , padding : "8px" } } /> < div > < Button icon = { < GoX />} label="Cancel" title="Cancel" onClick={() => { this . props . onCancel ( ) ; } } /> < Button icon = { < GoFile / > } label = "Create" title = "Create" isDisabled = { ! this . state . template } onClick = { ( ) => { return this . props . onCreate && this . props . onCreate ( this . state . template ) ; } } /> < /div> < /div> < /ReactModal>; } }