mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
fix(templates): put Channel first in the preview row and add All kinds to Applies to
The preview row now shows Channel, Severity and then Kind, so the first dropdown is the channel list again. The kind dropdown is labelled Kind. The Applies to select lists All kinds first. It is ticked when the list is empty, ticking it clears the chosen kinds, and ticking a kind while it is ticked selects that kind alone. The stored value stays applies_to [].
This commit is contained in:
@@ -990,6 +990,40 @@ describe("AddTemplate - applies to", () => {
|
||||
expect(sent.data.applies_to).toEqual(["anomaly", "on_call"]);
|
||||
});
|
||||
|
||||
it("lists All kinds first and ticking it clears the chosen kinds in one click", async () => {
|
||||
const w = await mountComp();
|
||||
await selectCustomMode(w);
|
||||
getForm(w).setFieldValue("name", "ops-card");
|
||||
await w.findComponent({ name: "QueryEditor" }).vm.$emit("update:query", '{"text":"x"}');
|
||||
expect((appliesTo(w).props("options") as any[])[0]).toEqual({
|
||||
label: "All kinds",
|
||||
value: "all_kinds",
|
||||
});
|
||||
expect(appliesTo(w).props("modelValue")).toEqual(["all_kinds"]);
|
||||
|
||||
await appliesTo(w).vm.$emit("update:modelValue", ["anomaly", "incident"]);
|
||||
await appliesTo(w).vm.$emit("update:modelValue", ["anomaly", "incident", "all_kinds"]);
|
||||
await flushPromises();
|
||||
expect(appliesTo(w).props("modelValue")).toEqual(["all_kinds"]);
|
||||
expect(w.find('[data-test="add-template-applies-to-mode"]').text()).toBe(
|
||||
String(i18n.global.t("alert_templates.appliesToManual")),
|
||||
);
|
||||
expect(w.find('[data-test="add-template-applies-to-reset"]').exists()).toBe(true);
|
||||
|
||||
await submit(w);
|
||||
expect((templateService.create as any).mock.calls[0][0].data.applies_to).toEqual([]);
|
||||
});
|
||||
|
||||
it("ticking a kind while All kinds is ticked selects that kind alone", async () => {
|
||||
const w = await mountComp();
|
||||
await selectCustomMode(w);
|
||||
expect(appliesTo(w).props("modelValue")).toEqual(["all_kinds"]);
|
||||
|
||||
await appliesTo(w).vm.$emit("update:modelValue", ["all_kinds", "synthetics"]);
|
||||
await flushPromises();
|
||||
expect(appliesTo(w).props("modelValue")).toEqual(["synthetics"]);
|
||||
});
|
||||
|
||||
it("an existing template starts in manual mode with its stored list", async () => {
|
||||
const w = await mountComp({
|
||||
template: {
|
||||
@@ -1008,7 +1042,7 @@ describe("AddTemplate - applies to", () => {
|
||||
const w = await mountComp({
|
||||
template: { name: "ops-card", body: '{"text":"x"}', type: "http", title: "", applies_to: [] },
|
||||
});
|
||||
expect(appliesTo(w).props("modelValue")).toEqual([]);
|
||||
expect(appliesTo(w).props("modelValue")).toEqual(["all_kinds"]);
|
||||
expect(w.find('[data-test="add-template-applies-to-mode"]').text()).toBe(
|
||||
String(i18n.global.t("alert_templates.appliesToInferred")),
|
||||
);
|
||||
|
||||
@@ -80,7 +80,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
<div class="w-full pb-3" data-test="add-template-applies-to">
|
||||
<OSelect
|
||||
:model-value="appliesTo"
|
||||
:model-value="appliesToSelection"
|
||||
:options="appliesToOptions"
|
||||
labelKey="label"
|
||||
valueKey="value"
|
||||
@@ -479,8 +479,14 @@ const appliesTo = ref<NotificationKind[]>([]);
|
||||
const appliesToMode = ref<"inferred" | "manual">("inferred");
|
||||
const appliesToError = ref<string | null>(null);
|
||||
const isPrebuiltTemplate = computed(() => !!props.template?.isPrebuilt && !props.isClone);
|
||||
const appliesToOptions = computed(() =>
|
||||
NOTIFICATION_KINDS.map((kind) => ({ label: t(kindLabelKey(kind)), value: kind })),
|
||||
// An empty list is stored for every kind; the select shows it as the ticked "All kinds" item.
|
||||
const ALL_KINDS = "all_kinds";
|
||||
const appliesToOptions = computed(() => [
|
||||
{ label: t("alert_templates.appliesToAll"), value: ALL_KINDS },
|
||||
...NOTIFICATION_KINDS.map((kind) => ({ label: t(kindLabelKey(kind)), value: kind })),
|
||||
]);
|
||||
const appliesToSelection = computed<string[]>(() =>
|
||||
appliesTo.value.length ? appliesTo.value : [ALL_KINDS],
|
||||
);
|
||||
const isKind = (k: unknown): k is NotificationKind =>
|
||||
NOTIFICATION_KINDS.includes(k as NotificationKind);
|
||||
@@ -491,7 +497,9 @@ const inferenceSource = computed(() =>
|
||||
);
|
||||
|
||||
const onAppliesToChange = (value: unknown) => {
|
||||
appliesTo.value = NOTIFICATION_KINDS.filter((k) => Array.isArray(value) && value.includes(k));
|
||||
const picked = Array.isArray(value) ? value : [];
|
||||
const allKindsJustTicked = picked.includes(ALL_KINDS) && appliesTo.value.length > 0;
|
||||
appliesTo.value = allKindsJustTicked ? [] : NOTIFICATION_KINDS.filter((k) => picked.includes(k));
|
||||
appliesToMode.value = "manual";
|
||||
appliesToError.value = null;
|
||||
};
|
||||
|
||||
@@ -270,6 +270,38 @@ describe("TemplatePreviewPanel", () => {
|
||||
expect(button.text()).toBe("View in OpenObserve");
|
||||
});
|
||||
|
||||
it("puts Channel first, Severity next and Kind last in the preview row", async () => {
|
||||
vi.spyOn(templateService, "preview").mockResolvedValue(makePreviewResponse() as any);
|
||||
const w = mount(TemplatePreviewPanel, {
|
||||
props: { spec: emptyContentSpec(), kinds: ["alert", "synthetics"] },
|
||||
global: { plugins: [i18n, makeStore()] },
|
||||
});
|
||||
await vi.advanceTimersByTimeAsync(300);
|
||||
await flushPromises();
|
||||
|
||||
const selects = w
|
||||
.find('[data-test="template-preview-panel-channel-select"]')
|
||||
.element.parentElement!.querySelectorAll(":scope > [data-test]");
|
||||
expect(Array.from(selects).map((el) => el.getAttribute("data-test"))).toEqual([
|
||||
"template-preview-panel-channel-select",
|
||||
"template-preview-panel-severity-select",
|
||||
"template-preview-panel-kind-select",
|
||||
]);
|
||||
const labels = w
|
||||
.findAllComponents({ name: "OSelect" })
|
||||
.slice(0, 3)
|
||||
.map((c) => c.props("label"));
|
||||
expect(labels).toEqual(["Channel", "Severity", "Kind"]);
|
||||
expect(
|
||||
(
|
||||
w
|
||||
.find('[data-test="template-preview-panel-channel-select"]')
|
||||
.findComponent({ name: "OSelect" })
|
||||
.props("options") as any[]
|
||||
).length,
|
||||
).toBe(10);
|
||||
});
|
||||
|
||||
it("previews as the first selected kind and sends kind on each request", async () => {
|
||||
const previewSpy = vi
|
||||
.spyOn(templateService, "preview")
|
||||
|
||||
@@ -46,14 +46,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
{{ t("alert_templates.previewGroupLabel") }}
|
||||
</div>
|
||||
<div class="flex flex-wrap items-end gap-3">
|
||||
<OSelect
|
||||
v-model="previewKind"
|
||||
:label="t('alert_templates.previewAs')"
|
||||
:options="kindOptions"
|
||||
width="sm"
|
||||
:searchable="false"
|
||||
data-test="template-preview-panel-kind-select"
|
||||
/>
|
||||
<OSelect
|
||||
v-model="channel"
|
||||
:label="t('alert_templates.previewChannel')"
|
||||
@@ -71,6 +63,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
:searchable="false"
|
||||
data-test="template-preview-panel-severity-select"
|
||||
/>
|
||||
<OSelect
|
||||
v-model="previewKind"
|
||||
:label="t('alert_templates.previewKind')"
|
||||
:options="kindOptions"
|
||||
width="sm"
|
||||
:searchable="false"
|
||||
data-test="template-preview-panel-kind-select"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!forbidden" class="border-border-default flex flex-col gap-1 border-s ps-4">
|
||||
|
||||
@@ -13805,7 +13805,7 @@
|
||||
"appliesToInferred": "Inferred from the variables in the body",
|
||||
"appliesToManual": "Chosen by you",
|
||||
"appliesToReset": "Reset to inferred",
|
||||
"previewAs": "Preview as",
|
||||
"previewKind": "Kind",
|
||||
"previewForbidden": "You do not have permission to preview templates",
|
||||
"previewFailed": "Preview failed: {message}",
|
||||
"severityFailed": "Failed",
|
||||
|
||||
Reference in New Issue
Block a user