diff --git a/.betterer.results b/.betterer.results index d9bb21e6d74..cc1ad31c492 100644 --- a/.betterer.results +++ b/.betterer.results @@ -3409,8 +3409,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "4"], [0, 0, 0, "Do not use any type assertions.", "5"], [0, 0, 0, "Do not use any type assertions.", "6"], - [0, 0, 0, "Unexpected any. Specify a different type.", "7"], - [0, 0, 0, "Unexpected any. Specify a different type.", "8"] + [0, 0, 0, "Unexpected any. Specify a different type.", "7"] ], "public/app/plugins/datasource/graphite/configuration/ConfigEditor.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], diff --git a/devenv/frontend-service/Tiltfile b/devenv/frontend-service/Tiltfile index efb5a9822e4..e5298d96bc7 100644 --- a/devenv/frontend-service/Tiltfile +++ b/devenv/frontend-service/Tiltfile @@ -93,6 +93,8 @@ docker_build('grafana-fs-dev', 'public/dashboards', 'public/app/plugins', 'public/build/assets-manifest.json', + 'public/gazetteer', + 'public/maps', ], # Sync paths are relative to the Tiltfile diff --git a/devenv/frontend-service/grafana-fs-dev.dockerfile b/devenv/frontend-service/grafana-fs-dev.dockerfile index b0d7d7ffd01..32b270c190d 100644 --- a/devenv/frontend-service/grafana-fs-dev.dockerfile +++ b/devenv/frontend-service/grafana-fs-dev.dockerfile @@ -22,9 +22,11 @@ COPY public/emails public/emails COPY public/views public/views COPY public/dashboards public/dashboards COPY public/app/plugins public/app/plugins +COPY public/gazetteer public/gazetteer +COPY public/maps public/maps ADD devenv/frontend-service/build/grafana bin/grafana COPY public/build/assets-manifest.json public/build/assets-manifest.json -ENTRYPOINT ["bin/grafana", "server"] \ No newline at end of file +ENTRYPOINT ["bin/grafana", "server"] diff --git a/public/app/features/geo/gazetteer/gazetteer.test.ts b/public/app/features/geo/gazetteer/gazetteer.test.ts index 8aa840ccdeb..7bd25dc454d 100644 --- a/public/app/features/geo/gazetteer/gazetteer.test.ts +++ b/public/app/features/geo/gazetteer/gazetteer.test.ts @@ -2,8 +2,6 @@ import { getCenterPointWGS84 } from 'app/features/transformers/spatial/utils'; import { getGazetteer } from './gazetteer'; -let backendResults: Record = { hello: 'world' }; - const geojsonObject = { type: 'FeatureCollection', features: [ @@ -43,20 +41,16 @@ const geojsonObject = { ], }; -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getBackendSrv: () => ({ - get: jest.fn().mockResolvedValue(backendResults), - }), -})); - describe('Placename lookup from geojson format', () => { beforeEach(() => { - backendResults = { hello: 'world' }; + jest.spyOn(global, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + json: jest.fn().mockResolvedValue(geojsonObject), + } as unknown as Response); }); it('can lookup by id', async () => { - backendResults = geojsonObject; const gaz = await getGazetteer('local'); expect(gaz.error).toBeUndefined(); expect(getCenterPointWGS84(gaz.find('A')?.geometry())).toMatchInlineSnapshot(` @@ -67,7 +61,6 @@ describe('Placename lookup from geojson format', () => { `); }); it('can look up by a code', async () => { - backendResults = geojsonObject; const gaz = await getGazetteer('airports'); expect(gaz.error).toBeUndefined(); expect(getCenterPointWGS84(gaz.find('B')?.geometry())).toMatchInlineSnapshot(` @@ -79,7 +72,6 @@ describe('Placename lookup from geojson format', () => { }); it('can look up by an id property', async () => { - backendResults = geojsonObject; const gaz = await getGazetteer('airports'); expect(gaz.error).toBeUndefined(); expect(getCenterPointWGS84(gaz.find('C')?.geometry())).toMatchInlineSnapshot(` diff --git a/public/app/features/geo/gazetteer/gazetteer.ts b/public/app/features/geo/gazetteer/gazetteer.ts index e9c12af892b..7dc88f39000 100644 --- a/public/app/features/geo/gazetteer/gazetteer.ts +++ b/public/app/features/geo/gazetteer/gazetteer.ts @@ -2,7 +2,6 @@ import { getCenter } from 'ol/extent'; import { Geometry, Point } from 'ol/geom'; import { DataFrame, Field, FieldType, KeyValue, toDataFrame } from '@grafana/data'; -import { getBackendSrv } from '@grafana/runtime'; import { frameFromGeoJSON } from '../format/geojson'; import { pointFieldFromLonLat, pointFieldFromGeohash } from '../format/utils'; @@ -181,7 +180,7 @@ export function frameAsGazetter(frame: DataFrame, opts: { path: string; keys?: s const registry: KeyValue = {}; -export const COUNTRIES_GAZETTEER_PATH = 'public/gazetteer/countries.json'; +export const COUNTRIES_GAZETTEER_PATH = `${window.__grafana_public_path__}build/gazetteer/countries.json`; /** * Given a path to a file return a cached lookup function @@ -196,7 +195,8 @@ export async function getGazetteer(path?: string): Promise { if (!lookup) { try { // block the async function - const data = await getBackendSrv().get(path!); + const response = await fetch(path); + const data = await response.json(); lookup = loadGazetteer(path, data); } catch (err) { console.warn('Error loading placename lookup', path, err); diff --git a/public/app/features/geo/gazetteer/worldmap.test.ts b/public/app/features/geo/gazetteer/worldmap.test.ts index 127f63a40b0..b5fae94e7f7 100644 --- a/public/app/features/geo/gazetteer/worldmap.test.ts +++ b/public/app/features/geo/gazetteer/worldmap.test.ts @@ -4,22 +4,18 @@ import countriesJSON from '../../../../gazetteer/countries.json'; import { getGazetteer } from './gazetteer'; -let backendResults: Record | Array> = { hello: 'world' }; - -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getBackendSrv: () => ({ - get: jest.fn().mockResolvedValue(backendResults), - }), -})); +const backendResults: Record | Array> = countriesJSON; describe('Placename lookup from worldmap format', () => { beforeEach(() => { - backendResults = { hello: 'world' }; + jest.spyOn(global, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + json: jest.fn().mockResolvedValue(backendResults), + } as unknown as Response); }); it('unified worldmap config', async () => { - backendResults = countriesJSON; const gaz = await getGazetteer('countries'); expect(gaz.error).toBeUndefined(); expect(toLonLat(gaz.find('US')?.point()?.getCoordinates()!)).toMatchInlineSnapshot(` diff --git a/public/app/features/geo/utils/location.test.ts b/public/app/features/geo/utils/location.test.ts index ccc22978b71..dfdf62e7038 100644 --- a/public/app/features/geo/utils/location.test.ts +++ b/public/app/features/geo/utils/location.test.ts @@ -10,10 +10,53 @@ const longitude = [0, -74.1]; const latitude = [0, 40.7]; const geohash = ['9q94r', 'dr5rs']; const names = ['A', 'B']; +const geojsonObject = { + type: 'FeatureCollection', + features: [ + { + id: 'A', + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 0], + }, + properties: { + hello: 'A', + }, + }, + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [1, 1], + }, + properties: { + some_code: 'B', + hello: 'B', + }, + }, + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [2, 2], + }, + properties: { + an_id: 'C', + hello: 'C', + }, + }, + ], +}; describe('handle location parsing', () => { beforeEach(() => { jest.spyOn(console, 'warn').mockImplementation(); + jest.spyOn(global, 'fetch').mockResolvedValue({ + ok: true, + status: 200, + json: jest.fn().mockResolvedValue(geojsonObject), + } as unknown as Response); }); it('auto should find geohash field', async () => { diff --git a/public/app/plugins/datasource/grafana/datasource.ts b/public/app/plugins/datasource/grafana/datasource.ts index 02216e02f73..9c8af582ddb 100644 --- a/public/app/plugins/datasource/grafana/datasource.ts +++ b/public/app/plugins/datasource/grafana/datasource.ts @@ -180,7 +180,7 @@ export class GrafanaDatasource extends DataSourceWithBackend { }, ], maxDataPoints, - } as any).pipe( + } as DataQueryRequest).pipe( map((v) => { const frame = v.data[0] ?? new MutableDataFrame(); return new DataFrameView(frame); diff --git a/public/app/plugins/panel/geomap/GeomapPanel.tsx b/public/app/plugins/panel/geomap/GeomapPanel.tsx index 6984228c6f7..eb7d7c7dad4 100644 --- a/public/app/plugins/panel/geomap/GeomapPanel.tsx +++ b/public/app/plugins/panel/geomap/GeomapPanel.tsx @@ -394,7 +394,7 @@ export class GeomapPanel extends Component { ); } - this.mouseWheelZoom!.setActive(Boolean(options.mouseWheelZoom)); + this.mouseWheelZoom?.setActive(Boolean(options.mouseWheelZoom)); if (options.showAttribution) { this.map.addControl(new Attribution({ collapsed: true, collapsible: true })); diff --git a/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts b/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts index b5d0a6da133..be427994830 100644 --- a/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts +++ b/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts @@ -80,7 +80,7 @@ export const geojsonLayer: MapLayerRegistryItem = { const interpolatedUrl = getTemplateSrv().replace(config.src || ''); const source = new VectorSource({ - url: interpolatedUrl, + url: `${window.__grafana_public_path__}build/${interpolatedUrl.replace(/^(public\/)/, '')}`, format: new GeoJSON(), }); diff --git a/public/app/plugins/panel/geomap/migrations.test.ts b/public/app/plugins/panel/geomap/migrations.test.ts index 6cf672211dd..b37cbcf7ec5 100644 --- a/public/app/plugins/panel/geomap/migrations.test.ts +++ b/public/app/plugins/panel/geomap/migrations.test.ts @@ -76,7 +76,7 @@ describe('Worldmap Migrations', () => { "min": 2, }, "symbol": { - "fixed": "img/icons/marker/circle.svg", + "fixed": "build/img/icons/marker/circle.svg", "mode": "fixed", }, "symbolAlign": { diff --git a/public/app/plugins/panel/geomap/style/types.ts b/public/app/plugins/panel/geomap/style/types.ts index 72703a90476..de8cf8008e0 100644 --- a/public/app/plugins/panel/geomap/style/types.ts +++ b/public/app/plugins/panel/geomap/style/types.ts @@ -74,7 +74,7 @@ export const defaultStyleConfig = Object.freeze({ opacity: 0.4, symbol: { mode: ResourceDimensionMode.Fixed, - fixed: 'img/icons/marker/circle.svg', + fixed: 'build/img/icons/marker/circle.svg', }, symbolAlign: { horizontal: HorizontalAlign.Center, diff --git a/scripts/webpack/webpack.common.js b/scripts/webpack/webpack.common.js index 67ec6606aa2..e694b812100 100644 --- a/scripts/webpack/webpack.common.js +++ b/scripts/webpack/webpack.common.js @@ -75,6 +75,14 @@ module.exports = { from: 'public/img', to: 'img', }, + { + from: 'public/maps', + to: 'maps', + }, + { + from: 'public/gazetteer', + to: 'gazetteer', + }, ], }), ],