From 89e473f39bad121079ea35f3a3e5bb936c2410d5 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 3 Dec 2024 16:09:07 +0300 Subject: [PATCH 1/9] replace variables added to urls --- src/components/TextPanel/TextPanel.tsx | 1 + src/hooks/useExternalResources.test.tsx | 3 ++- src/hooks/useExternalResources.ts | 15 ++++++++++++--- src/utils/html.test.tsx | 5 +++-- src/utils/html.ts | 2 +- src/utils/partials.test.ts | 4 ++-- src/utils/partials.ts | 6 ++++-- 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/components/TextPanel/TextPanel.tsx b/src/components/TextPanel/TextPanel.tsx index f143e9c4..cde44bf8 100644 --- a/src/components/TextPanel/TextPanel.tsx +++ b/src/components/TextPanel/TextPanel.tsx @@ -91,6 +91,7 @@ export const TextPanel: React.FC = ({ useExternalResources({ items: options.externalStyles, type: ResourceType.STYLES, + replaceVariables: replaceVariables, }); /** diff --git a/src/hooks/useExternalResources.test.tsx b/src/hooks/useExternalResources.test.tsx index 39872469..e957773a 100644 --- a/src/hooks/useExternalResources.test.tsx +++ b/src/hooks/useExternalResources.test.tsx @@ -24,7 +24,8 @@ describe('Use External Resources', () => { ]; const Component: React.FC<{ items: Resource[]; type: ResourceType }> = ({ items, type }) => { - const { isLoaded } = useExternalResources({ type, items }); + const replaceVariables = jest.fn((str: string) => str); + const { isLoaded } = useExternalResources({ type, items, replaceVariables }); return isLoaded ?
: null; }; diff --git a/src/hooks/useExternalResources.ts b/src/hooks/useExternalResources.ts index 8e1a836f..d398a136 100644 --- a/src/hooks/useExternalResources.ts +++ b/src/hooks/useExternalResources.ts @@ -1,3 +1,4 @@ +import { InterpolateFunction } from '@grafana/data'; import { useEffect, useState } from 'react'; import { Resource, ResourceType } from '../types'; @@ -18,7 +19,15 @@ const stylesManager = createResourcesManager(ResourceType.STYLES); * @param type * @param items */ -export const useExternalResources = ({ type, items }: { type: ResourceType; items: Resource[] }) => { +export const useExternalResources = ({ + type, + items, + replaceVariables, +}: { + type: ResourceType; + items: Resource[]; + replaceVariables: InterpolateFunction; +}) => { /** * Is Resources Loaded */ @@ -38,7 +47,7 @@ export const useExternalResources = ({ type, items }: { type: ResourceType; item /** * Add all resources */ - await Promise.all(items.map((item) => resourcesManager.add(item.url))); + await Promise.all(items.map((item) => resourcesManager.add(replaceVariables(item.url)))); /** * Set loaded @@ -57,7 +66,7 @@ export const useExternalResources = ({ type, items }: { type: ResourceType; item */ items.forEach((item) => resourcesManager.remove(item.url)); }; - }, [items, resourcesManager]); + }, [items, replaceVariables, resourcesManager]); return { isLoaded, diff --git a/src/utils/html.test.tsx b/src/utils/html.test.tsx index caec8c69..f727cc53 100644 --- a/src/utils/html.test.tsx +++ b/src/utils/html.test.tsx @@ -158,6 +158,7 @@ describe('HTML helpers', () => { it('Should use partial handler', async () => { const returnFetchedPartials = [{ name: 'partialName', content: 'some content' }] as any; + const replaceVariables = jest.fn((str: string) => str); const defaultParams = { data: { key: 'value' }, content: '{{> partialName}}', @@ -165,7 +166,7 @@ describe('HTML helpers', () => { helpers: '', timeRange: {}, timeZone: {}, - replaceVariables: jest.fn(), + replaceVariables: replaceVariables, eventBus: {}, options: { wrap: true }, panelData: {}, @@ -178,7 +179,7 @@ describe('HTML helpers', () => { const { html, unsubscribe } = await generateHtml(defaultParams); - expect(fetchAllPartials).toHaveBeenCalledWith(defaultParams.partials); + expect(fetchAllPartials).toHaveBeenCalledWith(defaultParams.partials, replaceVariables); expect(Handlebars.registerPartial).toHaveBeenCalledWith( returnFetchedPartials[0].name, diff --git a/src/utils/html.ts b/src/utils/html.ts index d224a1fb..01a7c632 100644 --- a/src/utils/html.ts +++ b/src/utils/html.ts @@ -143,7 +143,7 @@ export const generateHtml = async ({ /** * await fetching partials */ - const fetchedPartials = await fetchAllPartials(partials); + const fetchedPartials = await fetchAllPartials(partials, replaceVariables); /** * Register partials in handlebars diff --git a/src/utils/partials.test.ts b/src/utils/partials.test.ts index dc1306fa..4c30471e 100644 --- a/src/utils/partials.test.ts +++ b/src/utils/partials.test.ts @@ -60,7 +60,7 @@ describe('fetchAllPartials', () => { it('Should fetch HTML successfully', async () => { const item = { id: 'test', name: 'test partial', url: 'http://example.com/template' }; const item2 = { id: 'test2', name: 'test partial 2', url: 'http://example.com/template2' }; - + const replaceVariables = jest.fn((str: string) => str); jest.mocked(fetch).mockImplementation((url, options) => { return Promise.resolve({ ok: true, @@ -69,7 +69,7 @@ describe('fetchAllPartials', () => { } as any); }); - const result = await fetchAllPartials([item, item2]); + const result = await fetchAllPartials([item, item2], replaceVariables); expect(fetch).toHaveBeenCalledWith(item.url); expect(fetch).toHaveBeenCalledWith(item2.url); diff --git a/src/utils/partials.ts b/src/utils/partials.ts index 70655179..07782189 100644 --- a/src/utils/partials.ts +++ b/src/utils/partials.ts @@ -1,3 +1,5 @@ +import { InterpolateFunction } from '@grafana/data'; + import { PartialItem, PartialItemConfig } from '../types'; /** @@ -23,6 +25,6 @@ export const fetchHtml = async (url: string, partialName: string): Promise { - return await Promise.all(items.map((item) => fetchHtml(item.url, item.name))); +export const fetchAllPartials = async (items: PartialItemConfig[], replaceVariables: InterpolateFunction) => { + return await Promise.all(items.map((item) => fetchHtml(replaceVariables(item.url), item.name))); }; From 4408a56a6eb73865f0b28731a5f2c8e8c6d74dc0 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 3 Dec 2024 16:31:20 +0300 Subject: [PATCH 2/9] update examples and resources --- provisioning/dashboards/panels.json | 424 ++++++++++++++++++------- src/components/TextPanel/TextPanel.tsx | 3 +- src/hooks/useExternalResources.ts | 14 +- 3 files changed, 311 insertions(+), 130 deletions(-) diff --git a/provisioning/dashboards/panels.json b/provisioning/dashboards/panels.json index 0b1b2eb9..833bedcf 100644 --- a/provisioning/dashboards/panels.json +++ b/provisioning/dashboards/panels.json @@ -24,8 +24,8 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, + "id": 6, "links": [], - "liveNow": false, "panels": [ { "datasource": { @@ -56,7 +56,7 @@ }, "gridPos": { "h": 5, - "w": 8, + "w": 24, "x": 0, "y": 0 }, @@ -80,7 +80,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "repeat": "test", "repeatDirection": "h", "targets": [ @@ -143,7 +142,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -221,7 +219,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -294,7 +291,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -355,7 +351,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -423,32 +418,34 @@ "overrides": [] }, "gridPos": { - "h": 12, - "w": 6, + "h": 8, + "w": 12, "x": 12, "y": 13 }, - "id": 8, + "id": 26, "options": { "afterRender": "", - "content": "- Timestamp: {{variable \"__from\"}}\n- Seconds: {{variable \"__from:date:seconds\"}}\n- Parsed: {{variable \"__from:date:YYYY-MM-DD\"}}\n- ISO:\n - From {{variable \"__from:date:iso\"}}\n - To {{variable \"__from:date\"}}\n\n## {{test}}\n\n{{json @root}}", - "contentPartials": [], + "content": "```html\n{{> Index}}\n```", + "contentPartials": [ + { + "id": "1a363455-fd81-4afd-993b-beb062fe29ac", + "name": "Index", + "url": "https://volkovlabs.io/${pages}.html" + } + ], "defaultContent": "The query didn't return any results.", "editor": { "format": "auto", - "height": 400, "language": "markdown" }, "editors": [], - "externalScripts": [], "externalStyles": [], - "handlebars": "", "helpers": "", "renderMode": "everyRow", "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -468,89 +465,9 @@ "name": "test" }, "refId": "A" - }, - { - "datasource": { - "type": "marcusolsson-static-datasource", - "uid": "U0HP2Rv4z" - }, - "frame": { - "fields": [ - { - "config": {}, - "name": "test", - "type": "string", - "values": ["test2"] - } - ], - "meta": {}, - "name": "test2" - }, - "hide": false, - "refId": "B" - } - ], - "title": "Date Variables", - "type": "marcusolsson-dynamictext-panel" - }, - { - "datasource": { - "type": "grafana", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 12, - "w": 6, - "x": 18, - "y": 13 - }, - "id": 17, - "options": { - "afterRender": "", - "content": "```json\n{{{json @root}}}\n```", - "contentPartials": [], - "defaultContent": "The query didn't return any results.", - "editor": { - "format": "auto", - "height": 100, - "language": "markdown" - }, - "editors": ["styles"], - "externalScripts": [], - "externalStyles": [], - "helpers": "", - "renderMode": "allRows", - "styles": "& {\n padding: 0;\n margin: 0;\n}", - "wrap": true - }, - "pluginVersion": "5.3.0", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "refId": "A" } ], + "title": "Partial with replace", "type": "marcusolsson-dynamictext-panel" }, { @@ -601,7 +518,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -676,7 +592,6 @@ "styles": "td.name {\n border: 0;\n background-color: #5d3fc4;\n color: white;\n}\n\nb.name {\n font-family: silom;\n font-size:20px;\n}\n\ntd.photo {\n border:2px solid #5D3FC4;\n text-align:center;\n}\n\ntd.desc {\n text-align:right;\n border:0;\n background-color:#f6f2ff;\n color:#5F3DC4;\n}", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -777,15 +692,15 @@ "overrides": [] }, "gridPos": { - "h": 9, - "w": 12, + "h": 12, + "w": 6, "x": 12, - "y": 25 + "y": 21 }, - "id": 9, + "id": 8, "options": { "afterRender": "", - "content": "- Timestamp: {{variable \"__from\"}}\n- Seconds: {{variable \"__from:date:seconds\"}}\n- Parsed: {{variable \"__from:date:YYYY-MM-DD\"}}\n- ISO:\n - From {{variable \"__from:date:iso\"}}\n - To {{variable \"__from:date\"\n\n## {{test}}", + "content": "- Timestamp: {{variable \"__from\"}}\n- Seconds: {{variable \"__from:date:seconds\"}}\n- Parsed: {{variable \"__from:date:YYYY-MM-DD\"}}\n- ISO:\n - From {{variable \"__from:date:iso\"}}\n - To {{variable \"__from:date\"}}\n\n## {{test}}\n\n{{json @root}}", "contentPartials": [], "defaultContent": "The query didn't return any results.", "editor": { @@ -802,7 +717,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -844,7 +758,67 @@ "refId": "B" } ], - "title": "Error Output", + "title": "Date Variables", + "type": "marcusolsson-dynamictext-panel" + }, + { + "datasource": { + "type": "grafana", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 6, + "x": 18, + "y": 21 + }, + "id": 17, + "options": { + "afterRender": "", + "content": "```json\n{{{json @root}}}\n```", + "contentPartials": [], + "defaultContent": "The query didn't return any results.", + "editor": { + "format": "auto", + "height": 100, + "language": "markdown" + }, + "editors": ["styles"], + "externalScripts": [], + "externalStyles": [], + "helpers": "", + "renderMode": "allRows", + "styles": "& {\n padding: 0;\n margin: 0;\n}", + "wrap": true + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "", "type": "marcusolsson-dynamictext-panel" }, { @@ -896,7 +870,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -927,6 +900,99 @@ ], "type": "marcusolsson-dynamictext-panel" }, + { + "datasource": { + "type": "marcusolsson-static-datasource", + "uid": "U0HP2Rv4z" + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 9, + "options": { + "afterRender": "", + "content": "- Timestamp: {{variable \"__from\"}}\n- Seconds: {{variable \"__from:date:seconds\"}}\n- Parsed: {{variable \"__from:date:YYYY-MM-DD\"}}\n- ISO:\n - From {{variable \"__from:date:iso\"}}\n - To {{variable \"__from:date\"\n\n## {{test}}", + "contentPartials": [], + "defaultContent": "The query didn't return any results.", + "editor": { + "format": "auto", + "height": 400, + "language": "markdown" + }, + "editors": [], + "externalScripts": [], + "externalStyles": [], + "handlebars": "", + "helpers": "", + "renderMode": "everyRow", + "styles": "", + "wrap": true + }, + "targets": [ + { + "datasource": { + "type": "marcusolsson-static-datasource", + "uid": "U0HP2Rv4z" + }, + "frame": { + "fields": [ + { + "config": {}, + "name": "test", + "type": "string", + "values": ["test"] + } + ], + "meta": {}, + "name": "test" + }, + "refId": "A" + }, + { + "datasource": { + "type": "marcusolsson-static-datasource", + "uid": "U0HP2Rv4z" + }, + "frame": { + "fields": [ + { + "config": {}, + "name": "test", + "type": "string", + "values": ["test2"] + } + ], + "meta": {}, + "name": "test2" + }, + "hide": false, + "refId": "B" + } + ], + "title": "Error Output", + "type": "marcusolsson-dynamictext-panel" + }, { "datasource": { "type": "volkovlabs-rss-datasource", @@ -954,7 +1020,7 @@ "h": 12, "w": 12, "x": 12, - "y": 34 + "y": 42 }, "id": 3, "options": { @@ -976,7 +1042,6 @@ "styles": "", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -1055,7 +1120,6 @@ "styles": ".button {\n background-color: ${theme.colors.primary.main};\n border: none;\n color: ${theme.colors.primary.contrastText};\n padding: 4px 8px;\n border-radius: ${theme.shape.radius.default};\n}", "wrap": true }, - "pluginVersion": "5.3.0", "targets": [ { "datasource": { @@ -1078,21 +1142,94 @@ ], "title": "Theme", "type": "marcusolsson-dynamictext-panel" + }, + { + "datasource": { + "type": "marcusolsson-static-datasource", + "uid": "U0HP2Rv4z" + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 27, + "options": { + "afterRender": "", + "content": "\n\n", + "contentPartials": [], + "defaultContent": "The query didn't return any results.", + "editor": { + "format": "auto", + "language": "markdown" + }, + "editors": ["styles"], + "externalStyles": [ + { + "id": "cb68b10f-1878-40aa-bae2-b2da13189fd7", + "url": "https://cdnjs.cloudflare.com/ajax/${part}/hover.css/2.3.1/css/hover.css" + } + ], + "helpers": "", + "renderMode": "allRows", + "styles": "", + "wrap": true + }, + "targets": [ + { + "datasource": { + "type": "marcusolsson-static-datasource", + "uid": "U0HP2Rv4z" + }, + "frame": { + "fields": [ + { + "config": {}, + "name": "test", + "type": "string", + "values": ["", ""] + } + ], + "meta": {}, + "name": "test" + }, + "refId": "A" + } + ], + "title": "CSS external with variable", + "type": "marcusolsson-dynamictext-panel" } ], + "preload": false, "refresh": "", - "revision": 1, - "schemaVersion": 39, + "schemaVersion": 40, "tags": [], "templating": { "list": [ { "current": { - "selected": true, "text": ["All"], "value": ["$__all"] }, - "hide": 0, "includeAll": true, "multi": true, "name": "test", @@ -1119,8 +1256,61 @@ } ], "query": "test1,test2,test3", - "queryValue": "", - "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "text": "index", + "value": "index" + }, + "description": "", + "label": "pages", + "name": "pages", + "options": [ + { + "selected": true, + "text": "index", + "value": "index" + }, + { + "selected": false, + "text": "main", + "value": "main" + }, + { + "selected": false, + "text": "test", + "value": "test" + } + ], + "query": "index, main, test", + "type": "custom" + }, + { + "current": { + "text": "libs", + "value": "libs" + }, + "label": "part", + "name": "part", + "options": [ + { + "selected": true, + "text": "libs", + "value": "libs" + }, + { + "selected": false, + "text": "hover", + "value": "hover" + }, + { + "selected": false, + "text": "dark", + "value": "dark" + } + ], + "query": "libs, hover, dark", "type": "custom" } ] @@ -1133,6 +1323,6 @@ "timezone": "", "title": "Examples", "uid": "O4tc_E6Gz", - "version": 2, + "version": 8, "weekStart": "" } diff --git a/src/components/TextPanel/TextPanel.tsx b/src/components/TextPanel/TextPanel.tsx index cde44bf8..e1063d21 100644 --- a/src/components/TextPanel/TextPanel.tsx +++ b/src/components/TextPanel/TextPanel.tsx @@ -89,9 +89,8 @@ export const TextPanel: React.FC = ({ * External Styles */ useExternalResources({ - items: options.externalStyles, + items: options.externalStyles.map((resource) => ({ ...resource, url: replaceVariables(resource.url) })), type: ResourceType.STYLES, - replaceVariables: replaceVariables, }); /** diff --git a/src/hooks/useExternalResources.ts b/src/hooks/useExternalResources.ts index d398a136..25f27008 100644 --- a/src/hooks/useExternalResources.ts +++ b/src/hooks/useExternalResources.ts @@ -19,15 +19,7 @@ const stylesManager = createResourcesManager(ResourceType.STYLES); * @param type * @param items */ -export const useExternalResources = ({ - type, - items, - replaceVariables, -}: { - type: ResourceType; - items: Resource[]; - replaceVariables: InterpolateFunction; -}) => { +export const useExternalResources = ({ type, items }: { type: ResourceType; items: Resource[] }) => { /** * Is Resources Loaded */ @@ -47,7 +39,7 @@ export const useExternalResources = ({ /** * Add all resources */ - await Promise.all(items.map((item) => resourcesManager.add(replaceVariables(item.url)))); + await Promise.all(items.map((item) => resourcesManager.add(item.url))); /** * Set loaded @@ -66,7 +58,7 @@ export const useExternalResources = ({ */ items.forEach((item) => resourcesManager.remove(item.url)); }; - }, [items, replaceVariables, resourcesManager]); + }, [items, resourcesManager]); return { isLoaded, From 862bc1bad1ff9f450dd9ac1ac107daa422565f69 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 3 Dec 2024 16:34:18 +0300 Subject: [PATCH 3/9] ci lint fix --- src/hooks/useExternalResources.test.tsx | 3 +-- src/hooks/useExternalResources.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hooks/useExternalResources.test.tsx b/src/hooks/useExternalResources.test.tsx index e957773a..39872469 100644 --- a/src/hooks/useExternalResources.test.tsx +++ b/src/hooks/useExternalResources.test.tsx @@ -24,8 +24,7 @@ describe('Use External Resources', () => { ]; const Component: React.FC<{ items: Resource[]; type: ResourceType }> = ({ items, type }) => { - const replaceVariables = jest.fn((str: string) => str); - const { isLoaded } = useExternalResources({ type, items, replaceVariables }); + const { isLoaded } = useExternalResources({ type, items }); return isLoaded ?
: null; }; diff --git a/src/hooks/useExternalResources.ts b/src/hooks/useExternalResources.ts index 25f27008..8e1a836f 100644 --- a/src/hooks/useExternalResources.ts +++ b/src/hooks/useExternalResources.ts @@ -1,4 +1,3 @@ -import { InterpolateFunction } from '@grafana/data'; import { useEffect, useState } from 'react'; import { Resource, ResourceType } from '../types'; From 643ac41b1c6b32edbe6bde5aa764b058241ca2b8 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 3 Dec 2024 16:45:25 +0300 Subject: [PATCH 4/9] ci test updated --- src/components/TextPanel/TextPanel.test.tsx | 50 ++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/components/TextPanel/TextPanel.test.tsx b/src/components/TextPanel/TextPanel.test.tsx index a79dcf8c..0177e177 100644 --- a/src/components/TextPanel/TextPanel.test.tsx +++ b/src/components/TextPanel/TextPanel.test.tsx @@ -2,7 +2,7 @@ import { FieldType, toDataFrame } from '@grafana/data'; import { RefreshEvent } from '@grafana/runtime'; import { act, fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; - +import { useExternalResources } from '../../hooks'; import { CodeLanguage, Format, TEST_IDS } from '../../constants'; import { PanelOptions, RenderMode } from '../../types'; import { TextPanel } from './TextPanel'; @@ -214,6 +214,54 @@ describe('Panel', () => { expect(screen.getByTestId(TEST_IDS.text.content)).toHaveStyle({ color: 'red' }); }); + it('Should call replaceVariables with externalStyles css for component', async () => { + const streamSubscribe = jest.fn(() => ({ + unsubscribe: jest.fn(), + })); + + const eventBus = { + getStream: jest.fn(() => ({ + subscribe: streamSubscribe, + })), + }; + + const replaceVariables = jest.fn((str: string) => str); + + const items = [ + { + id: '1', + url: 'https://abc.com/main.js', + }, + { + id: '2', + url: 'https://bbb.com/main.js', + }, + ]; + + await act(async () => + render( + getComponent({ + options: { + ...defaultOptions, + defaultContent: 'hello', + styles: '.styles-test{}; .dt-row{color:red}', + externalStyles: items, + }, + replaceVariables, + data: { series: [] } as any, + eventBus: eventBus as any, + id: 5, + }) + ) + ); + + expect(replaceVariables).toHaveBeenCalledWith('https://abc.com/main.js'); + expect(replaceVariables).toHaveBeenCalledWith('https://bbb.com/main.js'); + expect(replaceVariables).toHaveBeenCalledWith('.styles-test{}; .dt-row{color:red}', { + theme: { value: { color: 'blue' } }, + }); + }); + describe('Helpers execution', () => { const helpers = ` const subscription = context.grafana.eventBus.subscribe('event', () => {}); From e179586b142507aded96093a16620afcc93bd695 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 3 Dec 2024 16:48:25 +0300 Subject: [PATCH 5/9] remove unused imports --- src/components/TextPanel/TextPanel.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextPanel/TextPanel.test.tsx b/src/components/TextPanel/TextPanel.test.tsx index 0177e177..bde066be 100644 --- a/src/components/TextPanel/TextPanel.test.tsx +++ b/src/components/TextPanel/TextPanel.test.tsx @@ -2,7 +2,7 @@ import { FieldType, toDataFrame } from '@grafana/data'; import { RefreshEvent } from '@grafana/runtime'; import { act, fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; -import { useExternalResources } from '../../hooks'; + import { CodeLanguage, Format, TEST_IDS } from '../../constants'; import { PanelOptions, RenderMode } from '../../types'; import { TextPanel } from './TextPanel'; From 63a988d0b1a65953dca4e023e7a4b722d09c524d Mon Sep 17 00:00:00 2001 From: Mikhail Volkov Date: Mon, 9 Dec 2024 11:21:52 -0500 Subject: [PATCH 6/9] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4d0ace..f7688f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Added helper statusColor from specific field (#375) - Updated E2E tests (#377) - Updated to Grafana 11.4 and dependencies (#378) +- Added replace variables in URLs (#376) ## 5.4.0 (2024-09-12) From bd2fc3c099afa760e7ddaffd7622bc3100b27425 Mon Sep 17 00:00:00 2001 From: Mikhail Volkov Date: Mon, 9 Dec 2024 11:30:58 -0500 Subject: [PATCH 7/9] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7688f40..ef140342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 5.5.0 (IN PROGRESS) +## 5.5.0 (2024-12-09) ### Features / Enhancements From bab30e6e6a0dcf4725aabf1c9984c962b432cc61 Mon Sep 17 00:00:00 2001 From: Mikhail Volkov Date: Mon, 9 Dec 2024 11:39:40 -0500 Subject: [PATCH 8/9] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84f2a113..5c77978d 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,8 @@ "lint:fix": "eslint --fix --ignore-path ./.eslintignore --ext .js,.jsx,.ts,.tsx .", "sign": "npx --yes @grafana/sign-plugin@latest", "start": "docker compose pull grafana && docker compose --profile dev up", - "start:main": "docker compose pull grafana-main && docker compose --profile main up", "start:dep": "docker compose pull grafana-dep && docker compose --profile dependency up", + "start:main": "docker compose pull grafana-main && docker compose --profile main up", "stop": "docker compose down", "test": "jest --watch --onlyChanged", "test:ci": "jest --maxWorkers 4 --coverage", From 5af8385098f89c94ab114261d6674f79e39862aa Mon Sep 17 00:00:00 2001 From: Mikhail Volkov Date: Mon, 9 Dec 2024 11:42:48 -0500 Subject: [PATCH 9/9] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d7d9662f..d559ce54 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Text](https://github.com/VolkovLabs/business-text/raw/main/src/img/screenshot.png) -![Grafana](https://img.shields.io/badge/Grafana-11.2-orange) +![Grafana](https://img.shields.io/badge/Grafana-11.4-orange) ![CI](https://github.com/volkovlabs/business-text/workflows/CI/badge.svg) ![E2E](https://github.com/volkovlabs/business-text/workflows/E2E/badge.svg) [![codecov](https://codecov.io/gh/VolkovLabs/business-text/branch/main/graph/badge.svg)](https://codecov.io/gh/VolkovLabs/business-text) @@ -28,9 +28,11 @@ You can install the Business Text panel from the [Grafana Plugins catalog](https For the latter, please use the following command: ```bash -grafana-cli plugins install marcusolsson-dynamictext-panel +grafana cli plugins install marcusolsson-dynamictext-panel ``` +[![Install Business Suite plugins in Cloud, OSS, Enterprise | Open source community plugins](https://raw.githubusercontent.com/volkovlabs/.github/main/started.png)](https://youtu.be/1qYzHfPXJF8) + ## Highlights - Uses Monaco Code Editor with automatic JavaScript code formatting.