From 02bb54762581cfc1a8592028e4c7858733a03147 Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 10 Mar 2022 02:32:42 +0100 Subject: [PATCH 1/3] server: add support for custom assets directory --- cmd/playground/main.go | 14 ++++++++++++-- pkg/langserver/spa.go | 10 +++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/playground/main.go b/cmd/playground/main.go index 1b5ee2ff..006c41b2 100644 --- a/cmd/playground/main.go +++ b/cmd/playground/main.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "os" + "path/filepath" "sync" "time" @@ -29,6 +30,7 @@ type appArgs struct { debug bool buildDir string cleanupInterval string + assetsDirectory string } func (a appArgs) getCleanDuration() (time.Duration, error) { @@ -36,6 +38,12 @@ func (a appArgs) getCleanDuration() (time.Duration, error) { } func main() { + wd, err := os.Getwd() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, "Failed to get current working directory:", err) + wd = "." + } + args := appArgs{} flag.StringVar(&args.packagesFile, "f", "packages.json", "Path to packages index JSON file") flag.StringVar(&args.addr, "addr", ":8080", "TCP Listen address") @@ -43,6 +51,7 @@ func main() { flag.StringVar(&args.cleanupInterval, "clean-interval", "10m", "Build directory cleanup interval") flag.StringVar(&args.playgroundUrl, "playground-url", goplay.DefaultPlaygroundURL, "Go Playground URL") flag.BoolVar(&args.debug, "debug", false, "Enable debug mode") + flag.StringVar(&args.assetsDirectory, "static-dir", filepath.Join(wd, "public"), "Path to web page assets (HTML, JS, etc)") l := getLogger(args.debug) defer l.Sync() //nolint:errcheck @@ -86,6 +95,7 @@ func start(goRoot string, args appArgs) error { zap.S().Infof("Playground url: %q", args.playgroundUrl) zap.S().Infof("Packages file is %q", args.packagesFile) zap.S().Infof("Cleanup interval is %s", cleanInterval.String()) + zap.S().Infof("Serving web page from %q", args.assetsDirectory) analyzer.SetRoot(goRoot) packages, err := analyzer.ReadPackagesFile(args.packagesFile) if err != nil { @@ -109,8 +119,8 @@ func start(goRoot string, args appArgs) error { Mount(r.PathPrefix("/api").Subrouter()) // Web UI routes - indexHandler := langserver.NewIndexFileServer("./public") - spaHandler := langserver.NewSpaFileServer("./public") + indexHandler := langserver.NewIndexFileServer(args.assetsDirectory) + spaHandler := langserver.NewSpaFileServer(args.assetsDirectory) r.Path("/"). Handler(indexHandler) r.Path("/snippet/{snippetID:[A-Za-z0-9_-]+}"). diff --git a/pkg/langserver/spa.go b/pkg/langserver/spa.go index 13962ba3..6cb68f88 100644 --- a/pkg/langserver/spa.go +++ b/pkg/langserver/spa.go @@ -27,7 +27,7 @@ type IndexFileServer struct { } // NewIndexFileServer returns handler which serves index.html page from root. -func NewIndexFileServer(root http.Dir) *IndexFileServer { +func NewIndexFileServer(root string) *IndexFileServer { return &IndexFileServer{ indexFilePath: filepath.Join(string(root), IndexFileName), } @@ -39,7 +39,7 @@ func (fs IndexFileServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) { // SpaFileServer is a wrapper around http.FileServer for serving SPA contents. type SpaFileServer struct { - root http.Dir + root string NotFoundHandler http.Handler } @@ -51,7 +51,7 @@ func (fs *SpaFileServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) { } //if empty, set current directory - dir := string(fs.root) + dir := fs.root if dir == "" { dir = "." } @@ -93,8 +93,8 @@ func containsDotDot(v string) bool { func isSlashRune(r rune) bool { return r == '/' || r == '\\' } // NewSpaFileServer returns SPA handler -func NewSpaFileServer(root http.Dir) *SpaFileServer { - notFoundHandler := NewFileServerWithStatus(filepath.Join(string(root), NotFoundFileName), http.StatusNotFound) +func NewSpaFileServer(root string) *SpaFileServer { + notFoundHandler := NewFileServerWithStatus(filepath.Join(root, NotFoundFileName), http.StatusNotFound) return &SpaFileServer{ NotFoundHandler: notFoundHandler, root: root, From e45ed61d5aac0571dbb9a8a592b6d80477174f4b Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 10 Mar 2022 02:35:57 +0100 Subject: [PATCH 2/3] make: use --static-dir flag --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0f1d1471..61cb2d72 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ include docker.mk .PHONY:run run: - @GOROOT=$(GOROOT) $(GO) run $(PKG) -f ./data/packages.json -debug=$(DEBUG) -addr $(LISTEN_ADDR) + @GOROOT=$(GOROOT) $(GO) run $(PKG) -f ./data/packages.json -static-dir="$(UI)/build" -debug=$(DEBUG) -addr $(LISTEN_ADDR) .PHONY:ui ui: From 5a57dd509f3790d60fa1d69b6d060ae3df5e0522 Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 10 Mar 2022 03:15:07 +0100 Subject: [PATCH 3/3] web: fix url handling in router --- web/public/404.html | 87 +--------------- web/public/gopher.svg | 118 ++++++++++++++++++++++ web/src/App.tsx | 10 +- web/src/components/pages/NotFoundPage.css | 85 ++++++++++++++++ web/src/components/pages/NotFoundPage.tsx | 57 +++++++++++ 5 files changed, 269 insertions(+), 88 deletions(-) create mode 100644 web/public/gopher.svg create mode 100644 web/src/components/pages/NotFoundPage.css create mode 100644 web/src/components/pages/NotFoundPage.tsx diff --git a/web/public/404.html b/web/public/404.html index 684f831a..7d41c3c1 100644 --- a/web/public/404.html +++ b/web/public/404.html @@ -102,92 +102,7 @@

Page Not Found

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Gopher
diff --git a/web/public/gopher.svg b/web/public/gopher.svg new file mode 100644 index 00000000..2031ac64 --- /dev/null +++ b/web/public/gopher.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/src/App.tsx b/web/src/App.tsx index 96a0cff8..6bcd181c 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -10,6 +10,7 @@ import { bootstrapGo } from './services/go'; import Playground from '~/components/pages/Playground'; import config from './services/config'; import './App.css'; +import NotFoundPage from "@components/pages/NotFoundPage"; // Configure store and import config from localStorage const store = configureStore(); @@ -25,9 +26,14 @@ function App() { + > + diff --git a/web/src/components/pages/NotFoundPage.css b/web/src/components/pages/NotFoundPage.css new file mode 100644 index 00000000..705edc86 --- /dev/null +++ b/web/src/components/pages/NotFoundPage.css @@ -0,0 +1,85 @@ +.errorPage { + background: #1f1f1f; + color: #f4f4f4; + margin: 0; + padding: 0; + font: 11pt system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} +.errorPage__inner { + display: flex; + justify-content: center; + justify-items: center; + position: fixed; + inset: 0; + flex-direction: row-reverse; + background: #1f1f1f; + color: #f4f4f4; + font-family: inherit; +} +.errorPage__container { + align-self: center; + width: 100%; + max-width: 480px; + font-family: inherit; +} +.errorPage__statusCode { + font: bold 6rem SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + margin: 0 0 2rem 0; + padding: 0; + display: block; + -webkit-filter: url(#chromatic-aberration); + filter: url(#chromatic-aberration); +} +.errorPage__statusText { + margin: 0; + padding: 0; + display: block; + font-size: 2rem; + font-family: inherit; +} +.errorPage__message { + margin: 1rem 0; + color: #999; +} +.errorPage__message p { + margin: 0 0 .3rem 0; + padding: 0; +} +.errorPage__actions { + margin-top: 4rem; + display: flex; + justify-content: flex-end; +} +.errorPage__actions>* { + margin-left: 1rem; +} +.btn--primary, .btn--transparent { + border: none; + text-decoration: none; + padding: .5rem 1rem; + font-family: inherit; +} +.btn--transparent { + color: #777; + background: transparent; + cursor: pointer; +} +.btn--transparent:hover, .btn--transparent:focus { + color: inherit; +} +.btn--primary { + color: #f4f4f4; + background: #005A9C; + border-radius: 2px; +} +.btn--primary:hover, .btn--primary:focus { + background: #00498B; +} +.gopher { + height: 320px; + align-self: center; + margin-right: 2.5rem; +} +.gopher__image { + height: 100%; +} diff --git a/web/src/components/pages/NotFoundPage.tsx b/web/src/components/pages/NotFoundPage.tsx new file mode 100644 index 00000000..cc5c39ac --- /dev/null +++ b/web/src/components/pages/NotFoundPage.tsx @@ -0,0 +1,57 @@ +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; +import './NotFoundPage.css'; + +const NotFoundPage: React.FC = () => { + const [catVisible, setCatVisible] = useState(false); + return ( +
+
+
+

404!

+

Page Not Found

+
+

+ Requested page does not exist or was deleted. +

+

+ That's all we know 🤷 +

+
+
+ { !catVisible && ( + + )} + Go To Home +
+
+
+ { catVisible ? ( + 😺 + ) : ( + Gopher + )} +
+
+ + + + + + + + + +
+ ); +}; + +export default NotFoundPage;