github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/examples/examples.go (about)

     1  // Copyright (c) 2016 Paul Jolly <paul@myitcv.org.uk>, all rights reserved.
     2  // Use of this document is governed by a license found in the LICENSE document.
     3  
     4  package examples // import "myitcv.io/react/examples"
     5  
     6  import (
     7  	"honnef.co/go/js/xhr"
     8  	"myitcv.io/highlightjs"
     9  	"myitcv.io/react"
    10  	"myitcv.io/react/examples/hellomessage"
    11  	"myitcv.io/react/examples/markdowneditor"
    12  	"myitcv.io/react/examples/timer"
    13  	"myitcv.io/react/examples/todoapp"
    14  	"myitcv.io/react/jsx"
    15  )
    16  
    17  //go:generate reactGen
    18  //go:generate immutableGen
    19  
    20  // ExamplesDef is the definition of the Examples component
    21  type ExamplesDef struct {
    22  	react.ComponentDef
    23  }
    24  
    25  type tab int
    26  
    27  const (
    28  	tabGo tab = iota
    29  	tabJsx
    30  )
    31  
    32  // Examples creates instances of the Examples component
    33  func Examples() *ExamplesElem {
    34  	return buildExamplesElem()
    35  }
    36  
    37  type (
    38  	_Imm_tabS map[exampleKey]tab
    39  )
    40  
    41  // ExamplesState is the state type for the Examples component
    42  type ExamplesState struct {
    43  	examples     *exampleSource
    44  	selectedTabs *tabS
    45  }
    46  
    47  // ComponentWillMount is a React lifecycle method for the Examples component
    48  func (p ExamplesDef) ComponentWillMount() {
    49  	if !fetchStarted {
    50  		for i, e := range sources.Range() {
    51  			go func(i exampleKey, e *source) {
    52  				req := xhr.NewRequest("GET", "https://raw.githubusercontent.com/myitcv/react/master/examples/"+e.file())
    53  				err := req.Send(nil)
    54  				if err != nil {
    55  					panic(err)
    56  				}
    57  
    58  				sources = sources.Set(i, e.setSrc(req.ResponseText))
    59  
    60  				newSt := p.State()
    61  				newSt.examples = sources
    62  				p.SetState(newSt)
    63  			}(i, e)
    64  		}
    65  
    66  		fetchStarted = true
    67  	}
    68  }
    69  
    70  // GetInitialState returns in the initial state for the Examples component
    71  func (p ExamplesDef) GetInitialState() ExamplesState {
    72  	return ExamplesState{
    73  		examples:     sources,
    74  		selectedTabs: newTabS(),
    75  	}
    76  }
    77  
    78  // Render renders the Examples component
    79  func (p ExamplesDef) Render() react.Element {
    80  	dc := jsx.HTML(`
    81  		<h3>Introduction</h3>
    82  
    83  		<p>This entire page is a React application. An outer <code>Examples</code> component
    84  		contains a number of inner components.</p>
    85  
    86  		<p>For the source code, raising issues, questions etc, please see
    87  		<a href="https://github.com/myitcv/react/tree/master/examples" target="_blank">the Github repo</a>.</p>
    88  
    89  		<p>Note the examples below show the Go source code from <code>master</code>.</p>
    90  		`)
    91  
    92  	dc = append(dc,
    93  		p.renderExample(
    94  			exampleHello,
    95  			react.S("A Simple Example"),
    96  			react.P(nil, react.S("The hellomessage.HelloMessage component demonstrates the simple use of a Props type.")),
    97  			helloMessageJsx,
    98  			hellomessage.HelloMessage(hellomessage.HelloMessageProps{Name: "Jane"}),
    99  		),
   100  
   101  		react.Hr(nil),
   102  
   103  		p.renderExample(
   104  			exampleTimer,
   105  			react.S("A Stateful Component"),
   106  			react.P(nil, react.S("The timer.Timer component demonstrates the use of a State type.")),
   107  			timerJsx,
   108  			timer.Timer(),
   109  		),
   110  
   111  		react.Hr(nil),
   112  
   113  		p.renderExample(
   114  			exampleTodo,
   115  			react.S("An Application"),
   116  			react.P(nil, react.S("The todoapp.TodoApp component demonstrates the use of state and event handling, but also the "+
   117  				"problems of having a non-comparable state struct type.")),
   118  			applicationJsx,
   119  			todoapp.TodoApp(),
   120  		),
   121  
   122  		react.Hr(nil),
   123  
   124  		p.renderExample(
   125  			exampleMarkdown,
   126  			react.S("A Component Using External Plugins"),
   127  			react.P(nil, react.S("The markdowneditor.MarkdownEditor component demonstrates the use of an external Javascript library.")),
   128  			markdownEditorJsx,
   129  			markdowneditor.MarkdownEditor(),
   130  		),
   131  
   132  		react.Hr(nil),
   133  
   134  		p.renderExample(
   135  			exampleLatency,
   136  			react.S("Latency Checker"),
   137  			react.P(nil,
   138  				react.S("By kind permission of "), react.A(&react.AProps{Href: "http://tjholowaychuk.com/"}, react.S("TJ Holowaychuk")),
   139  				react.S(", a basic, component-based version of the beautiful APEX "), react.A(&react.AProps{Href: "https://latency.apex.sh/"}, react.S("Latency Tool")),
   140  				react.S(" that uses randomly generated latency values."),
   141  			),
   142  			latencyJsx,
   143  			react.A(&react.AProps{Href: "../latency", Target: "_blank"}, react.S("Launch in new tab")),
   144  		),
   145  	)
   146  
   147  	return react.Div(&react.DivProps{ClassName: "container"},
   148  		dc...,
   149  	)
   150  }
   151  
   152  func (p ExamplesDef) renderExample(key exampleKey, title, msg react.Element, jsxSrc string, elem react.Element) react.Element {
   153  
   154  	var goSrc string
   155  	src, _ := p.State().examples.Get(key)
   156  	if src != nil {
   157  		goSrc = src.src()
   158  	}
   159  
   160  	var code *react.DangerousInnerHTML
   161  	switch v, _ := p.State().selectedTabs.Get(key); v {
   162  	case tabGo:
   163  		code = react.NewDangerousInnerHTML(highlightjs.Highlight("go", goSrc, true).Value)
   164  	case tabJsx:
   165  		code = react.NewDangerousInnerHTML(highlightjs.Highlight("javascript", jsxSrc, true).Value)
   166  	}
   167  
   168  	return react.Div(nil,
   169  		react.H3(nil, title),
   170  		msg,
   171  		react.Div(&react.DivProps{ClassName: "row"},
   172  			react.Div(&react.DivProps{ClassName: "col-md-8"},
   173  				react.Div(&react.DivProps{ClassName: "panel panel-default with-nav-tabs"},
   174  					react.Div(&react.DivProps{ClassName: "panel-heading"},
   175  						react.Ul(
   176  							&react.UlProps{ClassName: "nav nav-tabs"},
   177  
   178  							p.buildExampleNavTab(key, tabGo, "GopherJS"),
   179  							p.buildExampleNavTab(key, tabJsx, "JSX"),
   180  						),
   181  					),
   182  					react.Div(&react.DivProps{ClassName: "panel-body"},
   183  						react.Pre(&react.PreProps{
   184  							Style: &react.CSS{
   185  								MaxHeight: "400px",
   186  							},
   187  							DangerouslySetInnerHTML: code,
   188  						}),
   189  					),
   190  				),
   191  			),
   192  			react.Div(&react.DivProps{ClassName: "col-md-4"},
   193  				plainPanel(elem),
   194  			),
   195  		),
   196  	)
   197  }
   198  
   199  func (p ExamplesDef) buildExampleNavTab(key exampleKey, t tab, title string) *react.LiElem {
   200  	lip := &react.LiProps{Role: "presentation"}
   201  
   202  	if v, _ := p.State().selectedTabs.Get(key); v == t {
   203  		lip.ClassName = "active"
   204  	}
   205  
   206  	return react.Li(
   207  		lip,
   208  		react.A(
   209  			&react.AProps{Href: "#", OnClick: tabChange{p, key, t}},
   210  			react.S(title),
   211  		),
   212  	)
   213  
   214  }
   215  
   216  type tabChange struct {
   217  	e   ExamplesDef
   218  	key exampleKey
   219  	t   tab
   220  }
   221  
   222  func (tc tabChange) OnClick(e *react.SyntheticMouseEvent) {
   223  	p := tc.e
   224  	key := tc.key
   225  	t := tc.t
   226  
   227  	cts := p.State().selectedTabs
   228  	newSt := p.State()
   229  
   230  	newSt.selectedTabs = cts.Set(key, t)
   231  	p.SetState(newSt)
   232  
   233  	e.PreventDefault()
   234  }
   235  
   236  func plainPanel(children ...react.Element) react.Element {
   237  	return react.Div(&react.DivProps{ClassName: "panel panel-default panel-body"},
   238  		children...,
   239  	)
   240  }