From 2978d78b2d787678b07c5dee2e3e2474f294fdb2 Mon Sep 17 00:00:00 2001 From: rozetko Date: Mon, 19 Dec 2022 19:56:39 +0300 Subject: [PATCH] it works --- .../PluginConfigPage/PluginConfigPage.tsx | 83 ++++++++----------- src/plugin.json | 7 ++ src/plugin_state.ts | 13 ++- src/services/network_service.ts | 13 ++- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/components/PluginConfigPage/PluginConfigPage.tsx b/src/components/PluginConfigPage/PluginConfigPage.tsx index 694e00c..ea23f21 100644 --- a/src/components/PluginConfigPage/PluginConfigPage.tsx +++ b/src/components/PluginConfigPage/PluginConfigPage.tsx @@ -4,7 +4,7 @@ import { Legend, LoadingPlaceholder } from '@grafana/ui'; import { useLocation } from 'react-router-dom'; // import logo from '../../img/logo.svg'; -import PluginState from '../../plugin_state'; +import PluginState, { PluginConnectedStatusResponse } from '../../plugin_state'; import ConfigurationForm from './parts/ConfigurationForm'; import RemoveCurrentConfigurationButton from './parts/RemoveCurrentConfigurationButton'; @@ -14,6 +14,8 @@ import { DataExporterPluginConfigPageProps } from 'types'; const PLUGIN_CONFIGURED_QUERY_PARAM = 'pluginConfigured'; const PLUGIN_CONFIGURED_QUERY_PARAM_TRUTHY_VALUE = 'true'; +const PLUGIN_CONFIGURED_VERSION_QUERY_PARAM = 'pluginConfiguredVersion'; + const DEFAULT_API_URL = 'http://localhost:8080'; /** @@ -22,9 +24,12 @@ const DEFAULT_API_URL = 'http://localhost:8080'; * * Don't refresh the page if the plugin is already enabled.. */ -export const reloadPageWithPluginConfiguredQueryParams = (pluginEnabled: boolean): void => { +export const reloadPageWithPluginConfiguredQueryParams = ( + { version }: PluginConnectedStatusResponse, + pluginEnabled: boolean +): void => { if (!pluginEnabled) { - window.location.href = `${window.location.href}?${PLUGIN_CONFIGURED_QUERY_PARAM}=${PLUGIN_CONFIGURED_QUERY_PARAM_TRUTHY_VALUE}`; + window.location.href = `${window.location.href}?${PLUGIN_CONFIGURED_QUERY_PARAM}=${PLUGIN_CONFIGURED_QUERY_PARAM_TRUTHY_VALUE}&${PLUGIN_CONFIGURED_VERSION_QUERY_PARAM}=${version}`; } }; @@ -48,71 +53,53 @@ export const PluginConfigPage: FC = ({ const { search } = useLocation(); const queryParams = new URLSearchParams(search); const pluginConfiguredQueryParam = queryParams.get(PLUGIN_CONFIGURED_QUERY_PARAM); + const pluginConfiguredVersionQueryParam = queryParams.get(PLUGIN_CONFIGURED_VERSION_QUERY_PARAM); const pluginConfiguredRedirect = pluginConfiguredQueryParam === PLUGIN_CONFIGURED_QUERY_PARAM_TRUTHY_VALUE; - console.log(pluginConfiguredRedirect); const [checkingIfPluginIsConnected, setCheckingIfPluginIsConnected] = useState(!pluginConfiguredRedirect); const [pluginConnectionCheckError, setPluginConnectionCheckError] = useState(null); - const [pluginIsConnected, setPluginIsConnected] = useState(pluginConfiguredRedirect); + const [pluginIsConnected, setPluginIsConnected] = useState( + pluginConfiguredRedirect ? { version: pluginConfiguredVersionQueryParam as string } : null + ); const [resettingPlugin, setResettingPlugin] = useState(false); const [pluginResetError, setPluginResetError] = useState(null); const pluginMetaDataExporterApiUrl = jsonData?.dataExporterApiUrl; - const dataExporterApiUrl = pluginMetaDataExporterApiUrl || DEFAULT_API_URL; const resetQueryParams = useCallback(() => removePluginConfiguredQueryParams(pluginIsEnabled), [pluginIsEnabled]); + const checkConnection = useCallback(async () => { + setCheckingIfPluginIsConnected(true); + setPluginConnectionCheckError(null); + if (!pluginMetaDataExporterApiUrl) { + setCheckingIfPluginIsConnected(false); + return; + } + const pluginConnectionResponse = await PluginState.checkIfPluginIsConnected(pluginMetaDataExporterApiUrl); + + if (typeof pluginConnectionResponse === 'string') { + setPluginConnectionCheckError(pluginConnectionResponse); + } else { + setPluginIsConnected(pluginConnectionResponse); + } + + setCheckingIfPluginIsConnected(false); + }, [pluginMetaDataExporterApiUrl]); + useEffect(resetQueryParams, [resetQueryParams]); useEffect(() => { - const configurePluginAndSyncData = async () => { - /** - * If the plugin has never been configured, DataExporterApiUrl will be undefined in the plugin's jsonData - * In that case, check to see if DataExporter_API_URL has been supplied as an env var. - * Supplying the env var basically allows to skip the configuration form - * (check webpack.config.js to see how this is set) - */ - console.log(pluginMetaDataExporterApiUrl); - if (!pluginMetaDataExporterApiUrl) { - /** - * DataExporterApiUrl is not yet saved in the grafana plugin settings, but has been supplied as an env var - * lets auto-trigger a self-hosted plugin install w/ the DataExporterApiUrl passed in as an env var - */ - const errorMsg = await PluginState.installPlugin(dataExporterApiUrl); - if (errorMsg) { - setPluginConnectionCheckError(errorMsg); - setCheckingIfPluginIsConnected(false); - return; - } - } - - /** - * If the DataExporterApiUrl is not set in the plugin settings, and not supplied via an env var - * there's no reason to check if the plugin is connected, we know it can't be - */ - if (dataExporterApiUrl) { - const pluginConnectionResponse = await PluginState.checkIfPluginIsConnected(dataExporterApiUrl); - - console.log(pluginConnectionResponse); - - if (typeof pluginConnectionResponse === 'string') { - setPluginConnectionCheckError(pluginConnectionResponse); - } - } - setCheckingIfPluginIsConnected(false); - }; - /** * don't check the plugin status if the user was just redirected after a successful * plugin setup */ if (!pluginConfiguredRedirect) { - configurePluginAndSyncData(); + checkConnection(); } - }, [pluginMetaDataExporterApiUrl, dataExporterApiUrl, pluginConfiguredRedirect]); + }, [pluginMetaDataExporterApiUrl, pluginConfiguredRedirect, checkConnection]); const resetState = useCallback(() => { setPluginResetError(null); @@ -150,10 +137,6 @@ export const PluginConfigPage: FC = ({ setResettingPlugin(false); }, [resetState]); - const onSuccessfulSetup = useCallback(async () => { - reloadPageWithPluginConfiguredQueryParams(false); - }, []); - const RemoveConfigButton = useCallback( () => , [resettingPlugin, triggerPluginReset] @@ -171,7 +154,7 @@ export const PluginConfigPage: FC = ({ ); } else if (!pluginIsConnected) { - content = ; + content = ; } else { // plugin is fully connected and synced content = ; diff --git a/src/plugin.json b/src/plugin.json index 2ab2790..86eb74d 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -27,6 +27,13 @@ "defaultNav": true } ], + "routes": [ + { + "path": "api/*", + "method": "*", + "url": "{{ .JsonData.dataExporterApiUrl }}/api/" + } + ], "dependencies": { "grafanaDependency": ">=7.0.0", "plugins": [] diff --git a/src/plugin_state.ts b/src/plugin_state.ts index 8430bb5..450ed31 100644 --- a/src/plugin_state.ts +++ b/src/plugin_state.ts @@ -21,12 +21,11 @@ type InstallPluginResponse = Pick< dataExporterAPIResponse: DataExporterAPIResponse; }; -type PluginConnectedStatusResponse = { +export type PluginConnectedStatusResponse = { version: string; }; class PluginState { - static DATA_EXPORTER_BASE_URL = '/plugin'; static GRAFANA_PLUGIN_SETTINGS_URL = '/api/plugins/corpglory-dataexporter-app/settings'; static grafanaBackend = getBackendSrv(); @@ -111,17 +110,17 @@ class PluginState { static timeout = (pollCount: number) => new Promise((resolve) => setTimeout(resolve, 10 * 2 ** pollCount)); - static connectBackend = async (): Promise> => { + static connectBackend = async (): Promise> => { const { key: grafanaToken } = await this.createGrafanaToken(); await this.updateGrafanaPluginSettings({ secureJsonData: { grafanaToken } }); - const dataExporterAPIResponse = await makeRequest(`${this.DATA_EXPORTER_BASE_URL}/connect`, { + const dataExporterAPIResponse = await makeRequest(`/connect`, { method: 'POST', }); return { grafanaToken, dataExporterAPIResponse }; }; static installPlugin = async (dataExporterApiUrl: string): Promise => { - let pluginInstallationDataExporterResponse: InstallPluginResponse; + let pluginInstallationDataExporterResponse: InstallPluginResponse<{ version: string }>; // Step 1. Try provisioning the plugin w/ the Grafana API try { @@ -137,7 +136,7 @@ class PluginState { * - configure the plugin in DataExporter's backend */ try { - pluginInstallationDataExporterResponse = await this.connectBackend(); + pluginInstallationDataExporterResponse = await this.connectBackend<{ version: string }>(); } catch (e) { return this.getHumanReadableErrorFromDataExporterError(e, dataExporterApiUrl); } @@ -165,7 +164,7 @@ class PluginState { dataExporterApiUrl: string ): Promise => { try { - const resp = await makeRequest(`${this.DATA_EXPORTER_BASE_URL}/status`, { + const resp = await makeRequest(`/status`, { method: 'GET', }); diff --git a/src/services/network_service.ts b/src/services/network_service.ts index 6eb40c1..577860e 100644 --- a/src/services/network_service.ts +++ b/src/services/network_service.ts @@ -2,9 +2,20 @@ import axios from 'axios'; export const API_HOST = `${window.location.protocol}//${window.location.host}/`; export const API_PROXY_PREFIX = 'api/plugin-proxy/corpglory-dataexporter-app'; +export const API_PATH_PREFIX = '/api'; const instance = axios.create(); +instance.interceptors.request.use(function (config) { + config.validateStatus = (status) => { + return status >= 200 && status < 300; // default + }; + + return { + ...config, + }; +}); + interface RequestConfig { method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS'; params?: any; @@ -16,7 +27,7 @@ interface RequestConfig { export const makeRequest = async (path: string, config: RequestConfig) => { const { method = 'GET', params, data, validateStatus } = config; - const url = `${API_PROXY_PREFIX}${path}`; + const url = `${API_PROXY_PREFIX}${API_PATH_PREFIX}${path}`; const response = await instance({ method,