mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
feat: Confirm leaving Dashboard with unsaved changes (#444)
This commit is contained in:
parent
1751b2e16d
commit
47b758a5f9
5 changed files with 453 additions and 372 deletions
5
.changeset/warm-cougars-talk.md
Normal file
5
.changeset/warm-cougars-talk.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hyperdx/app': patch
|
||||
---
|
||||
|
||||
Confirm leaving Dashboard with unsaved changes
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
import DashboardPage from '../../src/DashboardPage';
|
||||
|
||||
export default DashboardPage;
|
||||
|
|
|
|||
363
packages/app/pages/dashboards/presets/[presetName].tsx
Normal file
363
packages/app/pages/dashboards/presets/[presetName].tsx
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
import { useRouter } from 'next/router';
|
||||
|
||||
import DashboardPage from '../../../src/DashboardPage';
|
||||
import { withAppNav } from '../../../src/layout';
|
||||
|
||||
const APP_PERFORMANCE_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'App Performance',
|
||||
charts: [
|
||||
{
|
||||
id: '1624425',
|
||||
name: 'P95 Latency by Operation',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 8,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: '',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '401924',
|
||||
name: 'Operations with Errors',
|
||||
x: 8,
|
||||
y: 0,
|
||||
w: 4,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'level:err',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '883200',
|
||||
name: 'Count of Operations',
|
||||
x: 0,
|
||||
y: 3,
|
||||
w: 8,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: '',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const HTTP_SERVER_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'HTTP Server',
|
||||
charts: [
|
||||
{
|
||||
id: '312739',
|
||||
name: 'P95 Latency by Endpoint',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '434437',
|
||||
name: 'HTTP Status Codes',
|
||||
x: 0,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.status_code'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '69137',
|
||||
name: 'HTTP 4xx, 5xx',
|
||||
x: 6,
|
||||
y: 4,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'http.status_code:>=400 span.kind:server',
|
||||
groupBy: ['http.status_code'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '34708',
|
||||
name: 'HTTP 5xx by Endpoint',
|
||||
x: 6,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server http.status_code:>=500',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '58773',
|
||||
name: 'Request Volume by Endpoint',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const REDIS_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'Redis',
|
||||
charts: [
|
||||
{
|
||||
id: '38463',
|
||||
name: 'GET Operations',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'db.system:"redis" span_name:GET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '488836',
|
||||
name: 'P95 GET Latency',
|
||||
x: 0,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'db.system:"redis" span_name:GET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '8355753',
|
||||
name: 'SET Operations',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'db.system:"redis" span_name:SET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '93278',
|
||||
name: 'P95 SET Latency',
|
||||
x: 6,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'db.system:"redis" span_name:SET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const MONGO_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'MongoDB',
|
||||
charts: [
|
||||
{
|
||||
id: '98180',
|
||||
name: 'P95 Read Operation Latency by Collection',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"find" OR db.operation:"findOne" OR db.operation:"aggregate")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '28877',
|
||||
name: 'P95 Write Operation Latency by Collection',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"insert" OR db.operation:"findOneAndUpdate" OR db.operation:"save" OR db.operation:"findAndModify")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '9901546',
|
||||
name: 'Count of Write Operations by Collection',
|
||||
x: 6,
|
||||
y: 3,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"insert" OR db.operation:"findOneAndUpdate" OR db.operation:"save" OR db.operation:"findAndModify")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '6894669',
|
||||
name: 'Count of Read Operations by Collection',
|
||||
x: 0,
|
||||
y: 3,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"find" OR db.operation:"findOne" OR db.operation:"aggregate")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const HYPERDX_USAGE_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'HyperDX Usage',
|
||||
charts: [
|
||||
{
|
||||
id: '15gykg',
|
||||
name: 'Log/Span Usage in Bytes',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 3,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
table: 'logs',
|
||||
type: 'number',
|
||||
aggFn: 'sum',
|
||||
field: 'hyperdx_event_size',
|
||||
where: '',
|
||||
groupBy: [],
|
||||
numberFormat: {
|
||||
output: 'byte',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '1k5pul',
|
||||
name: 'Logs/Span Usage over Time',
|
||||
x: 3,
|
||||
y: 0,
|
||||
w: 9,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
table: 'logs',
|
||||
type: 'time',
|
||||
aggFn: 'sum',
|
||||
field: 'hyperdx_event_size',
|
||||
where: '',
|
||||
groupBy: [],
|
||||
numberFormat: {
|
||||
output: 'byte',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const PRESETS: Record<string, any> = {
|
||||
'app-performance': APP_PERFORMANCE_DASHBOARD_CONFIG,
|
||||
'http-server': HTTP_SERVER_DASHBOARD_CONFIG,
|
||||
redis: REDIS_DASHBOARD_CONFIG,
|
||||
mongo: MONGO_DASHBOARD_CONFIG,
|
||||
'hyperdx-usage': HYPERDX_USAGE_DASHBOARD_CONFIG,
|
||||
};
|
||||
|
||||
export default function DashboardPresetPage() {
|
||||
const router = useRouter();
|
||||
|
||||
const presetName = router.query.presetName as string;
|
||||
|
||||
const presetConfig = PRESETS[presetName] as any;
|
||||
|
||||
return <DashboardPage presetConfig={presetConfig} />;
|
||||
}
|
||||
|
||||
DashboardPresetPage.getLayout = withAppNav;
|
||||
|
|
@ -47,362 +47,20 @@ import styles from '../styles/AppNav.module.scss';
|
|||
const UNTAGGED_SEARCHES_GROUP_NAME = 'Saved Searches';
|
||||
const UNTAGGED_DASHBOARDS_GROUP_NAME = 'Saved Dashboards';
|
||||
|
||||
const APP_PERFORMANCE_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'App Performance',
|
||||
charts: [
|
||||
{
|
||||
id: '1624425',
|
||||
name: 'P95 Latency by Operation',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 8,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: '',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '401924',
|
||||
name: 'Operations with Errors',
|
||||
x: 8,
|
||||
y: 0,
|
||||
w: 4,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'level:err',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '883200',
|
||||
name: 'Count of Operations',
|
||||
x: 0,
|
||||
y: 3,
|
||||
w: 8,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: '',
|
||||
groupBy: ['span_name'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const HTTP_SERVER_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'HTTP Server',
|
||||
charts: [
|
||||
{
|
||||
id: '312739',
|
||||
name: 'P95 Latency by Endpoint',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '434437',
|
||||
name: 'HTTP Status Codes',
|
||||
x: 0,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.status_code'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '69137',
|
||||
name: 'HTTP 4xx, 5xx',
|
||||
x: 6,
|
||||
y: 4,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'http.status_code:>=400 span.kind:server',
|
||||
groupBy: ['http.status_code'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '34708',
|
||||
name: 'HTTP 5xx by Endpoint',
|
||||
x: 6,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server http.status_code:>=500',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '58773',
|
||||
name: 'Request Volume by Endpoint',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'span.kind:server',
|
||||
groupBy: ['http.route'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const REDIS_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'Redis',
|
||||
charts: [
|
||||
{
|
||||
id: '38463',
|
||||
name: 'GET Operations',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'db.system:"redis" span_name:GET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '488836',
|
||||
name: 'P95 GET Latency',
|
||||
x: 0,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'db.system:"redis" span_name:GET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '8355753',
|
||||
name: 'SET Operations',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where: 'db.system:"redis" span_name:SET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '93278',
|
||||
name: 'P95 SET Latency',
|
||||
x: 6,
|
||||
y: 2,
|
||||
w: 6,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where: 'db.system:"redis" span_name:SET',
|
||||
groupBy: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const MONGO_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'MongoDB',
|
||||
charts: [
|
||||
{
|
||||
id: '98180',
|
||||
name: 'P95 Read Operation Latency by Collection',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"find" OR db.operation:"findOne" OR db.operation:"aggregate")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '28877',
|
||||
name: 'P95 Write Operation Latency by Collection',
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'p95',
|
||||
field: 'duration',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"insert" OR db.operation:"findOneAndUpdate" OR db.operation:"save" OR db.operation:"findAndModify")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '9901546',
|
||||
name: 'Count of Write Operations by Collection',
|
||||
x: 6,
|
||||
y: 3,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"insert" OR db.operation:"findOneAndUpdate" OR db.operation:"save" OR db.operation:"findAndModify")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '6894669',
|
||||
name: 'Count of Read Operations by Collection',
|
||||
x: 0,
|
||||
y: 3,
|
||||
w: 6,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
type: 'time',
|
||||
aggFn: 'count',
|
||||
where:
|
||||
'db.system:mongo (db.operation:"find" OR db.operation:"findOne" OR db.operation:"aggregate")',
|
||||
groupBy: ['db.mongodb.collection'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const HYPERDX_USAGE_DASHBOARD_CONFIG = {
|
||||
id: '',
|
||||
name: 'HyperDX Usage',
|
||||
charts: [
|
||||
{
|
||||
id: '15gykg',
|
||||
name: 'Log/Span Usage in Bytes',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 3,
|
||||
h: 2,
|
||||
series: [
|
||||
{
|
||||
table: 'logs',
|
||||
type: 'number',
|
||||
aggFn: 'sum',
|
||||
field: 'hyperdx_event_size',
|
||||
where: '',
|
||||
groupBy: [],
|
||||
numberFormat: {
|
||||
output: 'byte',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '1k5pul',
|
||||
name: 'Logs/Span Usage over Time',
|
||||
x: 3,
|
||||
y: 0,
|
||||
w: 9,
|
||||
h: 3,
|
||||
series: [
|
||||
{
|
||||
table: 'logs',
|
||||
type: 'time',
|
||||
aggFn: 'sum',
|
||||
field: 'hyperdx_event_size',
|
||||
where: '',
|
||||
groupBy: [],
|
||||
numberFormat: {
|
||||
output: 'byte',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
function PresetDashboardLink({
|
||||
query,
|
||||
config,
|
||||
name,
|
||||
presetName,
|
||||
}: {
|
||||
query: any;
|
||||
config: any;
|
||||
name: string;
|
||||
presetName: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<Link
|
||||
href={`/dashboards?config=${encodeURIComponent(JSON.stringify(config))}`}
|
||||
href={`/dashboards/presets/${presetName}`}
|
||||
tabIndex={0}
|
||||
className={cx(styles.listLink, {
|
||||
[styles.listLinkActive]:
|
||||
query.config === JSON.stringify(config) && query.dashboardId == null,
|
||||
'text-muted-hover': query.config !== JSON.stringify(config),
|
||||
[styles.listLinkActive]: router.query.presetName === presetName,
|
||||
})}
|
||||
>
|
||||
{name}
|
||||
|
|
@ -1241,13 +899,7 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
|
|||
styles.listLink,
|
||||
pathname.includes('/dashboard') &&
|
||||
query.dashboardId == null &&
|
||||
query.config !=
|
||||
JSON.stringify(APP_PERFORMANCE_DASHBOARD_CONFIG) &&
|
||||
query.config !=
|
||||
JSON.stringify(HTTP_SERVER_DASHBOARD_CONFIG) &&
|
||||
query.config !=
|
||||
JSON.stringify(REDIS_DASHBOARD_CONFIG) &&
|
||||
query.config != JSON.stringify(MONGO_DASHBOARD_CONFIG)
|
||||
!pathname.includes('/presets')
|
||||
? [styles.listLinkActive]
|
||||
: null,
|
||||
)}
|
||||
|
|
@ -1314,30 +966,19 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
|
|||
/>
|
||||
<Collapse in={!isDashboardsPresetsCollapsed}>
|
||||
<PresetDashboardLink
|
||||
query={query}
|
||||
config={HYPERDX_USAGE_DASHBOARD_CONFIG}
|
||||
presetName={'hyperdx-usage'}
|
||||
name="HyperDX Usage"
|
||||
/>
|
||||
<PresetDashboardLink
|
||||
query={query}
|
||||
config={APP_PERFORMANCE_DASHBOARD_CONFIG}
|
||||
presetName={'app-performance'}
|
||||
name="App Performance"
|
||||
/>
|
||||
<PresetDashboardLink
|
||||
query={query}
|
||||
config={HTTP_SERVER_DASHBOARD_CONFIG}
|
||||
presetName={'http-server'}
|
||||
name="HTTP Server"
|
||||
/>
|
||||
<PresetDashboardLink
|
||||
query={query}
|
||||
config={REDIS_DASHBOARD_CONFIG}
|
||||
name="Redis"
|
||||
/>
|
||||
<PresetDashboardLink
|
||||
query={query}
|
||||
config={MONGO_DASHBOARD_CONFIG}
|
||||
name="Mongo"
|
||||
/>
|
||||
<PresetDashboardLink presetName={'redis'} name="Redis" />
|
||||
<PresetDashboardLink presetName={'mongo'} name="Mongo" />
|
||||
</Collapse>
|
||||
</div>
|
||||
</Collapse>
|
||||
|
|
|
|||
|
|
@ -81,6 +81,54 @@ const buildAndWhereClause = (query1: string, query2: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
const useConfirmExit = ({
|
||||
hasUnsavedChanges,
|
||||
}: {
|
||||
hasUnsavedChanges?: boolean;
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
|
||||
const handleBeforeUnload = useCallback(
|
||||
(e: BeforeUnloadEvent) => {
|
||||
if (!hasUnsavedChanges) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.returnValue = '';
|
||||
},
|
||||
[hasUnsavedChanges],
|
||||
);
|
||||
|
||||
const handleRouteChangeStart = useCallback(
|
||||
(route: string) => {
|
||||
console.log(route, router.asPath);
|
||||
if (!hasUnsavedChanges || route.startsWith('/dashboards')) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
window.confirm(
|
||||
'You have unsaved changes. Are you sure you want to leave?',
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
router.events.emit('routeChangeError');
|
||||
throw 'aborted';
|
||||
},
|
||||
[hasUnsavedChanges, router.asPath, router.events],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||
router.events.on('routeChangeStart', handleRouteChangeStart);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||
router.events.off('routeChangeStart', handleRouteChangeStart);
|
||||
};
|
||||
}, [handleBeforeUnload, handleRouteChangeStart, router.events]);
|
||||
};
|
||||
|
||||
const Tile = forwardRef(
|
||||
(
|
||||
{
|
||||
|
|
@ -568,7 +616,12 @@ function DashboardFilter({
|
|||
|
||||
// TODO: This is a hack to set the default time range
|
||||
const defaultTimeRange = parseTimeQuery('Past 1h', false) as [Date, Date];
|
||||
export default function DashboardPage() {
|
||||
|
||||
export default function DashboardPage({
|
||||
presetConfig,
|
||||
}: {
|
||||
presetConfig?: Dashboard;
|
||||
}) {
|
||||
const { data: dashboardsData, isLoading: isDashboardsLoading } =
|
||||
api.useDashboards();
|
||||
const { data: meData } = api.useMe();
|
||||
|
|
@ -578,7 +631,9 @@ export default function DashboardPage() {
|
|||
const deleteAlert = api.useDeleteAlert();
|
||||
const updateAlert = api.useUpdateAlert();
|
||||
const router = useRouter();
|
||||
|
||||
const { dashboardId, config } = router.query;
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const confirm = useConfirm();
|
||||
|
|
@ -600,6 +655,9 @@ export default function DashboardPage() {
|
|||
dashboardId != null ? dashboardId : hashCode(`${config}`);
|
||||
|
||||
const dashboard: Dashboard | undefined = useMemo(() => {
|
||||
if (presetConfig) {
|
||||
return presetConfig;
|
||||
}
|
||||
if (isLocalDashboard) {
|
||||
return localDashboard;
|
||||
}
|
||||
|
|
@ -609,7 +667,13 @@ export default function DashboardPage() {
|
|||
);
|
||||
return matchedDashboard;
|
||||
}
|
||||
}, [dashboardsData, dashboardId, isLocalDashboard, localDashboard]);
|
||||
}, [
|
||||
presetConfig,
|
||||
isLocalDashboard,
|
||||
dashboardsData,
|
||||
localDashboard,
|
||||
dashboardId,
|
||||
]);
|
||||
|
||||
// Update dashboard
|
||||
const [isSavedNow, _setSavedNow] = useState(false);
|
||||
|
|
@ -728,6 +792,13 @@ export default function DashboardPage() {
|
|||
}
|
||||
}, [isLocalDashboard, router, dashboard?.charts.length]);
|
||||
|
||||
useConfirmExit({
|
||||
hasUnsavedChanges:
|
||||
isLocalDashboard &&
|
||||
(dashboard?.charts.length || 0) > 0 &&
|
||||
presetConfig == null,
|
||||
});
|
||||
|
||||
const [highlightedChartId] = useQueryParam('highlightedChartId');
|
||||
|
||||
const tiles = useMemo(
|
||||
|
|
|
|||
Loading…
Reference in a new issue