From c2f763654b0a63af7939596a7b339af9bb4e3327 Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Sun, 22 Jan 2017 21:03:46 -0800 Subject: [PATCH] Finish conversion to React --- README.md | 2 +- client/package.json | 2 +- client/src/app.jsx | 41 +++++++++++++++++++++++++++++++++ client/src/index.jsx | 13 ++--------- client/webpack.config.js | 42 ++++++++++++++++++++++++++++++++++ cmd/kuard/main.go | 40 ++++++++++++++++++-------------- pkg/htmlutils/filters.go | 10 ++++++++ sitedata/static/css/styles.css | 1 + sitedata/templates/index.html | 28 ++++------------------- 9 files changed, 125 insertions(+), 54 deletions(-) create mode 100644 client/src/app.jsx diff --git a/README.md b/README.md index 0a317cc..5d07fec 100644 --- a/README.md +++ b/README.md @@ -59,5 +59,5 @@ These have been heavily modified. ### TODO * [ ] Make file system browser better. Show size, permissions, etc. Might be able to do this by faking out an `index.html` as part of the http.FileSystem stuff. -* [ ] Switch to React with an API to the server? This mixed template stuff sucks. +* [x] Switch to React with an API to the server? This mixed template stuff sucks. * [ ] Find a better way to pick unique colors to show version. Perhaps just have a table based on the fakeversion. diff --git a/client/package.json b/client/package.json index 4f7cb40..58d8fd9 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "webpack-dev-server", "dev": "webpack -d --watch", - "build": "webpack -p" + "build": "NODE_ENV=production webpack" }, "author": "", "private": true, diff --git a/client/src/app.jsx b/client/src/app.jsx new file mode 100644 index 0000000..f7a3439 --- /dev/null +++ b/client/src/app.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import Details from './details'; +import Env from './env'; +import Probe from './probe'; + +class App extends React.Component { + render () { + return ( +
+
+

Kubernetes Up and Running

+
Demo application version {this.props.page.version}
+
+ +
WARNING: This server may expose sensitive and secret information. Be careful.
+ +
+
Proto: {this.props.page.requestProto}
+
Client addr: {this.props.page.requestAddr}
+
Dump:
+
+            {this.props.page.requestDump}
+          
+
+ + + + + + + + +
+ Browse the root file system for this server. +
+
+ ) + } +} + +module.exports = App; diff --git a/client/src/index.jsx b/client/src/index.jsx index 2c923e3..9c1fade 100644 --- a/client/src/index.jsx +++ b/client/src/index.jsx @@ -1,14 +1,5 @@ import React from 'react'; import {render} from 'react-dom'; -import Details from './details'; -import Probe from './probe' -import Env from './env' +import App from './app' -render(, document.getElementById("liveness")); -render(, document.getElementById("readiness")); -render(, document.getElementById("env")); - -render( -
- Browse the root file system for this server. -
, document.getElementById("fs")) +render(, document.getElementById("root")) diff --git a/client/webpack.config.js b/client/webpack.config.js index 8ccac8e..eb9a954 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -1,9 +1,50 @@ var webpack = require('webpack'); var path = require('path'); +var isProd = (process.env.NODE_ENV === 'production'); + var BUILD_DIR = path.resolve(__dirname, '../sitedata/built'); var APP_DIR = path.resolve(__dirname, 'src'); +// Conditionally return a list of plugins to use based on the current environment. +// Repeat this pattern for any other config key (ie: loaders, etc). +function getPlugins() { + var plugins = []; + + // Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV` + // inside your code for any environment checks; UglifyJS will automatically + // drop any unreachable code. + plugins.push(new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify(process.env.NODE_ENV) + } + })); + + + // Conditionally add plugins for Production builds. + if (isProd) { + // This helps ensure the builds are consistent if source hasn't changed + plugins.push(new webpack.optimize.OccurrenceOrderPlugin()) + // Try to dedupe duplicated modules, if any + plugins.push(new webpack.optimize.DedupePlugin()) + // Minify the code. + plugins.push(new webpack.optimize.UglifyJsPlugin({ + compress: { + screw_ie8: true, // React doesn't support IE8 + warnings: false + }, + mangle: { + screw_ie8: true + }, + output: { + comments: false, + screw_ie8: true + } + })); + } + return plugins; +} + var config = { entry: APP_DIR + '/index.jsx', output: { @@ -24,6 +65,7 @@ var config = { }, ] }, + plugins: getPlugins(), resolve: { extensions: ['', '.js', '.jsx'] }, diff --git a/cmd/kuard/main.go b/cmd/kuard/main.go index 03aad9b..048f4bb 100644 --- a/cmd/kuard/main.go +++ b/cmd/kuard/main.go @@ -47,11 +47,11 @@ func loggingMiddleware(handler http.Handler) http.Handler { } type pageContext struct { - Version string - VersionColor template.CSS - RequestDump string - RequestProto string - RequestAddr string + Version string `json:"version"` + VersionColor template.CSS `json:"versionColor"` + RequestDump string `json:"requestDump"` + RequestProto string `json:"requestProto"` + RequestAddr string `json:"requestAddr"` } type kuard struct { @@ -74,32 +74,38 @@ func (k *kuard) rootHandler(w http.ResponseWriter, r *http.Request, _ httprouter k.tg.Render(w, "index.html", k.getPageContext(r)) } -func NewApp(router *httprouter.Router) *kuard { - k := &kuard{ - tg: &htmlutils.TemplateGroup{}, - } - - // Add the root handler - router.GET("/", k.rootHandler) - - // Add the static files +func fsHandlerForPrefix(prefix string) http.Handler { var fs http.FileSystem if *config.Debug { fs = &assetfs.AssetFS{ Asset: debugsitedata.Asset, AssetDir: func(path string) ([]string, error) { return nil, os.ErrNotExist }, AssetInfo: debugsitedata.AssetInfo, - Prefix: "static", + Prefix: prefix, } } else { fs = &assetfs.AssetFS{ Asset: sitedata.Asset, AssetDir: func(path string) ([]string, error) { return nil, os.ErrNotExist }, AssetInfo: sitedata.AssetInfo, - Prefix: "static", + Prefix: prefix, } } - router.Handler("GET", "/static/*filepath", http.StripPrefix("/static/", http.FileServer(fs))) + return http.StripPrefix("/"+prefix+"/", http.FileServer(fs)) +} + +func NewApp(router *httprouter.Router) *kuard { + k := &kuard{ + tg: &htmlutils.TemplateGroup{}, + } + + // Add the root handler + router.GET("/", k.rootHandler) + + // Add the static files + router.Handler("GET", "/built/*filepath", fsHandlerForPrefix("built")) + router.Handler("GET", "/static/*filepath", fsHandlerForPrefix("static")) + router.Handler("GET", "/fs/*filepath", http.StripPrefix("/fs", http.FileServer(http.Dir("/")))) debugprobe.New("/healthy").AddRoutes(router) diff --git a/pkg/htmlutils/filters.go b/pkg/htmlutils/filters.go index f682537..9bee0c8 100644 --- a/pkg/htmlutils/filters.go +++ b/pkg/htmlutils/filters.go @@ -17,6 +17,7 @@ limitations under the License. package htmlutils import ( + "encoding/json" "html/template" "time" @@ -27,6 +28,7 @@ func FuncMap() template.FuncMap { return template.FuncMap{ "friendlytime": FriendlyTime, "reltime": RelativeTime, + "jsonstring": JSONString, } } @@ -37,3 +39,11 @@ func FriendlyTime(t time.Time) string { func RelativeTime(t time.Time) string { return humanize.RelTime(t, time.Now(), "ago", "from now") } + +func JSONString(v interface{}) (template.JS, error) { + a, err := json.Marshal(v) + if err != nil { + return template.JS(""), err + } + return template.JS(a), nil +} diff --git a/sitedata/static/css/styles.css b/sitedata/static/css/styles.css index 9f71088..6ba57f0 100644 --- a/sitedata/static/css/styles.css +++ b/sitedata/static/css/styles.css @@ -1,6 +1,7 @@ body { font-size: 12pt; font-family: sans-serif; + margin: 0; } .title { diff --git a/sitedata/templates/index.html b/sitedata/templates/index.html index 09f256c..31f4dab 100644 --- a/sitedata/templates/index.html +++ b/sitedata/templates/index.html @@ -12,33 +12,13 @@ color: {{ .VersionColor }}; } + -
-

Kubernetes Up and Running

-
Demo application version {{.Version}}
-
- -
WARNING: This server may expose sensitive and secret information. Be careful.
- -
- Request Details -
-
Proto: {{.RequestProto}}
-
Client addr: {{.RequestAddr}}
-
Dump:
-
-        {{- .RequestDump -}}
-      
-
-
- -
-
-
-
- +