mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
fix(ui): migrate code to mobx v6
This commit is contained in:
committed by
Łukasz Mierzwa
parent
3c935aa684
commit
e02754016c
@@ -15,6 +15,7 @@ import {
|
||||
APIAlertsResponseSilenceMapT,
|
||||
APIAlertsResponseUpstreamsT,
|
||||
APIAlertsResponseUpstreamsClusterMapT,
|
||||
APISettingsT,
|
||||
} from "Models/APITypes";
|
||||
|
||||
const QueryStringEncodeOptions = {
|
||||
@@ -121,280 +122,358 @@ function NewUnappliedFilter(raw: string): FilterT {
|
||||
};
|
||||
}
|
||||
|
||||
interface AlertStoreFiltersT {
|
||||
values: FilterT[];
|
||||
addFilter: (raw: string) => void;
|
||||
removeFilter: (raw: string) => void;
|
||||
replaceFilter: (oldRaw: string, newRaw: string) => void;
|
||||
setFilters: (raws: string[]) => void;
|
||||
setFilterValues: (v: FilterT[]) => void;
|
||||
setWithoutLocation: (raws: string[]) => void;
|
||||
applyAllFilters: () => void;
|
||||
}
|
||||
|
||||
interface AlertStoreDataT {
|
||||
colors: APIAlertsResponseColorsT;
|
||||
counters: APILabelCounterT[];
|
||||
grids: APIGridT[];
|
||||
silences: APIAlertsResponseSilenceMapT;
|
||||
upstreams: APIAlertsResponseUpstreamsT;
|
||||
receivers: string[];
|
||||
readonly gridPadding: number;
|
||||
getAlertmanagerByName: (name: string) => APIAlertmanagerUpstreamT | undefined;
|
||||
isReadOnlyAlertmanager: (name: string) => boolean;
|
||||
getClusterAlertmanagersWithoutReadOnly: (clusterID: string) => string[];
|
||||
readonly readOnlyAlertmanagers: APIAlertmanagerUpstreamT[];
|
||||
readonly readWriteAlertmanagers: APIAlertmanagerUpstreamT[];
|
||||
readonly clustersWithoutReadOnly: APIAlertsResponseUpstreamsClusterMapT;
|
||||
getColorData: (name: string, value: string) => APILabelColorT | undefined;
|
||||
setGrids: (g: APIGridT[]) => void;
|
||||
setUpstreams: (u: APIAlertsResponseUpstreamsT) => void;
|
||||
setInstances: (i: APIAlertmanagerUpstreamT[]) => void;
|
||||
setClusters: (c: APIAlertsResponseUpstreamsClusterMapT) => void;
|
||||
}
|
||||
|
||||
interface AlertStoreInfoT {
|
||||
authentication: {
|
||||
enabled: boolean;
|
||||
username: string;
|
||||
};
|
||||
totalAlerts: number;
|
||||
version: string;
|
||||
upgradeReady: boolean;
|
||||
upgradeNeeded: boolean;
|
||||
isRetrying: boolean;
|
||||
reloadNeeded: boolean;
|
||||
setIsRetrying: () => void;
|
||||
clearIsRetrying: () => void;
|
||||
setUpgradeNeeded: () => void;
|
||||
setReloadNeeded: () => void;
|
||||
setTotalAlerts: (n: number) => void;
|
||||
}
|
||||
|
||||
interface AlertStoreSettingsT {
|
||||
values: APISettingsT;
|
||||
}
|
||||
|
||||
interface AlertStoreStatusT {
|
||||
value: symbol;
|
||||
lastUpdateAt: number | Date;
|
||||
error: null | string;
|
||||
stopped: boolean;
|
||||
paused: boolean;
|
||||
setIdle: () => void;
|
||||
setFetching: () => void;
|
||||
setProcessing: () => void;
|
||||
setFailure: (err: string) => void;
|
||||
pause: () => void;
|
||||
resume: () => void;
|
||||
togglePause: () => void;
|
||||
stop: () => void;
|
||||
}
|
||||
|
||||
class AlertStore {
|
||||
filters = observable(
|
||||
{
|
||||
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: 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: string, newRaw: string) {
|
||||
const index = this.values.findIndex((e) => e.raw === oldRaw);
|
||||
if (index >= 0) {
|
||||
// first check if we would create a duplicated filter
|
||||
if (this.values.findIndex((e) => e.raw === newRaw) >= 0) {
|
||||
// we already have newRaw, simply drop oldRaw
|
||||
this.removeFilter(oldRaw);
|
||||
} else {
|
||||
// no dups, continue with a swap
|
||||
this.values[index] = NewUnappliedFilter(newRaw);
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
}
|
||||
}
|
||||
},
|
||||
setFilters(raws: string[]) {
|
||||
this.values = raws.map((raw) => NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
},
|
||||
setFilterValues(v: FilterT[]) {
|
||||
this.values = v;
|
||||
},
|
||||
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)
|
||||
);
|
||||
},
|
||||
applyAllFilters() {
|
||||
for (let i = 0; i < this.values.length; i++) {
|
||||
this.values[i].applied = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
addFilter: action.bound,
|
||||
removeFilter: action.bound,
|
||||
replaceFilter: action.bound,
|
||||
setFilters: action.bound,
|
||||
setFilterValues: action.bound,
|
||||
setWithoutLocation: action.bound,
|
||||
applyAllFilters: action.bound,
|
||||
},
|
||||
{ name: "API Filters" }
|
||||
);
|
||||
|
||||
data = observable(
|
||||
{
|
||||
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: string
|
||||
): APIAlertmanagerUpstreamT | undefined {
|
||||
return this.upstreams.instances.find((am) => am.name === name);
|
||||
},
|
||||
isReadOnlyAlertmanager(name: string): boolean {
|
||||
return this.readOnlyAlertmanagers.map((am) => am.name).includes(name);
|
||||
},
|
||||
getClusterAlertmanagersWithoutReadOnly(clusterID: string): string[] {
|
||||
return this.clustersWithoutReadOnly[clusterID] || [];
|
||||
},
|
||||
get readOnlyAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances.filter((am) => am.readonly === true);
|
||||
},
|
||||
get readWriteAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances
|
||||
.filter((am) => am.readonly === false)
|
||||
.map((am) =>
|
||||
Object.assign({}, am, {
|
||||
clusterMembers: am.clusterMembers.filter(
|
||||
(m) => this.isReadOnlyAlertmanager(m) === false
|
||||
),
|
||||
})
|
||||
);
|
||||
},
|
||||
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
|
||||
);
|
||||
if (members.length > 0) {
|
||||
clusters[clusterID] = members;
|
||||
}
|
||||
}
|
||||
return clusters;
|
||||
},
|
||||
getColorData(name: string, value: string): APILabelColorT | undefined {
|
||||
if (this.colors[name] !== undefined) {
|
||||
return this.colors[name][value];
|
||||
}
|
||||
},
|
||||
setGrids(g: APIGridT[]) {
|
||||
this.grids = g;
|
||||
},
|
||||
setUpstreams(u: APIAlertsResponseUpstreamsT) {
|
||||
this.upstreams = u;
|
||||
},
|
||||
setInstances(i: APIAlertmanagerUpstreamT[]) {
|
||||
this.upstreams.instances = i;
|
||||
},
|
||||
setClusters(c: APIAlertsResponseUpstreamsClusterMapT) {
|
||||
this.upstreams.clusters = c;
|
||||
},
|
||||
},
|
||||
{
|
||||
gridPadding: computed,
|
||||
readOnlyAlertmanagers: computed,
|
||||
readWriteAlertmanagers: computed,
|
||||
clustersWithoutReadOnly: computed,
|
||||
setGrids: action.bound,
|
||||
setUpstreams: action.bound,
|
||||
setInstances: action.bound,
|
||||
setClusters: action.bound,
|
||||
},
|
||||
{ name: "API Response data" }
|
||||
);
|
||||
|
||||
info = observable(
|
||||
{
|
||||
authentication: {
|
||||
enabled: false as boolean,
|
||||
username: "",
|
||||
},
|
||||
totalAlerts: 0,
|
||||
version: "unknown",
|
||||
upgradeReady: false as boolean,
|
||||
upgradeNeeded: false as boolean,
|
||||
isRetrying: false as boolean,
|
||||
reloadNeeded: false as boolean,
|
||||
setIsRetrying() {
|
||||
this.isRetrying = true;
|
||||
},
|
||||
clearIsRetrying() {
|
||||
this.isRetrying = false;
|
||||
},
|
||||
setUpgradeNeeded() {
|
||||
this.upgradeNeeded = true;
|
||||
},
|
||||
setReloadNeeded() {
|
||||
this.reloadNeeded = true;
|
||||
},
|
||||
setTotalAlerts(n: number) {
|
||||
this.totalAlerts = n;
|
||||
},
|
||||
},
|
||||
{
|
||||
setIsRetrying: action.bound,
|
||||
clearIsRetrying: action.bound,
|
||||
setReloadNeeded: action.bound,
|
||||
setUpgradeNeeded: action.bound,
|
||||
setTotalAlerts: action.bound,
|
||||
},
|
||||
{ name: "API response info" }
|
||||
);
|
||||
|
||||
settings = observable(
|
||||
{
|
||||
values: {
|
||||
staticColorLabels: [] as string[],
|
||||
annotationsDefaultHidden: false as boolean,
|
||||
annotationsHidden: [] as string[],
|
||||
annotationsVisible: [] as string[],
|
||||
sorting: {
|
||||
grid: {
|
||||
order: "startsAt",
|
||||
reverse: false as boolean,
|
||||
label: "alertname",
|
||||
},
|
||||
valueMapping: {},
|
||||
},
|
||||
silenceForm: {
|
||||
strip: {
|
||||
labels: [] as string[],
|
||||
},
|
||||
},
|
||||
alertAcknowledgement: {
|
||||
enabled: false as boolean,
|
||||
durationSeconds: 900,
|
||||
author: "karma / author missing",
|
||||
commentPrefix: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{},
|
||||
{
|
||||
name: "Global settings",
|
||||
}
|
||||
);
|
||||
|
||||
status = observable(
|
||||
{
|
||||
value: AlertStoreStatuses.Idle,
|
||||
lastUpdateAt: 0 as number | Date,
|
||||
error: null as null | string,
|
||||
stopped: false as boolean,
|
||||
paused: false as boolean,
|
||||
setIdle() {
|
||||
this.value = AlertStoreStatuses.Idle;
|
||||
this.error = null;
|
||||
this.lastUpdateAt = new Date();
|
||||
},
|
||||
setFetching() {
|
||||
this.value = AlertStoreStatuses.Fetching;
|
||||
},
|
||||
setProcessing() {
|
||||
this.value = AlertStoreStatuses.Processing;
|
||||
this.error = null;
|
||||
},
|
||||
setFailure(err: string) {
|
||||
this.value = AlertStoreStatuses.Failure;
|
||||
this.error = err;
|
||||
this.lastUpdateAt = new Date();
|
||||
},
|
||||
pause() {
|
||||
this.paused = true;
|
||||
},
|
||||
resume() {
|
||||
this.paused = this.stopped ? true : false;
|
||||
},
|
||||
togglePause() {
|
||||
this.paused = this.stopped ? true : !this.paused;
|
||||
},
|
||||
stop() {
|
||||
this.paused = true;
|
||||
this.stopped = true;
|
||||
},
|
||||
},
|
||||
{
|
||||
setIdle: action,
|
||||
setFetching: action,
|
||||
setProcessing: action,
|
||||
setFailure: action,
|
||||
pause: action.bound,
|
||||
resume: action.bound,
|
||||
togglePause: action.bound,
|
||||
stop: action.bound,
|
||||
},
|
||||
{ name: "Store status" }
|
||||
);
|
||||
filters: AlertStoreFiltersT;
|
||||
data: AlertStoreDataT;
|
||||
info: AlertStoreInfoT;
|
||||
settings: AlertStoreSettingsT;
|
||||
status: AlertStoreStatusT;
|
||||
|
||||
constructor(initialFilters: null | string[]) {
|
||||
this.filters = observable(
|
||||
{
|
||||
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: 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: string, newRaw: string) {
|
||||
const index = this.values.findIndex((e) => e.raw === oldRaw);
|
||||
if (index >= 0) {
|
||||
// first check if we would create a duplicated filter
|
||||
if (this.values.findIndex((e) => e.raw === newRaw) >= 0) {
|
||||
// we already have newRaw, simply drop oldRaw
|
||||
this.removeFilter(oldRaw);
|
||||
} else {
|
||||
// no dups, continue with a swap
|
||||
this.values[index] = NewUnappliedFilter(newRaw);
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
}
|
||||
}
|
||||
},
|
||||
setFilters(raws: string[]) {
|
||||
this.values = raws.map((raw) => NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map((f) => f.raw) });
|
||||
},
|
||||
setFilterValues(v: FilterT[]) {
|
||||
this.values = v;
|
||||
},
|
||||
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)
|
||||
);
|
||||
},
|
||||
applyAllFilters() {
|
||||
for (let i = 0; i < this.values.length; i++) {
|
||||
this.values[i].applied = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
addFilter: action.bound,
|
||||
removeFilter: action.bound,
|
||||
replaceFilter: action.bound,
|
||||
setFilters: action.bound,
|
||||
setFilterValues: action.bound,
|
||||
setWithoutLocation: action.bound,
|
||||
applyAllFilters: action.bound,
|
||||
},
|
||||
{ name: "API Filters" }
|
||||
);
|
||||
|
||||
this.data = observable(
|
||||
{
|
||||
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: string
|
||||
): APIAlertmanagerUpstreamT | undefined {
|
||||
return this.upstreams.instances.find((am) => am.name === name);
|
||||
},
|
||||
isReadOnlyAlertmanager(name: string): boolean {
|
||||
return this.readOnlyAlertmanagers.map((am) => am.name).includes(name);
|
||||
},
|
||||
getClusterAlertmanagersWithoutReadOnly(clusterID: string): string[] {
|
||||
return this.clustersWithoutReadOnly[clusterID] || [];
|
||||
},
|
||||
get readOnlyAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances.filter((am) => am.readonly === true);
|
||||
},
|
||||
get readWriteAlertmanagers(): APIAlertmanagerUpstreamT[] {
|
||||
return this.upstreams.instances
|
||||
.filter((am) => am.readonly === false)
|
||||
.map((am) =>
|
||||
Object.assign({}, am, {
|
||||
clusterMembers: am.clusterMembers.filter(
|
||||
(m) => this.isReadOnlyAlertmanager(m) === false
|
||||
),
|
||||
})
|
||||
);
|
||||
},
|
||||
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
|
||||
);
|
||||
if (members.length > 0) {
|
||||
clusters[clusterID] = members;
|
||||
}
|
||||
}
|
||||
return clusters;
|
||||
},
|
||||
getColorData(name: string, value: string): APILabelColorT | undefined {
|
||||
if (this.colors[name] !== undefined) {
|
||||
return this.colors[name][value];
|
||||
}
|
||||
},
|
||||
setGrids(g: APIGridT[]) {
|
||||
this.grids = g;
|
||||
},
|
||||
setUpstreams(u: APIAlertsResponseUpstreamsT) {
|
||||
this.upstreams = u;
|
||||
},
|
||||
setInstances(i: APIAlertmanagerUpstreamT[]) {
|
||||
this.upstreams.instances = i;
|
||||
},
|
||||
setClusters(c: APIAlertsResponseUpstreamsClusterMapT) {
|
||||
this.upstreams.clusters = c;
|
||||
},
|
||||
},
|
||||
{
|
||||
gridPadding: computed,
|
||||
readOnlyAlertmanagers: computed,
|
||||
readWriteAlertmanagers: computed,
|
||||
clustersWithoutReadOnly: computed,
|
||||
setGrids: action.bound,
|
||||
setUpstreams: action.bound,
|
||||
setInstances: action.bound,
|
||||
setClusters: action.bound,
|
||||
},
|
||||
{ name: "API Response data" }
|
||||
);
|
||||
|
||||
this.info = observable(
|
||||
{
|
||||
authentication: {
|
||||
enabled: false as boolean,
|
||||
username: "",
|
||||
},
|
||||
totalAlerts: 0,
|
||||
version: "unknown",
|
||||
upgradeReady: false as boolean,
|
||||
upgradeNeeded: false as boolean,
|
||||
isRetrying: false as boolean,
|
||||
reloadNeeded: false as boolean,
|
||||
setIsRetrying() {
|
||||
this.isRetrying = true;
|
||||
},
|
||||
clearIsRetrying() {
|
||||
this.isRetrying = false;
|
||||
},
|
||||
setUpgradeNeeded() {
|
||||
this.upgradeNeeded = true;
|
||||
},
|
||||
setReloadNeeded() {
|
||||
this.reloadNeeded = true;
|
||||
},
|
||||
setTotalAlerts(n: number) {
|
||||
this.totalAlerts = n;
|
||||
},
|
||||
},
|
||||
{
|
||||
setIsRetrying: action.bound,
|
||||
clearIsRetrying: action.bound,
|
||||
setReloadNeeded: action.bound,
|
||||
setUpgradeNeeded: action.bound,
|
||||
setTotalAlerts: action.bound,
|
||||
},
|
||||
{ name: "API response info" }
|
||||
);
|
||||
|
||||
this.settings = observable(
|
||||
{
|
||||
values: {
|
||||
staticColorLabels: [] as string[],
|
||||
annotationsDefaultHidden: false as boolean,
|
||||
annotationsHidden: [] as string[],
|
||||
annotationsVisible: [] as string[],
|
||||
sorting: {
|
||||
grid: {
|
||||
order: "startsAt",
|
||||
reverse: false as boolean,
|
||||
label: "alertname",
|
||||
},
|
||||
valueMapping: {},
|
||||
},
|
||||
silenceForm: {
|
||||
strip: {
|
||||
labels: [] as string[],
|
||||
},
|
||||
},
|
||||
alertAcknowledgement: {
|
||||
enabled: false as boolean,
|
||||
durationSeconds: 900,
|
||||
author: "karma / author missing",
|
||||
commentPrefix: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{},
|
||||
{
|
||||
name: "Global settings",
|
||||
}
|
||||
);
|
||||
|
||||
this.status = observable(
|
||||
{
|
||||
value: AlertStoreStatuses.Idle,
|
||||
lastUpdateAt: 0 as number | Date,
|
||||
error: null as null | string,
|
||||
stopped: false as boolean,
|
||||
paused: false as boolean,
|
||||
setIdle() {
|
||||
this.value = AlertStoreStatuses.Idle;
|
||||
this.error = null;
|
||||
this.lastUpdateAt = new Date();
|
||||
},
|
||||
setFetching() {
|
||||
this.value = AlertStoreStatuses.Fetching;
|
||||
},
|
||||
setProcessing() {
|
||||
this.value = AlertStoreStatuses.Processing;
|
||||
this.error = null;
|
||||
},
|
||||
setFailure(err: string) {
|
||||
this.value = AlertStoreStatuses.Failure;
|
||||
this.error = err;
|
||||
this.lastUpdateAt = new Date();
|
||||
},
|
||||
pause() {
|
||||
this.paused = true;
|
||||
},
|
||||
resume() {
|
||||
this.paused = this.stopped ? true : false;
|
||||
},
|
||||
togglePause() {
|
||||
this.paused = this.stopped ? true : !this.paused;
|
||||
},
|
||||
stop() {
|
||||
this.paused = true;
|
||||
this.stopped = true;
|
||||
},
|
||||
},
|
||||
{
|
||||
setIdle: action,
|
||||
setFetching: action,
|
||||
setProcessing: action,
|
||||
setFailure: action,
|
||||
pause: action.bound,
|
||||
resume: action.bound,
|
||||
togglePause: action.bound,
|
||||
stop: action.bound,
|
||||
},
|
||||
{ name: "Store status" }
|
||||
);
|
||||
|
||||
if (initialFilters !== null) this.filters.setFilters(initialFilters);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,331 +198,408 @@ const UnpackRegexMatcherValues = (isRegex: boolean, value: string) => {
|
||||
export type SilenceFormTabT = "editor" | "browser";
|
||||
export type SilenceFormStageT = "form" | "preview" | "submit";
|
||||
|
||||
interface SilenceFormStoreToggleT {
|
||||
visible: boolean;
|
||||
blurred: boolean;
|
||||
toggle: () => void;
|
||||
hide: () => void;
|
||||
show: () => void;
|
||||
setBlur: (val: boolean) => void;
|
||||
}
|
||||
|
||||
interface SilenceFormStoreTabT {
|
||||
current: SilenceFormTabT;
|
||||
setTab: (value: SilenceFormTabT) => void;
|
||||
}
|
||||
|
||||
interface DurationT {
|
||||
days: number;
|
||||
hours: number;
|
||||
minutes: number;
|
||||
}
|
||||
|
||||
interface SilenceFormStoreDataT {
|
||||
currentStage: SilenceFormStageT;
|
||||
wasValidated: boolean;
|
||||
silenceID: null | undefined | string;
|
||||
alertmanagers: MultiValueOptionT[];
|
||||
matchers: MatcherWithIDT[];
|
||||
startsAt: Date;
|
||||
endsAt: Date;
|
||||
comment: string;
|
||||
author: string;
|
||||
requestsByCluster: { [key: string]: ClusterRequestT };
|
||||
autofillMatchers: boolean;
|
||||
resetInputs: boolean;
|
||||
readonly toBase64: string;
|
||||
fromBase64: (s: string) => void;
|
||||
readonly isValid: boolean;
|
||||
resetStartEnd: () => void;
|
||||
resetProgress: () => void;
|
||||
resetSilenceID: () => void;
|
||||
setSilenceID: (id: string) => void;
|
||||
setAlertmanagers: (val: MultiValueOptionT[]) => void;
|
||||
setAutofillMatchers: (v: boolean) => void;
|
||||
setResetInputs: (v: boolean) => void;
|
||||
setStageSubmit: () => void;
|
||||
setMatchers: (m: MatcherWithIDT[]) => void;
|
||||
addEmptyMatcher: () => void;
|
||||
deleteMatcher: (id: string) => void;
|
||||
fillMatchersFromGroup: (
|
||||
group: APIAlertGroupT,
|
||||
stripLabels: string[],
|
||||
alertmanagers: MultiValueOptionT[],
|
||||
alerts?: APIAlertT[]
|
||||
) => void;
|
||||
fillFormFromSilence: (
|
||||
alertmanager: APIAlertmanagerUpstreamT,
|
||||
silence: AlertmanagerSilencePayloadT
|
||||
) => void;
|
||||
setAuthor: (a: string) => void;
|
||||
setComment: (c: string) => void;
|
||||
verifyStarEnd: () => void;
|
||||
setStart: (startsAt: Date) => void;
|
||||
setEnd: (endsAt: Date) => void;
|
||||
incStart: (minutes: number) => void;
|
||||
decStart: (minutes: number) => void;
|
||||
incEnd: (minutes: number) => void;
|
||||
decEnd: (minutes: number) => void;
|
||||
setWasValidated: (v: boolean) => void;
|
||||
readonly toAlertmanagerPayload: AlertmanagerSilencePayloadT;
|
||||
readonly toDuration: DurationT;
|
||||
}
|
||||
|
||||
class SilenceFormStore {
|
||||
toggle = observable(
|
||||
{
|
||||
visible: false,
|
||||
blurred: false,
|
||||
toggle() {
|
||||
this.visible = !this.visible;
|
||||
},
|
||||
hide() {
|
||||
this.visible = false;
|
||||
},
|
||||
show() {
|
||||
this.visible = true;
|
||||
},
|
||||
setBlur(val: boolean) {
|
||||
this.blurred = val;
|
||||
},
|
||||
},
|
||||
{
|
||||
toggle: action.bound,
|
||||
hide: action.bound,
|
||||
show: action.bound,
|
||||
setBlur: action.bound,
|
||||
}
|
||||
);
|
||||
toggle: SilenceFormStoreToggleT;
|
||||
tab: SilenceFormStoreTabT;
|
||||
data: SilenceFormStoreDataT;
|
||||
|
||||
tab = observable(
|
||||
{
|
||||
current: "editor" as SilenceFormTabT,
|
||||
setTab(value: SilenceFormTabT) {
|
||||
this.current = value;
|
||||
constructor() {
|
||||
this.toggle = observable(
|
||||
{
|
||||
visible: false as boolean,
|
||||
blurred: false as boolean,
|
||||
toggle() {
|
||||
this.visible = !this.visible;
|
||||
},
|
||||
hide() {
|
||||
this.visible = false;
|
||||
},
|
||||
show() {
|
||||
this.visible = true;
|
||||
},
|
||||
setBlur(val: boolean) {
|
||||
this.blurred = val;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
setTab: action.bound,
|
||||
}
|
||||
);
|
||||
{
|
||||
toggle: action.bound,
|
||||
hide: action.bound,
|
||||
show: action.bound,
|
||||
setBlur: action.bound,
|
||||
}
|
||||
);
|
||||
|
||||
// form data is stored here, it's global (rather than attached to the form)
|
||||
// so it can be manipulated from other parts of the code
|
||||
// example: when user clicks a silence button on alert we should populate
|
||||
// this form from that alert so user can easily silence that alert
|
||||
data = observable(
|
||||
{
|
||||
currentStage: "form" as SilenceFormStageT,
|
||||
wasValidated: false as boolean,
|
||||
silenceID: null as null | undefined | string,
|
||||
alertmanagers: [] as MultiValueOptionT[],
|
||||
matchers: [] as MatcherWithIDT[],
|
||||
startsAt: new Date(),
|
||||
endsAt: addHours(new Date(), 1),
|
||||
comment: "",
|
||||
author: "",
|
||||
requestsByCluster: {} as { [key: string]: ClusterRequestT },
|
||||
autofillMatchers: true as boolean,
|
||||
resetInputs: true as boolean,
|
||||
|
||||
get toBase64() {
|
||||
const json = JSON.stringify({
|
||||
am: this.alertmanagers,
|
||||
m: this.matchers.map((m: MatcherWithIDT) => ({
|
||||
n: m.name,
|
||||
r: m.isRegex,
|
||||
v: m.values.map((v) => v.value),
|
||||
})),
|
||||
d: differenceInMinutes(this.endsAt, this.startsAt),
|
||||
c: this.comment,
|
||||
});
|
||||
return window.btoa(json);
|
||||
this.tab = observable(
|
||||
{
|
||||
current: "editor" as SilenceFormTabT,
|
||||
setTab(value: SilenceFormTabT) {
|
||||
this.current = value;
|
||||
},
|
||||
},
|
||||
{
|
||||
setTab: action.bound,
|
||||
}
|
||||
);
|
||||
|
||||
// form data is stored here, it's global (rather than attached to the form)
|
||||
// so it can be manipulated from other parts of the code
|
||||
// example: when user clicks a silence button on alert we should populate
|
||||
// this form from that alert so user can easily silence that alert
|
||||
this.data = observable(
|
||||
{
|
||||
currentStage: "form" as SilenceFormStageT,
|
||||
wasValidated: false as boolean,
|
||||
silenceID: null as null | undefined | string,
|
||||
alertmanagers: [] as MultiValueOptionT[],
|
||||
matchers: [] as MatcherWithIDT[],
|
||||
startsAt: new Date(),
|
||||
endsAt: addHours(new Date(), 1),
|
||||
comment: "",
|
||||
author: "",
|
||||
requestsByCluster: {} as { [key: string]: ClusterRequestT },
|
||||
autofillMatchers: true as boolean,
|
||||
resetInputs: true as boolean,
|
||||
|
||||
get toBase64() {
|
||||
const json = JSON.stringify({
|
||||
am: this.alertmanagers,
|
||||
m: this.matchers.map((m: MatcherWithIDT) => ({
|
||||
n: m.name,
|
||||
r: m.isRegex,
|
||||
v: m.values.map((v) => v.value),
|
||||
})),
|
||||
d: differenceInMinutes(this.endsAt, this.startsAt),
|
||||
c: this.comment,
|
||||
});
|
||||
return window.btoa(json);
|
||||
},
|
||||
|
||||
fromBase64(s: string) {
|
||||
let parsed: SilenceFormDataFromBase64;
|
||||
try {
|
||||
parsed = JSON.parse(window.atob(s));
|
||||
} catch (error) {
|
||||
console.error(`Failed to parse JSON: ${error}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const matchers: MatcherWithIDT[] = [];
|
||||
parsed.m.forEach((m: SimplifiedMatcherT) => {
|
||||
const matcher = NewEmptyMatcher();
|
||||
matcher.name = m.n;
|
||||
matcher.isRegex = m.r;
|
||||
matcher.values = m.v.map((v) => StringToOption(v));
|
||||
matchers.push(matcher);
|
||||
});
|
||||
|
||||
if (matchers.length > 0) {
|
||||
this.alertmanagers = parsed.am;
|
||||
this.matchers = matchers;
|
||||
|
||||
this.startsAt = new Date();
|
||||
this.endsAt = addMinutes(this.startsAt, parsed.d);
|
||||
this.comment = parsed.c;
|
||||
|
||||
this.silenceID = null;
|
||||
this.autofillMatchers = false;
|
||||
this.resetInputs = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fromBase64(s: string) {
|
||||
let parsed: SilenceFormDataFromBase64;
|
||||
try {
|
||||
parsed = JSON.parse(window.atob(s));
|
||||
} catch (error) {
|
||||
console.error(`Failed to parse JSON: ${error}`);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
const matchers: MatcherWithIDT[] = [];
|
||||
parsed.m.forEach((m: SimplifiedMatcherT) => {
|
||||
const matcher = NewEmptyMatcher();
|
||||
matcher.name = m.n;
|
||||
matcher.isRegex = m.r;
|
||||
matcher.values = m.v.map((v) => StringToOption(v));
|
||||
matchers.push(matcher);
|
||||
});
|
||||
get isValid() {
|
||||
if (this.alertmanagers.length === 0) return false;
|
||||
if (this.matchers.length === 0) return false;
|
||||
if (
|
||||
this.matchers.filter(
|
||||
(m) =>
|
||||
m.name === "" ||
|
||||
m.values.length === 0 ||
|
||||
m.values.filter((v) => v.value === "").length > 0
|
||||
).length > 0
|
||||
)
|
||||
return false;
|
||||
if (this.comment === "") return false;
|
||||
if (this.author === "") return false;
|
||||
return true;
|
||||
},
|
||||
|
||||
if (matchers.length > 0) {
|
||||
this.alertmanagers = parsed.am;
|
||||
resetStartEnd() {
|
||||
this.startsAt = new Date();
|
||||
this.endsAt = addHours(new Date(), 1);
|
||||
},
|
||||
|
||||
resetProgress() {
|
||||
this.currentStage = "form";
|
||||
this.wasValidated = false;
|
||||
},
|
||||
|
||||
resetSilenceID() {
|
||||
this.silenceID = null;
|
||||
},
|
||||
|
||||
setSilenceID(id: string) {
|
||||
this.silenceID = id;
|
||||
},
|
||||
|
||||
setAlertmanagers(val: MultiValueOptionT[]) {
|
||||
this.alertmanagers = val;
|
||||
},
|
||||
|
||||
setAutofillMatchers(v: boolean) {
|
||||
this.autofillMatchers = v;
|
||||
},
|
||||
setResetInputs(v: boolean) {
|
||||
this.resetInputs = v;
|
||||
},
|
||||
|
||||
setStageSubmit() {
|
||||
this.currentStage = "submit";
|
||||
},
|
||||
|
||||
setMatchers(m: MatcherWithIDT[]) {
|
||||
this.matchers = m;
|
||||
},
|
||||
|
||||
// append a new empty matcher to the list
|
||||
addEmptyMatcher() {
|
||||
this.matchers.push(NewEmptyMatcher());
|
||||
},
|
||||
|
||||
deleteMatcher(id: string) {
|
||||
// only delete matchers if we have more than 1
|
||||
if (this.matchers.length > 1) {
|
||||
this.matchers = this.matchers.filter((m) => m.id !== id);
|
||||
}
|
||||
},
|
||||
|
||||
// if alerts argument is not passed all group alerts will be used
|
||||
fillMatchersFromGroup(
|
||||
group: APIAlertGroupT,
|
||||
stripLabels: string[],
|
||||
alertmanagers: MultiValueOptionT[],
|
||||
alerts?: APIAlertT[]
|
||||
) {
|
||||
this.alertmanagers = alertmanagers;
|
||||
|
||||
this.matchers = MatchersFromGroup(group, stripLabels, alerts);
|
||||
// ensure that silenceID is nulled, since it's used to edit silences
|
||||
// and this is used to silence groups
|
||||
this.silenceID = null;
|
||||
// disable matcher autofill
|
||||
this.autofillMatchers = false;
|
||||
// disable alertmanager input reset
|
||||
this.resetInputs = false;
|
||||
},
|
||||
|
||||
fillFormFromSilence(
|
||||
alertmanager: APIAlertmanagerUpstreamT,
|
||||
silence: AlertmanagerSilencePayloadT
|
||||
) {
|
||||
this.silenceID = silence.id;
|
||||
|
||||
this.alertmanagers = AlertmanagerClustersToOption({
|
||||
[alertmanager.cluster]: alertmanager.clusterMembers,
|
||||
});
|
||||
|
||||
const matchers: MatcherWithIDT[] = [];
|
||||
for (const m of silence.matchers) {
|
||||
const matcher = NewEmptyMatcher();
|
||||
matcher.name = m.name;
|
||||
matcher.values = UnpackRegexMatcherValues(m.isRegex, m.value);
|
||||
matcher.isRegex = m.isRegex;
|
||||
matchers.push(matcher);
|
||||
}
|
||||
this.matchers = matchers;
|
||||
|
||||
this.startsAt = new Date();
|
||||
this.endsAt = addMinutes(this.startsAt, parsed.d);
|
||||
this.comment = parsed.c;
|
||||
this.startsAt = parseISO(silence.startsAt);
|
||||
this.endsAt = parseISO(silence.endsAt);
|
||||
this.comment = silence.comment;
|
||||
this.author = silence.createdBy;
|
||||
|
||||
this.silenceID = null;
|
||||
// disable matcher autofill
|
||||
this.autofillMatchers = false;
|
||||
this.resetInputs = false;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
return false;
|
||||
},
|
||||
setAuthor(a: string) {
|
||||
this.author = a;
|
||||
},
|
||||
|
||||
get isValid() {
|
||||
if (this.alertmanagers.length === 0) return false;
|
||||
if (this.matchers.length === 0) return false;
|
||||
if (
|
||||
this.matchers.filter(
|
||||
(m) =>
|
||||
m.name === "" ||
|
||||
m.values.length === 0 ||
|
||||
m.values.filter((v) => v.value === "").length > 0
|
||||
).length > 0
|
||||
)
|
||||
return false;
|
||||
if (this.comment === "") return false;
|
||||
if (this.author === "") return false;
|
||||
return true;
|
||||
},
|
||||
setComment(c: string) {
|
||||
this.comment = c;
|
||||
},
|
||||
|
||||
resetStartEnd() {
|
||||
this.startsAt = new Date();
|
||||
this.endsAt = addHours(new Date(), 1);
|
||||
},
|
||||
verifyStarEnd() {
|
||||
const now = new Date();
|
||||
now.setSeconds(0);
|
||||
if (this.startsAt < now) {
|
||||
this.startsAt = now;
|
||||
}
|
||||
|
||||
resetProgress() {
|
||||
this.currentStage = "form";
|
||||
this.wasValidated = false;
|
||||
},
|
||||
if (this.endsAt <= this.startsAt) {
|
||||
this.endsAt = addMinutes(this.startsAt, 1);
|
||||
}
|
||||
},
|
||||
setStart(startsAt: Date) {
|
||||
this.startsAt = startsAt;
|
||||
},
|
||||
setEnd(endsAt: Date) {
|
||||
this.endsAt = endsAt;
|
||||
},
|
||||
incStart(minutes: number) {
|
||||
this.startsAt = addMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decStart(minutes: number) {
|
||||
this.startsAt = subMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
resetSilenceID() {
|
||||
this.silenceID = null;
|
||||
},
|
||||
incEnd(minutes: number) {
|
||||
this.endsAt = addMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decEnd(minutes: number) {
|
||||
this.endsAt = subMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
setSilenceID(id: string) {
|
||||
this.silenceID = id;
|
||||
},
|
||||
setWasValidated(v: boolean) {
|
||||
this.wasValidated = v;
|
||||
},
|
||||
|
||||
setAlertmanagers(val: MultiValueOptionT[]) {
|
||||
this.alertmanagers = val;
|
||||
},
|
||||
get toAlertmanagerPayload() {
|
||||
const startsAt = new Date(this.startsAt);
|
||||
startsAt.setSeconds(0);
|
||||
startsAt.setMilliseconds(0);
|
||||
const endsAt = new Date(this.endsAt);
|
||||
endsAt.setSeconds(0);
|
||||
endsAt.setMilliseconds(0);
|
||||
return GenerateAlertmanagerSilenceData(
|
||||
startsAt,
|
||||
endsAt,
|
||||
this.matchers,
|
||||
this.author,
|
||||
this.comment,
|
||||
this.silenceID
|
||||
);
|
||||
},
|
||||
|
||||
setAutofillMatchers(v: boolean) {
|
||||
this.autofillMatchers = v;
|
||||
get toDuration() {
|
||||
const data: DurationT = {
|
||||
days: differenceInDays(this.endsAt, this.startsAt),
|
||||
hours: differenceInHours(this.endsAt, this.startsAt) % 24,
|
||||
minutes: differenceInMinutes(this.endsAt, this.startsAt) % 60,
|
||||
};
|
||||
return data;
|
||||
},
|
||||
},
|
||||
setResetInputs(v: boolean) {
|
||||
this.resetInputs = v;
|
||||
{
|
||||
toBase64: computed,
|
||||
fromBase64: action.bound,
|
||||
resetStartEnd: action.bound,
|
||||
resetProgress: action.bound,
|
||||
resetSilenceID: action.bound,
|
||||
setSilenceID: action.bound,
|
||||
setAlertmanagers: action.bound,
|
||||
setAutofillMatchers: action.bound,
|
||||
setResetInputs: action.bound,
|
||||
setStageSubmit: action.bound,
|
||||
setMatchers: action.bound,
|
||||
addEmptyMatcher: action.bound,
|
||||
deleteMatcher: action.bound,
|
||||
fillMatchersFromGroup: action.bound,
|
||||
fillFormFromSilence: action.bound,
|
||||
setAuthor: action.bound,
|
||||
setComment: action.bound,
|
||||
verifyStarEnd: action.bound,
|
||||
setStart: action.bound,
|
||||
setEnd: action.bound,
|
||||
incStart: action.bound,
|
||||
decStart: action.bound,
|
||||
incEnd: action.bound,
|
||||
decEnd: action.bound,
|
||||
isValid: computed,
|
||||
setWasValidated: action.bound,
|
||||
toAlertmanagerPayload: computed,
|
||||
toDuration: computed,
|
||||
},
|
||||
|
||||
setStageSubmit() {
|
||||
this.currentStage = "submit";
|
||||
},
|
||||
|
||||
setMatchers(m: MatcherWithIDT[]) {
|
||||
this.matchers = m;
|
||||
},
|
||||
|
||||
// append a new empty matcher to the list
|
||||
addEmptyMatcher() {
|
||||
this.matchers.push(NewEmptyMatcher());
|
||||
},
|
||||
|
||||
deleteMatcher(id: string) {
|
||||
// only delete matchers if we have more than 1
|
||||
if (this.matchers.length > 1) {
|
||||
this.matchers = this.matchers.filter((m) => m.id !== id);
|
||||
}
|
||||
},
|
||||
|
||||
// if alerts argument is not passed all group alerts will be used
|
||||
fillMatchersFromGroup(
|
||||
group: APIAlertGroupT,
|
||||
stripLabels: string[],
|
||||
alertmanagers: MultiValueOptionT[],
|
||||
alerts?: APIAlertT[]
|
||||
) {
|
||||
this.alertmanagers = alertmanagers;
|
||||
|
||||
this.matchers = MatchersFromGroup(group, stripLabels, alerts);
|
||||
// ensure that silenceID is nulled, since it's used to edit silences
|
||||
// and this is used to silence groups
|
||||
this.silenceID = null;
|
||||
// disable matcher autofill
|
||||
this.autofillMatchers = false;
|
||||
// disable alertmanager input reset
|
||||
this.resetInputs = false;
|
||||
},
|
||||
|
||||
fillFormFromSilence(
|
||||
alertmanager: APIAlertmanagerUpstreamT,
|
||||
silence: AlertmanagerSilencePayloadT
|
||||
) {
|
||||
this.silenceID = silence.id;
|
||||
|
||||
this.alertmanagers = AlertmanagerClustersToOption({
|
||||
[alertmanager.cluster]: alertmanager.clusterMembers,
|
||||
});
|
||||
|
||||
const matchers: MatcherWithIDT[] = [];
|
||||
for (const m of silence.matchers) {
|
||||
const matcher = NewEmptyMatcher();
|
||||
matcher.name = m.name;
|
||||
matcher.values = UnpackRegexMatcherValues(m.isRegex, m.value);
|
||||
matcher.isRegex = m.isRegex;
|
||||
matchers.push(matcher);
|
||||
}
|
||||
this.matchers = matchers;
|
||||
|
||||
this.startsAt = parseISO(silence.startsAt);
|
||||
this.endsAt = parseISO(silence.endsAt);
|
||||
this.comment = silence.comment;
|
||||
this.author = silence.createdBy;
|
||||
|
||||
// disable matcher autofill
|
||||
this.autofillMatchers = false;
|
||||
},
|
||||
|
||||
setAuthor(a: string) {
|
||||
this.author = a;
|
||||
},
|
||||
|
||||
setComment(c: string) {
|
||||
this.comment = c;
|
||||
},
|
||||
|
||||
verifyStarEnd() {
|
||||
const now = new Date();
|
||||
now.setSeconds(0);
|
||||
if (this.startsAt < now) {
|
||||
this.startsAt = now;
|
||||
}
|
||||
|
||||
if (this.endsAt <= this.startsAt) {
|
||||
this.endsAt = addMinutes(this.startsAt, 1);
|
||||
}
|
||||
},
|
||||
setStart(startsAt: Date) {
|
||||
this.startsAt = startsAt;
|
||||
},
|
||||
setEnd(endsAt: Date) {
|
||||
this.endsAt = endsAt;
|
||||
},
|
||||
incStart(minutes: number) {
|
||||
this.startsAt = addMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decStart(minutes: number) {
|
||||
this.startsAt = subMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
incEnd(minutes: number) {
|
||||
this.endsAt = addMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decEnd(minutes: number) {
|
||||
this.endsAt = subMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
setWasValidated(v: boolean) {
|
||||
this.wasValidated = v;
|
||||
},
|
||||
|
||||
get toAlertmanagerPayload() {
|
||||
const startsAt = new Date(this.startsAt);
|
||||
startsAt.setSeconds(0);
|
||||
startsAt.setMilliseconds(0);
|
||||
const endsAt = new Date(this.endsAt);
|
||||
endsAt.setSeconds(0);
|
||||
endsAt.setMilliseconds(0);
|
||||
return GenerateAlertmanagerSilenceData(
|
||||
startsAt,
|
||||
endsAt,
|
||||
this.matchers,
|
||||
this.author,
|
||||
this.comment,
|
||||
this.silenceID
|
||||
);
|
||||
},
|
||||
|
||||
get toDuration() {
|
||||
const data = {
|
||||
days: differenceInDays(this.endsAt, this.startsAt),
|
||||
hours: differenceInHours(this.endsAt, this.startsAt) % 24,
|
||||
minutes: differenceInMinutes(this.endsAt, this.startsAt) % 60,
|
||||
};
|
||||
return data;
|
||||
},
|
||||
},
|
||||
{
|
||||
toBase64: computed,
|
||||
fromBase64: action.bound,
|
||||
resetStartEnd: action.bound,
|
||||
resetProgress: action.bound,
|
||||
resetSilenceID: action.bound,
|
||||
setSilenceID: action.bound,
|
||||
setAlertmanagers: action.bound,
|
||||
setAutofillMatchers: action.bound,
|
||||
setResetInputs: action.bound,
|
||||
setStageSubmit: action.bound,
|
||||
setMatchers: action.bound,
|
||||
addEmptyMatcher: action.bound,
|
||||
deleteMatcher: action.bound,
|
||||
fillMatchersFromGroup: action.bound,
|
||||
fillFormFromSilence: action.bound,
|
||||
setAuthor: action.bound,
|
||||
setComment: action.bound,
|
||||
verifyStarEnd: action.bound,
|
||||
setStart: action.bound,
|
||||
setEnd: action.bound,
|
||||
incStart: action.bound,
|
||||
decStart: action.bound,
|
||||
incEnd: action.bound,
|
||||
decEnd: action.bound,
|
||||
isValid: computed,
|
||||
setWasValidated: action.bound,
|
||||
toAlertmanagerPayload: computed,
|
||||
toDuration: computed,
|
||||
},
|
||||
{ name: "Silence form store" }
|
||||
);
|
||||
{ name: "Silence form store" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user