mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
chore(ui): migrate AlertStore to typescript
This commit is contained in:
committed by
Łukasz Mierzwa
parent
0e803c3b99
commit
c5d399e3eb
Generated
+13
@@ -5025,6 +5025,14 @@
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"@types/lodash.throttle": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.6.tgz",
|
||||
"integrity": "sha512-/UIH96i/sIRYGC60NoY72jGkCJtFN5KVPhEMMMTjol65effe1gPn0tycJqV5tlSwMTzX8FqzB5yAj0rfGHTPNg==",
|
||||
"requires": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"@types/lodash.uniqueid": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.uniqueid/-/lodash.uniqueid-4.0.6.tgz",
|
||||
@@ -5084,6 +5092,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
|
||||
"integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA=="
|
||||
},
|
||||
"@types/reach__router": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.3.5.tgz",
|
||||
|
||||
+4
-1
@@ -15,8 +15,10 @@
|
||||
"@types/bricks.js": "1.8.1",
|
||||
"@types/lodash.debounce": "4.0.6",
|
||||
"@types/lodash.merge": "4.6.6",
|
||||
"@types/lodash.throttle": "4.1.6",
|
||||
"@types/lodash.uniqueid": "4.0.6",
|
||||
"@types/promise-retry": "1.1.3",
|
||||
"@types/qs": "6.9.3",
|
||||
"@types/react": "16.9.43",
|
||||
"@types/react-dom": "16.9.8",
|
||||
"@types/react-js-pagination": "3.0.3",
|
||||
@@ -76,7 +78,8 @@
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.{js,ts,tsx}",
|
||||
"!src/**/*.stories.{js,ts,tsx}",
|
||||
"!src/react-app-env.d.ts"
|
||||
"!src/react-app-env.d.ts",
|
||||
"!src/Models/*.ts"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -96,3 +96,101 @@ export interface APIAlertmanagerUpstreamT {
|
||||
version: string;
|
||||
clusterMembers: string[];
|
||||
}
|
||||
|
||||
export interface APIFilterT {
|
||||
text: string;
|
||||
name: string;
|
||||
matcher: string;
|
||||
value: string;
|
||||
hits: number;
|
||||
isValid: boolean;
|
||||
}
|
||||
|
||||
export interface APIAlertsResponseUpstreamsCountersT {
|
||||
total: number;
|
||||
healthy: number;
|
||||
failed: number;
|
||||
}
|
||||
|
||||
export type APIAlertsResponseUpstreamsClusterMapT = {
|
||||
[clusterName: string]: string[];
|
||||
};
|
||||
|
||||
export type APIAlertsResponseSilenceMapT = {
|
||||
[clusterName: string]: { [silenceID: string]: APISilenceT };
|
||||
};
|
||||
|
||||
export interface APIAlertsResponseAuthenticationT {
|
||||
enabled: boolean;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface APILabelColorT {
|
||||
brightness: number;
|
||||
background: string;
|
||||
}
|
||||
export type APIAlertsResponseColorsT = {
|
||||
[labelName: string]: { [labelValue: string]: APILabelColorT };
|
||||
};
|
||||
|
||||
export interface APIAlertsResponseUpstreamsT {
|
||||
counters: APIAlertsResponseUpstreamsCountersT;
|
||||
instances: APIAlertmanagerUpstreamT[];
|
||||
clusters: APIAlertsResponseUpstreamsClusterMapT;
|
||||
}
|
||||
|
||||
export interface APILabelCounterValueT {
|
||||
value: string;
|
||||
raw: string;
|
||||
hits: number;
|
||||
precent: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
export interface APILabelCounterT {
|
||||
name: string;
|
||||
values: APILabelCounterValueT[];
|
||||
}
|
||||
|
||||
export interface APISettingsT {
|
||||
staticColorLabels: string[];
|
||||
annotationsDefaultHidden: boolean;
|
||||
annotationsHidden: string[];
|
||||
annotationsVisible: string[];
|
||||
sorting: {
|
||||
grid: {
|
||||
order: string;
|
||||
reverse: boolean;
|
||||
label: string;
|
||||
};
|
||||
valueMapping: { [labelName: string]: { [labelValue: string]: number } };
|
||||
};
|
||||
silenceForm: {
|
||||
strip: {
|
||||
labels: string[];
|
||||
};
|
||||
};
|
||||
alertAcknowledgement: {
|
||||
enabled: boolean;
|
||||
durationSeconds: number;
|
||||
author: string;
|
||||
commentPrefix: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface APIAlertsResponseT {
|
||||
status: string;
|
||||
error: string;
|
||||
timestamp: string;
|
||||
version: string;
|
||||
upstreams: APIAlertsResponseUpstreamsT;
|
||||
silences: APIAlertsResponseSilenceMapT;
|
||||
grids: APIGridT[];
|
||||
totalAlerts: number;
|
||||
colors: APIAlertsResponseColorsT;
|
||||
filters: APIFilterT[];
|
||||
counters: APILabelCounterT[];
|
||||
settings: APISettingsT;
|
||||
authentication: APIAlertsResponseAuthenticationT;
|
||||
receivers: string[];
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ describe("AlertStore.filters", () => {
|
||||
store.filters.addFilter("foo");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"http://localhost/?q=foo"
|
||||
);
|
||||
});
|
||||
@@ -228,7 +228,7 @@ describe("AlertStore.filters", () => {
|
||||
store.filters.replaceFilter("foo", "bar");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"http://localhost/?q=bar"
|
||||
);
|
||||
});
|
||||
@@ -239,7 +239,7 @@ describe("AlertStore.filters", () => {
|
||||
store.filters.addFilter("foo");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"http://localhost/?q=foo"
|
||||
);
|
||||
});
|
||||
@@ -256,7 +256,7 @@ describe("AlertStore.filters", () => {
|
||||
expect(store.filters.values[1]).toMatchObject(NewUnappliedFilter("far"));
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"http://localhost/?q=baz&q=far"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -5,18 +5,29 @@ import throttle from "lodash.throttle";
|
||||
import qs from "qs";
|
||||
|
||||
import { FetchGet } from "Common/Fetch";
|
||||
import {
|
||||
APIAlertmanagerUpstreamT,
|
||||
APILabelColorT,
|
||||
APIAlertsResponseT,
|
||||
APIAlertsResponseColorsT,
|
||||
APILabelCounterT,
|
||||
APIGridT,
|
||||
APIAlertsResponseSilenceMapT,
|
||||
APIAlertsResponseUpstreamsT,
|
||||
APIAlertsResponseUpstreamsClusterMapT,
|
||||
} from "Models/APITypes";
|
||||
|
||||
const QueryStringEncodeOptions = {
|
||||
encodeValuesOnly: true, // don't encode q[]
|
||||
indices: false, // go-gin doesn't support parsing q[0]=foo&q[1]=bar
|
||||
};
|
||||
|
||||
function FormatAlertsQ(filters) {
|
||||
function FormatAlertsQ(filters: string[]) {
|
||||
return qs.stringify({ q: filters }, QueryStringEncodeOptions);
|
||||
}
|
||||
|
||||
// generate URL for the UI with a set of filters
|
||||
function FormatAPIFilterQuery(filters) {
|
||||
function FormatAPIFilterQuery(filters: string[]) {
|
||||
return qs.stringify(
|
||||
Object.assign(DecodeLocationSearch(window.location.search).params, {
|
||||
q: filters,
|
||||
@@ -26,19 +37,30 @@ function FormatAPIFilterQuery(filters) {
|
||||
}
|
||||
|
||||
// format URI for react UI -> Go backend requests
|
||||
function FormatBackendURI(path) {
|
||||
function FormatBackendURI(path: string) {
|
||||
const uri = process.env.REACT_APP_BACKEND_URI || ".";
|
||||
return `${uri}/${path}`;
|
||||
}
|
||||
|
||||
// takes the '?foo=bar&foo=baz' part of http://example.com?foo=bar&foo=baz
|
||||
// and decodes it into a dict with some extra metadata
|
||||
function DecodeLocationSearch(searchString) {
|
||||
interface QueryParamsT {
|
||||
q: string[];
|
||||
}
|
||||
interface DecodeLocationSearchReturnT {
|
||||
params: QueryParamsT;
|
||||
defaultsUsed: boolean;
|
||||
}
|
||||
function DecodeLocationSearch(
|
||||
searchString: string
|
||||
): DecodeLocationSearchReturnT {
|
||||
let defaultsUsed = true;
|
||||
let params = { q: [] };
|
||||
let params: QueryParamsT = { q: [] };
|
||||
|
||||
if (searchString !== "") {
|
||||
const parsed = qs.parse(searchString.split("?")[1]);
|
||||
const parsed = qs.parse(searchString.split("?")[1]) as {
|
||||
[key: string]: string | string[];
|
||||
};
|
||||
params = Object.assign(params, parsed);
|
||||
|
||||
if (parsed.q !== undefined) {
|
||||
@@ -49,8 +71,8 @@ function DecodeLocationSearch(searchString) {
|
||||
// first filter out duplicates
|
||||
// then filter out empty strings, so 'q=' doesn't end up [""] but rather []
|
||||
params.q = parsed.q
|
||||
.filter((v, i) => parsed.q.indexOf(v) === i)
|
||||
.filter((v) => v !== "");
|
||||
.filter((v: string, i: number) => parsed.q.indexOf(v) === i)
|
||||
.filter((v: string) => v !== "");
|
||||
} else {
|
||||
params.q = [parsed.q];
|
||||
}
|
||||
@@ -60,12 +82,12 @@ function DecodeLocationSearch(searchString) {
|
||||
return { params: params, defaultsUsed: defaultsUsed };
|
||||
}
|
||||
|
||||
function UpdateLocationSearch(newParams) {
|
||||
function UpdateLocationSearch(newParams: QueryParamsT) {
|
||||
const baseURLWithoutSearch = window.location.href.split("?")[0];
|
||||
const newSearch = FormatAPIFilterQuery(newParams.q);
|
||||
window.history.pushState(
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
`${baseURLWithoutSearch}?${newSearch || "q="}`
|
||||
);
|
||||
}
|
||||
@@ -77,7 +99,17 @@ const AlertStoreStatuses = Object.freeze({
|
||||
Failure: Symbol("failure"),
|
||||
});
|
||||
|
||||
function NewUnappliedFilter(raw) {
|
||||
export interface FilterT {
|
||||
applied: boolean;
|
||||
isValid: boolean;
|
||||
raw: string;
|
||||
hits: number;
|
||||
name: string;
|
||||
matcher: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
function NewUnappliedFilter(raw: string): FilterT {
|
||||
return {
|
||||
applied: false,
|
||||
isValid: true,
|
||||
@@ -92,20 +124,20 @@ function NewUnappliedFilter(raw) {
|
||||
class AlertStore {
|
||||
filters = observable(
|
||||
{
|
||||
values: [],
|
||||
addFilter(raw) {
|
||||
values: [] as FilterT[],
|
||||
addFilter(raw: string) {
|
||||
if (this.values.filter((f) => f.raw === raw).length === 0) {
|
||||
this.values.push(NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
}
|
||||
},
|
||||
removeFilter(raw) {
|
||||
removeFilter(raw: string) {
|
||||
if (this.values.filter((f) => f.raw === raw).length > 0) {
|
||||
this.values = this.values.filter((f) => f.raw !== raw);
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
}
|
||||
},
|
||||
replaceFilter(oldRaw, newRaw) {
|
||||
replaceFilter(oldRaw: string, newRaw: string) {
|
||||
const index = this.values.findIndex((e) => e.raw === oldRaw);
|
||||
if (index >= 0) {
|
||||
// first check if we would create a duplicated filter
|
||||
@@ -119,15 +151,18 @@ class AlertStore {
|
||||
}
|
||||
}
|
||||
},
|
||||
setFilters(raws) {
|
||||
setFilters(raws: string[]) {
|
||||
this.values = raws.map((raw) => NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
},
|
||||
setWithoutLocation(raws) {
|
||||
const filtersByRaw = this.values.reduce(function (map, obj) {
|
||||
map[toJS(obj.raw)] = toJS(obj);
|
||||
return map;
|
||||
}, {});
|
||||
setWithoutLocation(raws: string[]) {
|
||||
const filtersByRaw: { [key: string]: FilterT } = this.values.reduce(
|
||||
function (map: { [key: string]: FilterT }, obj) {
|
||||
map[toJS(obj.raw)] = toJS(obj);
|
||||
return map;
|
||||
},
|
||||
{}
|
||||
);
|
||||
this.values = raws.map((raw) =>
|
||||
filtersByRaw[raw] ? filtersByRaw[raw] : NewUnappliedFilter(raw)
|
||||
);
|
||||
@@ -151,28 +186,34 @@ class AlertStore {
|
||||
|
||||
data = observable(
|
||||
{
|
||||
colors: {},
|
||||
counters: [],
|
||||
grids: [],
|
||||
silences: {},
|
||||
upstreams: { instances: [], clusters: {} },
|
||||
receivers: [],
|
||||
get gridPadding() {
|
||||
colors: {} as APIAlertsResponseColorsT,
|
||||
counters: [] as APILabelCounterT[],
|
||||
grids: [] as APIGridT[],
|
||||
silences: {} as APIAlertsResponseSilenceMapT,
|
||||
upstreams: {
|
||||
counters: { total: 0, healthy: 0, failed: 0 },
|
||||
instances: [],
|
||||
clusters: {},
|
||||
} as APIAlertsResponseUpstreamsT,
|
||||
receivers: [] as string[],
|
||||
get gridPadding(): number {
|
||||
return this.grids.filter((g) => g.labelName !== "").length > 0 ? 5 : 0;
|
||||
},
|
||||
getAlertmanagerByName(name) {
|
||||
getAlertmanagerByName(
|
||||
name: string
|
||||
): APIAlertmanagerUpstreamT | undefined {
|
||||
return this.upstreams.instances.find((am) => am.name === name);
|
||||
},
|
||||
isReadOnlyAlertmanager(name) {
|
||||
isReadOnlyAlertmanager(name: string): boolean {
|
||||
return this.readOnlyAlertmanagers.map((am) => am.name).includes(name);
|
||||
},
|
||||
getClusterAlertmanagersWithoutReadOnly(clusterID) {
|
||||
getClusterAlertmanagersWithoutReadOnly(clusterID: string): string[] {
|
||||
return this.clustersWithoutReadOnly[clusterID] || [];
|
||||
},
|
||||
get readOnlyAlertmanagers() {
|
||||
get readOnlyAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances.filter((am) => am.readonly === true);
|
||||
},
|
||||
get readWriteAlertmanagers() {
|
||||
get readWriteAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances
|
||||
.filter((am) => am.readonly === false)
|
||||
.map((am) =>
|
||||
@@ -183,8 +224,8 @@ class AlertStore {
|
||||
})
|
||||
);
|
||||
},
|
||||
get clustersWithoutReadOnly() {
|
||||
const clusters = {};
|
||||
get clustersWithoutReadOnly(): APIAlertsResponseUpstreamsClusterMapT {
|
||||
const clusters: APIAlertsResponseUpstreamsClusterMapT = {};
|
||||
for (const clusterID of Object.keys(this.upstreams.clusters)) {
|
||||
const members = this.upstreams.clusters[clusterID].filter(
|
||||
(member) => this.isReadOnlyAlertmanager(member) === false
|
||||
@@ -195,7 +236,7 @@ class AlertStore {
|
||||
}
|
||||
return clusters;
|
||||
},
|
||||
getColorData(name, value) {
|
||||
getColorData(name: string, value: string): APILabelColorT | undefined {
|
||||
if (this.colors[name] !== undefined) {
|
||||
return this.colors[name][value];
|
||||
}
|
||||
@@ -213,14 +254,14 @@ class AlertStore {
|
||||
info = observable(
|
||||
{
|
||||
authentication: {
|
||||
enabled: false,
|
||||
enabled: false as boolean,
|
||||
username: "",
|
||||
},
|
||||
totalAlerts: 0,
|
||||
version: "unknown",
|
||||
upgradeNeeded: false,
|
||||
isRetrying: false,
|
||||
reloadNeeded: false,
|
||||
upgradeNeeded: false as boolean,
|
||||
isRetrying: false as boolean,
|
||||
reloadNeeded: false as boolean,
|
||||
setIsRetrying() {
|
||||
this.isRetrying = true;
|
||||
},
|
||||
@@ -242,25 +283,25 @@ class AlertStore {
|
||||
settings = observable(
|
||||
{
|
||||
values: {
|
||||
staticColorLabels: [],
|
||||
annotationsDefaultHidden: false,
|
||||
annotationsHidden: [],
|
||||
annotationsVisible: [],
|
||||
staticColorLabels: [] as string[],
|
||||
annotationsDefaultHidden: false as boolean,
|
||||
annotationsHidden: [] as string[],
|
||||
annotationsVisible: [] as string[],
|
||||
sorting: {
|
||||
grid: {
|
||||
order: "startsAt",
|
||||
reverse: false,
|
||||
reverse: false as boolean,
|
||||
label: "alertname",
|
||||
},
|
||||
valueMapping: {},
|
||||
},
|
||||
silenceForm: {
|
||||
strip: {
|
||||
labels: [],
|
||||
labels: [] as string[],
|
||||
},
|
||||
},
|
||||
alertAcknowledgement: {
|
||||
enabled: false,
|
||||
enabled: false as boolean,
|
||||
durationSeconds: 900,
|
||||
author: "karma / author missing",
|
||||
commentPrefix: "",
|
||||
@@ -276,9 +317,9 @@ class AlertStore {
|
||||
status = observable(
|
||||
{
|
||||
value: AlertStoreStatuses.Idle,
|
||||
lastUpdateAt: 0,
|
||||
error: null,
|
||||
paused: false,
|
||||
lastUpdateAt: 0 as number | Date,
|
||||
error: null as null | string,
|
||||
paused: false as boolean,
|
||||
setIdle() {
|
||||
this.value = AlertStoreStatuses.Idle;
|
||||
this.error = null;
|
||||
@@ -291,7 +332,7 @@ class AlertStore {
|
||||
this.value = AlertStoreStatuses.Processing;
|
||||
this.error = null;
|
||||
},
|
||||
setFailure(err) {
|
||||
setFailure(err: string) {
|
||||
this.value = AlertStoreStatuses.Failure;
|
||||
this.error = err;
|
||||
this.lastUpdateAt = new Date();
|
||||
@@ -314,12 +355,18 @@ class AlertStore {
|
||||
{ name: "Store status" }
|
||||
);
|
||||
|
||||
constructor(initialFilters) {
|
||||
constructor(initialFilters: null | string[]) {
|
||||
if (initialFilters !== null) this.filters.setFilters(initialFilters);
|
||||
}
|
||||
|
||||
fetch = action(
|
||||
(gridLabel, gridSortReverse, sortOrder, sortLabel, sortReverse) => {
|
||||
async (
|
||||
gridLabel: string,
|
||||
gridSortReverse: boolean,
|
||||
sortOrder: string,
|
||||
sortLabel: string,
|
||||
sortReverse: string
|
||||
) => {
|
||||
this.status.setFetching();
|
||||
|
||||
const args = [
|
||||
@@ -334,7 +381,7 @@ class AlertStore {
|
||||
FormatBackendURI(`alerts.json?&${args.join("&")}&`) +
|
||||
FormatAPIFilterQuery(this.filters.values.map((f) => f.raw));
|
||||
|
||||
return FetchGet(alertsURI, {}, this.info.setIsRetrying)
|
||||
return await FetchGet(alertsURI, {}, this.info.setIsRetrying)
|
||||
.then((result) => {
|
||||
// we're sending requests with mode=cors so the response should also be type=cors
|
||||
// after a few failures in the retry loop we will switch to no-cors
|
||||
@@ -361,23 +408,23 @@ class AlertStore {
|
||||
|
||||
fetchWithThrottle = throttle(this.fetch, 300);
|
||||
|
||||
parseAPIResponse = action((result) => {
|
||||
parseAPIResponse = action((result: APIAlertsResponseT) => {
|
||||
if (result.error) {
|
||||
this.handleFetchError(result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const queryFilters = [
|
||||
...new Set(
|
||||
const queryFilters = Array.from(
|
||||
new Set(
|
||||
this.filters.values
|
||||
.map((f) => f.raw)
|
||||
.slice()
|
||||
.sort()
|
||||
),
|
||||
];
|
||||
const responseFilters = [
|
||||
...new Set(result.filters.map((m) => m.text).sort()),
|
||||
];
|
||||
)
|
||||
);
|
||||
const responseFilters = Array.from(
|
||||
new Set(result.filters.map((m) => m.text).sort())
|
||||
);
|
||||
if (JSON.stringify(queryFilters) !== JSON.stringify(responseFilters)) {
|
||||
console.info(
|
||||
`Got response with filters '${responseFilters}' while expecting results for '${queryFilters}', ignoring`
|
||||
@@ -402,17 +449,13 @@ class AlertStore {
|
||||
);
|
||||
}
|
||||
|
||||
let updates = {};
|
||||
for (const key of [
|
||||
"colors",
|
||||
"counters",
|
||||
"grids",
|
||||
"silences",
|
||||
"upstreams",
|
||||
"receivers",
|
||||
]) {
|
||||
updates[key] = result[key];
|
||||
}
|
||||
let updates: Partial<APIAlertsResponseT> = {};
|
||||
updates.colors = result.colors;
|
||||
updates.counters = result.counters;
|
||||
updates.grids = result.grids;
|
||||
updates.silences = result.silences;
|
||||
updates.upstreams = result.upstreams;
|
||||
updates.receivers = result.receivers;
|
||||
this.data = Object.assign(this.data, updates);
|
||||
|
||||
// before storing new version check if we need to reload
|
||||
@@ -423,11 +466,9 @@ class AlertStore {
|
||||
this.info.upgradeNeeded = true;
|
||||
}
|
||||
// update extra root level keys that are stored under 'info'
|
||||
for (const key of ["totalAlerts", "version", "authentication"]) {
|
||||
if (this.info[key] !== result[key]) {
|
||||
this.info[key] = result[key];
|
||||
}
|
||||
}
|
||||
this.info.totalAlerts = result.totalAlerts;
|
||||
this.info.version = result.version;
|
||||
this.info.authentication = result.authentication;
|
||||
|
||||
// settings exported via API
|
||||
this.settings.values = result.settings;
|
||||
@@ -435,7 +476,7 @@ class AlertStore {
|
||||
this.status.setIdle();
|
||||
});
|
||||
|
||||
handleFetchError = action((err) => {
|
||||
handleFetchError = action((err: string) => {
|
||||
this.status.setFailure(err);
|
||||
|
||||
// reset alert counter since we won't be rendering any alerts
|
||||
@@ -3,15 +3,8 @@ import { localStored } from "mobx-stored";
|
||||
|
||||
import { UIDefaults } from "Models/UI";
|
||||
|
||||
interface SavedFilter {
|
||||
raw: string;
|
||||
name: string;
|
||||
matcher: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface SavedFiltersStorage {
|
||||
filters: SavedFilter[];
|
||||
filters: string[];
|
||||
present: boolean;
|
||||
}
|
||||
class SavedFilters {
|
||||
@@ -26,7 +19,7 @@ class SavedFilters {
|
||||
}
|
||||
);
|
||||
|
||||
save = action((newFilters: SavedFilter[]) => {
|
||||
save = action((newFilters: string[]) => {
|
||||
this.config.filters = newFilters;
|
||||
this.config.present = true;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user