From 77576d903fadaeca13ed19c8eb833553532ad153 Mon Sep 17 00:00:00 2001 From: Sparkle <1284531+baurine@users.noreply.github.com> Date: Sun, 9 Oct 2022 13:23:50 +0800 Subject: [PATCH] refine clinic cloud variant (#1414) * add start entry * refine start options * refine start options * add more app options * make slow query app configurable from html * support cloud ngm topsql --- .../package.json | 2 +- .../public/index.html | 62 ++++--- .../public/ngm.html | 169 ++++++++++++++++++ .../src/apps/SlowQuery/context.ts | 10 +- .../src/apps/SlowQuery/index.tsx | 5 +- .../src/apps/TopSQL/context.ts | 12 +- .../src/apps/TopSQL/index.tsx | 3 +- .../src/client/index.tsx | 58 ++++-- .../src/dashboardApp/index.ts | 4 +- .../src/dashboardApp/main.tsx | 133 +++++++------- .../src/uilts/appOptions.ts | 38 +++- .../src/apps/TopSQL/context.ts | 6 +- .../tidb-dashboard-for-op/.env.development | 2 +- .../src/apps/TopSQL/context.ts | 6 +- .../src/apps/SlowQuery/context/index.ts | 10 +- .../src/apps/SlowQuery/pages/List/index.tsx | 2 + .../utils/useSlowQueryTableController.ts | 5 + .../Statement/pages/Detail/SlowQueryTab.tsx | 2 + .../src/apps/TopSQL/context/index.ts | 6 + .../src/apps/TopSQL/index.tsx | 10 +- .../src/apps/TopSQL/pages/List/List.tsx | 31 ++-- 21 files changed, 426 insertions(+), 150 deletions(-) create mode 100644 ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/package.json b/ui/packages/tidb-dashboard-for-clinic-cloud/package.json index b7ae0655a8..2b5dde33ba 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/package.json +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@pingcap/tidb-dashboard-for-clinic-cloud", - "version": "0.0.17", + "version": "0.0.19", "main": "dist/dashboardApp.js", "module": "dist/dashboardApp.js", "files": [ diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/public/index.html b/ui/packages/tidb-dashboard-for-clinic-cloud/public/index.html index 03e055f034..ff317605e8 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/public/index.html +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/public/index.html @@ -25,6 +25,12 @@ left: 50%; } + #dashboard_page_spinner p { + margin-left: -50%; + margin-top: 8px; + color: #888; + } + .dot-flashing { position: relative; width: 10px; @@ -93,36 +99,40 @@ -
+ +
+
+

+ It may take a bit long time to load for the first time, due to download + some js files. +

+
- - diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html b/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html new file mode 100644 index 0000000000..24084af6e9 --- /dev/null +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/public/ngm.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + +
+
+

+ It may take a bit long time to load for the first time, due to download + some js files. +

+
+
+ + + + diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/context.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/context.ts index ab1946d59f..d122e3d9d1 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/context.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/context.ts @@ -1,6 +1,7 @@ import { ISlowQueryDataSource, ISlowQueryContext, + ISlowQueryConfig, ReqConfig } from '@pingcap/tidb-dashboard-lib' @@ -68,11 +69,14 @@ class DataSource implements ISlowQueryDataSource { const ds = new DataSource() -export const ctx: ISlowQueryContext = { +export const ctx: (cfg: Partial) => ISlowQueryContext = ( + cfg +) => ({ ds, cfg: { apiPathBase: client.getBasePath(), enableExport: true, - showDBFilter: true + showDBFilter: true, + ...cfg } -} +}) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/index.tsx b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/index.tsx index 8e9c463b61..c1cb73ca84 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/index.tsx +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/SlowQuery/index.tsx @@ -1,10 +1,13 @@ import React from 'react' import { SlowQueryApp, SlowQueryProvider } from '@pingcap/tidb-dashboard-lib' +import { getStartOptions } from '~/uilts/appOptions' import { ctx } from './context' export default function () { return ( - + ) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/context.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/context.ts index a04bae4e05..436ad3bc19 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/context.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/context.ts @@ -1,6 +1,7 @@ import { ITopSQLDataSource, ITopSQLContext, + ITopSQLConfig, ReqConfig } from '@pingcap/tidb-dashboard-lib' @@ -44,6 +45,11 @@ class DataSource implements ITopSQLDataSource { const ds = new DataSource() -export const ctx: ITopSQLContext = { - ds -} +export const ctx: (cfg: Partial) => ITopSQLContext = (cfg) => ({ + ds, + cfg: { + checkNgm: true, + showSetting: true, + ...cfg + } +}) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/index.tsx b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/index.tsx index efd5c29774..4176c42a40 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/index.tsx +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/TopSQL/index.tsx @@ -1,10 +1,11 @@ import React from 'react' import { TopSQLApp, TopSQLProvider } from '@pingcap/tidb-dashboard-lib' +import { getStartOptions } from '~/uilts/appOptions' import { ctx } from './context' export default function () { return ( - + ) diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/client/index.tsx b/ui/packages/tidb-dashboard-for-clinic-cloud/src/client/index.tsx index ac1de40123..5798505d80 100755 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/client/index.tsx +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/client/index.tsx @@ -96,31 +96,55 @@ function applyErrorHandlerInterceptor(instance: AxiosInstance) { }) } -function initAxios(token: string, orgId: string, clusterId: string) { - const instance = axios.create({ - headers: { - 'x-csrf-token': token, - 'x-org-id': orgId, - 'x-cluster-id': clusterId - } - }) +export type ClientOptions = { + apiPathBase: string + apiToken: string + + provider?: string + region?: string + orgId?: string + projectId?: string + clusterId?: string +} + +function initAxios({ + apiToken, + provider, + region, + orgId, + projectId, + clusterId +}: Omit) { + let headers = {} + headers['x-csrf-token'] = apiToken + if (provider) { + headers['x-provider'] = provider + } + if (region) { + headers['x-region'] = region + } + if (orgId) { + headers['x-org-id'] = orgId + } + if (projectId) { + headers['x-project-id'] = projectId + } + if (clusterId) { + headers['x-cluster-id'] = clusterId + } + const instance = axios.create({ headers }) applyErrorHandlerInterceptor(instance) return instance } -export function setupClient( - apiBasePath: string, - token: string, - orgId: string, - clusterId: string -) { +export function setupClient(options: ClientOptions) { i18n.addTranslations(translations) - const axiosInstance = initAxios(token, orgId, clusterId) + const axiosInstance = initAxios(options) const dashboardApi = new DashboardApi( new Configuration({ - basePath: apiBasePath, + basePath: options.apiPathBase, baseOptions: { handleError: 'default' } @@ -129,5 +153,5 @@ export function setupClient( axiosInstance ) - client.init(apiBasePath, dashboardApi) + client.init(options.apiPathBase, dashboardApi) } diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/index.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/index.ts index 9ec9b65769..ea4a1d8145 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/index.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/index.ts @@ -1,6 +1,8 @@ import '../styles/style.less' import '@pingcap/tidb-dashboard-lib/dist/index.css' -import './main' +import { start } from './main' import '../styles/override.less' + +export default start diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/main.tsx b/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/main.tsx index 8ac4dac170..4a450de5c0 100755 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/main.tsx +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/dashboardApp/main.tsx @@ -20,7 +20,12 @@ import { import { InfoInfoResponse, setupClient } from '~/client' import { mustLoadAppInfo, reloadWhoAmI } from '~/uilts/store' -import { AppOptions } from '~/uilts/appOptions' +import { + AppOptions, + defAppOptions, + setStartOptions, + StartOptions +} from '~/uilts/appOptions' import AppRegistry from '~/uilts/registry' import AppOverview from '~/apps/Overview/meta' @@ -56,20 +61,50 @@ function removeSpinner() { } } -async function webPageStart() { +async function webPageStart(appOptions: AppOptions) { + i18n.addTranslations(translations) + i18next.changeLanguage(appOptions.lang) + let info: InfoInfoResponse - try { - info = await mustLoadAppInfo() - } catch (e) { - Modal.error({ - title: `Failed to connect to server`, - content: '' + e, - okText: 'Reload', - onOk: () => window.location.reload() - }) - removeSpinner() - return + if (!appOptions.skipLoadAppInfo) { + try { + info = await mustLoadAppInfo() + + if (!appOptions.skipNgmCheck && info?.ngm_state === NgmState.NotStarted) { + notification.error({ + key: 'ngm_not_started', + message: i18next.t('health_check.failed_notification_title'), + description: ( + + {i18next.t('health_check.ngm_not_started')} + {!isDistro() && ( + <> + {' '} + + {i18next.t('health_check.help_text')} + + + )} + + ), + duration: null + }) + } + } catch (e) { + Modal.error({ + title: `Failed to connect to server`, + content: '' + e, + okText: 'Reload', + onOk: () => window.location.reload() + }) + removeSpinner() + return + } } telemetry.init( @@ -82,6 +117,7 @@ async function webPageStart() { telemetry.enable( `tidb-dashboard-for-clinic-cloud-${process.env.REACT_APP_VERSION}` ) + let preRoute = '' window.addEventListener('single-spa:routing-event', () => { const curRoute = routing.getPathInLocationHash() @@ -91,37 +127,7 @@ async function webPageStart() { } }) - const options: AppOptions = { - lang: 'en', - skipNgmCheck: false, - hideNav: false - } - if (!options.skipNgmCheck && info?.ngm_state === NgmState.NotStarted) { - notification.error({ - key: 'ngm_not_started', - message: i18next.t('health_check.failed_notification_title'), - description: ( - - {i18next.t('health_check.ngm_not_started')} - {!isDistro() && ( - <> - {' '} - - {i18next.t('health_check.help_text')} - - - )} - - ), - duration: null - }) - } - - const registry = new AppRegistry(options) + const registry = new AppRegistry(appOptions) NProgress.configure({ showSpinner: false @@ -162,14 +168,16 @@ async function webPageStart() { .register(AppOptimizerTrace) .register(AppDeadlock) - try { - const ok = await reloadWhoAmI() + if (!appOptions.skipReloadWhoAmI) { + try { + const ok = await reloadWhoAmI() - if (routing.isLocationMatch('/') && ok) { - singleSpa.navigateToUrl('#' + registry.getDefaultRouter()) + if (routing.isLocationMatch('/') && ok) { + singleSpa.navigateToUrl('#' + registry.getDefaultRouter()) + } + } catch (e) { + // If there are auth errors, redirection will happen any way. So we continue. } - } catch (e) { - // If there are auth errors, redirection will happen any way. So we continue. } window.addEventListener('single-spa:first-mount', () => { @@ -179,28 +187,11 @@ async function webPageStart() { singleSpa.start() } -function main() { +export function start(startOptions: StartOptions) { document.title = `${distro().tidb} Dashboard` - function handleSameWindowPortalEvent(event) { - const { type, token, apiBasePath, orgId, clusterId } = event.detail - // the event type must be "DASHBOARD_PORTAL_EVENT" - if (type !== 'DASHBOARD_PORTAL_EVENT') { - return - } - - i18next.changeLanguage('en') - i18n.addTranslations(translations) - setupClient(apiBasePath, token, orgId, clusterId) + setStartOptions(startOptions) - window.removeEventListener( - 'dashboard:portal_event', - handleSameWindowPortalEvent - ) - - webPageStart() - } - window.addEventListener('dashboard:portal_event', handleSameWindowPortalEvent) + setupClient(startOptions.clientOptions) + webPageStart({ ...defAppOptions, ...startOptions.appOptions }) } - -main() diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/uilts/appOptions.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/uilts/appOptions.ts index 14be23bdd5..b33ac871bd 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/uilts/appOptions.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/uilts/appOptions.ts @@ -1,13 +1,22 @@ +import { ISlowQueryConfig, ITopSQLConfig } from '@pingcap/tidb-dashboard-lib' +import { ClientOptions } from '~/client' + export type AppOptions = { + lang: string hideNav: boolean + skipNgmCheck: boolean - lang: string + skipLoadAppInfo: boolean + skipReloadWhoAmI: boolean } -const defAppOptions: AppOptions = { +export const defAppOptions: AppOptions = { + lang: 'en', hideNav: false, + skipNgmCheck: false, - lang: '' + skipLoadAppInfo: false, + skipReloadWhoAmI: false } const optionsKey = 'dashboard_app_options' @@ -27,3 +36,26 @@ export function loadAppOptions(): AppOptions { } return defAppOptions } + +//////////////////////////////////// + +export type AppsConfig = { + slowQuery?: Partial + topSQL?: Partial +} + +export type StartOptions = { + clientOptions: ClientOptions + appOptions?: AppOptions + appsConfig?: AppsConfig +} + +let _startOptions: StartOptions + +export function setStartOptions(opt: StartOptions) { + _startOptions = opt +} + +export function getStartOptions(): StartOptions { + return _startOptions +} diff --git a/ui/packages/tidb-dashboard-for-dbaas/src/apps/TopSQL/context.ts b/ui/packages/tidb-dashboard-for-dbaas/src/apps/TopSQL/context.ts index 5e51df3589..e21d7700fe 100644 --- a/ui/packages/tidb-dashboard-for-dbaas/src/apps/TopSQL/context.ts +++ b/ui/packages/tidb-dashboard-for-dbaas/src/apps/TopSQL/context.ts @@ -45,5 +45,9 @@ class DataSource implements ITopSQLDataSource { const ds = new DataSource() export const ctx: () => ITopSQLContext = () => ({ - ds + ds, + cfg: { + checkNgm: false, + showSetting: false + } }) diff --git a/ui/packages/tidb-dashboard-for-op/.env.development b/ui/packages/tidb-dashboard-for-op/.env.development index 5d54702b6d..32f1fb23a3 100644 --- a/ui/packages/tidb-dashboard-for-op/.env.development +++ b/ui/packages/tidb-dashboard-for-op/.env.development @@ -3,4 +3,4 @@ PUBLIC_URL='/dashboard' REACT_APP_VERSION=$npm_package_version REACT_APP_MIXPANEL_HOST=https://telemetry.pingcap.com/api/v1/dashboard/report REACT_APP_MIXPANEL_TOKEN= -REACT_APP_DASHBOARD_API_URL=http://172.16.7.147:12333 \ No newline at end of file +REACT_APP_DASHBOARD_API_URL=http://127.0.0.1:2379 diff --git a/ui/packages/tidb-dashboard-for-op/src/apps/TopSQL/context.ts b/ui/packages/tidb-dashboard-for-op/src/apps/TopSQL/context.ts index a04bae4e05..b30d31f98a 100644 --- a/ui/packages/tidb-dashboard-for-op/src/apps/TopSQL/context.ts +++ b/ui/packages/tidb-dashboard-for-op/src/apps/TopSQL/context.ts @@ -45,5 +45,9 @@ class DataSource implements ITopSQLDataSource { const ds = new DataSource() export const ctx: ITopSQLContext = { - ds + ds, + cfg: { + checkNgm: true, + showSetting: true + } } diff --git a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/context/index.ts b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/context/index.ts index 28cd60ba9c..0253b06111 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/context/index.ts +++ b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/context/index.ts @@ -42,13 +42,15 @@ export interface ISlowQueryEvent { selectSlowQueryItem(item: SlowqueryModel): void } +export interface ISlowQueryConfig extends IContextConfig { + enableExport: boolean + showDBFilter: boolean +} + export interface ISlowQueryContext { ds: ISlowQueryDataSource event?: ISlowQueryEvent - cfg: IContextConfig & { - enableExport: boolean - showDBFilter: boolean - } + cfg: ISlowQueryConfig } export const SlowQueryContext = createContext(null) diff --git a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx index e4c312c7d8..025b887d5e 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx @@ -67,10 +67,12 @@ function List() { const controller = useSlowQueryTableController({ cacheMgr, showFullSQL, + fetchSchemas: ctx?.cfg.showDBFilter, initialQueryOptions: { ...DEF_SLOW_QUERY_OPTIONS, visibleColumnKeys }, + ds: ctx!.ds }) diff --git a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/utils/useSlowQueryTableController.ts b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/utils/useSlowQueryTableController.ts index ece30a455a..a3e79f9a4c 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/utils/useSlowQueryTableController.ts +++ b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/utils/useSlowQueryTableController.ts @@ -93,6 +93,7 @@ function useQueryOptions( export interface ISlowQueryTableControllerOpts { cacheMgr?: CacheMgr showFullSQL?: boolean + fetchSchemas?: boolean initialQueryOptions?: ISlowQueryOptions persistQueryInSession?: boolean @@ -122,6 +123,7 @@ export interface ISlowQueryTableController { export default function useSlowQueryTableController({ cacheMgr, showFullSQL = false, + fetchSchemas = true, initialQueryOptions, persistQueryInSession = true, ds @@ -152,6 +154,9 @@ export default function useSlowQueryTableController({ // Reload these options when sending a new request. useChange(() => { async function querySchemas() { + if (!fetchSchemas) { + return + } try { const res = await ds.infoListDatabases({ handleError: 'custom' diff --git a/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/Detail/SlowQueryTab.tsx b/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/Detail/SlowQueryTab.tsx index 8ac9c703ad..41946655bc 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/Detail/SlowQueryTab.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/Detail/SlowQueryTab.tsx @@ -24,6 +24,8 @@ export default function SlowQueryTab({ query }: ISlowQueryTabProps) { plans: query.plans }, persistQueryInSession: false, + fetchSchemas: false, + ds: ctx!.ds }) diff --git a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/context/index.ts b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/context/index.ts index dc155019ac..a9c52220d3 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/context/index.ts +++ b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/context/index.ts @@ -35,8 +35,14 @@ export interface ITopSQLDataSource { ): AxiosPromise } +export interface ITopSQLConfig { + checkNgm: boolean + showSetting: boolean +} + export interface ITopSQLContext { ds: ITopSQLDataSource + cfg: ITopSQLConfig } export const TopSQLContext = createContext(null) diff --git a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/index.tsx b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/index.tsx index e9a6cb6475..82066110df 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/index.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/index.tsx @@ -12,6 +12,8 @@ import translations from './translations' addTranslations(translations) function AppRoutes() { + const ctx = useContext(TopSQLContext) + useLocationChange() return ( @@ -19,9 +21,13 @@ function AppRoutes() { + ctx?.cfg.checkNgm ? ( + + + + ) : ( - + ) } /> diff --git a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/pages/List/List.tsx b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/pages/List/List.tsx index 6f26524860..cdc624ccc5 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/pages/List/List.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/TopSQL/pages/List/List.tsx @@ -46,6 +46,7 @@ const TOP_N = 5 const CHART_BAR_WIDTH = 8 export function TopSQLList() { + const ctx = useContext(TopSQLContext) const { t } = useTranslation() const { topSQLConfig, isConfigLoading, updateConfig, haveHistoryData } = useTopSQLConfig() @@ -195,20 +196,22 @@ export function TopSQLList() { - - { - setShowSettings(true) - telemetry.clickSettings('settingIcon') - }} - /> - + {ctx?.cfg.showSetting && ( + + { + setShowSettings(true) + telemetry.clickSettings('settingIcon') + }} + /> + + )} {!isDistro() && (