From 41c900c9c475a5b48220a3362e6e2c51a3bae738 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Fri, 21 Apr 2017 10:52:44 -0500 Subject: [PATCH 01/45] Add WIP pared-down webui/console prototype --- glide.yaml | 2 + handler.go | 17 +++++++ webui/assets/main.css | 63 +++++++++++++++++++++++ webui/assets/main.js | 114 ++++++++++++++++++++++++++++++++++++++++++ webui/index.html | 51 +++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 webui/assets/main.css create mode 100644 webui/assets/main.js create mode 100644 webui/index.html diff --git a/glide.yaml b/glide.yaml index d4615b0ba..b70957c75 100644 --- a/glide.yaml +++ b/glide.yaml @@ -31,3 +31,5 @@ import: - package: github.com/spf13/viper - package: github.com/gorilla/mux version: ^1.3.0 +- name: github.com/rakyll/statik + version: 274df120e9065bdd08eb1120e0375e3dc1ae8465 diff --git a/handler.go b/handler.go index 0e25c3f2f..c8de9bfe4 100644 --- a/handler.go +++ b/handler.go @@ -1,3 +1,5 @@ +//go:generate statik -src=./webui + package pilosa import ( @@ -21,6 +23,9 @@ import ( "github.com/gorilla/mux" "github.com/pilosa/pilosa/internal" "github.com/pilosa/pilosa/pql" + + _ "github.com/pilosa/pilosa/statik" + "github.com/rakyll/statik/fs" ) // Handler represents an HTTP handler. @@ -56,6 +61,8 @@ func NewHandler() *Handler { func NewRouter(handler *Handler) *mux.Router { router := mux.NewRouter() + router.HandleFunc("/", handler.handleWebUI).Methods("GET") + router.HandleFunc("/assets/{file}", handler.handleWebUI).Methods("GET") router.HandleFunc("/db", handler.handleGetDBs).Methods("GET") router.HandleFunc("/db/{db}", handler.handleGetDB).Methods("GET") router.HandleFunc("/db/{db}", handler.handlePostDB).Methods("POST") @@ -102,6 +109,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.Router.ServeHTTP(w, r) } +func (h *Handler) handleWebUI(w http.ResponseWriter, r *http.Request) { + // If user is using curl, don't chuck HTML at them + if strings.HasPrefix(r.UserAgent(), "curl") { + http.Error(w, "Welcome. Pilosa is running. Visit https://www.pilosa.com/docs/ for more information or try the web console by visiting this URL in your browser.", http.StatusNotFound) + return + } + statikFS, _ := fs.New() + http.FileServer(statikFS).ServeHTTP(w, r) +} + // handleGetSchema handles GET /schema requests. func (h *Handler) handleGetSchema(w http.ResponseWriter, r *http.Request) { if err := json.NewEncoder(w).Encode(getSchemaResponse{ diff --git a/webui/assets/main.css b/webui/assets/main.css new file mode 100644 index 000000000..3db45d2f1 --- /dev/null +++ b/webui/assets/main.css @@ -0,0 +1,63 @@ +.output { + overflow: auto; + padding: 0 8px; +} + +.output .query { + font-family: monospace; +} + +.output .response { + font-family: monospace; +} + +.input-bar { + padding-right: 2em; + background-color: #eeeeee; +} + +.input-textarea { + font-family: monospace; + font-size: 14px; + background-color: #dddddd; + width: 100%; + border: 0; + outline: 0; + margin: 1em; +} + +body { + padding-top: 5rem; +} + +.controls { + padding: 1em; +} + +.output { + padding: 1em; +} + +.result { + background-color: #eeeeee; + padding: 1em; + margin-top: 1em; +} +.result > .tab-content > .tab-pane { + padding: 1em; +} + +.query { + background-color: #dddddd; + padding: 0.5em +} + +#exTab3 .nav-pills > li > a { + border-radius: 4px 4px 0 0 ; +} + +#exTab3 .tab-content { + color : white; + background-color: #428bca; + padding : 5px 15px; +} diff --git a/webui/assets/main.js b/webui/assets/main.js new file mode 100644 index 000000000..efd0542ed --- /dev/null +++ b/webui/assets/main.js @@ -0,0 +1,114 @@ +class REPL { + constructor(input, output) { + this.input = input + this.output = output + this.history = [] + this.history_index = 0 + this.history_buffer = '' + this.result_number = 0 + } + bind_events() { + const repl = this + const keys = { + ENTER: 13, + UP_ARROW: 38, + DOWN_ARROW: 40 + } + + this.input.addEventListener("keydown", (e) => { + if (e.keyCode == keys.UP_ARROW) { + e.preventDefault() + if (this.input.value.substring(0, this.input.selectionStart).indexOf('\n') == '-1') { + if (this.history_index == 0) { + return + } else { + if (this.history_index == this.history.length) { + this.history_buffer = this.input.value + } + this.history_index-- + this.input.value = this.history[this.history_index] + this.input.setSelectionRange(this.input.value.length, this.input.value.length) + } + } + } + if (e.keyCode == keys.DOWN_ARROW) { + e.preventDefault() + if (this.input.value.substring(this.input.selectionEnd, this.input.length).indexOf('\n') == '-1') { + if (this.history_index == this.history.length) { + return + } else { + this.history_index++ + if (this.history_index == this.history.length) { + this.input.value = this.history_buffer + } else { + this.input.value = this.history[this.history_index] + } + this.input.setSelectionRange(this.input.value.length, this.input.value.length) + } + } + } + if (e.keyCode == keys.ENTER && !e.shiftKey) { + e.preventDefault() + this.history_buffer = '' + this.history_index = this.history.length + this.history[this.history_index] = this.input.value + this.history_index++ + this.process_query(this.input.value) + this.input.value = "" + } + }) + } + + process_query(query) { + var xhr = new XMLHttpRequest(); + var dbname = 'foo'; // todo: get db name from dropdown menu + xhr.open('POST', '/db/' + dbname + '/query'); + xhr.setRequestHeader('Content-Type', 'application/text'); + + const repl = this + xhr.onload = function() { + repl.result_number++ +//const entry = document.createElement('p') + const result = ( + '
' + + '' + +'' + + '
' + + '
' + + '

' + + query + + '

' + + '

Response

' + + '

' + + xhr.responseText + + '

' + + '
' + + '
' + + '' + + '' + + '' + + '' + + '
Response code' + xhr.status + '
Response text' + xhr.responseText + '
Response URL' + xhr.responseURL + '
' + + '
' + + '
' + + '
') + // TODO: remove jquery + $(repl.output).prepend($(result)) + }; + xhr.send(query); + } +} + +function startup() { + const input = document.querySelector('.input-textarea') + const output = document.querySelector('.output') + repl = new REPL(input, output) + repl.bind_events() +} diff --git a/webui/index.html b/webui/index.html new file mode 100644 index 000000000..1fe4b9f68 --- /dev/null +++ b/webui/index.html @@ -0,0 +1,51 @@ + + + + + + + + + + +
+
+ + +
+
+
+ + + + + + + + From 2163dc38290451df486b8b02bd480bcd894d8722 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Fri, 21 Apr 2017 10:53:31 -0500 Subject: [PATCH 02/45] .gitignore additions --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5fe629f6a..4b571e192 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ default.etcd/ *.test vendor .protoc-gen-gofast +statik +.DS_Store From 1cdbca1a1eea6420fc9c67d62c3060fc26ceaea2 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 24 Apr 2017 11:22:28 -0500 Subject: [PATCH 03/45] Install statik in build process, fix glide.yaml --- Makefile | 12 +++++++++--- glide.yaml | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 78c3e71f6..2c8fd4fa5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -.PHONY: glide vendor-update docker pilosa crossbuild install generate +.PHONY: glide vendor-update docker pilosa crossbuild install generate statik GLIDE := $(shell command -v glide 2>/dev/null) +STATIK := $(shell command -v statik 2>/dev/null) PROTOC := $(shell command -v protoc 2>/dev/null) VERSION := $(shell git describe --tags 2> /dev/null || echo unknown) IDENTIFIER := $(VERSION)-$(GOOS)-$(GOARCH) @@ -26,7 +27,7 @@ glide.lock: glide glide.yaml vendor-update: glide.lock -test: vendor +test: vendor generate go test $(shell cd $(GOPATH)/src/$(CLONE_URL); go list ./... | grep -v vendor) pilosa: vendor @@ -46,9 +47,14 @@ endif go build -o .protoc-gen-gofast ./vendor/github.com/gogo/protobuf/protoc-gen-gofast cp ./.protoc-gen-gofast $(GOPATH)/bin/protoc-gen-gofast -generate: .protoc-gen-gofast +generate: .protoc-gen-gofast statik go generate github.com/pilosa/pilosa/internal +statik: +ifndef STATIK + go install github.com/rakyll/statik +endif + docker: docker build -t "pilosa:$(VERSION)" \ --build-arg ldflags="-X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME)" . diff --git a/glide.yaml b/glide.yaml index b70957c75..c453a7cae 100644 --- a/glide.yaml +++ b/glide.yaml @@ -31,5 +31,5 @@ import: - package: github.com/spf13/viper - package: github.com/gorilla/mux version: ^1.3.0 -- name: github.com/rakyll/statik +- package: github.com/rakyll/statik version: 274df120e9065bdd08eb1120e0375e3dc1ae8465 From 3db8b02865385430b0efbfe1e438c94ba59084a4 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 24 Apr 2017 11:57:26 -0500 Subject: [PATCH 04/45] Track statik directory in git so it will build without first running `go generate` --- .gitignore | 1 - statik/.gitignore | 1 + statik/doc.go | 3 +++ 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 statik/.gitignore create mode 100644 statik/doc.go diff --git a/.gitignore b/.gitignore index 4b571e192..c924add8b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ default.etcd/ *.test vendor .protoc-gen-gofast -statik .DS_Store diff --git a/statik/.gitignore b/statik/.gitignore new file mode 100644 index 000000000..514ee40a1 --- /dev/null +++ b/statik/.gitignore @@ -0,0 +1 @@ +statik.go diff --git a/statik/doc.go b/statik/doc.go new file mode 100644 index 000000000..85edd9e6f --- /dev/null +++ b/statik/doc.go @@ -0,0 +1,3 @@ +// Package statik contains static assets for the Web UI. `go generate` will +// produce statik.go, which is ignored by git. +package statik From 18f6d3cd152d0017ba9e218e2bf388e0d5bba8b4 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 24 Apr 2017 12:16:44 -0500 Subject: [PATCH 05/45] Separate `go generate` make targets, remove generate from test requirements --- Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 2c8fd4fa5..cd3add926 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ glide.lock: glide glide.yaml vendor-update: glide.lock -test: vendor generate +test: vendor go test $(shell cd $(GOPATH)/src/$(CLONE_URL); go list ./... | grep -v vendor) pilosa: vendor @@ -42,14 +42,19 @@ install: vendor .protoc-gen-gofast: vendor ifndef PROTOC - $(error "protoc is not available please install protoc from https://github.com/google/protobuf/releases") + $(error "protoc is not available. please install protoc from https://github.com/google/protobuf/releases") endif go build -o .protoc-gen-gofast ./vendor/github.com/gogo/protobuf/protoc-gen-gofast cp ./.protoc-gen-gofast $(GOPATH)/bin/protoc-gen-gofast -generate: .protoc-gen-gofast statik +generate-protoc: .protoc-gen-gofast go generate github.com/pilosa/pilosa/internal +generate-statik: statik + go generate github.com/pilosa/pilosa/handler + +generate: generate-protoc generate-statik + statik: ifndef STATIK go install github.com/rakyll/statik From 15378c02dab77fc6a816299e8ee51b528896970b Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 24 Apr 2017 12:36:13 -0500 Subject: [PATCH 06/45] Update statik version and add subdependency --- glide.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glide.yaml b/glide.yaml index c453a7cae..54cabbdb4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -32,4 +32,6 @@ import: - package: github.com/gorilla/mux version: ^1.3.0 - package: github.com/rakyll/statik - version: 274df120e9065bdd08eb1120e0375e3dc1ae8465 + version: 89fe3459b5c829c32e89bdff9c43f18aad728f2f + subpackages: + - fs From 92ec0a0cb056ca4ffcbb15cd63f4bd36ac4551b1 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 24 Apr 2017 14:25:33 -0500 Subject: [PATCH 07/45] Update glide.lock --- glide.lock | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 7fffeca5e..561d9eeec 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 743e8f978eb4ad8f80a2ab71b05caebbf50b6769b71aa457bc4f144fef8c6595 -updated: 2017-04-18T15:33:39.035615802-05:00 +hash: 5321aa381179f691f250e415abaf7776a9e701df4cf6216a1d8f2e9fa27e2b52 +updated: 2017-04-24T14:24:06.986585051-05:00 imports: - name: github.com/boltdb/bolt version: 4b1ebc1869ad66568b313d0dc410e2be72670dda @@ -52,6 +52,10 @@ imports: version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a +- name: github.com/rakyll/statik + version: 89fe3459b5c829c32e89bdff9c43f18aad728f2f + subpackages: + - fs - name: github.com/satori/go.uuid version: 879c5887cd475cd7864858769793b2ceb0d44feb - name: github.com/spf13/afero From 60c8ba238cc6f966d046317699a48e3c22e6f050 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Tue, 25 Apr 2017 08:57:15 -0500 Subject: [PATCH 08/45] Add new webui design from Joe --- webui/assets/chevron-down.png | Bin 0 -> 3655 bytes webui/assets/main.css | 63 --------- webui/assets/main.js | 114 --------------- webui/assets/nav_cluster.svg | 1 + webui/assets/nav_console.svg | 1 + webui/assets/nav_documentation.svg | 1 + webui/assets/nav_item1.svg | 1 + webui/assets/style.css | 220 +++++++++++++++++++++++++++++ webui/index.html | 209 +++++++++++++++++++++------ 9 files changed, 389 insertions(+), 221 deletions(-) create mode 100644 webui/assets/chevron-down.png delete mode 100644 webui/assets/main.css delete mode 100644 webui/assets/main.js create mode 100644 webui/assets/nav_cluster.svg create mode 100644 webui/assets/nav_console.svg create mode 100644 webui/assets/nav_documentation.svg create mode 100644 webui/assets/nav_item1.svg create mode 100644 webui/assets/style.css diff --git a/webui/assets/chevron-down.png b/webui/assets/chevron-down.png new file mode 100644 index 0000000000000000000000000000000000000000..3312489a21a768a90cb73633e3a596c792c6941b GIT binary patch literal 3655 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 literal 0 HcmV?d00001 diff --git a/webui/assets/main.css b/webui/assets/main.css deleted file mode 100644 index 3db45d2f1..000000000 --- a/webui/assets/main.css +++ /dev/null @@ -1,63 +0,0 @@ -.output { - overflow: auto; - padding: 0 8px; -} - -.output .query { - font-family: monospace; -} - -.output .response { - font-family: monospace; -} - -.input-bar { - padding-right: 2em; - background-color: #eeeeee; -} - -.input-textarea { - font-family: monospace; - font-size: 14px; - background-color: #dddddd; - width: 100%; - border: 0; - outline: 0; - margin: 1em; -} - -body { - padding-top: 5rem; -} - -.controls { - padding: 1em; -} - -.output { - padding: 1em; -} - -.result { - background-color: #eeeeee; - padding: 1em; - margin-top: 1em; -} -.result > .tab-content > .tab-pane { - padding: 1em; -} - -.query { - background-color: #dddddd; - padding: 0.5em -} - -#exTab3 .nav-pills > li > a { - border-radius: 4px 4px 0 0 ; -} - -#exTab3 .tab-content { - color : white; - background-color: #428bca; - padding : 5px 15px; -} diff --git a/webui/assets/main.js b/webui/assets/main.js deleted file mode 100644 index efd0542ed..000000000 --- a/webui/assets/main.js +++ /dev/null @@ -1,114 +0,0 @@ -class REPL { - constructor(input, output) { - this.input = input - this.output = output - this.history = [] - this.history_index = 0 - this.history_buffer = '' - this.result_number = 0 - } - bind_events() { - const repl = this - const keys = { - ENTER: 13, - UP_ARROW: 38, - DOWN_ARROW: 40 - } - - this.input.addEventListener("keydown", (e) => { - if (e.keyCode == keys.UP_ARROW) { - e.preventDefault() - if (this.input.value.substring(0, this.input.selectionStart).indexOf('\n') == '-1') { - if (this.history_index == 0) { - return - } else { - if (this.history_index == this.history.length) { - this.history_buffer = this.input.value - } - this.history_index-- - this.input.value = this.history[this.history_index] - this.input.setSelectionRange(this.input.value.length, this.input.value.length) - } - } - } - if (e.keyCode == keys.DOWN_ARROW) { - e.preventDefault() - if (this.input.value.substring(this.input.selectionEnd, this.input.length).indexOf('\n') == '-1') { - if (this.history_index == this.history.length) { - return - } else { - this.history_index++ - if (this.history_index == this.history.length) { - this.input.value = this.history_buffer - } else { - this.input.value = this.history[this.history_index] - } - this.input.setSelectionRange(this.input.value.length, this.input.value.length) - } - } - } - if (e.keyCode == keys.ENTER && !e.shiftKey) { - e.preventDefault() - this.history_buffer = '' - this.history_index = this.history.length - this.history[this.history_index] = this.input.value - this.history_index++ - this.process_query(this.input.value) - this.input.value = "" - } - }) - } - - process_query(query) { - var xhr = new XMLHttpRequest(); - var dbname = 'foo'; // todo: get db name from dropdown menu - xhr.open('POST', '/db/' + dbname + '/query'); - xhr.setRequestHeader('Content-Type', 'application/text'); - - const repl = this - xhr.onload = function() { - repl.result_number++ -//const entry = document.createElement('p') - const result = ( - '
' + - '' + -'' + - '
' + - '
' + - '

' + - query + - '

' + - '

Response

' + - '

' + - xhr.responseText + - '

' + - '
' + - '
' + - '' + - '' + - '' + - '' + - '
Response code' + xhr.status + '
Response text' + xhr.responseText + '
Response URL' + xhr.responseURL + '
' + - '
' + - '
' + - '
') - // TODO: remove jquery - $(repl.output).prepend($(result)) - }; - xhr.send(query); - } -} - -function startup() { - const input = document.querySelector('.input-textarea') - const output = document.querySelector('.output') - repl = new REPL(input, output) - repl.bind_events() -} diff --git a/webui/assets/nav_cluster.svg b/webui/assets/nav_cluster.svg new file mode 100644 index 000000000..baf6310ea --- /dev/null +++ b/webui/assets/nav_cluster.svg @@ -0,0 +1 @@ +nav_cluster_1 \ No newline at end of file diff --git a/webui/assets/nav_console.svg b/webui/assets/nav_console.svg new file mode 100644 index 000000000..2263c2a69 --- /dev/null +++ b/webui/assets/nav_console.svg @@ -0,0 +1 @@ +nav_console \ No newline at end of file diff --git a/webui/assets/nav_documentation.svg b/webui/assets/nav_documentation.svg new file mode 100644 index 000000000..12cd2108c --- /dev/null +++ b/webui/assets/nav_documentation.svg @@ -0,0 +1 @@ +documentation \ No newline at end of file diff --git a/webui/assets/nav_item1.svg b/webui/assets/nav_item1.svg new file mode 100644 index 000000000..d6d7f779e --- /dev/null +++ b/webui/assets/nav_item1.svg @@ -0,0 +1 @@ +nav_item1 \ No newline at end of file diff --git a/webui/assets/style.css b/webui/assets/style.css new file mode 100644 index 000000000..940d6657f --- /dev/null +++ b/webui/assets/style.css @@ -0,0 +1,220 @@ +*{ + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +body{ + font-family: sans-serif; + background-color: #fbfcfd; + margin: 0; + color: #102445; +} +h2{ + margin-bottom: 30px; +} + +h5{ + text-transform: uppercase; + letter-spacing: 2px; + line-height: 1.21; + margin: 0; +} +a{ + line-height: 1.38; + letter-spacing: 0.2px; + text-decoration: none; + color: #102445; +} + + +a:hover{ + color: #1db598; +} + +textarea{ + width: 100%; + margin-bottom: 10px; + border-radius: 2px; + background-color: #fbfcfd; + border: solid 1.5px #e4eff4; + font-family: monospace; + font-size: 16px; + line-height: 1.5; + letter-spacing: 1.1px; + outline: none; + padding: 30px; +} + + +select{ + /*-webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: url("img/chevron-down.png") no-repeat calc(100% - 10px) !important;*/ + border-radius: 3px; + background-color: #fbfcfd; + width: 187px; + height: 50px; + border: solid 1.5px #e4eff4; + font-size: 18px; + font-weight: bold; + line-height: 1.39; + letter-spacing: 0.2px; + color: #102445; + padding: 10.5px; + +} + +button{ + width: 165px; + height: 50px; + border-radius: 3px; + background-color: #1db598; + outline: none; + border: none; + font-size: 16px; + color: white; +} + +em{ + font-style: normal; + opacity: 0.5; + font-size: 14px; + font-weight: 500; + letter-spacing: 0.2px; + color: #102445; +} + +.header{ + height: 92px; + display: flex; + align-items: center; + justify-content: space-between; + width: 90%; + margin: auto; +} + +.container{ + display: flex; + height:100%; + min-height: 100vh; +} +.nav{ + color: white; + display: flex; + flex-direction: column; + width: 150px; + background: #3c5f8d; +} + +.nav-item{ + height:150px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + border-bottom: 3px solid #2a4871; + cursor: pointer; +} + +.nav-active{ + background: #f2f7f9; + font-weight: bold; + color: #1db598; +} + + + +.interface{ + display: flex; + flex: 1; + flex-direction: column; + align-items: center; + background: #f2f7f9; +} + +.query{ + margin-bottom: 30px; +} +.query, +.output-container{ + width: 75%; +} + +.output{ + margin-bottom: 30px; +} + +.input-controls{ + display: flex; + justify-content: flex-end; +} + +.tabs{ + display: flex; + background: #eaf2f6; +} +.active-tab{ + background: white; + font-weight: bold; + color: #1db598; + +} + +.tab{ + height:60px; + width: 100px; + border-top-right-radius: 5px; + display: flex; + align-items: center; + justify-content: center; + visibility: visible; + cursor: pointer; + +} + +.pane{ + background: white; + padding: 30px; + display: none; +} + +.active{ + display: block; +} + + + +.result-io-header{ + display: flex; + align-items: center; + margin-bottom: 15px; +} + +.result-input, +.result-ouput{ + border-radius: 2px; + background-color: #fafafa; + border: solid 1.5px #e4eff4; + font-family: monospace; + font-size: 16px; + line-height: 1.5; + letter-spacing: 1.1px; + color: #102445; + padding: 15px; + margin-bottom: 15px; +} + + +.result-ouput{ + background-color: #edf9f7; + border-left: solid 4px #1db598; +} + + +.raw{ + height: 253px; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/webui/index.html b/webui/index.html index 1fe4b9f68..a14d202bf 100644 --- a/webui/index.html +++ b/webui/index.html @@ -1,51 +1,172 @@ - - - - - - - - -
-
- - + +
-
+
- - - - - - +
+

Query

+ +
+ + +     + +
+
+ + +
+ +

Output

+
+ + +
+ +
+ + + +
+ +
+ + + From a0e496f6a0301e45f40ba9bd907c61aa0703bcf6 Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Tue, 25 Apr 2017 09:40:17 -0500 Subject: [PATCH 09/45] Update JS to hit Pilosa --- webui/assets/main.js | 129 +++++++++++++++++++++++++++++++++++++++++++ webui/index.html | 110 +----------------------------------- 2 files changed, 130 insertions(+), 109 deletions(-) create mode 100644 webui/assets/main.js diff --git a/webui/assets/main.js b/webui/assets/main.js new file mode 100644 index 000000000..b24d3ac51 --- /dev/null +++ b/webui/assets/main.js @@ -0,0 +1,129 @@ +class REPL { + constructor(input, output, button) { + this.input = input + this.output = output + this.button = button + this.history = [] + this.history_index = 0 + this.history_buffer = '' + this.result_number = 0 + } + bind_events() { + const repl = this + const keys = { + ENTER: 13, + UP_ARROW: 38, + DOWN_ARROW: 40 + } + + this.input.addEventListener("keydown", (e) => { + if (e.keyCode == keys.UP_ARROW) { + e.preventDefault() + if (this.input.value.substring(0, this.input.selectionStart).indexOf('\n') == '-1') { + if (this.history_index == 0) { + return + } else { + if (this.history_index == this.history.length) { + this.history_buffer = this.input.value + } + this.history_index-- + this.input.value = this.history[this.history_index] + this.input.setSelectionRange(this.input.value.length, this.input.value.length) + } + } + } + if (e.keyCode == keys.DOWN_ARROW) { + e.preventDefault() + if (this.input.value.substring(this.input.selectionEnd, this.input.length).indexOf('\n') == '-1') { + if (this.history_index == this.history.length) { + return + } else { + this.history_index++ + if (this.history_index == this.history.length) { + this.input.value = this.history_buffer + } else { + this.input.value = this.history[this.history_index] + } + this.input.setSelectionRange(this.input.value.length, this.input.value.length) + } + } + } + if (e.keyCode == keys.ENTER && !e.shiftKey) { + e.preventDefault() + this.submit(); + } + }) + this.button.onclick = function() { + repl.submit(); + }; + } + + submit() { + this.history_buffer = '' + this.history_index = this.history.length + this.history[this.history_index] = this.input.value + this.history_index++ + this.process_query(this.input.value) + this.input.value = "" + } + + process_query(query) { + var xhr = new XMLHttpRequest(); + var dbname = 'foo'; // todo: get db name from dropdown menu + xhr.open('POST', '/db/' + dbname + '/query'); + xhr.setRequestHeader('Content-Type', 'application/text'); + + const repl = this + xhr.onload = function() { + repl.result_number++ + repl.createSingleOutput({"input": query, "output": xhr.responseText}) + } + xhr.send(query) + } + + createSingleOutput(res) { + var node = document.createElement("div"); + node.classList.add('output'); + var markup =` +
+
+
+
+
Input
+        + Source: Index +
+
+ ${res.input} +
+
+
+
+
output
+        + .42 ms +
+
+ ${res.output} +
+
+
+
+ +
+
+ ` + node.innerHTML = markup; + this.output.insertBefore(node, this.output.firstChild) + } +} + +const input = document.getElementById('query') +const output = document.getElementById('outputs') +const button = document.getElementById('query-btn') + +repl = new REPL(input, output, button) +repl.bind_events() diff --git a/webui/index.html b/webui/index.html index a14d202bf..607c55167 100644 --- a/webui/index.html +++ b/webui/index.html @@ -59,114 +59,6 @@ - + From 7ee65e602211cd878d6872ba96258e834628427e Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 11:46:17 -0500 Subject: [PATCH 10/45] Populate dropdown from /schema, use selected index for queries --- webui/assets/main.js | 32 ++++++++++++++++++++++++++++---- webui/index.html | 4 ++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/webui/assets/main.js b/webui/assets/main.js index b24d3ac51..6ee89ffc4 100644 --- a/webui/assets/main.js +++ b/webui/assets/main.js @@ -69,14 +69,19 @@ class REPL { process_query(query) { var xhr = new XMLHttpRequest(); - var dbname = 'foo'; // todo: get db name from dropdown menu - xhr.open('POST', '/db/' + dbname + '/query'); + var e = document.getElementById("index-dropdown"); + var indexname = e.options[e.selectedIndex].text; + xhr.open('POST', '/db/' + indexname + '/query'); // TODO db->index xhr.setRequestHeader('Content-Type', 'application/text'); const repl = this xhr.onload = function() { repl.result_number++ - repl.createSingleOutput({"input": query, "output": xhr.responseText}) + repl.createSingleOutput({ + "input": query, + "output": xhr.responseText, + "indexname": indexname, + }) } xhr.send(query) } @@ -91,7 +96,7 @@ class REPL {
Input
       - Source: Index + Source: ${res.indexname}
${res.input} @@ -119,11 +124,30 @@ class REPL { node.innerHTML = markup; this.output.insertBefore(node, this.output.firstChild) } + + populate_index_dropdown() { + var xhr = new XMLHttpRequest(); + xhr.open('GET', '/schema') + var select = document.getElementById('index-dropdown') + + xhr.onload = function() { + var schema = JSON.parse(xhr.responseText) + for(var i=0; iindex + var opt = document.createElement('option') + opt.innerHTML = schema['dbs'][i]['name'] + select.appendChild(opt) + } + } + xhr.send(null) + } + } + const input = document.getElementById('query') const output = document.getElementById('outputs') const button = document.getElementById('query-btn') repl = new REPL(input, output, button) +repl.populate_index_dropdown() repl.bind_events() diff --git a/webui/index.html b/webui/index.html index 607c55167..36030af61 100644 --- a/webui/index.html +++ b/webui/index.html @@ -34,8 +34,8 @@
-     From cd30b412f8d5113a9371cfb12dda82779758bd59 Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 11:59:49 -0500 Subject: [PATCH 11/45] Add real query time to output --- webui/assets/main.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/webui/assets/main.js b/webui/assets/main.js index 6ee89ffc4..bf16cb2df 100644 --- a/webui/assets/main.js +++ b/webui/assets/main.js @@ -75,15 +75,19 @@ class REPL { xhr.setRequestHeader('Content-Type', 'application/text'); const repl = this + var start_time = new Date().getTime(); + xhr.send(query) xhr.onload = function() { + var end_time = new Date().getTime() repl.result_number++ repl.createSingleOutput({ "input": query, "output": xhr.responseText, "indexname": indexname, + "querytime_ms": end_time - start_time, }) } - xhr.send(query) + } createSingleOutput(res) { @@ -106,7 +110,7 @@ class REPL {
output
       - .42 ms + ${res.querytime_ms} ms
${res.output} From fe6d2189a708317ab179eca533e6e1ed5126086c Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 12:10:27 -0500 Subject: [PATCH 12/45] Change output background to red on error --- webui/assets/main.js | 7 ++++++- webui/assets/style.css | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/webui/assets/main.js b/webui/assets/main.js index bf16cb2df..a91391a38 100644 --- a/webui/assets/main.js +++ b/webui/assets/main.js @@ -93,6 +93,11 @@ class REPL { createSingleOutput(res) { var node = document.createElement("div"); node.classList.add('output'); + var result_class = "result-output" + var output = JSON.parse(res['output']) + if("error" in output) { + result_class = "result-error" + } var markup =`
@@ -112,7 +117,7 @@ class REPL {        ${res.querytime_ms} ms
-
+
${res.output}
diff --git a/webui/assets/style.css b/webui/assets/style.css index 940d6657f..a4ed3df1f 100644 --- a/webui/assets/style.css +++ b/webui/assets/style.css @@ -192,7 +192,8 @@ em{ } .result-input, -.result-ouput{ +.result-output, +.result-error{ border-radius: 2px; background-color: #fafafa; border: solid 1.5px #e4eff4; @@ -206,11 +207,16 @@ em{ } -.result-ouput{ +.result-output{ background-color: #edf9f7; border-left: solid 4px #1db598; } +.result-error{ + background-color: #f9edf4; + border-left: solid 4px #b51d78; +} + .raw{ height: 253px; From 56797833efd646469204fb72ea93854ddd3438a1 Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 12:10:41 -0500 Subject: [PATCH 13/45] Add TODO comment --- webui/assets/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webui/assets/main.js b/webui/assets/main.js index a91391a38..d27978921 100644 --- a/webui/assets/main.js +++ b/webui/assets/main.js @@ -136,7 +136,7 @@ class REPL { populate_index_dropdown() { var xhr = new XMLHttpRequest(); - xhr.open('GET', '/schema') + xhr.open('GET', '/schema') // TODO schema->status (?) var select = document.getElementById('index-dropdown') xhr.onload = function() { From a899dbb2d5923e5e2bbb92ed80be46707cdf8663 Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 12:11:04 -0500 Subject: [PATCH 14/45] Add favicon from cloudfront --- webui/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/webui/index.html b/webui/index.html index 36030af61..eda59baa0 100644 --- a/webui/index.html +++ b/webui/index.html @@ -6,6 +6,7 @@ Pilosa Console +
From 29127362042032a0920fa038a1973acdd711ae0c Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 13:17:11 -0500 Subject: [PATCH 15/45] Change red error color to match style --- webui/assets/style.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webui/assets/style.css b/webui/assets/style.css index a4ed3df1f..68240ad32 100644 --- a/webui/assets/style.css +++ b/webui/assets/style.css @@ -213,8 +213,9 @@ em{ } .result-error{ - background-color: #f9edf4; - border-left: solid 4px #b51d78; + background-color: #fbf1f0; + border-left: solid 4px #fa3035; + color: #fa3035; } From 79031316f7a871f9a4b7dbe91463f78fc7f7a1c4 Mon Sep 17 00:00:00 2001 From: Alan Bernstein Date: Tue, 25 Apr 2017 13:17:39 -0500 Subject: [PATCH 16/45] Remove dropdown label and add header --- webui/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webui/index.html b/webui/index.html index eda59baa0..c8c8aa2a1 100644 --- a/webui/index.html +++ b/webui/index.html @@ -16,7 +16,7 @@