diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a32529627e0..75a32514213 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -618,7 +618,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /scripts/trigger_windows_build.sh @grafana/grafana-developer-enablement-squad /scripts/cleanup-husky.sh @grafana/frontend-ops /scripts/verify-repo-update/ @grafana/grafana-developer-enablement-squad -/scripts/generate-icon-bundle.js @grafana/plugins-platform-frontend @grafana/grafana-frontend-platform /scripts/generate-rtk-apis.ts @grafana/grafana-frontend-platform /scripts/generate-alerting-rtk-apis.ts @grafana/alerting-frontend /scripts/levitate-parse-json-report.js @grafana/plugins-platform-frontend diff --git a/package.json b/package.json index 5981f55e46d..ae08163634a 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "betterer:merge": "betterer merge --tsconfig ./scripts/cli/tsconfig.json", "betterer:stats": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/reportBettererStats.ts", "betterer:issues": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/generateBettererIssues.ts", - "generate-icons-bundle-cache-file": "node ./scripts/generate-icon-bundle.js", "plugin:build": "nx run-many -t build --projects='tag:scope:plugin'", "plugin:build:commit": "nx run-many -t build:commit --projects='tag:scope:plugin'", "plugin:build:dev": "nx run-many -t dev --projects='tag:scope:plugin' --maxParallel=100", @@ -377,7 +376,7 @@ "react-highlight-words": "0.20.0", "react-hook-form": "^7.49.2", "react-i18next": "^14.0.0", - "react-inlinesvg": "3.0.2", + "react-inlinesvg": "4.1.5", "react-loading-skeleton": "3.5.0", "react-moveable": "0.56.0", "react-redux": "9.1.2", diff --git a/packages/grafana-ui/.storybook/main.ts b/packages/grafana-ui/.storybook/main.ts index 6314014c9f9..5b169002dc9 100644 --- a/packages/grafana-ui/.storybook/main.ts +++ b/packages/grafana-ui/.storybook/main.ts @@ -87,12 +87,6 @@ const mainConfig: StorybookConfig = { }, }); - // use the asset module for SVGS for compatibility with grafana/ui Icon component. - config.module?.rules?.push({ - test: /(unicons|mono|custom)[\\/].*\.svg$/, - type: 'asset/source', - }); - return config; }, }; diff --git a/packages/grafana-ui/.storybook/storybookTheme.ts b/packages/grafana-ui/.storybook/storybookTheme.ts index debe4713bf7..32649630d9f 100644 --- a/packages/grafana-ui/.storybook/storybookTheme.ts +++ b/packages/grafana-ui/.storybook/storybookTheme.ts @@ -1,7 +1,6 @@ import { GrafanaTheme2, createTheme } from '@grafana/data'; //@ts-ignore import { create } from '@storybook/theming'; -import '../../../public/app/core/icons/iconBundle'; const createStorybookTheme = (theme: GrafanaTheme2) => { return create({ diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index ce04c95e188..665db5f4d5f 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -38,7 +38,6 @@ "storybook": "storybook dev -p 9001 -c .storybook --no-open", "storybook:build": "storybook build -o ./dist/storybook -c .storybook", "typecheck": "tsc --emitDeclarationOnly false --noEmit", - "generate-icons-bundle-cache-file": "node ./scripts/generate-icon-bundle.js", "prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js", "postpack": "mv package.json.bak package.json" }, @@ -96,7 +95,7 @@ "react-highlight-words": "0.20.0", "react-hook-form": "^7.49.2", "react-i18next": "^14.0.0", - "react-inlinesvg": "3.0.2", + "react-inlinesvg": "4.1.5", "react-loading-skeleton": "3.5.0", "react-router-dom-v5-compat": "^6.26.1", "react-select": "5.8.3", diff --git a/packages/grafana-ui/src/components/Icon/Icon.tsx b/packages/grafana-ui/src/components/Icon/Icon.tsx index d760c3a3185..f961cafcc14 100644 --- a/packages/grafana-ui/src/components/Icon/Icon.tsx +++ b/packages/grafana-ui/src/components/Icon/Icon.tsx @@ -85,6 +85,20 @@ export const Icon = React.forwardRef( title={title} className={composedClassName} style={style} + // render an empty div with the correct dimensions while loading + // this prevents content layout shift whilst the icon asynchronously loads + // which happens even if the icon is in the cache(!) + loader={ +
+ } {...rest} /> ); diff --git a/public/app/AppWrapper.tsx b/public/app/AppWrapper.tsx index 570d2d97756..04c8fb80615 100644 --- a/public/app/AppWrapper.tsx +++ b/public/app/AppWrapper.tsx @@ -1,5 +1,6 @@ import { Action, KBarProvider } from 'kbar'; import { Component, ComponentType, Fragment } from 'react'; +import CacheProvider from 'react-inlinesvg/provider'; import { Provider } from 'react-redux'; import { Route, Routes } from 'react-router-dom-v5-compat'; @@ -46,6 +47,8 @@ export function addPageBanner(fn: ComponentType) { } export class AppWrapper extends Component { + private iconCacheID = `grafana-icon-cache-${config.buildInfo.commit}`; + constructor(props: AppWrapperProps) { super(props); this.state = {}; @@ -55,6 +58,14 @@ export class AppWrapper extends Component { await loadAndInitAngularIfEnabled(); this.setState({ ready: true }); $('.preloader').remove(); + + // clear any old icon caches + const cacheKeys = await window.caches.keys(); + for (const key of cacheKeys) { + if (key.startsWith('grafana-icon-cache') && key !== this.iconCacheID) { + window.caches.delete(key); + } + } } renderRoute = (route: RouteDescriptor) => { @@ -98,27 +109,29 @@ export class AppWrapper extends Component { - - - - - -
- {config.featureToggles.appSidecar ? ( - - ) : ( - - )} - - -
-
-
-
-
+ + + + + + +
+ {config.featureToggles.appSidecar ? ( + + ) : ( + + )} + + +
+
+
+
+
+
diff --git a/public/app/app.ts b/public/app/app.ts index 556952c0775..17ba4c04d73 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -57,7 +57,6 @@ import { getAllOptionEditors, getAllStandardFieldConfigs } from './core/componen import { PluginPage } from './core/components/Page/PluginPage'; import { GrafanaContextType, useChromeHeaderHeight, useReturnToPreviousInternal } from './core/context/GrafanaContext'; import { initializeCrashDetection } from './core/crash'; -import { initIconCache } from './core/icons/iconBundle'; import { initializeI18n } from './core/internationalization'; import { setMonacoEnv } from './core/monacoEnv'; import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks'; @@ -138,7 +137,6 @@ export class GrafanaApp { setBackendSrv(backendSrv); initEchoSrv(); - initIconCache(); // This needs to be done after the `initEchoSrv` since it is being used under the hood. startMeasure('frontend_app_init'); diff --git a/public/app/core/icons/iconBundle.ts b/public/app/core/icons/iconBundle.ts deleted file mode 100644 index 54485041685..00000000000 --- a/public/app/core/icons/iconBundle.ts +++ /dev/null @@ -1,395 +0,0 @@ -/* eslint-disable import/order */ -// DO NOT EDIT THIS FILE -// This file is automatically generated (do not edit it here) -// see @grafana/ui/scripts/generate-icon-bundle.js - -import { cacheStore } from 'react-inlinesvg'; - -// do not edit this list directly -// the list of icons live here: @grafana/ui/components/Icon/cached.json -import u1000 from '../../../img/icons/unicons/at.svg'; -import u1001 from '../../../img/icons/unicons/adjust-circle.svg'; -import u1002 from '../../../img/icons/unicons/align-left.svg'; -import u1003 from '../../../img/icons/unicons/align-right.svg'; -import u1004 from '../../../img/icons/unicons/angle-double-down.svg'; -import u1005 from '../../../img/icons/unicons/angle-double-right.svg'; -import u1006 from '../../../img/icons/unicons/angle-down.svg'; -import u1007 from '../../../img/icons/unicons/angle-left.svg'; -import u1008 from '../../../img/icons/unicons/angle-right.svg'; -import u1009 from '../../../img/icons/unicons/angle-up.svg'; -import u1010 from '../../../img/icons/unicons/apps.svg'; -import u1011 from '../../../img/icons/unicons/arrow.svg'; -import u1012 from '../../../img/icons/unicons/arrow-down.svg'; -import u1013 from '../../../img/icons/unicons/arrow-from-right.svg'; -import u1014 from '../../../img/icons/unicons/arrow-left.svg'; -import u1015 from '../../../img/icons/unicons/arrow-random.svg'; -import u1016 from '../../../img/icons/unicons/arrow-right.svg'; -import u1017 from '../../../img/icons/unicons/arrow-to-right.svg'; -import u1018 from '../../../img/icons/unicons/arrow-up.svg'; -import u1019 from '../../../img/icons/unicons/arrows-h.svg'; -import u1020 from '../../../img/icons/unicons/backward.svg'; -import u1021 from '../../../img/icons/unicons/bars.svg'; -import u1022 from '../../../img/icons/unicons/bell.svg'; -import u1023 from '../../../img/icons/unicons/bell-slash.svg'; -import u1024 from '../../../img/icons/unicons/bolt.svg'; -import u1025 from '../../../img/icons/unicons/book.svg'; -import u1026 from '../../../img/icons/unicons/bookmark.svg'; -import u1027 from '../../../img/icons/unicons/book-open.svg'; -import u1028 from '../../../img/icons/unicons/brackets-curly.svg'; -import u1029 from '../../../img/icons/unicons/bug.svg'; -import u1030 from '../../../img/icons/unicons/building.svg'; -import u1031 from '../../../img/icons/unicons/calculator-alt.svg'; -import u1032 from '../../../img/icons/unicons/calendar-alt.svg'; -import u1033 from '../../../img/icons/unicons/calendar-slash.svg'; -import u1034 from '../../../img/icons/unicons/camera.svg'; -import u1035 from '../../../img/icons/unicons/channel-add.svg'; -import u1036 from '../../../img/icons/unicons/chart-line.svg'; -import u1037 from '../../../img/icons/unicons/check.svg'; -import u1038 from '../../../img/icons/unicons/check-circle.svg'; -import u1039 from '../../../img/icons/unicons/times-circle.svg'; -import u1040 from '../../../img/icons/unicons/circle.svg'; -import u1041 from '../../../img/icons/unicons/clipboard-alt.svg'; -import u1042 from '../../../img/icons/unicons/clock-nine.svg'; -import u1043 from '../../../img/icons/unicons/cloud.svg'; -import u1044 from '../../../img/icons/unicons/cloud-download.svg'; -import u1045 from '../../../img/icons/unicons/code-branch.svg'; -import u1046 from '../../../img/icons/unicons/cog.svg'; -import u1047 from '../../../img/icons/unicons/columns.svg'; -import u1048 from '../../../img/icons/unicons/comment-alt.svg'; -import u1049 from '../../../img/icons/unicons/comment-alt-share.svg'; -import u1050 from '../../../img/icons/unicons/comments-alt.svg'; -import u1051 from '../../../img/icons/unicons/compass.svg'; -import u1052 from '../../../img/icons/unicons/copy.svg'; -import u1053 from '../../../img/icons/unicons/corner-down-right-alt.svg'; -import u1054 from '../../../img/icons/unicons/cube.svg'; -import u1055 from '../../../img/icons/unicons/dashboard.svg'; -import u1056 from '../../../img/icons/unicons/database.svg'; -import u1057 from '../../../img/icons/unicons/document-info.svg'; -import u1058 from '../../../img/icons/unicons/download-alt.svg'; -import u1059 from '../../../img/icons/unicons/draggabledots.svg'; -import u1060 from '../../../img/icons/unicons/edit.svg'; -import u1061 from '../../../img/icons/unicons/ellipsis-v.svg'; -import u1062 from '../../../img/icons/unicons/ellipsis-h.svg'; -import u1063 from '../../../img/icons/unicons/envelope.svg'; -import u1064 from '../../../img/icons/unicons/exchange-alt.svg'; -import u1065 from '../../../img/icons/unicons/exclamation-circle.svg'; -import u1066 from '../../../img/icons/unicons/exclamation-triangle.svg'; -import u1067 from '../../../img/icons/unicons/external-link-alt.svg'; -import u1068 from '../../../img/icons/unicons/eye.svg'; -import u1069 from '../../../img/icons/unicons/eye-slash.svg'; -import u1070 from '../../../img/icons/unicons/file-alt.svg'; -import u1071 from '../../../img/icons/unicons/file-blank.svg'; -import u1072 from '../../../img/icons/unicons/filter.svg'; -import u1073 from '../../../img/icons/unicons/folder.svg'; -import u1074 from '../../../img/icons/unicons/folder-open.svg'; -import u1075 from '../../../img/icons/unicons/folder-plus.svg'; -import u1076 from '../../../img/icons/unicons/folder-upload.svg'; -import u1077 from '../../../img/icons/unicons/forward.svg'; -import u1078 from '../../../img/icons/unicons/graph-bar.svg'; -import u1079 from '../../../img/icons/unicons/history.svg'; -import u1080 from '../../../img/icons/unicons/history-alt.svg'; -import u1081 from '../../../img/icons/unicons/home-alt.svg'; -import u1082 from '../../../img/icons/unicons/import.svg'; -import u1083 from '../../../img/icons/unicons/info.svg'; -import u1084 from '../../../img/icons/unicons/info-circle.svg'; -import u1085 from '../../../img/icons/unicons/k6.svg'; -import u1086 from '../../../img/icons/unicons/key-skeleton-alt.svg'; -import u1087 from '../../../img/icons/unicons/keyboard.svg'; -import u1088 from '../../../img/icons/unicons/link.svg'; -import u1089 from '../../../img/icons/unicons/list-ul.svg'; -import u1090 from '../../../img/icons/unicons/lock.svg'; -import u1091 from '../../../img/icons/unicons/minus.svg'; -import u1092 from '../../../img/icons/unicons/minus-circle.svg'; -import u1093 from '../../../img/icons/unicons/mobile-android.svg'; -import u1094 from '../../../img/icons/unicons/monitor.svg'; -import u1095 from '../../../img/icons/unicons/pause.svg'; -import u1096 from '../../../img/icons/unicons/pen.svg'; -import u1097 from '../../../img/icons/unicons/play.svg'; -import u1098 from '../../../img/icons/unicons/plug.svg'; -import u1099 from '../../../img/icons/unicons/plus.svg'; -import u1100 from '../../../img/icons/unicons/plus-circle.svg'; -import u1101 from '../../../img/icons/unicons/power.svg'; -import u1102 from '../../../img/icons/unicons/presentation-play.svg'; -import u1103 from '../../../img/icons/unicons/process.svg'; -import u1104 from '../../../img/icons/unicons/question-circle.svg'; -import u1105 from '../../../img/icons/unicons/repeat.svg'; -import u1106 from '../../../img/icons/unicons/rocket.svg'; -import u1107 from '../../../img/icons/unicons/rss.svg'; -import u1108 from '../../../img/icons/unicons/save.svg'; -import u1109 from '../../../img/icons/unicons/search.svg'; -import u1110 from '../../../img/icons/unicons/search-minus.svg'; -import u1111 from '../../../img/icons/unicons/search-plus.svg'; -import u1112 from '../../../img/icons/unicons/share-alt.svg'; -import u1113 from '../../../img/icons/unicons/shield.svg'; -import u1114 from '../../../img/icons/unicons/signal.svg'; -import u1115 from '../../../img/icons/unicons/signin.svg'; -import u1116 from '../../../img/icons/unicons/signout.svg'; -import u1117 from '../../../img/icons/unicons/sitemap.svg'; -import u1118 from '../../../img/icons/unicons/slack.svg'; -import u1119 from '../../../img/icons/unicons/sliders-v-alt.svg'; -import u1120 from '../../../img/icons/unicons/sort-amount-down.svg'; -import u1121 from '../../../img/icons/unicons/sort-amount-up.svg'; -import u1122 from '../../../img/icons/unicons/square-shape.svg'; -import u1123 from '../../../img/icons/unicons/star.svg'; -import u1124 from '../../../img/icons/unicons/step-backward.svg'; -import u1125 from '../../../img/icons/unicons/sync.svg'; -import u1126 from '../../../img/icons/unicons/stopwatch.svg'; -import u1127 from '../../../img/icons/unicons/table.svg'; -import u1128 from '../../../img/icons/unicons/tag-alt.svg'; -import u1129 from '../../../img/icons/unicons/times.svg'; -import u1130 from '../../../img/icons/unicons/trash-alt.svg'; -import u1131 from '../../../img/icons/unicons/unlock.svg'; -import u1132 from '../../../img/icons/unicons/upload.svg'; -import u1133 from '../../../img/icons/unicons/user.svg'; -import u1134 from '../../../img/icons/unicons/users-alt.svg'; -import u1135 from '../../../img/icons/unicons/wrap-text.svg'; -import u1136 from '../../../img/icons/unicons/cloud-upload.svg'; -import u1137 from '../../../img/icons/unicons/credit-card.svg'; -import u1138 from '../../../img/icons/unicons/file-copy-alt.svg'; -import u1139 from '../../../img/icons/unicons/fire.svg'; -import u1140 from '../../../img/icons/unicons/hourglass.svg'; -import u1141 from '../../../img/icons/unicons/layer-group.svg'; -import u1142 from '../../../img/icons/unicons/layers-alt.svg'; -import u1143 from '../../../img/icons/unicons/line-alt.svg'; -import u1144 from '../../../img/icons/unicons/list-ui-alt.svg'; -import u1145 from '../../../img/icons/unicons/message.svg'; -import u1146 from '../../../img/icons/unicons/palette.svg'; -import u1147 from '../../../img/icons/unicons/percentage.svg'; -import u1148 from '../../../img/icons/unicons/shield-exclamation.svg'; -import u1149 from '../../../img/icons/unicons/plus-square.svg'; -import u1150 from '../../../img/icons/unicons/x.svg'; -import u1151 from '../../../img/icons/unicons/capture.svg'; -import u1152 from '../../../img/icons/custom/gf-grid.svg'; -import u1153 from '../../../img/icons/custom/gf-landscape.svg'; -import u1154 from '../../../img/icons/custom/gf-layout-simple.svg'; -import u1155 from '../../../img/icons/custom/gf-portrait.svg'; -import u1156 from '../../../img/icons/custom/gf-show-context.svg'; -import u1157 from '../../../img/icons/custom/gf-bar-alignment-after.svg'; -import u1158 from '../../../img/icons/custom/gf-bar-alignment-before.svg'; -import u1159 from '../../../img/icons/custom/gf-bar-alignment-center.svg'; -import u1160 from '../../../img/icons/custom/gf-interpolation-linear.svg'; -import u1161 from '../../../img/icons/custom/gf-interpolation-smooth.svg'; -import u1162 from '../../../img/icons/custom/gf-interpolation-step-after.svg'; -import u1163 from '../../../img/icons/custom/gf-interpolation-step-before.svg'; -import u1164 from '../../../img/icons/custom/gf-logs.svg'; -import u1165 from '../../../img/icons/custom/gf-movepane-left.svg'; -import u1166 from '../../../img/icons/custom/gf-movepane-right.svg'; -import u1167 from '../../../img/icons/mono/favorite.svg'; -import u1168 from '../../../img/icons/mono/grafana.svg'; -import u1169 from '../../../img/icons/mono/heart.svg'; -import u1170 from '../../../img/icons/mono/heart-break.svg'; -import u1171 from '../../../img/icons/mono/panel-add.svg'; -import u1172 from '../../../img/icons/mono/library-panel.svg'; -import u1173 from '../../../img/icons/unicons/record-audio.svg'; -import u1174 from '../../../img/icons/solid/bookmark.svg'; -// do not edit this list directly -// the list of icons live here: @grafana/ui/components/Icon/cached.json - -let cacheInitialized = false; - -function cacheItem(content: string, path: string) { - cacheStore[path] = { content, status: 'loaded' }; -} - -function createPathResolver() { - let root = 'public/img/icons/'; - - // This function needs to be called after index.js loads to give the - // application time to modify __webpack_public_path__ with a CDN path - const grafanaPublicPath = typeof window !== 'undefined' && window.__grafana_public_path__; - if (grafanaPublicPath) { - root = grafanaPublicPath + 'img/icons/'; - } - - return (path: string) => { - return root + path; - }; -} - -export function initIconCache() { - if (cacheInitialized) { - return; - } - cacheInitialized = true; - const resolvePath = createPathResolver(); - - // do not edit this list directly - // the list of icons live here: @grafana/ui/components/Icon/cached.json - cacheItem(u1000, resolvePath('unicons/at.svg')); - cacheItem(u1001, resolvePath('unicons/adjust-circle.svg')); - cacheItem(u1002, resolvePath('unicons/align-left.svg')); - cacheItem(u1003, resolvePath('unicons/align-right.svg')); - cacheItem(u1004, resolvePath('unicons/angle-double-down.svg')); - cacheItem(u1005, resolvePath('unicons/angle-double-right.svg')); - cacheItem(u1006, resolvePath('unicons/angle-down.svg')); - cacheItem(u1007, resolvePath('unicons/angle-left.svg')); - cacheItem(u1008, resolvePath('unicons/angle-right.svg')); - cacheItem(u1009, resolvePath('unicons/angle-up.svg')); - cacheItem(u1010, resolvePath('unicons/apps.svg')); - cacheItem(u1011, resolvePath('unicons/arrow.svg')); - cacheItem(u1012, resolvePath('unicons/arrow-down.svg')); - cacheItem(u1013, resolvePath('unicons/arrow-from-right.svg')); - cacheItem(u1014, resolvePath('unicons/arrow-left.svg')); - cacheItem(u1015, resolvePath('unicons/arrow-random.svg')); - cacheItem(u1016, resolvePath('unicons/arrow-right.svg')); - cacheItem(u1017, resolvePath('unicons/arrow-to-right.svg')); - cacheItem(u1018, resolvePath('unicons/arrow-up.svg')); - cacheItem(u1019, resolvePath('unicons/arrows-h.svg')); - cacheItem(u1020, resolvePath('unicons/backward.svg')); - cacheItem(u1021, resolvePath('unicons/bars.svg')); - cacheItem(u1022, resolvePath('unicons/bell.svg')); - cacheItem(u1023, resolvePath('unicons/bell-slash.svg')); - cacheItem(u1024, resolvePath('unicons/bolt.svg')); - cacheItem(u1025, resolvePath('unicons/book.svg')); - cacheItem(u1026, resolvePath('unicons/bookmark.svg')); - cacheItem(u1027, resolvePath('unicons/book-open.svg')); - cacheItem(u1028, resolvePath('unicons/brackets-curly.svg')); - cacheItem(u1029, resolvePath('unicons/bug.svg')); - cacheItem(u1030, resolvePath('unicons/building.svg')); - cacheItem(u1031, resolvePath('unicons/calculator-alt.svg')); - cacheItem(u1032, resolvePath('unicons/calendar-alt.svg')); - cacheItem(u1033, resolvePath('unicons/calendar-slash.svg')); - cacheItem(u1034, resolvePath('unicons/camera.svg')); - cacheItem(u1035, resolvePath('unicons/channel-add.svg')); - cacheItem(u1036, resolvePath('unicons/chart-line.svg')); - cacheItem(u1037, resolvePath('unicons/check.svg')); - cacheItem(u1038, resolvePath('unicons/check-circle.svg')); - cacheItem(u1039, resolvePath('unicons/times-circle.svg')); - cacheItem(u1040, resolvePath('unicons/circle.svg')); - cacheItem(u1041, resolvePath('unicons/clipboard-alt.svg')); - cacheItem(u1042, resolvePath('unicons/clock-nine.svg')); - cacheItem(u1043, resolvePath('unicons/cloud.svg')); - cacheItem(u1044, resolvePath('unicons/cloud-download.svg')); - cacheItem(u1045, resolvePath('unicons/code-branch.svg')); - cacheItem(u1046, resolvePath('unicons/cog.svg')); - cacheItem(u1047, resolvePath('unicons/columns.svg')); - cacheItem(u1048, resolvePath('unicons/comment-alt.svg')); - cacheItem(u1049, resolvePath('unicons/comment-alt-share.svg')); - cacheItem(u1050, resolvePath('unicons/comments-alt.svg')); - cacheItem(u1051, resolvePath('unicons/compass.svg')); - cacheItem(u1052, resolvePath('unicons/copy.svg')); - cacheItem(u1053, resolvePath('unicons/corner-down-right-alt.svg')); - cacheItem(u1054, resolvePath('unicons/cube.svg')); - cacheItem(u1055, resolvePath('unicons/dashboard.svg')); - cacheItem(u1056, resolvePath('unicons/database.svg')); - cacheItem(u1057, resolvePath('unicons/document-info.svg')); - cacheItem(u1058, resolvePath('unicons/download-alt.svg')); - cacheItem(u1059, resolvePath('unicons/draggabledots.svg')); - cacheItem(u1060, resolvePath('unicons/edit.svg')); - cacheItem(u1061, resolvePath('unicons/ellipsis-v.svg')); - cacheItem(u1062, resolvePath('unicons/ellipsis-h.svg')); - cacheItem(u1063, resolvePath('unicons/envelope.svg')); - cacheItem(u1064, resolvePath('unicons/exchange-alt.svg')); - cacheItem(u1065, resolvePath('unicons/exclamation-circle.svg')); - cacheItem(u1066, resolvePath('unicons/exclamation-triangle.svg')); - cacheItem(u1067, resolvePath('unicons/external-link-alt.svg')); - cacheItem(u1068, resolvePath('unicons/eye.svg')); - cacheItem(u1069, resolvePath('unicons/eye-slash.svg')); - cacheItem(u1070, resolvePath('unicons/file-alt.svg')); - cacheItem(u1071, resolvePath('unicons/file-blank.svg')); - cacheItem(u1072, resolvePath('unicons/filter.svg')); - cacheItem(u1073, resolvePath('unicons/folder.svg')); - cacheItem(u1074, resolvePath('unicons/folder-open.svg')); - cacheItem(u1075, resolvePath('unicons/folder-plus.svg')); - cacheItem(u1076, resolvePath('unicons/folder-upload.svg')); - cacheItem(u1077, resolvePath('unicons/forward.svg')); - cacheItem(u1078, resolvePath('unicons/graph-bar.svg')); - cacheItem(u1079, resolvePath('unicons/history.svg')); - cacheItem(u1080, resolvePath('unicons/history-alt.svg')); - cacheItem(u1081, resolvePath('unicons/home-alt.svg')); - cacheItem(u1082, resolvePath('unicons/import.svg')); - cacheItem(u1083, resolvePath('unicons/info.svg')); - cacheItem(u1084, resolvePath('unicons/info-circle.svg')); - cacheItem(u1085, resolvePath('unicons/k6.svg')); - cacheItem(u1086, resolvePath('unicons/key-skeleton-alt.svg')); - cacheItem(u1087, resolvePath('unicons/keyboard.svg')); - cacheItem(u1088, resolvePath('unicons/link.svg')); - cacheItem(u1089, resolvePath('unicons/list-ul.svg')); - cacheItem(u1090, resolvePath('unicons/lock.svg')); - cacheItem(u1091, resolvePath('unicons/minus.svg')); - cacheItem(u1092, resolvePath('unicons/minus-circle.svg')); - cacheItem(u1093, resolvePath('unicons/mobile-android.svg')); - cacheItem(u1094, resolvePath('unicons/monitor.svg')); - cacheItem(u1095, resolvePath('unicons/pause.svg')); - cacheItem(u1096, resolvePath('unicons/pen.svg')); - cacheItem(u1097, resolvePath('unicons/play.svg')); - cacheItem(u1098, resolvePath('unicons/plug.svg')); - cacheItem(u1099, resolvePath('unicons/plus.svg')); - cacheItem(u1100, resolvePath('unicons/plus-circle.svg')); - cacheItem(u1101, resolvePath('unicons/power.svg')); - cacheItem(u1102, resolvePath('unicons/presentation-play.svg')); - cacheItem(u1103, resolvePath('unicons/process.svg')); - cacheItem(u1104, resolvePath('unicons/question-circle.svg')); - cacheItem(u1105, resolvePath('unicons/repeat.svg')); - cacheItem(u1106, resolvePath('unicons/rocket.svg')); - cacheItem(u1107, resolvePath('unicons/rss.svg')); - cacheItem(u1108, resolvePath('unicons/save.svg')); - cacheItem(u1109, resolvePath('unicons/search.svg')); - cacheItem(u1110, resolvePath('unicons/search-minus.svg')); - cacheItem(u1111, resolvePath('unicons/search-plus.svg')); - cacheItem(u1112, resolvePath('unicons/share-alt.svg')); - cacheItem(u1113, resolvePath('unicons/shield.svg')); - cacheItem(u1114, resolvePath('unicons/signal.svg')); - cacheItem(u1115, resolvePath('unicons/signin.svg')); - cacheItem(u1116, resolvePath('unicons/signout.svg')); - cacheItem(u1117, resolvePath('unicons/sitemap.svg')); - cacheItem(u1118, resolvePath('unicons/slack.svg')); - cacheItem(u1119, resolvePath('unicons/sliders-v-alt.svg')); - cacheItem(u1120, resolvePath('unicons/sort-amount-down.svg')); - cacheItem(u1121, resolvePath('unicons/sort-amount-up.svg')); - cacheItem(u1122, resolvePath('unicons/square-shape.svg')); - cacheItem(u1123, resolvePath('unicons/star.svg')); - cacheItem(u1124, resolvePath('unicons/step-backward.svg')); - cacheItem(u1125, resolvePath('unicons/sync.svg')); - cacheItem(u1126, resolvePath('unicons/stopwatch.svg')); - cacheItem(u1127, resolvePath('unicons/table.svg')); - cacheItem(u1128, resolvePath('unicons/tag-alt.svg')); - cacheItem(u1129, resolvePath('unicons/times.svg')); - cacheItem(u1130, resolvePath('unicons/trash-alt.svg')); - cacheItem(u1131, resolvePath('unicons/unlock.svg')); - cacheItem(u1132, resolvePath('unicons/upload.svg')); - cacheItem(u1133, resolvePath('unicons/user.svg')); - cacheItem(u1134, resolvePath('unicons/users-alt.svg')); - cacheItem(u1135, resolvePath('unicons/wrap-text.svg')); - cacheItem(u1136, resolvePath('unicons/cloud-upload.svg')); - cacheItem(u1137, resolvePath('unicons/credit-card.svg')); - cacheItem(u1138, resolvePath('unicons/file-copy-alt.svg')); - cacheItem(u1139, resolvePath('unicons/fire.svg')); - cacheItem(u1140, resolvePath('unicons/hourglass.svg')); - cacheItem(u1141, resolvePath('unicons/layer-group.svg')); - cacheItem(u1142, resolvePath('unicons/layers-alt.svg')); - cacheItem(u1143, resolvePath('unicons/line-alt.svg')); - cacheItem(u1144, resolvePath('unicons/list-ui-alt.svg')); - cacheItem(u1145, resolvePath('unicons/message.svg')); - cacheItem(u1146, resolvePath('unicons/palette.svg')); - cacheItem(u1147, resolvePath('unicons/percentage.svg')); - cacheItem(u1148, resolvePath('unicons/shield-exclamation.svg')); - cacheItem(u1149, resolvePath('unicons/plus-square.svg')); - cacheItem(u1150, resolvePath('unicons/x.svg')); - cacheItem(u1151, resolvePath('unicons/capture.svg')); - cacheItem(u1152, resolvePath('custom/gf-grid.svg')); - cacheItem(u1153, resolvePath('custom/gf-landscape.svg')); - cacheItem(u1154, resolvePath('custom/gf-layout-simple.svg')); - cacheItem(u1155, resolvePath('custom/gf-portrait.svg')); - cacheItem(u1156, resolvePath('custom/gf-show-context.svg')); - cacheItem(u1157, resolvePath('custom/gf-bar-alignment-after.svg')); - cacheItem(u1158, resolvePath('custom/gf-bar-alignment-before.svg')); - cacheItem(u1159, resolvePath('custom/gf-bar-alignment-center.svg')); - cacheItem(u1160, resolvePath('custom/gf-interpolation-linear.svg')); - cacheItem(u1161, resolvePath('custom/gf-interpolation-smooth.svg')); - cacheItem(u1162, resolvePath('custom/gf-interpolation-step-after.svg')); - cacheItem(u1163, resolvePath('custom/gf-interpolation-step-before.svg')); - cacheItem(u1164, resolvePath('custom/gf-logs.svg')); - cacheItem(u1165, resolvePath('custom/gf-movepane-left.svg')); - cacheItem(u1166, resolvePath('custom/gf-movepane-right.svg')); - cacheItem(u1167, resolvePath('mono/favorite.svg')); - cacheItem(u1168, resolvePath('mono/grafana.svg')); - cacheItem(u1169, resolvePath('mono/heart.svg')); - cacheItem(u1170, resolvePath('mono/heart-break.svg')); - cacheItem(u1171, resolvePath('mono/panel-add.svg')); - cacheItem(u1172, resolvePath('mono/library-panel.svg')); - cacheItem(u1173, resolvePath('unicons/record-audio.svg')); - cacheItem(u1174, resolvePath('solid/bookmark.svg')); - // do not edit this list directly - // the list of icons live here: @grafana/ui/components/Icon/cached.json -} diff --git a/public/app/core/icons/iconBundle.ts.template b/public/app/core/icons/iconBundle.ts.template deleted file mode 100644 index ffb748cfbad..00000000000 --- a/public/app/core/icons/iconBundle.ts.template +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable import/order */ -// DO NOT EDIT THIS FILE -// This file is automatically generated (do not edit it here) -// see @grafana/ui/scripts/generate-icon-bundle.js - - -import { cacheStore } from 'react-inlinesvg'; - -// do not edit this list directly -// the list of icons live here: @grafana/ui/components/Icon/cached.json -//{{imports}} -// do not edit this list directly -// the list of icons live here: @grafana/ui/components/Icon/cached.json - -let cacheInitialized = false; - -function cacheItem(content: string, path: string) { - cacheStore[path] = { content, status: 'loaded' }; -} - -function createPathResolver() { - let root = 'public/img/icons/'; - - // This function needs to be called after index.js loads to give the - // application time to modify __webpack_public_path__ with a CDN path - const grafanaPublicPath = typeof window !== 'undefined' && window.__grafana_public_path__; - if (grafanaPublicPath) { - root = grafanaPublicPath + 'img/icons/'; - } - - return (path: string) => { - return root + path; - }; -} - -export function initIconCache() { - if (cacheInitialized) { - return; - } - cacheInitialized = true; - const resolvePath = createPathResolver(); - - // do not edit this list directly - // the list of icons live here: @grafana/ui/components/Icon/cached.json -//{{cacheItems}} - // do not edit this list directly - // the list of icons live here: @grafana/ui/components/Icon/cached.json -} diff --git a/public/app/plugins/datasource/cloud-monitoring/components/__snapshots__/VariableQueryEditor.test.tsx.snap b/public/app/plugins/datasource/cloud-monitoring/components/__snapshots__/VariableQueryEditor.test.tsx.snap index 59a0857a532..4f09826d038 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/__snapshots__/VariableQueryEditor.test.tsx.snap +++ b/public/app/plugins/datasource/cloud-monitoring/components/__snapshots__/VariableQueryEditor.test.tsx.snap @@ -95,6 +95,11 @@ exports[`VariableQueryEditor renders correctly 1`] = ` className="css-1d3xu67-Icon" height={16} id="public/img/icons/unicons/angle-down.svg" + loader={ +
+ } title="" width={16} /> diff --git a/public/img/icons/README.md b/public/img/icons/README.md index 7bc59fcf984..b181d69d867 100644 --- a/public/img/icons/README.md +++ b/public/img/icons/README.md @@ -3,6 +3,7 @@ - Add the new icon svg to the `unicons/` directory - Yes, even if it's not a unicon icon or from [IconScout](https://iconscout.com/unicons/solid-icons) - We will eventually condense all the separate folders into a single `icons/` directory, and since `unicons/` is the default it makes sense to add new icons there +- Add the new icon path to `public/app/core/icons/cached.json` - Ensure the new icon source is formatted correctly: - Remove any `width` or `height` attributes - If the icon is a single color, ensure any explicitly defined fill or stroke colors are either removed (or set to `currentColor` if a color must be defined) diff --git a/public/test/jest-setup.ts b/public/test/jest-setup.ts index 9511a3e6a97..c0286b53e06 100644 --- a/public/test/jest-setup.ts +++ b/public/test/jest-setup.ts @@ -8,7 +8,6 @@ import { TextEncoder, TextDecoder } from 'util'; import { EventBusSrv } from '@grafana/data'; import { GrafanaBootConfig } from '@grafana/runtime'; -import { initIconCache } from 'app/core/icons/iconBundle'; import 'blob-polyfill'; import 'mutationobserver-shim'; @@ -17,10 +16,6 @@ import './mocks/workers'; import '../vendor/flot/jquery.flot'; import '../vendor/flot/jquery.flot.time'; -// icon cache needs to be initialized for test to prevent -// libraries such as msw from throwing "unhandled resource"-errors -initIconCache(); - const testAppEvents = new EventBusSrv(); const global = window as any; global.$ = global.jQuery = $; diff --git a/scripts/generate-icon-bundle.js b/scripts/generate-icon-bundle.js deleted file mode 100644 index ffa13c2f4c9..00000000000 --- a/scripts/generate-icon-bundle.js +++ /dev/null @@ -1,51 +0,0 @@ -const fs = require('fs'); -const os = require('os'); -const path = require('path'); - -const cachedListPath = path.join(__dirname, '../public/app/core/icons/cached.json'); -const iconsList = require(cachedListPath); - -const iconsBundleJsTemplatePath = path.join(__dirname, '../public/app/core/icons/iconBundle.ts.template'); -const iconsBundleJsPath = path.join(__dirname, '../public/app/core/icons/iconBundle.ts'); - -const iconsBundleJsTemplate = fs.readFileSync(iconsBundleJsTemplatePath).toString(); - -const importsStatements = []; -const cacheStatements = []; - -const grafanaIconsPublicPath = '../../../img/icons/'; - -function generateIconBundle({ outputPath, verbose = false }) { - const modulePrefix = 'u'; - let moduleNameCount = 1000; - - for (iconEntry of iconsList) { - // skip empty and commented - if (iconEntry === '' || iconEntry.startsWith('#')) { - continue; - } - - importsStatements.push( - `import ${modulePrefix}${moduleNameCount} from '${grafanaIconsPublicPath}${iconEntry}.svg';` - ); - cacheStatements.push(` cacheItem(${modulePrefix}${moduleNameCount}, resolvePath('${iconEntry}.svg'));`); - moduleNameCount++; - } - const output = iconsBundleJsTemplate - .replace('//{{imports}}', importsStatements.join('\n')) - .replace('//{{cacheItems}}', cacheStatements.join('\n')); - - fs.writeFileSync(outputPath, output); - if (verbose) { - console.log('The iconsBundle file was successfully written.'); - console.log(`The file is located at ${outputPath}`); - } - return outputPath; -} - -// if invoked directly -if (require.main === module) { - generateIconBundle({ outputPath: iconsBundleJsPath, verbose: true }); -} - -module.exports = generateIconBundle; diff --git a/scripts/webpack/webpack.common.js b/scripts/webpack/webpack.common.js index 5c2aacf59c2..8da51b2e202 100644 --- a/scripts/webpack/webpack.common.js +++ b/scripts/webpack/webpack.common.js @@ -105,11 +105,6 @@ module.exports = { type: 'asset/resource', generator: { filename: 'static/img/[name].[hash:8][ext]' }, }, - // for pre-caching SVGs as part of the JS bundles - { - test: /(unicons|mono|custom|solid)[\\/].*\.svg$/, - type: 'asset/source', - }, { // Required for msagl library (used in Nodegraph panel) to work test: /\.m?js$/, @@ -126,12 +121,6 @@ module.exports = { chunks: 'all', minChunks: 1, cacheGroups: { - unicons: { - test: /[\\/]node_modules[\\/]@iconscout[\\/]react-unicons[\\/].*[jt]sx?$/, - chunks: 'initial', - priority: 20, - enforce: true, - }, moment: { test: /[\\/]node_modules[\\/]moment[\\/].*[jt]sx?$/, chunks: 'initial', diff --git a/yarn.lock b/yarn.lock index 799cf1b463c..38f29617f87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4012,7 +4012,7 @@ __metadata: react-highlight-words: "npm:0.20.0" react-hook-form: "npm:^7.49.2" react-i18next: "npm:^14.0.0" - react-inlinesvg: "npm:3.0.2" + react-inlinesvg: "npm:4.1.5" react-loading-skeleton: "npm:3.5.0" react-router-dom-v5-compat: "npm:^6.26.1" react-select: "npm:5.8.3" @@ -16211,13 +16211,6 @@ __metadata: languageName: node linkType: hard -"exenv@npm:^1.2.2": - version: 1.2.2 - resolution: "exenv@npm:1.2.2" - checksum: 10/6840185e421394bcb143debb866d31d19c3e4a4bca87d2f319d68d61afff353b3c678f2eb389e3b98ab9aecbec19f6bebbdc4193984378af0a3366c498a7efc8 - languageName: node - linkType: hard - "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -17833,7 +17826,7 @@ __metadata: react-highlight-words: "npm:0.20.0" react-hook-form: "npm:^7.49.2" react-i18next: "npm:^14.0.0" - react-inlinesvg: "npm:3.0.2" + react-inlinesvg: "npm:4.1.5" react-loading-skeleton: "npm:3.5.0" react-moveable: "npm:0.56.0" react-redux: "npm:9.1.2" @@ -25400,12 +25393,12 @@ __metadata: languageName: node linkType: hard -"react-from-dom@npm:^0.6.2": - version: 0.6.2 - resolution: "react-from-dom@npm:0.6.2" +"react-from-dom@npm:^0.7.3": + version: 0.7.3 + resolution: "react-from-dom@npm:0.7.3" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10/f3954737c2677e82f72ecedcdcf5f187d2a1b86a6c5b915f7300796ac153437581ee0111c9f524e7c18124d25d0d31391d54cdee318ea390722ca57e66813ed7 + checksum: 10/55d6365af5b2aeaa0f2d80808dfa96114367e63849821b7ea277d193d4f6b1fce020e9754d4527ebc7f8628c5333f19dae38fc7b7956f69d5f640ac28b37ab0f languageName: node linkType: hard @@ -25514,15 +25507,14 @@ __metadata: languageName: node linkType: hard -"react-inlinesvg@npm:3.0.2": - version: 3.0.2 - resolution: "react-inlinesvg@npm:3.0.2" +"react-inlinesvg@npm:4.1.5": + version: 4.1.5 + resolution: "react-inlinesvg@npm:4.1.5" dependencies: - exenv: "npm:^1.2.2" - react-from-dom: "npm:^0.6.2" + react-from-dom: "npm:^0.7.3" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10/740fa33c7a09012bb96509f9003dc26e4e412eed2fc861ca40bfee9a3dddcf7c4d86fd20f824d4c017e44526aa9d747d6c9543ef3f2215bc0ace72754e025316 + react: 16.8 - 19 + checksum: 10/475666855056007bfec56968d61793530f2089997d8a2956d603e03d9da8cd353a00368f220f07ef554c65feb4f5839112cefb2c84b22e511d8a470bea8eee61 languageName: node linkType: hard