mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 06:17:27 -08:00
Initial uPlot work in Mantine UI
Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
d9520b1a79
commit
1c91b82206
|
@ -16,6 +16,7 @@
|
|||
"@codemirror/lint": "^6.5.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.24.0",
|
||||
"@floating-ui/dom": "^1.6.7",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@mantine/code-highlight": "^7.6.1",
|
||||
|
|
935
web/ui/mantine-ui/src/pages/query/ColorPool.ts
Normal file
935
web/ui/mantine-ui/src/pages/query/ColorPool.ts
Normal file
|
@ -0,0 +1,935 @@
|
|||
export const colorPool = [
|
||||
"#008000",
|
||||
"#008080",
|
||||
"#800000",
|
||||
"#800080",
|
||||
"#808000",
|
||||
"#808080",
|
||||
"#0000c0",
|
||||
"#008040",
|
||||
"#0080c0",
|
||||
"#800040",
|
||||
"#8000c0",
|
||||
"#808040",
|
||||
"#8080c0",
|
||||
"#00c000",
|
||||
"#00c080",
|
||||
"#804000",
|
||||
"#804080",
|
||||
"#80c000",
|
||||
"#80c080",
|
||||
"#0040c0",
|
||||
"#00c040",
|
||||
"#00c0c0",
|
||||
"#804040",
|
||||
"#8040c0",
|
||||
"#80c040",
|
||||
"#80c0c0",
|
||||
"#408000",
|
||||
"#408080",
|
||||
"#c00000",
|
||||
"#c00080",
|
||||
"#c08000",
|
||||
"#c08080",
|
||||
"#4000c0",
|
||||
"#408040",
|
||||
"#4080c0",
|
||||
"#c00040",
|
||||
"#c000c0",
|
||||
"#c08040",
|
||||
"#c080c0",
|
||||
"#404000",
|
||||
"#404080",
|
||||
"#40c000",
|
||||
"#40c080",
|
||||
"#c04000",
|
||||
"#c04080",
|
||||
"#c0c000",
|
||||
"#c0c080",
|
||||
"#404040",
|
||||
"#4040c0",
|
||||
"#40c040",
|
||||
"#40c0c0",
|
||||
"#c04040",
|
||||
"#c040c0",
|
||||
"#c0c040",
|
||||
"#0000a0",
|
||||
"#008020",
|
||||
"#0080a0",
|
||||
"#800020",
|
||||
"#8000a0",
|
||||
"#808020",
|
||||
"#8080a0",
|
||||
"#0000e0",
|
||||
"#008060",
|
||||
"#0080e0",
|
||||
"#800060",
|
||||
"#8000e0",
|
||||
"#808060",
|
||||
"#8080e0",
|
||||
"#0040a0",
|
||||
"#00c020",
|
||||
"#00c0a0",
|
||||
"#804020",
|
||||
"#8040a0",
|
||||
"#80c020",
|
||||
"#80c0a0",
|
||||
"#0040e0",
|
||||
"#00c060",
|
||||
"#00c0e0",
|
||||
"#804060",
|
||||
"#8040e0",
|
||||
"#80c060",
|
||||
"#80c0e0",
|
||||
"#4000a0",
|
||||
"#408020",
|
||||
"#4080a0",
|
||||
"#c00020",
|
||||
"#c000a0",
|
||||
"#c08020",
|
||||
"#c080a0",
|
||||
"#4000e0",
|
||||
"#408060",
|
||||
"#4080e0",
|
||||
"#c00060",
|
||||
"#c000e0",
|
||||
"#c08060",
|
||||
"#c080e0",
|
||||
"#404020",
|
||||
"#4040a0",
|
||||
"#40c020",
|
||||
"#40c0a0",
|
||||
"#c04020",
|
||||
"#c040a0",
|
||||
"#c0c020",
|
||||
"#c0c0a0",
|
||||
"#404060",
|
||||
"#4040e0",
|
||||
"#40c060",
|
||||
"#40c0e0",
|
||||
"#c04060",
|
||||
"#c040e0",
|
||||
"#c0c060",
|
||||
"#00a000",
|
||||
"#00a080",
|
||||
"#802000",
|
||||
"#802080",
|
||||
"#80a000",
|
||||
"#80a080",
|
||||
"#0020c0",
|
||||
"#00a040",
|
||||
"#00a0c0",
|
||||
"#802040",
|
||||
"#8020c0",
|
||||
"#80a040",
|
||||
"#80a0c0",
|
||||
"#006000",
|
||||
"#006080",
|
||||
"#00e000",
|
||||
"#00e080",
|
||||
"#806000",
|
||||
"#806080",
|
||||
"#80e000",
|
||||
"#80e080",
|
||||
"#006040",
|
||||
"#0060c0",
|
||||
"#00e040",
|
||||
"#00e0c0",
|
||||
"#806040",
|
||||
"#8060c0",
|
||||
"#80e040",
|
||||
"#80e0c0",
|
||||
"#40a000",
|
||||
"#40a080",
|
||||
"#c02000",
|
||||
"#c02080",
|
||||
"#c0a000",
|
||||
"#c0a080",
|
||||
"#4020c0",
|
||||
"#40a040",
|
||||
"#40a0c0",
|
||||
"#c02040",
|
||||
"#c020c0",
|
||||
"#c0a040",
|
||||
"#c0a0c0",
|
||||
"#406000",
|
||||
"#406080",
|
||||
"#40e000",
|
||||
"#40e080",
|
||||
"#c06000",
|
||||
"#c06080",
|
||||
"#c0e000",
|
||||
"#c0e080",
|
||||
"#406040",
|
||||
"#4060c0",
|
||||
"#40e040",
|
||||
"#40e0c0",
|
||||
"#c06040",
|
||||
"#c060c0",
|
||||
"#c0e040",
|
||||
"#c0e0c0",
|
||||
"#0020a0",
|
||||
"#00a020",
|
||||
"#00a0a0",
|
||||
"#802020",
|
||||
"#8020a0",
|
||||
"#80a020",
|
||||
"#80a0a0",
|
||||
"#0020e0",
|
||||
"#00a060",
|
||||
"#00a0e0",
|
||||
"#802060",
|
||||
"#8020e0",
|
||||
"#80a060",
|
||||
"#80a0e0",
|
||||
"#006020",
|
||||
"#0060a0",
|
||||
"#00e020",
|
||||
"#00e0a0",
|
||||
"#806020",
|
||||
"#8060a0",
|
||||
"#80e020",
|
||||
"#80e0a0",
|
||||
"#006060",
|
||||
"#0060e0",
|
||||
"#00e060",
|
||||
"#00e0e0",
|
||||
"#806060",
|
||||
"#8060e0",
|
||||
"#80e060",
|
||||
"#80e0e0",
|
||||
"#4020a0",
|
||||
"#40a020",
|
||||
"#40a0a0",
|
||||
"#c02020",
|
||||
"#c020a0",
|
||||
"#c0a020",
|
||||
"#c0a0a0",
|
||||
"#4020e0",
|
||||
"#40a060",
|
||||
"#40a0e0",
|
||||
"#c02060",
|
||||
"#c020e0",
|
||||
"#c0a060",
|
||||
"#c0a0e0",
|
||||
"#406020",
|
||||
"#4060a0",
|
||||
"#40e020",
|
||||
"#40e0a0",
|
||||
"#c06020",
|
||||
"#c060a0",
|
||||
"#c0e020",
|
||||
"#c0e0a0",
|
||||
"#406060",
|
||||
"#4060e0",
|
||||
"#40e060",
|
||||
"#40e0e0",
|
||||
"#c06060",
|
||||
"#c060e0",
|
||||
"#c0e060",
|
||||
"#208000",
|
||||
"#208080",
|
||||
"#a00000",
|
||||
"#a00080",
|
||||
"#a08000",
|
||||
"#a08080",
|
||||
"#208040",
|
||||
"#2080c0",
|
||||
"#a00040",
|
||||
"#a000c0",
|
||||
"#a08040",
|
||||
"#a080c0",
|
||||
"#204080",
|
||||
"#20c000",
|
||||
"#20c080",
|
||||
"#a04000",
|
||||
"#a04080",
|
||||
"#a0c000",
|
||||
"#a0c080",
|
||||
"#2040c0",
|
||||
"#20c040",
|
||||
"#20c0c0",
|
||||
"#a04040",
|
||||
"#a040c0",
|
||||
"#a0c040",
|
||||
"#a0c0c0",
|
||||
"#608000",
|
||||
"#608080",
|
||||
"#e00000",
|
||||
"#e00080",
|
||||
"#e08000",
|
||||
"#e08080",
|
||||
"#6000c0",
|
||||
"#608040",
|
||||
"#6080c0",
|
||||
"#e00040",
|
||||
"#e000c0",
|
||||
"#e08040",
|
||||
"#e080c0",
|
||||
"#604080",
|
||||
"#60c000",
|
||||
"#60c080",
|
||||
"#e04000",
|
||||
"#e04080",
|
||||
"#e0c000",
|
||||
"#e0c080",
|
||||
"#604040",
|
||||
"#6040c0",
|
||||
"#60c040",
|
||||
"#60c0c0",
|
||||
"#e04040",
|
||||
"#e040c0",
|
||||
"#e0c040",
|
||||
"#e0c0c0",
|
||||
"#208020",
|
||||
"#2080a0",
|
||||
"#a00020",
|
||||
"#a000a0",
|
||||
"#a08020",
|
||||
"#a080a0",
|
||||
"#2000e0",
|
||||
"#208060",
|
||||
"#2080e0",
|
||||
"#a00060",
|
||||
"#a000e0",
|
||||
"#a08060",
|
||||
"#a080e0",
|
||||
"#2040a0",
|
||||
"#20c020",
|
||||
"#20c0a0",
|
||||
"#a04020",
|
||||
"#a040a0",
|
||||
"#a0c020",
|
||||
"#2040e0",
|
||||
"#20c060",
|
||||
"#20c0e0",
|
||||
"#a04060",
|
||||
"#a040e0",
|
||||
"#a0c060",
|
||||
"#a0c0e0",
|
||||
"#6000a0",
|
||||
"#608020",
|
||||
"#6080a0",
|
||||
"#e00020",
|
||||
"#e000a0",
|
||||
"#e08020",
|
||||
"#e080a0",
|
||||
"#6000e0",
|
||||
"#608060",
|
||||
"#6080e0",
|
||||
"#e00060",
|
||||
"#e000e0",
|
||||
"#e08060",
|
||||
"#e080e0",
|
||||
"#604020",
|
||||
"#6040a0",
|
||||
"#60c020",
|
||||
"#60c0a0",
|
||||
"#e04020",
|
||||
"#e040a0",
|
||||
"#e0c020",
|
||||
"#e0c0a0",
|
||||
"#604060",
|
||||
"#6040e0",
|
||||
"#60c060",
|
||||
"#60c0e0",
|
||||
"#e04060",
|
||||
"#e040e0",
|
||||
"#e0c060",
|
||||
"#e0c0e0",
|
||||
"#20a000",
|
||||
"#20a080",
|
||||
"#a02000",
|
||||
"#a02080",
|
||||
"#a0a000",
|
||||
"#a0a080",
|
||||
"#2020c0",
|
||||
"#20a040",
|
||||
"#20a0c0",
|
||||
"#a02040",
|
||||
"#a020c0",
|
||||
"#a0a040",
|
||||
"#a0a0c0",
|
||||
"#206000",
|
||||
"#206080",
|
||||
"#20e000",
|
||||
"#20e080",
|
||||
"#a06000",
|
||||
"#a06080",
|
||||
"#a0e000",
|
||||
"#a0e080",
|
||||
"#206040",
|
||||
"#2060c0",
|
||||
"#20e040",
|
||||
"#20e0c0",
|
||||
"#a06040",
|
||||
"#a060c0",
|
||||
"#a0e040",
|
||||
"#a0e0c0",
|
||||
"#602080",
|
||||
"#60a000",
|
||||
"#60a080",
|
||||
"#e02000",
|
||||
"#e02080",
|
||||
"#e0a000",
|
||||
"#e0a080",
|
||||
"#6020c0",
|
||||
"#60a040",
|
||||
"#60a0c0",
|
||||
"#e02040",
|
||||
"#e020c0",
|
||||
"#e0a040",
|
||||
"#e0a0c0",
|
||||
"#606000",
|
||||
"#606080",
|
||||
"#60e000",
|
||||
"#60e080",
|
||||
"#e06000",
|
||||
"#e06080",
|
||||
"#e0e000",
|
||||
"#e0e080",
|
||||
"#606040",
|
||||
"#6060c0",
|
||||
"#60e040",
|
||||
"#60e0c0",
|
||||
"#e06040",
|
||||
"#e060c0",
|
||||
"#e0e040",
|
||||
"#e0e0c0",
|
||||
"#20a020",
|
||||
"#20a0a0",
|
||||
"#a02020",
|
||||
"#a020a0",
|
||||
"#a0a020",
|
||||
"#a0a0a0",
|
||||
"#2020e0",
|
||||
"#20a060",
|
||||
"#20a0e0",
|
||||
"#a02060",
|
||||
"#a020e0",
|
||||
"#a0a060",
|
||||
"#a0a0e0",
|
||||
"#206020",
|
||||
"#2060a0",
|
||||
"#20e020",
|
||||
"#20e0a0",
|
||||
"#a06020",
|
||||
"#a060a0",
|
||||
"#a0e020",
|
||||
"#a0e0a0",
|
||||
"#206060",
|
||||
"#2060e0",
|
||||
"#20e060",
|
||||
"#20e0e0",
|
||||
"#a06060",
|
||||
"#a060e0",
|
||||
"#a0e060",
|
||||
"#a0e0e0",
|
||||
"#6020a0",
|
||||
"#60a020",
|
||||
"#60a0a0",
|
||||
"#e02020",
|
||||
"#e020a0",
|
||||
"#e0a020",
|
||||
"#e0a0a0",
|
||||
"#602060",
|
||||
"#6020e0",
|
||||
"#60a060",
|
||||
"#60a0e0",
|
||||
"#e02060",
|
||||
"#e020e0",
|
||||
"#e0a060",
|
||||
"#e0a0e0",
|
||||
"#606020",
|
||||
"#6060a0",
|
||||
"#60e020",
|
||||
"#60e0a0",
|
||||
"#e06020",
|
||||
"#e060a0",
|
||||
"#e0e020",
|
||||
"#e0e0a0",
|
||||
"#606060",
|
||||
"#6060e0",
|
||||
"#60e060",
|
||||
"#60e0e0",
|
||||
"#e06060",
|
||||
"#e060e0",
|
||||
"#e0e060",
|
||||
"#008010",
|
||||
"#008090",
|
||||
"#800010",
|
||||
"#800090",
|
||||
"#808010",
|
||||
"#808090",
|
||||
"#0000d0",
|
||||
"#008050",
|
||||
"#0080d0",
|
||||
"#800050",
|
||||
"#8000d0",
|
||||
"#808050",
|
||||
"#8080d0",
|
||||
"#004010",
|
||||
"#004090",
|
||||
"#00c010",
|
||||
"#00c090",
|
||||
"#804010",
|
||||
"#804090",
|
||||
"#80c010",
|
||||
"#80c090",
|
||||
"#004050",
|
||||
"#0040d0",
|
||||
"#00c050",
|
||||
"#00c0d0",
|
||||
"#804050",
|
||||
"#8040d0",
|
||||
"#80c050",
|
||||
"#80c0d0",
|
||||
"#400090",
|
||||
"#408010",
|
||||
"#408090",
|
||||
"#c00010",
|
||||
"#c00090",
|
||||
"#c08010",
|
||||
"#c08090",
|
||||
"#4000d0",
|
||||
"#408050",
|
||||
"#4080d0",
|
||||
"#c00050",
|
||||
"#c000d0",
|
||||
"#c08050",
|
||||
"#c080d0",
|
||||
"#404010",
|
||||
"#404090",
|
||||
"#40c010",
|
||||
"#40c090",
|
||||
"#c04010",
|
||||
"#c04090",
|
||||
"#c0c010",
|
||||
"#c0c090",
|
||||
"#404050",
|
||||
"#4040d0",
|
||||
"#40c050",
|
||||
"#40c0d0",
|
||||
"#c04050",
|
||||
"#c040d0",
|
||||
"#c0c050",
|
||||
"#0000b0",
|
||||
"#008030",
|
||||
"#0080b0",
|
||||
"#800030",
|
||||
"#8000b0",
|
||||
"#808030",
|
||||
"#8080b0",
|
||||
"#0000f0",
|
||||
"#008070",
|
||||
"#0080f0",
|
||||
"#800070",
|
||||
"#8000f0",
|
||||
"#808070",
|
||||
"#8080f0",
|
||||
"#004030",
|
||||
"#0040b0",
|
||||
"#00c030",
|
||||
"#00c0b0",
|
||||
"#804030",
|
||||
"#8040b0",
|
||||
"#80c030",
|
||||
"#80c0b0",
|
||||
"#004070",
|
||||
"#0040f0",
|
||||
"#00c070",
|
||||
"#00c0f0",
|
||||
"#804070",
|
||||
"#8040f0",
|
||||
"#80c070",
|
||||
"#80c0f0",
|
||||
"#4000b0",
|
||||
"#408030",
|
||||
"#4080b0",
|
||||
"#c00030",
|
||||
"#c000b0",
|
||||
"#c08030",
|
||||
"#c080b0",
|
||||
"#400070",
|
||||
"#4000f0",
|
||||
"#408070",
|
||||
"#4080f0",
|
||||
"#c00070",
|
||||
"#c000f0",
|
||||
"#c08070",
|
||||
"#c080f0",
|
||||
"#404030",
|
||||
"#4040b0",
|
||||
"#40c030",
|
||||
"#40c0b0",
|
||||
"#c04030",
|
||||
"#c040b0",
|
||||
"#c0c030",
|
||||
"#c0c0b0",
|
||||
"#404070",
|
||||
"#4040f0",
|
||||
"#40c070",
|
||||
"#40c0f0",
|
||||
"#c04070",
|
||||
"#c040f0",
|
||||
"#c0c070",
|
||||
"#c0c0f0",
|
||||
"#002090",
|
||||
"#00a010",
|
||||
"#00a090",
|
||||
"#802010",
|
||||
"#802090",
|
||||
"#80a010",
|
||||
"#80a090",
|
||||
"#0020d0",
|
||||
"#00a050",
|
||||
"#00a0d0",
|
||||
"#802050",
|
||||
"#8020d0",
|
||||
"#80a050",
|
||||
"#80a0d0",
|
||||
"#006010",
|
||||
"#006090",
|
||||
"#00e010",
|
||||
"#00e090",
|
||||
"#806010",
|
||||
"#806090",
|
||||
"#80e010",
|
||||
"#80e090",
|
||||
"#006050",
|
||||
"#0060d0",
|
||||
"#00e050",
|
||||
"#00e0d0",
|
||||
"#806050",
|
||||
"#8060d0",
|
||||
"#80e050",
|
||||
"#80e0d0",
|
||||
"#402090",
|
||||
"#40a010",
|
||||
"#40a090",
|
||||
"#c02010",
|
||||
"#c02090",
|
||||
"#c0a010",
|
||||
"#c0a090",
|
||||
"#402050",
|
||||
"#4020d0",
|
||||
"#40a050",
|
||||
"#40a0d0",
|
||||
"#c02050",
|
||||
"#c020d0",
|
||||
"#c0a050",
|
||||
"#c0a0d0",
|
||||
"#406010",
|
||||
"#406090",
|
||||
"#40e010",
|
||||
"#40e090",
|
||||
"#c06010",
|
||||
"#c06090",
|
||||
"#c0e010",
|
||||
"#c0e090",
|
||||
"#406050",
|
||||
"#4060d0",
|
||||
"#40e050",
|
||||
"#40e0d0",
|
||||
"#c06050",
|
||||
"#c060d0",
|
||||
"#c0e050",
|
||||
"#c0e0d0",
|
||||
"#0020b0",
|
||||
"#00a030",
|
||||
"#00a0b0",
|
||||
"#802030",
|
||||
"#8020b0",
|
||||
"#80a030",
|
||||
"#80a0b0",
|
||||
"#0020f0",
|
||||
"#00a070",
|
||||
"#00a0f0",
|
||||
"#802070",
|
||||
"#8020f0",
|
||||
"#80a070",
|
||||
"#80a0f0",
|
||||
"#006030",
|
||||
"#0060b0",
|
||||
"#00e030",
|
||||
"#00e0b0",
|
||||
"#806030",
|
||||
"#8060b0",
|
||||
"#80e030",
|
||||
"#80e0b0",
|
||||
"#006070",
|
||||
"#0060f0",
|
||||
"#00e070",
|
||||
"#00e0f0",
|
||||
"#806070",
|
||||
"#8060f0",
|
||||
"#80e070",
|
||||
"#80e0f0",
|
||||
"#4020b0",
|
||||
"#40a030",
|
||||
"#40a0b0",
|
||||
"#c02030",
|
||||
"#c020b0",
|
||||
"#c0a030",
|
||||
"#c0a0b0",
|
||||
"#4020f0",
|
||||
"#40a070",
|
||||
"#40a0f0",
|
||||
"#c02070",
|
||||
"#c020f0",
|
||||
"#c0a070",
|
||||
"#c0a0f0",
|
||||
"#406030",
|
||||
"#4060b0",
|
||||
"#40e030",
|
||||
"#40e0b0",
|
||||
"#c06030",
|
||||
"#c060b0",
|
||||
"#c0e030",
|
||||
"#c0e0b0",
|
||||
"#406070",
|
||||
"#4060f0",
|
||||
"#40e070",
|
||||
"#40e0f0",
|
||||
"#c06070",
|
||||
"#c060f0",
|
||||
"#c0e070",
|
||||
"#208010",
|
||||
"#208090",
|
||||
"#a00010",
|
||||
"#a00090",
|
||||
"#a08010",
|
||||
"#a08090",
|
||||
"#2000d0",
|
||||
"#208050",
|
||||
"#2080d0",
|
||||
"#a00050",
|
||||
"#a000d0",
|
||||
"#a08050",
|
||||
"#a080d0",
|
||||
"#204010",
|
||||
"#204090",
|
||||
"#20c010",
|
||||
"#20c090",
|
||||
"#a04010",
|
||||
"#a04090",
|
||||
"#a0c010",
|
||||
"#a0c090",
|
||||
"#204050",
|
||||
"#2040d0",
|
||||
"#20c050",
|
||||
"#20c0d0",
|
||||
"#a04050",
|
||||
"#a040d0",
|
||||
"#a0c050",
|
||||
"#a0c0d0",
|
||||
"#600090",
|
||||
"#608010",
|
||||
"#608090",
|
||||
"#e00010",
|
||||
"#e00090",
|
||||
"#e08010",
|
||||
"#e08090",
|
||||
"#600050",
|
||||
"#6000d0",
|
||||
"#608050",
|
||||
"#6080d0",
|
||||
"#e00050",
|
||||
"#e000d0",
|
||||
"#e08050",
|
||||
"#e080d0",
|
||||
"#604010",
|
||||
"#604090",
|
||||
"#60c010",
|
||||
"#60c090",
|
||||
"#e04010",
|
||||
"#e04090",
|
||||
"#e0c010",
|
||||
"#e0c090",
|
||||
"#604050",
|
||||
"#6040d0",
|
||||
"#60c050",
|
||||
"#60c0d0",
|
||||
"#e04050",
|
||||
"#e040d0",
|
||||
"#e0c050",
|
||||
"#e0c0d0",
|
||||
"#2000b0",
|
||||
"#208030",
|
||||
"#2080b0",
|
||||
"#a00030",
|
||||
"#a000b0",
|
||||
"#a08030",
|
||||
"#a080b0",
|
||||
"#2000f0",
|
||||
"#208070",
|
||||
"#2080f0",
|
||||
"#a00070",
|
||||
"#a000f0",
|
||||
"#a08070",
|
||||
"#a080f0",
|
||||
"#204030",
|
||||
"#2040b0",
|
||||
"#20c030",
|
||||
"#20c0b0",
|
||||
"#a04030",
|
||||
"#a040b0",
|
||||
"#a0c030",
|
||||
"#a0c0b0",
|
||||
"#204070",
|
||||
"#2040f0",
|
||||
"#20c070",
|
||||
"#20c0f0",
|
||||
"#a04070",
|
||||
"#a040f0",
|
||||
"#a0c070",
|
||||
"#a0c0f0",
|
||||
"#6000b0",
|
||||
"#608030",
|
||||
"#6080b0",
|
||||
"#e00030",
|
||||
"#e000b0",
|
||||
"#e08030",
|
||||
"#e080b0",
|
||||
"#600070",
|
||||
"#6000f0",
|
||||
"#608070",
|
||||
"#e00070",
|
||||
"#e000f0",
|
||||
"#e08070",
|
||||
"#e080f0",
|
||||
"#604030",
|
||||
"#6040b0",
|
||||
"#60c030",
|
||||
"#60c0b0",
|
||||
"#e04030",
|
||||
"#e040b0",
|
||||
"#e0c030",
|
||||
"#e0c0b0",
|
||||
"#604070",
|
||||
"#6040f0",
|
||||
"#60c070",
|
||||
"#60c0f0",
|
||||
"#e04070",
|
||||
"#e040f0",
|
||||
"#e0c070",
|
||||
"#e0c0f0",
|
||||
"#20a010",
|
||||
"#20a090",
|
||||
"#a02010",
|
||||
"#a02090",
|
||||
"#a0a010",
|
||||
"#a0a090",
|
||||
"#2020d0",
|
||||
"#20a050",
|
||||
"#20a0d0",
|
||||
"#a02050",
|
||||
"#a020d0",
|
||||
"#a0a050",
|
||||
"#a0a0d0",
|
||||
"#206010",
|
||||
"#206090",
|
||||
"#20e010",
|
||||
"#20e090",
|
||||
"#a06010",
|
||||
"#a06090",
|
||||
"#a0e010",
|
||||
"#a0e090",
|
||||
"#206050",
|
||||
"#2060d0",
|
||||
"#20e050",
|
||||
"#20e0d0",
|
||||
"#a06050",
|
||||
"#a060d0",
|
||||
"#a0e050",
|
||||
"#a0e0d0",
|
||||
"#602090",
|
||||
"#60a010",
|
||||
"#60a090",
|
||||
"#e02010",
|
||||
"#e02090",
|
||||
"#e0a010",
|
||||
"#e0a090",
|
||||
"#602050",
|
||||
"#6020d0",
|
||||
"#60a050",
|
||||
"#60a0d0",
|
||||
"#e02050",
|
||||
"#e020d0",
|
||||
"#e0a050",
|
||||
"#e0a0d0",
|
||||
"#606010",
|
||||
"#606090",
|
||||
"#60e010",
|
||||
"#60e090",
|
||||
"#e06010",
|
||||
"#e06090",
|
||||
"#e0e010",
|
||||
"#e0e090",
|
||||
"#606050",
|
||||
"#6060d0",
|
||||
"#60e050",
|
||||
"#60e0d0",
|
||||
"#e06050",
|
||||
"#e060d0",
|
||||
"#e0e050",
|
||||
"#2020b0",
|
||||
"#20a030",
|
||||
"#20a0b0",
|
||||
"#a02030",
|
||||
"#a020b0",
|
||||
"#a0a030",
|
||||
"#a0a0b0",
|
||||
"#2020f0",
|
||||
"#20a070",
|
||||
"#20a0f0",
|
||||
"#a02070",
|
||||
"#a020f0",
|
||||
"#a0a070",
|
||||
"#a0a0f0",
|
||||
"#206030",
|
||||
"#2060b0",
|
||||
"#20e030",
|
||||
"#20e0b0",
|
||||
"#a06030",
|
||||
"#a060b0",
|
||||
"#a0e030",
|
||||
"#a0e0b0",
|
||||
"#206070",
|
||||
"#2060f0",
|
||||
"#20e070",
|
||||
"#20e0f0",
|
||||
"#a06070",
|
||||
"#a060f0",
|
||||
"#a0e070",
|
||||
"#a0e0f0",
|
||||
"#6020b0",
|
||||
"#60a030",
|
||||
"#60a0b0",
|
||||
"#e02030",
|
||||
"#e020b0",
|
||||
"#e0a030",
|
||||
"#e0a0b0",
|
||||
"#6020f0",
|
||||
"#60a070",
|
||||
"#60a0f0",
|
||||
"#e02070",
|
||||
"#e020f0",
|
||||
"#e0a070",
|
||||
"#e0a0f0",
|
||||
"#606030",
|
||||
"#6060b0",
|
||||
"#60e030",
|
||||
"#60e0b0",
|
||||
"#e06030",
|
||||
"#e060b0",
|
||||
"#e0e030",
|
||||
"#e0e0b0",
|
||||
"#606070",
|
||||
"#6060f0",
|
||||
"#60e070",
|
||||
"#60e0f0",
|
||||
"#e06070",
|
||||
"#e060f0",
|
||||
"#e0e070",
|
||||
];
|
|
@ -107,6 +107,10 @@ export class HistoryCompleteStrategy implements CompleteStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
// This is just a placeholder until query history is implemented, so disable the linter warning.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const queryHistory = [] as string[];
|
||||
|
||||
interface ExpressionInputProps {
|
||||
initialExpr: string;
|
||||
metricNames: string[];
|
||||
|
@ -166,10 +170,6 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
|
|||
}
|
||||
}, [formatResult, formatError]);
|
||||
|
||||
// This is just a placeholder until query history is implemented, so disable the linter warning.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const queryHistory = [] as string[];
|
||||
|
||||
// (Re)initialize editor based on settings / setting changes.
|
||||
useEffect(() => {
|
||||
// Build the dynamic part of the config.
|
||||
|
@ -205,7 +205,7 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
|
|||
size="lg"
|
||||
variant="transparent"
|
||||
color="gray"
|
||||
aria-label="Decrease range"
|
||||
aria-label="Show query options"
|
||||
>
|
||||
<IconDotsVertical style={{ width: "1rem", height: "1rem" }} />
|
||||
</ActionIcon>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@ import {
|
|||
Input,
|
||||
SegmentedControl,
|
||||
Stack,
|
||||
Select,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconChartAreaFilled,
|
||||
|
@ -122,7 +123,53 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
|
|||
}
|
||||
/>
|
||||
|
||||
<Input value="" placeholder="Res. (s)" style={{ width: 80 }} />
|
||||
<Select
|
||||
placeholder="Resolution"
|
||||
maxDropdownHeight={500}
|
||||
data={[
|
||||
{
|
||||
group: "Automatic resolution",
|
||||
items: [
|
||||
{ label: "Low", value: "low" },
|
||||
{ label: "Medium", value: "medium" },
|
||||
{ label: "High", value: "high" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Fixed resolution",
|
||||
items: [
|
||||
{ label: "10s", value: "10" },
|
||||
{ label: "30s", value: "30" },
|
||||
{ label: "1m", value: "60" },
|
||||
{ label: "5m", value: "300" },
|
||||
{ label: "15m", value: "900" },
|
||||
{ label: "1h", value: "3600" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Custom resolution",
|
||||
items: [{ label: "Enter value", value: "custom" }],
|
||||
},
|
||||
]}
|
||||
w={160}
|
||||
// value={value ? value.value : null}
|
||||
onChange={(_value, option) => {
|
||||
dispatch(
|
||||
setVisualizer({
|
||||
idx,
|
||||
visualizer: {
|
||||
...panel.visualizer,
|
||||
resolution: option
|
||||
? option.value
|
||||
? parseInt(option.value)
|
||||
: null
|
||||
: null,
|
||||
},
|
||||
})
|
||||
);
|
||||
}}
|
||||
clearable
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<SegmentedControl
|
||||
|
@ -211,6 +258,18 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
|
|||
showExemplars={panel.visualizer.showExemplars}
|
||||
displayMode={panel.visualizer.displayMode}
|
||||
retriggerIdx={retriggerIdx}
|
||||
onSelectRange={(start: number, end: number) =>
|
||||
dispatch(
|
||||
setVisualizer({
|
||||
idx,
|
||||
visualizer: {
|
||||
...panel.visualizer,
|
||||
range: (end - start) * 1000,
|
||||
endTime: end * 1000,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { FC, useState } from "react";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { ActionIcon, Group, Input } from "@mantine/core";
|
||||
import { IconMinus, IconPlus } from "@tabler/icons-react";
|
||||
import {
|
||||
|
@ -43,6 +43,10 @@ const RangeInput: FC<RangeInputProps> = ({ range, onChangeRange }) => {
|
|||
formatPrometheusDuration(range)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setRangeInput(formatPrometheusDuration(range));
|
||||
}, [range]);
|
||||
|
||||
const onChangeRangeInput = (rangeText: string): void => {
|
||||
const newRange = parsePrometheusDuration(rangeText);
|
||||
if (newRange === null) {
|
||||
|
|
429
web/ui/mantine-ui/src/pages/query/UPlotChart.tsx
Normal file
429
web/ui/mantine-ui/src/pages/query/UPlotChart.tsx
Normal file
|
@ -0,0 +1,429 @@
|
|||
import { FC, useEffect, useId, useState } from "react";
|
||||
import { Alert, Skeleton, Box, LoadingOverlay } from "@mantine/core";
|
||||
import { IconAlertTriangle, IconInfoCircle } from "@tabler/icons-react";
|
||||
import {
|
||||
InstantQueryResult,
|
||||
RangeSamples,
|
||||
} from "../../api/responseTypes/query";
|
||||
import { useAPIQuery } from "../../api/api";
|
||||
import classes from "./Graph.module.css";
|
||||
import { GraphDisplayMode } from "../../state/queryPageSlice";
|
||||
import { formatSeries } from "../../lib/formatSeries";
|
||||
import uPlot, { Series } from "uplot";
|
||||
import UplotReact from "uplot-react";
|
||||
import "uplot/dist/uPlot.min.css";
|
||||
import "./uplot.css";
|
||||
import { useElementSize } from "@mantine/hooks";
|
||||
import { formatTimestamp } from "../../lib/formatTime";
|
||||
import { computePosition, shift, flip, offset, Axis } from "@floating-ui/dom";
|
||||
import { colorPool } from "./ColorPool";
|
||||
|
||||
const formatYAxisTickValue = (y: number | null): string => {
|
||||
if (y === null) {
|
||||
return "null";
|
||||
}
|
||||
const absY = Math.abs(y);
|
||||
|
||||
if (absY >= 1e24) {
|
||||
return (y / 1e24).toFixed(2) + "Y";
|
||||
} else if (absY >= 1e21) {
|
||||
return (y / 1e21).toFixed(2) + "Z";
|
||||
} else if (absY >= 1e18) {
|
||||
return (y / 1e18).toFixed(2) + "E";
|
||||
} else if (absY >= 1e15) {
|
||||
return (y / 1e15).toFixed(2) + "P";
|
||||
} else if (absY >= 1e12) {
|
||||
return (y / 1e12).toFixed(2) + "T";
|
||||
} else if (absY >= 1e9) {
|
||||
return (y / 1e9).toFixed(2) + "G";
|
||||
} else if (absY >= 1e6) {
|
||||
return (y / 1e6).toFixed(2) + "M";
|
||||
} else if (absY >= 1e3) {
|
||||
return (y / 1e3).toFixed(2) + "k";
|
||||
} else if (absY >= 1) {
|
||||
return y.toFixed(2);
|
||||
} else if (absY === 0) {
|
||||
return y.toFixed(2);
|
||||
} else if (absY < 1e-23) {
|
||||
return (y / 1e-24).toFixed(2) + "y";
|
||||
} else if (absY < 1e-20) {
|
||||
return (y / 1e-21).toFixed(2) + "z";
|
||||
} else if (absY < 1e-17) {
|
||||
return (y / 1e-18).toFixed(2) + "a";
|
||||
} else if (absY < 1e-14) {
|
||||
return (y / 1e-15).toFixed(2) + "f";
|
||||
} else if (absY < 1e-11) {
|
||||
return (y / 1e-12).toFixed(2) + "p";
|
||||
} else if (absY < 1e-8) {
|
||||
return (y / 1e-9).toFixed(2) + "n";
|
||||
} else if (absY < 1e-5) {
|
||||
return (y / 1e-6).toFixed(2) + "µ";
|
||||
} else if (absY < 1e-2) {
|
||||
return (y / 1e-3).toFixed(2) + "m";
|
||||
} else if (absY <= 1) {
|
||||
return y.toFixed(2);
|
||||
}
|
||||
throw Error("couldn't format a value, this is a bug");
|
||||
};
|
||||
|
||||
const escapeHTML = (str: string): string => {
|
||||
const entityMap: { [key: string]: string } = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
"/": "/",
|
||||
};
|
||||
|
||||
return String(str).replace(/[&<>"'/]/g, function (s) {
|
||||
return entityMap[s];
|
||||
});
|
||||
};
|
||||
|
||||
const formatLabels = (labels: { [key: string]: string }): string => `
|
||||
<div class="labels">
|
||||
${Object.keys(labels).length === 0 ? '<div class="no-labels">no labels</div>' : ""}
|
||||
${labels["__name__"] ? `<div><strong>${labels["__name__"]}</strong></div>` : ""}
|
||||
${Object.keys(labels)
|
||||
.filter((k) => k !== "__name__")
|
||||
.map(
|
||||
(k) =>
|
||||
`<div><strong>${k}</strong>: ${escapeHTML(labels[k])}</div>`
|
||||
)
|
||||
.join("")}
|
||||
</div>`;
|
||||
|
||||
const tooltipPlugin = () => {
|
||||
let over: HTMLDivElement;
|
||||
let boundingLeft: number;
|
||||
let boundingTop: number;
|
||||
let selectedSeriesIdx: number | null = null;
|
||||
|
||||
const overlay = document.createElement("div");
|
||||
overlay.className = "u-tooltip";
|
||||
overlay.style.display = "none";
|
||||
|
||||
return {
|
||||
hooks: {
|
||||
// Set up event handlers and append overlay.
|
||||
init: (u: uPlot) => {
|
||||
over = u.over;
|
||||
|
||||
over.addEventListener("mouseenter", () => {
|
||||
overlay.style.display = "block";
|
||||
});
|
||||
|
||||
over.addEventListener("mouseleave", () => {
|
||||
overlay.style.display = "none";
|
||||
});
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
},
|
||||
// When the chart is destroyed, remove the overlay from the DOM.
|
||||
destroy: () => {
|
||||
overlay.remove();
|
||||
},
|
||||
// When the chart is resized, store the bounding box of the overlay.
|
||||
setSize: () => {
|
||||
const bbox = over.getBoundingClientRect();
|
||||
boundingLeft = bbox.left;
|
||||
boundingTop = bbox.top;
|
||||
},
|
||||
// When a series is selected by hovering close to it, store the
|
||||
// index of the selected series.
|
||||
setSeries: (self: uPlot, seriesIdx: number | null, opts: Series) => {
|
||||
selectedSeriesIdx = seriesIdx;
|
||||
},
|
||||
// When the cursor is moved, update the tooltip with the current
|
||||
// series value and position it near the cursor.
|
||||
setCursor: (u: uPlot) => {
|
||||
const { left, top, idx } = u.cursor;
|
||||
|
||||
if (
|
||||
idx === null ||
|
||||
idx === undefined ||
|
||||
left === null ||
|
||||
left === undefined ||
|
||||
top === null ||
|
||||
top === undefined ||
|
||||
selectedSeriesIdx === null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ts = u.data[0][idx];
|
||||
const value = u.data[selectedSeriesIdx][idx];
|
||||
const series = u.series[selectedSeriesIdx];
|
||||
const labels = series.labels;
|
||||
const color = series.stroke();
|
||||
|
||||
const x = left + boundingLeft;
|
||||
const y = top + boundingTop;
|
||||
|
||||
// overlay.style.borderColor = color;
|
||||
|
||||
// TODO: Use local time in formatTimestamp!
|
||||
overlay.innerHTML = `
|
||||
<div class="date">${formatTimestamp(ts, false)}</div>
|
||||
<div class="series-value">
|
||||
<span class="detail-swatch" style="background-color: ${color}"></span>
|
||||
<span>${labels.__name__ ? labels.__name__ + ": " : " "}<strong>${value}</strong></span>
|
||||
</div>
|
||||
${formatLabels(labels)}
|
||||
`.trimEnd();
|
||||
|
||||
const virtualEl = {
|
||||
getBoundingClientRect() {
|
||||
return {
|
||||
width: 0,
|
||||
height: 0,
|
||||
x: x,
|
||||
y: y,
|
||||
left: x,
|
||||
right: x,
|
||||
top: y,
|
||||
bottom: y,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
computePosition(virtualEl, overlay, {
|
||||
placement: "right-start",
|
||||
middleware: [offset(5), flip(), shift()],
|
||||
}).then(({ x, y }) => {
|
||||
Object.assign(overlay.style, {
|
||||
top: `${y}px`,
|
||||
left: `${x}px`,
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// A helper function to automatically create enough space for the Y axis
|
||||
// ticket labels depending on their length.
|
||||
const autoPadLeft = (
|
||||
self: uPlot,
|
||||
values: string[],
|
||||
axisIdx: number,
|
||||
cycleNum: number
|
||||
) => {
|
||||
const axis = self.axes[axisIdx];
|
||||
|
||||
// bail out, force convergence
|
||||
if (cycleNum > 1) {
|
||||
return axis._size;
|
||||
}
|
||||
|
||||
let axisSize = axis.ticks.size + axis.gap;
|
||||
|
||||
// find longest value
|
||||
const longestVal = (values ?? []).reduce(
|
||||
(acc, val) => (val.length > acc.length ? val : acc),
|
||||
""
|
||||
);
|
||||
|
||||
if (longestVal != "") {
|
||||
self.ctx.font = axis.font[0];
|
||||
axisSize += self.ctx.measureText(longestVal).width / devicePixelRatio;
|
||||
}
|
||||
|
||||
return Math.ceil(axisSize);
|
||||
};
|
||||
|
||||
const getOptions = (
|
||||
width: number,
|
||||
result: RangeSamples[],
|
||||
onSelectRange: (start: number, end: number) => void
|
||||
): uPlot.Options => ({
|
||||
width: width - 30,
|
||||
height: 550,
|
||||
// padding: [null, autoPadRight, null, null],
|
||||
cursor: {
|
||||
focus: {
|
||||
prox: 1000,
|
||||
},
|
||||
// Whether dragging on the chart should select a zoom area.
|
||||
drag: {
|
||||
x: true,
|
||||
// Don't zoom into the existing via uPlot, we want to load new (finger-grained) data instead.
|
||||
setScale: false,
|
||||
},
|
||||
},
|
||||
plugins: [tooltipPlugin()],
|
||||
legend: {
|
||||
show: true,
|
||||
live: false,
|
||||
markers: {
|
||||
fill: (
|
||||
self: uPlot,
|
||||
seriesIdx: number
|
||||
): CSSStyleDeclaration["borderColor"] => {
|
||||
return colorPool[seriesIdx % colorPool.length];
|
||||
},
|
||||
},
|
||||
},
|
||||
// @ts-expect-error - uPlot enum types don't work across module boundaries,
|
||||
// see https://github.com/leeoniya/uPlot/issues/973.
|
||||
drawOrder: ["series", "axes"],
|
||||
focus: {
|
||||
alpha: 0.4,
|
||||
},
|
||||
axes: [
|
||||
// X axis (time).
|
||||
{
|
||||
labelSize: 20,
|
||||
stroke: "#333",
|
||||
grid: {
|
||||
show: false,
|
||||
stroke: "#eee",
|
||||
width: 2,
|
||||
dash: [],
|
||||
},
|
||||
},
|
||||
// Y axis (sample value).
|
||||
{
|
||||
values: (u: uPlot, splits: number[]) => splits.map(formatYAxisTickValue),
|
||||
border: {
|
||||
show: true,
|
||||
stroke: "#333",
|
||||
width: 1,
|
||||
},
|
||||
labelGap: 8,
|
||||
labelSize: 8 + 12 + 8,
|
||||
stroke: "#333",
|
||||
size: autoPadLeft,
|
||||
},
|
||||
],
|
||||
series: [
|
||||
...result.map((r, idx) => ({
|
||||
label: formatSeries(r.metric),
|
||||
width: 2,
|
||||
labels: r.metric,
|
||||
stroke: colorPool[idx % colorPool.length],
|
||||
})),
|
||||
],
|
||||
hooks: {
|
||||
setSelect: [
|
||||
(self: uPlot) => {
|
||||
onSelectRange(
|
||||
self.posToVal(self.select.left, "x"),
|
||||
self.posToVal(self.select.left + self.select.width, "x")
|
||||
);
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export const normalizeData = (
|
||||
inputData: RangeSamples[],
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
resolution: number
|
||||
): uPlot.AlignedData => {
|
||||
const timeData: (number | null)[][] = [];
|
||||
timeData[0] = [];
|
||||
for (let t = startTime; t <= endTime; t += resolution) {
|
||||
timeData[0].push(t);
|
||||
}
|
||||
|
||||
return timeData.concat(
|
||||
inputData.map(({ values, histograms }) => {
|
||||
// Insert nulls for all missing steps.
|
||||
const data: (number | null)[] = [];
|
||||
let valuePos = 0;
|
||||
let histogramPos = 0;
|
||||
|
||||
for (let t = startTime; t <= endTime; t += resolution) {
|
||||
// Allow for floating point inaccuracy.
|
||||
const currentValue = values && values[valuePos];
|
||||
const currentHistogram = histograms && histograms[histogramPos];
|
||||
if (
|
||||
currentValue &&
|
||||
values.length > valuePos &&
|
||||
currentValue[0] < t + resolution / 100
|
||||
) {
|
||||
data.push(parseValue(currentValue[1]));
|
||||
valuePos++;
|
||||
} else if (
|
||||
currentHistogram &&
|
||||
histograms.length > histogramPos &&
|
||||
currentHistogram[0] < t + resolution / 100
|
||||
) {
|
||||
data.push(parseValue(currentHistogram[1].sum));
|
||||
histogramPos++;
|
||||
} else {
|
||||
data.push(null);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const parseValue = (value: string): null | number => {
|
||||
const val = parseFloat(value);
|
||||
// "+Inf", "-Inf", "+Inf" will be parsed into NaN by parseFloat(). They
|
||||
// can't be graphed, so show them as gaps (null).
|
||||
return isNaN(val) ? null : val;
|
||||
};
|
||||
|
||||
export interface UPlotChartRange {
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
resolution: number;
|
||||
}
|
||||
|
||||
export interface UPlotChartProps {
|
||||
data: RangeSamples[];
|
||||
range: UPlotChartRange;
|
||||
width: number;
|
||||
showExemplars: boolean;
|
||||
displayMode: GraphDisplayMode;
|
||||
onSelectRange: (start: number, end: number) => void;
|
||||
}
|
||||
|
||||
const UPlotChart: FC<UPlotChartProps> = ({
|
||||
data,
|
||||
range: { startTime, endTime, resolution },
|
||||
displayMode,
|
||||
width,
|
||||
onSelectRange,
|
||||
}) => {
|
||||
const [options, setOptions] = useState<uPlot.Options | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (width === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setOptions(getOptions(width, data, onSelectRange));
|
||||
}, [width, data, onSelectRange]);
|
||||
|
||||
const seriesData: uPlot.AlignedData = normalizeData(
|
||||
data,
|
||||
startTime,
|
||||
endTime,
|
||||
resolution
|
||||
);
|
||||
// data[0].values?.map((v) => v[0]),
|
||||
// ...data.map((r) => r.values?.map((v) => parseFloat(v[1]))),
|
||||
// ...normalizeData(data, startTime, endTime, resolution),
|
||||
// ];
|
||||
|
||||
if (options === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<UplotReact
|
||||
options={options}
|
||||
data={seriesData}
|
||||
className={classes.uplotChart}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default UPlotChart;
|
|
@ -24,3 +24,75 @@
|
|||
} */
|
||||
}
|
||||
}
|
||||
|
||||
.uplot {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.u-over {
|
||||
box-shadow: 0px 0px 0px 0.5px #ccc;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.u-legend {
|
||||
text-align: left;
|
||||
margin-top: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.u-inline tr {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.u-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.u-tooltip {
|
||||
font-size: 0.8em;
|
||||
white-space: nowrap;
|
||||
/* background: var(--mantine-color-gray-7);
|
||||
color: var(--mantine-color-gray-1); */
|
||||
/* background: rgba(0, 0, 0, 0.8); */
|
||||
/* color: #fff; */
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 2px solid var(--mantine-color-gray-6);
|
||||
color: var(--mantine-color-gray-9);
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
padding: 0.8em 1.5em;
|
||||
margin: 0.75rem;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
|
||||
.series-value {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.series-label {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.labels {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.3em;
|
||||
|
||||
div {
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
.no-labels {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-swatch {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,14 @@ export default defineConfig({
|
|||
server: {
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://localhost:9090",
|
||||
target: "https://demo.promlabs.com",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
"/-/": {
|
||||
target: "http://localhost:9090",
|
||||
target: "https://demo.promlabs.com",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
19
web/ui/package-lock.json
generated
19
web/ui/package-lock.json
generated
|
@ -113,6 +113,7 @@
|
|||
"@codemirror/lint": "^6.5.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.24.0",
|
||||
"@floating-ui/dom": "^1.6.7",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@mantine/code-highlight": "^7.6.1",
|
||||
|
@ -1647,12 +1648,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
|
||||
"integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz",
|
||||
"integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.0.0",
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
"@floating-ui/core": "^1.6.0",
|
||||
"@floating-ui/utils": "^0.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react": {
|
||||
|
@ -1682,9 +1684,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
|
||||
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
|
||||
"integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.14",
|
||||
|
|
Loading…
Reference in a new issue