Unverified Commit bca6e90e by Julius Volz Committed by GitHub

Integrate beginning of React UI (#5694)

* Initial commit from Create React App
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Initial Prometheus expression browser code
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Grpahing, try out echarts
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Switch to flot
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add metrics fetching and stuff
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Autosuggest and graph improvements
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Start implementing graph controls, add loading spinner
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* So many new features and fixes
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Fixed and built more features
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Make datetimepicker clear work
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Don't abort when executing empty expression
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove TabPaneAlert
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Split components into separate files
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add table time input
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Move first files to TypeScript!
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TypeScript conversions
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TS conversions
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TS conversions
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TS conversions
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TS conversions
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* More TS fixes
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Convert Graph to TS
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Changes
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Resize detector, start building legend, axis font colors
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Make graph legend work
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add URL params support and much more
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Put panel state into panel list, write URL options
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Change order of Graph and Table tabs
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Generalize time input naming more
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Work on history functionality
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* npm updates
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Move loading indicator into "Execute" button
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Fix typo
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Revert "Move loading indicator into "Execute" button"

This reverts commit ce7daee1f1af35da6c0d8b5517272839285ccfec.
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Improve error message when failing to fetch server time
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Move all code to Prometheus repo target dir
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add react-app Makefile step and check in generated assets
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add preliminary npm packages notice to NOTICE file
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Update React app's favicon and metadata
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove RP server refs, cleanups
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Use CircleCI image that includes NodeJS
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add some missing React output assets
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Preserve CRLF in generated React files
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Switch from npm to yarn for React UI
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Save npm licenses and include them in release tarball
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Install npm on Travis
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove npm license tarball from source
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove React graph bundle from source
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Don't check in any compiled web assets
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Update README.md with node/yarn/React UI info
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Fix asset build step on CircleCI promu crossbuild
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Try to fix multi-arch go generate
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove check_assets from Travis CI build
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Prevent rebuilding of unchanged React app parts
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Fix npm license tarball path for promu
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Simplify Makefile
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Clarify build instructions in README.md
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Make minimal JS test pass
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Integrate React app tests into Makefile
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Separate react-app-tests target, but run it from CI
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Fix working directory for React app tests
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove local modifications to Makefile.common

This means that CircleCI will not run the React app tests, but at least
Travis still will...
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Depend on node_modules path for npm_licenses target
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Simplify tarball/docker/build Makefile targets
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Include React tests in "test" target
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Remove reference to removed "check_assets" target
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Do initial resize of expression input field
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>

* Add React app proxying to local Prometheus in dev mode
Signed-off-by: 's avatarJulius Volz <julius.volz@gmail.com>
parent 16370e68
......@@ -9,7 +9,7 @@ executors:
# should also be updated.
- image: circleci/golang:1.13
- image: circleci/golang:1.13-node
......@@ -16,3 +16,7 @@ benchmark.txt
......@@ -12,7 +12,7 @@ build:
path: ./cmd/promtool
- name: tsdb
path: ./tsdb/cmd/tsdb
flags: -mod=vendor -a -tags netgo
flags: -mod=vendor -a -tags netgo,builtinassets
ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}}
......@@ -26,6 +26,7 @@ tarball:
- documentation/examples/prometheus.yml
- npm_licenses.tar.bz2
- linux/amd64
......@@ -12,8 +12,11 @@ go_import_path: github.com/prometheus/prometheus
# random issues on Travis.
- travis_retry make deps
- . $HOME/.nvm/nvm.sh
- nvm install stable
- nvm use stable
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install make; fi
- make check_license style unused test lint check_assets
- make check_license style unused test lint
- git diff --exit-code
......@@ -10,6 +10,9 @@ COPY .build/${OS}-${ARCH}/promtool /bin/promtool
COPY documentation/examples/prometheus.yml /etc/prometheus/prometheus.yml
COPY console_libraries/ /usr/share/prometheus/console_libraries/
COPY consoles/ /usr/share/prometheus/consoles/
COPY npm_licenses.tar.bz2 /npm_licenses.tar.bz2
RUN ln -s /usr/share/prometheus/console_libraries /usr/share/prometheus/consoles/ /etc/prometheus/
RUN mkdir -p /prometheus && \
......@@ -14,6 +14,12 @@
# Needs to be defined before including Makefile.common to auto-generate targets
DOCKER_ARCHS ?= amd64 armv7 arm64
REACT_APP_PATH = web/ui/react-app
REACT_APP_SOURCE_FILES = $(wildcard $(REACT_APP_PATH)/public/* $(REACT_APP_PATH)/src/* $(REACT_APP_PATH)/tsconfig.json)
REACT_APP_OUTPUT_DIR = web/ui/static/graph-new
REACT_APP_NPM_LICENSES_TARBALL = "npm_licenses.tar.bz2"
......@@ -21,26 +27,48 @@ TSDB_BENCHMARK_NUM_METRICS ?= 1000
TSDB_BENCHMARK_DATASET ?= "$(TSDB_PROJECT_DIR)/testdata/20kseries.json"
.PHONY: all
all: common-all check_assets
include Makefile.common
DOCKER_IMAGE_NAME ?= prometheus
cd $(REACT_APP_PATH) && yarn --frozen-lockfile
@echo ">> building React app"
.PHONY: assets
@echo ">> writing assets"
cd $(PREFIX)/web/ui && GO111MODULE=$(GO111MODULE) $(GO) generate -x -v $(GOOPTS)
# Un-setting GOOS and GOARCH here because the generated Go code is always the same,
# but the cached object code is incompatible between architectures and OSes (which
# breaks cross-building for different combinations on CI in the same container).
cd web/ui && GO111MODULE=$(GO111MODULE) GOOS= GOARCH= $(GO) generate -x -v $(GOOPTS)
@$(GOFMT) -w ./web/ui
.PHONY: check_assets
check_assets: assets
@echo ">> checking that assets are up-to-date"
@if ! (cd $(PREFIX)/web/ui && git diff --exit-code); then \
echo "Run 'make assets' and commit the changes to fix the error."; \
exit 1; \
.PHONY: react-app-test
react-app-test: $(REACT_APP_NODE_MODULES_PATH)
@echo ">> running React app tests"
cd $(REACT_APP_PATH) && yarn test --no-watch
.PHONY: test
test: common-test react-app-test
.PHONY: npm_licenses
@echo ">> bundling npm licenses"
find $(REACT_APP_NODE_MODULES_PATH) -iname "license*" | tar cfj $(REACT_APP_NPM_LICENSES_TARBALL) --transform 's/^/npm_licenses\//' --files-from=-
.PHONY: tarball
tarball: npm_licenses common-tarball
.PHONY: docker
docker: npm_licenses common-docker
.PHONY: build
build: assets common-build
.PHONY: build_tsdb
......@@ -85,3 +85,9 @@ go-zookeeper - Native ZooKeeper client for Go
Copyright (c) 2013, Samuel Stauffer <samuel@descolada.com>
See https://github.com/samuel/go-zookeeper/blob/master/LICENSE for license details.
We also use code from a large number of npm packages. For details, see:
- https://github.com/prometheus/prometheus/blob/master/web/ui/react-app/package.json
- https://github.com/prometheus/prometheus/blob/master/web/ui/react-app/package-lock.json
- The individual package licenses as copied from the node_modules directory can be found in
the npm_licenses.tar.bz2 archive in release tarballs and Docker images.
# Prometheus
# Prometheus
[![Build Status](https://travis-ci.org/prometheus/prometheus.svg)][travis]
......@@ -60,6 +60,8 @@ Prometheus will now be reachable at http://localhost:9090/.
To build Prometheus from the source code yourself you need to have a working
Go environment with [version 1.13 or greater installed](https://golang.org/doc/install).
You will also need to have [Node.js](https://nodejs.org/) and [Yarn](https://yarnpkg.com/)
installed in order to build the frontend assets.
You can directly use the `go` tool to download and install the `prometheus`
and `promtool` binaries into your `GOPATH`:
......@@ -67,7 +69,14 @@ and `promtool` binaries into your `GOPATH`:
$ go get github.com/prometheus/prometheus/cmd/...
$ prometheus --config.file=your_config.yml
You can also clone the repository yourself and build using `make`:
*However*, when using `go get` to build Prometheus, Prometheus will expect to be able to
read its web assets from local filesystem directories under `web/ui/static` and
`web/ui/templates`. In order for these assets to be found, you will have to run Prometheus
from the root of the cloned repository. Note also that these directories do not include the
new experimental React UI unless it has been built explicitly using `make assets` or `make build`.
You can also clone the repository yourself and build using `make build`, which will compile in
the web assets so that Prometheus can be run from anywhere:
$ mkdir -p $GOPATH/src/github.com/prometheus
$ cd $GOPATH/src/github.com/prometheus
......@@ -78,12 +87,11 @@ You can also clone the repository yourself and build using `make`:
The Makefile provides several targets:
* *build*: build the `prometheus` and `promtool` binaries
* *build*: build the `prometheus` and `promtool` binaries (includes building and compiling in web assets)
* *test*: run the tests
* *test-short*: run the short tests
* *format*: format the source code
* *vet*: check the source code for common errors
* *assets*: rebuild the static assets
* *docker*: build a docker container for the current `HEAD`
## More information
#!/usr/bin/env bash
# Build React web UI.
# Run from repository root.
set -e
set -u
if ! [[ "$0" =~ "scripts/build_react_app.sh" ]]; then
echo "must be run from repository root"
exit 255
cd web/ui/react-app
echo "building React app"
PUBLIC_URL=. yarn build
rm -rf ../static/graph-new
mv build ../static/graph-new
# Prevent bad redirect due to Go HTTP router treating index.html specially.
mv ../static/graph-new/index.html ../static/graph-new/app.html
......@@ -4,7 +4,8 @@ using the vfsgen library (c.f. Makefile).
During development it is more convenient to always use the files on disk to
directly see changes without recompiling.
To make this work, add `-tags dev` to the `flags` entry in `.promu.yml`, and then `make build`.
To make this work, remove the `builtinassets` build tag in the `flags` entry
in `.promu.yml`, and then `make build`.
This will serve all files from your local filesystem.
This is for development purposes only.
......@@ -29,7 +29,7 @@ func main() {
fs := modtimevfs.New(ui.Assets, time.Unix(1, 0))
err := vfsgen.Generate(fs, vfsgen.Options{
PackageName: "ui",
BuildTags: "!dev",
BuildTags: "builtinassets",
VariableName: "Assets",
if err != nil {
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -16,7 +16,9 @@ package ui
import (
// The blank import is to make Go modules happy.
_ "github.com/shurcooL/httpfs/filter"
_ "github.com/shurcooL/httpfs/union"
_ "github.com/shurcooL/vfsgen"
//go:generate go run -mod=vendor -tags=dev assets_generate.go
//go:generate go run -mod=vendor assets_generate.go
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
# testing
# production
# misc
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.<br>
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
### Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
### Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
### Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
### Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
### `npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
"name": "graph",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.14",
"@fortawesome/free-solid-svg-icons": "^5.7.1",
"@fortawesome/react-fontawesome": "^0.1.4",
"@types/jest": "^24.0.4",
"@types/jquery": "^3.3.29",
"@types/node": "^11.9.3",
"@types/react": "^16.8.2",
"@types/react-dom": "^16.8.0",
"@types/react-resize-detector": "^3.1.0",
"bootstrap": "^4.2.1",
"downshift": "^3.2.2",
"flot": "^2.1.6",
"fuzzy": "^0.1.3",
"i": "^0.3.6",
"jquery": "^3.3.1",
"jquery.flot.tooltip": "^0.9.0",
"jsdom": "^9.6.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.23",
"popper.js": "^1.14.3",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-resize-detector": "^3.4.0",
"react-scripts": "^2.1.5",
"reactstrap": "^7.1.0",
"tempusdominus-bootstrap-4": "^5.1.2",
"tempusdominus-core": "^5.0.3",
"typescript": "^3.3.3"
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eslintConfig": {
"extends": "react-app"
"browserslist": [
"not dead",
"not ie <= 11",
"not op_mini all"
"devDependencies": {
"@types/flot": "0.0.31",
"@types/moment-timezone": "^0.5.10",
"@types/reactstrap": "^7.1.3"
"proxy": "http://localhost:9090"
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
content="width=device-width, initial-scale=1, shrink-to-fit=no"
<meta name="theme-color" content="#000000" />
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
<title>Prometheus Expression Browser</title>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
"short_name": "Prometheus UI",
"name": "Prometheus Server Web Interface",
"icons": [
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
body {
padding-top: 10px; /* TODO remove */
.panel {
margin-bottom: 20px;
.expression-input {
margin-bottom: 10px;
.expression-input textarea {
/* font-family: Menlo,Monaco,Consolas,'Courier New',monospace; */
resize: none;
button.execute-btn {
width: 84px;
.alert.alert-danger {
margin-bottom: 10px;
.nav-tabs .nav-link {
cursor: pointer;
.tab-content {
border-left: 1px solid #dee2e6;
border-right: 1px solid #dee2e6;
border-bottom: 1px solid #dee2e6;
padding: 10px;
.tab-content .alert {
margin-bottom: 0;
.data-table.table {
margin: 10px 0 2px 0;
.data-table > tbody > tr > td {
padding: 5px 0 5px 8px;
font-size: 0.8em;
overflow: hidden;
.autosuggest-dropdown {
position: absolute;
border: 1px solid #ced4da;
border-radius: .25rem;
background-color: #fff;
color: #495057;
font-size: 1rem;
z-index: 1000;
min-width: 10rem;
top: 100%;
left: 56px;
float: left;
padding: .5rem 1px .5rem 1px;
margin: -5px;
list-style: none;
.autosuggest-dropdown li {
width: 100%;
padding: .25rem 1.5rem;
clear: both;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
.graph-controls, .table-controls {
margin-bottom: 10px;
.graph-controls input {
text-align: center;
.graph-controls .range-input input {
width: 50px;
.graph-controls .time-input input {
border-right: none;
div.time-input {
width: 240px !important;
.table-controls input {
text-align: center;
.graph-controls input.resolution-input {
width: 90px;
.graph-controls .time-input, .graph-controls .resolution-input, .graph-controls .stacked-input {
margin-left: 20px;
.graph-controls .clear-time-btn {
background: #fff;
border-left: none;
border-top: 1px solid #ced4da;
border-bottom: 1px solid #ced4da;
color: #495057;
.graph-legend {
margin: 15px 0 15px 25px;
font-size: 0.8em;
.graph-legend .legend-swatch {
padding: 5px;
height: 5px;
outline-offset: 1px;
outline: 1.5px solid #ccc;
margin: 2px 8px 2px 0;
.legend-metric-name {
margin-right: 1px;
.legend-label-name {
font-weight: bold;
.graph {
margin: 0 5px 0 5px;
.graph-chart {
height: 500px;
width: 100%;
/* This is picked up by Flot's axis label font renderer,
which ignores "color" and uses "fill" instead. */
fill: #495057;
font-size: 0.8em;
.graph-chart .flot-overlay {
cursor: crosshair;
.graph-tooltip {
background: rgba(0,0,0,.8);
color: #fff;
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
white-space: nowrap;
padding: 8px;
border-radius: 3px;
.graph-tooltip .labels {
font-size: 11px;
line-height: 11px;
.graph-tooltip .detail-swatch {
display: inline-block;
width: 10px;
height: 10px;
margin: 0 5px 0 0;
.add-panel-btn {
margin-bottom: 20px;
import './globals';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
import React, { Component, ReactNode } from 'react';
import { Container } from 'reactstrap';
import PanelList from './PanelList';
import './App.css';
class App extends Component {
render() {
return (
<Container fluid={true}>
<PanelList />
export default App;
import React, { PureComponent, ReactNode } from 'react';
import { Alert, Table } from 'reactstrap';
import SeriesName from './SeriesName';
export interface QueryResult {
data: null | {
resultType: 'vector',
result: InstantSample[],
} | {
resultType: 'matrix',
result: RangeSamples[],
} | {
resultType: 'scalar',
result: SampleValue,
} | {
resultType: 'string',
result: string,
interface InstantSample {
metric: Metric,
value: SampleValue,
interface RangeSamples {
metric: Metric,
values: SampleValue[],
interface Metric {
[key: string]: string,
type SampleValue = [number, string];
class DataTable extends PureComponent<QueryResult> {
limitSeries(series: InstantSample[] | RangeSamples[]): InstantSample[] | RangeSamples[] {
const maxSeries = 10000;