feat(ui): read config from index.html and use it to setup Sentry & default filters

This commit is contained in:
Łukasz Mierzwa
2018-07-19 23:38:11 +02:00
parent 32e3f946ab
commit 99a3671e9b
7 changed files with 106 additions and 13 deletions
-1
View File
@@ -161,7 +161,6 @@ func (ag *APIAlertGroup) DedupSharedMaps() {
// Settings is used to export unsee configuration that is used by UI
type Settings struct {
StaticColorLabels []string `json:"staticColorLabels"`
DefaultFilters []string `json:"defaultFilters"`
}
// AlertsResponse is the structure of JSON response UI will use to get alert data
+5
View File
@@ -9487,6 +9487,11 @@
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
},
"raven-js": {
"version": "3.26.3",
"resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.26.3.tgz",
"integrity": "sha512-VPAsPfK73A9VPcJx5X/kt0GxOqUGpGDM8vdzsYNQXMhYemyZGiW1JX1AI+f4jxm37Apijj6VVtCyJcYFz3ocSQ=="
},
"raw-body": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
+1
View File
@@ -19,6 +19,7 @@
"moment": "^2.22.2",
"prop-types": "^15.6.2",
"qs": "^6.5.2",
"raven-js": "^3.26.3",
"react": "^16.4.1",
"react-autosuggest": "^9.3.4",
"react-dom": "^16.4.1",
+9
View File
@@ -16,6 +16,15 @@
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<!--
Settings span is used to pass config keys that needs to be accessible
early, before the UI app is started.
-->
<span id="settings"
data-raven-dsn="{{ .SentryDSN }}"
data-version="{{ .Version }}"
data-default-filters-base64="{{ .DefaultFilter }}">
</span>
<div id="root"></div>
<!--
This HTML file is a template.
+21 -2
View File
@@ -1,4 +1,5 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { Provider } from "mobx-react";
@@ -10,12 +11,30 @@ import { Fetcher } from "Components/Fetcher";
import "./App.css";
class App extends Component {
static propTypes = {
defaultFilters: PropTypes.arrayOf(PropTypes.string).isRequired
};
constructor(props) {
super(props);
const params = DecodeLocationSearch();
const { defaultFilters } = this.props;
this.alertStore = new AlertStore(params.q);
let filters;
// parse and decode request query args
const p = DecodeLocationSearch();
// p.defaultsUsed means that unsee URI didn't have ?q=foo query args
if (p.defaultsUsed) {
// no ?q=foo set, use defaults from backend config
filters = defaultFilters;
} else {
// user passed ?q=foo, use it as initial filters
filters = p.params.q;
}
this.alertStore = new AlertStore(filters);
}
render() {
+20 -9
View File
@@ -8,10 +8,13 @@ import qs from "qs";
// generate URL for the UI with a set of filters
function FormatAPIFilterQuery(filters) {
return qs.stringify(Object.assign(DecodeLocationSearch(), { q: filters }), {
encodeValuesOnly: true, // don't encode q[]
indices: false // go-gin doesn't support parsing q[0]=foo&q[1]=bar
});
return qs.stringify(
Object.assign(DecodeLocationSearch().params, { q: filters }),
{
encodeValuesOnly: true, // don't encode q[]
indices: false // go-gin doesn't support parsing q[0]=foo&q[1]=bar
}
);
}
// format URI for react UI -> Go backend requests
@@ -21,18 +24,26 @@ function FormatUnseeBackendURI(path) {
}
function DecodeLocationSearch() {
let defaultsUsed = true;
let params = { q: [] };
if (window.location.search !== "") {
const parsed = qs.parse(window.location.search.split("?")[1]);
if (Array.isArray(parsed.q)) {
params.q = parsed.q;
} else {
params.q = [parsed.q];
params = Object.assign(params, parsed);
if (parsed.q !== undefined) {
defaultsUsed = false;
if (parsed.q === "") {
params.q = [];
} else if (Array.isArray(parsed.q)) {
params.q = parsed.q;
} else {
params.q = [parsed.q];
}
}
}
return params;
return { params: params, defaultsUsed: defaultsUsed };
}
function UpdateLocationSearch(newParams) {
+50 -1
View File
@@ -1,10 +1,56 @@
import React from "react";
import ReactDOM from "react-dom";
import Raven from "raven-js";
import Moment from "react-moment";
import { App } from "./App";
let defaultFilters = [];
// check if we have early settings
const settings = document.getElementById("settings");
if (settings !== null) {
// sentry setup if sentry dsn is set
if (
settings.dataset.ravenDsn &&
settings.dataset.ravenDsn !== "{{ .SentryDSN }}"
) {
let version = "unknown";
if (
settings.dataset.version &&
settings.dataset.version !== "{{ .Version }}"
) {
version = settings.dataset.version;
}
try {
Raven.config(settings.dataset.ravenDsn, { release: version }).install();
} catch (err) {
console.error("Raven config failed: " + err);
}
}
// default filters, JSON blob encoded with base64
if (
settings.dataset.defaultFiltersBase64 &&
settings.dataset.defaultFiltersBase64 !== "{{ .DefaultFilter }}"
) {
// decode from base64 to a string
const decoded = Buffer.from(
settings.dataset.defaultFiltersBase64,
"base64"
).toString("ascii");
// parse decoded string as JSON
const json = JSON.parse(decoded);
// if we got an array then use it as default filters
if (Array.isArray(json)) {
defaultFilters = json;
}
}
}
// enable console warnings, but only for dev
if (process.env.NODE_ENV === "development") {
const { whyDidYouUpdate } = require("why-did-you-update");
@@ -18,4 +64,7 @@ if (process.env.NODE_ENV === "development") {
// https://www.npmjs.com/package/react-moment#pooled-timer
Moment.startPooledTimer();
ReactDOM.render(<App />, document.getElementById("root"));
ReactDOM.render(
<App defaultFilters={defaultFilters} />,
document.getElementById("root")
);