@cloudcare/guance-front-tools 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +8 -0
  2. package/guance-all-charts.json +3415 -0
  3. package/lib/cjs/generated/dashboardCharts.d.ts +54 -13
  4. package/lib/cjs/scripts/grafana-covert-to-guance-core.d.ts +4 -0
  5. package/lib/cjs/scripts/grafana-covert-to-guance-core.js +10 -0
  6. package/lib/cjs/scripts/grafana-dashbord.d.ts +2220 -0
  7. package/lib/cjs/scripts/grafana-dashbord.js +4 -0
  8. package/lib/cjs/src/grafana-covert-to-guance.d.ts +2 -0
  9. package/lib/cjs/src/grafana-covert-to-guance.js +5 -0
  10. package/lib/cjs/src/index.d.ts +1 -0
  11. package/lib/cjs/src/index.js +1 -0
  12. package/lib/esm/generated/dashboardCharts.d.ts +54 -13
  13. package/lib/esm/scripts/grafana-covert-to-guance-core.d.ts +4 -0
  14. package/lib/esm/scripts/grafana-covert-to-guance-core.js +7 -0
  15. package/lib/esm/scripts/grafana-dashbord.d.ts +2220 -0
  16. package/lib/esm/scripts/grafana-dashbord.js +1 -0
  17. package/lib/esm/src/grafana-covert-to-guance.d.ts +2 -0
  18. package/lib/esm/src/grafana-covert-to-guance.js +1 -0
  19. package/lib/esm/src/index.d.ts +1 -0
  20. package/lib/esm/src/index.js +1 -0
  21. package/lib/example/grafana2.json +878 -0
  22. package/lib/example/guance-dahs-3.json +348 -0
  23. package/lib/scripts/grafana-covert-to-guance-core.js +7 -0
  24. package/lib/scripts/grafana-covert-to-guance-core.ts +23 -0
  25. package/lib/scripts/grafana-covert-to-guance.js +52 -397
  26. package/lib/scripts/grafana-covert-to-guance.ts +58 -410
  27. package/lib/src/grafana-covert-to-guance.ts +7 -0
  28. package/lib/src/index.ts +1 -0
  29. package/package.json +6 -4
  30. package/schemas/charts/chart-schema.json +8 -5
  31. package/schemas/charts/common/chart-link-item-schema.json +48 -0
  32. package/schemas/charts/common/chart-links-schema.json +9 -0
  33. package/schemas/charts/common/common-chart-types-schema.json +3 -1
  34. package/schemas/charts/dashboard-schema.json +11 -4
  35. package/schemas/charts/query/query-item-schema.json +19 -1
  36. package/schemas/charts/settings/settings-time-schema.json +1 -5
  37. package/schemas/charts/settings/settings-unit-items-schema.json +3 -1
  38. package/schemas/charts/settings/settings-units-schema.json +2 -3
  39. package/scripts/validate-file.mjs +57 -0
  40. package/skills/grafana-to-guance-dashboard/SKILL.md +102 -0
  41. package/skills/grafana-to-guance-dashboard/agents/openai.yaml +4 -0
  42. package/skills/grafana-to-guance-dashboard/references/converter-notes.md +134 -0
  43. package/skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs +1899 -0
  44. package/test/cli.test.mjs +373 -0
  45. package/test-output/grafana2.cli.guance.json +1029 -0
  46. package/test-output/grafana2.guance.json +1029 -0
  47. package/test-output/grafana2.keep-meta.guance.json +1384 -0
  48. package/test-output/pod.guance.json +2153 -0
  49. package/test-output/skill-test2-enhanced.guance.json +21596 -0
  50. package/test-output/skill-test2-validated.guance.json +11610 -0
  51. package/test-output/skill-test2.guance.json +11610 -0
  52. package/test-output/test.guance.json +1086 -0
  53. package/test-output/test2.guance.guance-promql.json +23212 -0
  54. package/test-output/test2.guance.json +17554 -0
@@ -1,421 +1,69 @@
1
- import * as fs from 'fs'
2
- import * as path from 'path'
1
+ import fs from 'fs'
2
+ import path from 'path'
3
3
  import yargs from 'yargs'
4
- import type {
5
- DashboardData as GuanceDashboardType,
6
- ChartVarsSettings,
7
- ChartVarsItem,
8
- ChartData as GuanceChartData,
9
- ChartType1 as GuanceChartType,
10
- ChartQueries as GuanceChartQueries,
11
- ChartQueryItem as GuanceChartQueryItem,
12
- ChartSettings as GuanceChartSettings,
13
- ChartTextSettings,
14
- } from '../generated/dashboardCharts'
15
- import type { DashboardData as GrafanaDashboardType, VariableModel, Panel, RowPanel } from './grafana-dashbord'
16
- import dataJson from '../example/test2.json'
17
- // 1. Graph (折线图) - 用于展示时间序列数据的线图或柱状图。
18
- // 2. Stat (统计) - 用于显示单个数值,如当前值、最小值或最大值。
19
- // 3. Gauge (仪表盘) - 用于显示单个数值,并通过仪表盘样式进行可视化。
20
- // 4. Bar Gauge (柱状仪表盘) - 类似于仪表盘,但以柱状方式显示。
21
- // 5. Table (表格) - 用于以表格形式展示数据,支持多列、多行显示。
22
- // 6. Singlestat (单数值) - 适合展示单个重要的数值(现已被 Stat 面板替代)。
23
- // 7. Heatmap (热力图) - 用于显示数据密度或强度的热力图。
24
- // 8. Alert List (告警列表) - 用于展示触发的告警和状态。
25
- // 9. Logs (日志) - 用于展示和查询日志数据,尤其是通过 Loki 数据源。
26
- // 10. Pie Chart (饼图) - 用于显示数据的饼图。
27
- // 11. Text (文本) - 用于展示静态文本,支持 Markdown、HTML 格式。
28
- // 12. Gauge (Gauge 仪表) - 显示环形图表用于单个值的展示。
29
- // 13. Bar Chart (柱状图) - 显示条形图或柱状图。
30
- // 14. Timeseries (时间序列) - 最新的时间序列图表,提供更多功能和配置选项。
31
- // 15. Geomap (地理图) - 基于地图的地理数据可视化。
32
- // 16. Histogram (直方图) - 展示数据分布的图表。
33
- // 17. Status History (状态历史) - 显示状态随时间变化的历史记录。
34
- // 18. Canvas (画布) - 允许自定义绘制的可视化。
35
- // 19. Node Graph (节点图) - 可视化连接点之间的网络关系。
36
- // 20. XY Chart (XY 图表) - 显示二维数据的 XY 图表。
37
- // | 'group'
38
- // | 'sequence'
39
- // | 'singlestat'
40
- // | 'pie'
41
- // | 'bar'
42
- // | 'histogram'
43
- // | 'slo'
44
- // | 'toplist'
45
- // | 'gauge'
46
- // | 'scatter'
47
- // | 'bubble'
48
- // | 'table'
49
- // | 'treemap'
50
- // | 'funnel'
51
- // | 'chinamap'
52
- // | 'worldmap'
53
- // | 'hexgon'
54
- // | 'heatmap'
55
- // | 'topology'
56
- // | 'sankey'
57
- // | 'log'
58
- // | 'object'
59
- // | 'alarm'
60
- // | 'text'
61
- // | 'video'
62
- // | 'picture'
63
- // | 'command'
64
- // | 'iframe'
65
- const grafanaPanelTypeToGuanceChartMap: { [key: string]: GuanceChartType } = {
66
- stat: 'singlestat',
67
- singlestat: 'singlestat',
68
- barchart: 'bar',
69
- timeseries: 'sequence',
70
- graph: 'sequence',
71
- piechart: 'pie',
72
- histogram: 'histogram',
73
- bargauge: 'toplist',
74
- gauge: 'gauge',
75
- table: 'table',
76
- text: 'text',
77
- heatmap: 'heatmap',
78
- treemap: 'treemap',
79
- }
80
- const GRAFANA_KEYWORKD = ['__interval']
81
- function replaceVariableStr(grafanaExpr: string): string {
82
- return grafanaExpr.replace(/\$\{?([\d_\w]+)\}?/g, function (match, variable) {
83
- if (GRAFANA_KEYWORKD.includes(variable)) return match
84
- return `#{${variable}}`
85
- })
86
- }
87
- /**
88
- * Get layout items sorted from top left to right and down.
89
- *
90
- * @return {Array} Array of layout objects.
91
- * @return {Array} Layout, sorted static items first.
92
- */
93
- function sortPanelItemsByRowCol(panels: Panel[]): Panel[] {
94
- return panels.slice(0).sort(function (panelA, panelB) {
95
- // 宽度长的在前面
96
- const { gridPos: posA } = panelA
97
- const { gridPos: posB } = panelB
98
- if (!posA || !posB) return -1
99
- if (posA.y === posB.y && posA.x === posB.x && posA.w > posB.w) {
100
- return -1
101
- }
102
- if (posA.y === posB.y && posA.x === posB.x) {
103
- return 0
104
- }
105
-
106
- if (posA.y > posB.y || (posA.y === posB.y && posA.x > posB.x)) {
107
- return 1
108
- }
109
-
110
- return -1
111
- })
112
- }
113
- // 数字转成abc
114
- function tenToTweenty(source: number = 1): string {
115
- let numArr: any = []
116
- source--
117
- do {
118
- numArr.push(source % 26)
119
- source = Math.floor(source / 26)
120
- } while (source > 0)
121
- return numArr
122
- .reverse()
123
- .map((item: number, index: number) => {
124
- return String.fromCharCode(item + 97 + (index === numArr.length - 1 ? 0 : -1))
125
- })
126
- .join('')
127
- .toLowerCase()
128
- }
129
- function getGridH(h: number, rowHeight: number, margin: number) {
130
- return Math.round(h * rowHeight + Math.max(0, 2 * (h - 1)) * margin)
131
- }
4
+ // @ts-ignore
5
+ import {
6
+ convertDashboard,
7
+ validateDashboardFile,
8
+ } from '../../skills/grafana-to-guance-dashboard/scripts/convert-grafana-dashboard.mjs'
132
9
 
133
- function getGuanceHByGrafanaH(granfanH: number) {
134
- return (getGridH(granfanH, 30, 4) + 10) / 20
135
- }
136
- function covertPanelToGuanceChart(grafanaPanel: Panel, rowPanel: RowPanel | undefined): GuanceChartData {
137
- const { gridPos, title, type, targets, options } = grafanaPanel
138
- // const { gridPos: rowGridPos } = rowPanel
139
- const chartType: GuanceChartType = grafanaPanelTypeToGuanceChartMap[type]
140
- let pos = {
141
- x: gridPos!.x,
142
- w: gridPos!.w,
143
- y: gridPos!.y,
144
- h: gridPos!.h,
145
- }
146
- if (rowPanel) {
147
- const { gridPos: rowGridPos } = rowPanel
148
- if (rowGridPos && gridPos) {
149
- if (!rowPanel.collapsed) {
150
- pos = {
151
- x: gridPos.x,
152
- w: gridPos.w,
153
- y: gridPos.y - rowGridPos.y,
154
- h: gridPos.h,
155
- }
156
- }
157
- }
158
- }
159
- const queries: GuanceChartQueries = []
160
- if (targets && targets.length) {
161
- let currentIndex = 0
162
- targets.forEach((_target) => {
163
- const queryStr: string | unknown = _target.expr || _target.query || _target.queryText
164
- if (!queryStr) return
165
- currentIndex++
166
- const queryItem: GuanceChartQueryItem = {
167
- datasource: 'dataflux',
168
- qtype: 'promql',
169
- type: chartType,
170
- query: {
171
- q: replaceVariableStr(queryStr as string),
172
- type: 'promql',
173
- code: tenToTweenty(currentIndex),
174
- promqlCode: currentIndex,
175
- },
176
- }
177
- queries.push(queryItem)
178
- })
179
- }
180
- let settings: GuanceChartSettings = {}
181
- if (options) {
182
- switch (chartType) {
183
- case 'text':
184
- const queryItem: GuanceChartQueryItem = {
185
- query: {
186
- content: options.content,
187
- },
188
- }
189
- queries.push(queryItem)
190
- break
191
- case 'toplist':
192
- settings = {
193
- showTopSize: true,
194
- chartType: 'bar',
195
- }
196
- break
197
- default:
198
- break
199
- }
200
- }
201
- const guanceChart: GuanceChartData = {
202
- extend: {
203
- settings: settings,
204
- },
205
- group: {
206
- name: rowPanel ? rowPanel.title : null,
207
- },
208
- pos: {
209
- x: pos.x,
210
- y: getGuanceHByGrafanaH(pos.y),
211
- h: getGuanceHByGrafanaH(pos.h),
212
- w: pos.w,
213
- },
214
- name: replaceVariableStr(title || ''),
215
- queries: queries,
216
- type: chartType,
217
- }
218
- return guanceChart
219
- }
220
- const covertPanelsToCharts = (grafanaPanelData: Panel[], rowPanel: RowPanel | undefined): GuanceChartData[] => {
221
- const guanceCharts: GuanceChartData[] = []
222
- grafanaPanelData.forEach((grafanaPanel) => {
223
- if (!grafanaPanel.gridPos) return
224
- guanceCharts.push(covertPanelToGuanceChart(grafanaPanel, rowPanel))
225
- })
226
- return guanceCharts
227
- }
228
-
229
- const VARIABLE_MAP = {
230
- query: 'PROMQL_QUERY',
231
- custom: 'CUSTOM_LIST',
232
- }
233
- const VARIABLE_DATASOURCE_MAP = {
234
- query: 'dataflux',
235
- custom: 'custom',
236
- }
237
- const covert = (grafanaData: GrafanaDashboardType): GuanceDashboardType => {
238
- const covertGuanceResult: GuanceDashboardType = {}
239
- // 标题
240
- covertGuanceResult.title = grafanaData.title
241
- // 视图变量
242
- const guanceVars: ChartVarsSettings = []
243
- grafanaData.templating?.list?.forEach((_variable: VariableModel, index: number) => {
244
- const { current, type, allValue } = _variable
245
- if (!VARIABLE_MAP[type]) return
246
- let defaultVal = {
247
- label: '',
248
- value: '',
249
- }
250
- if (current) {
251
- let labels: string[] = []
252
- let values: string[] = []
253
- if (Array.isArray(current.text)) {
254
- labels = current.text
255
- } else if (typeof current.text === 'string') {
256
- labels = [current.text]
257
- }
258
- if (Array.isArray(current.value)) {
259
- values = current.value
260
- } else if (typeof current.value === 'string') {
261
- values = [current.value]
262
- }
263
- labels = labels.map((label) => {
264
- // all 的情况需要适配观测云
265
- if (label === 'All') {
266
- if (allValue === '.*') {
267
- return '*'
268
- } else {
269
- return 'all values'
270
- }
271
- } else {
272
- return label
273
- }
274
- })
275
- values = values.map((value) => {
276
- // all 的情况需要适配观测云
277
- if (value === '$__all') {
278
- if (allValue === '.*') {
279
- return '*'
280
- } else {
281
- return '__all__'
282
- }
283
- } else {
284
- return value
10
+ export async function run(args: string[]) {
11
+ const { argv } = yargs(args)
12
+ .usage('Convert grafana dashboard json template to guance dashboard json template.')
13
+ .option('d', {
14
+ alias: 'input',
15
+ type: 'string',
16
+ demandOption: true,
17
+ describe: 'path to grafana dashboard json file path',
18
+ coerce: (value: string) => {
19
+ const resolved = value && path.resolve(value)
20
+ if (fs.existsSync(resolved) && /\.json$/.test(resolved)) {
21
+ return resolved
285
22
  }
286
- })
287
- defaultVal = {
288
- label: labels.join(','),
289
- value: values.join(','),
290
- }
291
- }
292
- let value = _variable.query
293
- if (value && typeof value === 'object' && value.query) {
294
- value = replaceVariableStr(value.query as string)
295
- } else if (value && typeof value === 'string') {
296
- value = replaceVariableStr(_variable.query as string)
297
- } else {
298
- return
299
- }
300
- const guanceVariableItem: ChartVarsItem = {
301
- type: VARIABLE_MAP[type],
302
- datasource: VARIABLE_DATASOURCE_MAP[type],
303
- name: _variable.label || _variable.name || '',
304
- seq: index,
305
- hide: _variable.hide ? 1 : 0,
306
- multiple: _variable.multi !== undefined ? _variable.multi : true,
307
- includeStar: _variable.includeAll !== undefined ? _variable.includeAll : true,
308
- valueSort: 'desc',
309
- code: _variable.name,
310
- definition: {
311
- value: value,
312
- defaultVal: defaultVal,
23
+ throw new Error(`Input Grafana JSON File "${value}" is not a JSON!`)
313
24
  },
314
- }
315
- guanceVars.push(guanceVariableItem)
316
- })
317
- // 分组
318
- const guanceGroups: {
319
- name?: string
320
- }[] = []
321
- // 分组展开信息
322
- const guanceExpand: {
323
- [key: string]: boolean
324
- } = {}
25
+ })
26
+ .option('o', {
27
+ alias: 'out',
28
+ type: 'string',
29
+ default: path.resolve(path.join('.', 'guance-dashboard.json')),
30
+ describe: 'path to output json file path',
31
+ coerce: (value: string) => path.resolve(value),
32
+ })
33
+ .option('validate', {
34
+ type: 'boolean',
35
+ default: false,
36
+ describe: 'validate generated dashboard against schema',
37
+ })
38
+ .option('schema', {
39
+ type: 'string',
40
+ default: 'dashboard-schema.json',
41
+ describe: 'schema file name under schemas/',
42
+ })
43
+ .option('guance-promql-compatible', {
44
+ type: 'boolean',
45
+ default: false,
46
+ describe: 'rewrite PromQL metric names to Guance compatible measurement:field form',
47
+ })
48
+ .option('keep-grafana-meta', {
49
+ type: 'boolean',
50
+ default: false,
51
+ describe: 'keep source grafana metadata under extend.grafana',
52
+ })
325
53
 
326
- // 图表
327
- const guanceCharts: GuanceChartData[] = []
328
- // 前一次分组,也就是当前图表的分组
329
- let lastRowPanel: RowPanel | undefined
330
- // 当前分组的 panel 列表
331
- let lastPanels: Panel[] = []
332
- let grafanaCharts =
333
- grafanaData.panels?.filter(
334
- (_panel: Panel | RowPanel) => _panel.type === 'row' || grafanaPanelTypeToGuanceChartMap[_panel.type]
335
- ) || []
336
- grafanaCharts = sortPanelItemsByRowCol(grafanaCharts)
337
- grafanaCharts.forEach((_panel) => {
338
- if (_panel.type === 'row') {
339
- const _rowPanel = _panel as RowPanel
54
+ const grafanaJsonPath = argv.d as string
55
+ const outGuanceJsonPath = argv.o as string
340
56
 
341
- if (_rowPanel.title) {
342
- guanceGroups.push({
343
- name: _rowPanel.title,
344
- })
345
- // 分组展开收起数据
346
- guanceExpand[_rowPanel.title] = !_rowPanel.collapsed
347
- }
348
- if (lastPanels.length) {
349
- // 上一个分组的图表转换,
350
- guanceCharts.push(...covertPanelsToCharts(lastPanels, lastRowPanel))
351
- //清空上一个分组列表
352
- lastPanels = []
353
- //清空上一个分组
354
- lastRowPanel = undefined
355
- }
356
- if (_rowPanel.collapsed) {
357
- // 收起
358
- const subPanels =
359
- _rowPanel.panels?.filter(
360
- (_panel: Panel | RowPanel) => _panel.type === 'row' || grafanaPanelTypeToGuanceChartMap[_panel.type]
361
- ) || []
362
- guanceCharts.push(...covertPanelsToCharts(subPanels, _rowPanel))
363
- } else {
364
- lastRowPanel = _rowPanel
365
- // 展开
366
- }
367
- } else {
368
- lastPanels.push(_panel)
369
- }
57
+ const grafanaJSONData = JSON.parse(fs.readFileSync(grafanaJsonPath, 'utf-8'))
58
+ const convertResult = convertDashboard(grafanaJSONData, {
59
+ guancePromqlCompatible: Boolean(argv.guancePromqlCompatible),
60
+ keepGrafanaMeta: Boolean(argv.keepGrafanaMeta),
370
61
  })
371
- // 最后一个分组
372
- if (lastPanels.length) {
373
- guanceCharts.push(...covertPanelsToCharts(lastPanels, lastRowPanel))
374
- }
375
- covertGuanceResult.dashboardExtend = {
376
- groupUnfoldStatus: guanceExpand,
377
- }
378
- covertGuanceResult.main = {
379
- vars: guanceVars,
380
- charts: guanceCharts,
381
- groups: guanceGroups,
382
- }
383
- return covertGuanceResult
384
- }
385
-
386
- export async function run(args) {
387
- const { argv } = yargs(args)
388
- .usage('Convert grafana dashboard json template to guance dashboard json template.')
389
-
390
- .demand('d')
391
- .alias('d', 'input')
392
- .describe('d', 'path to grafana dashboard json file path')
393
- .coerce('d', (d) => {
394
- const resolved = d && path.resolve(d)
395
- if (fs.existsSync(resolved) && /\.json$/.test(resolved)) {
396
- return resolved
397
- }
398
- throw new Error(`Input Grafana JSON File "${d}" is not a JSON!`)
399
- })
400
62
 
401
- .alias('o', 'out')
402
- .describe('o', 'path to output json file path')
403
- .default('o', path.resolve(path.join('.', 'guance-dashboard.json')))
404
- .coerce('o', (o) => path.resolve(o))
405
- const grafanaJsonPath = argv.d
406
- const outGuanceJsonPath = argv.o
63
+ fs.mkdirSync(path.dirname(outGuanceJsonPath), { recursive: true })
64
+ fs.writeFileSync(outGuanceJsonPath, `${JSON.stringify(convertResult, null, 2)}\n`, 'utf-8')
407
65
 
408
- try {
409
- const grafanaJSONData = JSON.parse(fs.readFileSync(grafanaJsonPath, 'utf-8'))
410
- const covertResult = covert(grafanaJSONData)
411
- // 确保目录存在
412
- const dir = path.dirname(outGuanceJsonPath)
413
- if (!fs.existsSync(dir)) {
414
- fs.mkdirSync(dir, { recursive: true }) // recursive: true 确保递归创建目录
415
- }
416
- fs.writeFileSync(outGuanceJsonPath, JSON.stringify(covertResult), 'utf-8')
417
- } catch (err) {
418
- throw new Error(err)
66
+ if (argv.validate) {
67
+ validateDashboardFile(outGuanceJsonPath, String(argv.schema))
419
68
  }
420
69
  }
421
- // console.log(JSON.stringify(result, null, 2))
@@ -0,0 +1,7 @@
1
+ export { covert } from '../scripts/grafana-covert-to-guance-core.js'
2
+ export type {
3
+ GrafanaDashboardType,
4
+ GrafanaPanel,
5
+ GrafanaRowPanel,
6
+ GrafanaVariableModel,
7
+ } from '../scripts/grafana-covert-to-guance-core.js'
package/lib/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './session-replay'
2
2
  export * from './dashboard-charts'
3
+ export * from './grafana-covert-to-guance'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/guance-front-tools",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -22,8 +22,10 @@
22
22
  "build:script": "tsc -p tsconfig.script.json",
23
23
  "clean": "rm -rf ./lib/generated && rm -rf ./lib/esm && rm -rf ./lib/cjs",
24
24
  "generate": "node scripts/generate.mjs",
25
+ "test": "node --test test/*.test.mjs",
25
26
  "format": "prettier -c .",
26
- "validate": "node scripts/validate.mjs",
27
+ "validate": "node scripts/validate.mjs && npm run validate:dashboard",
28
+ "validate:dashboard": "node scripts/validate-file.mjs guance-dashboard.json guance-all-charts.json",
27
29
  "prepare": "npm run build"
28
30
  },
29
31
  "devDependencies": {
@@ -36,11 +38,11 @@
36
38
  "@types/node": "^12.20.55"
37
39
  },
38
40
  "engines": {
39
- "node": ">=12.7.0"
41
+ "node": ">=18.0.0"
40
42
  },
41
43
  "author": "",
42
44
  "license": "ISC",
43
45
  "dependencies": {
44
46
  "yargs": "^17.7.2"
45
47
  }
46
- }
48
+ }
@@ -16,6 +16,9 @@
16
16
  "type": "object",
17
17
  "additionalProperties": true,
18
18
  "properties": {
19
+ "links": {
20
+ "$ref": "common/chart-links-schema.json"
21
+ },
19
22
  "settings": {
20
23
  "$ref": "settings/settings-schema.json"
21
24
  }
@@ -54,18 +57,18 @@
54
57
  "properties": {
55
58
  "h": {
56
59
  "description": "图表高度,每行的高度默认为10像素,比如 h 为12, 则实际高度为 12 * 10",
57
- "type": "integer"
60
+ "type": "number"
58
61
  },
59
62
  "w": {
60
- "type": "integer",
63
+ "type": "number",
61
64
  "description": "图表宽度,栅格系统的最大列数为 24, 比如 w为12,则显示宽度则为容器宽度的 1/2 倍 "
62
65
  },
63
66
  "x": {
64
- "type": "integer",
67
+ "type": "number",
65
68
  "description": "图表距离容器的水平距离,栅格系统的最大列数为 24, 比如 x为12,则图表距离容器左边的水平距离为容器宽度 1/2 倍 "
66
69
  },
67
70
  "y": {
68
- "type": "integer",
71
+ "type": "number",
69
72
  "description": "图表距离容器垂直距离,每行的高度默认为10像素,比如 y为12, 则实际高度为 12 * 10"
70
73
  }
71
74
  }
@@ -78,4 +81,4 @@
78
81
  "$ref": "query/queries-schema.json"
79
82
  }
80
83
  }
81
- }
84
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "charts/common/chart-link-item-schema.json",
4
+ "type": "object",
5
+ "description": "图表联动跳转项",
6
+ "required": [
7
+ "url",
8
+ "open",
9
+ "show",
10
+ "type",
11
+ "showChanged"
12
+ ],
13
+ "properties": {
14
+ "url": {
15
+ "type": "string",
16
+ "description": "跳转地址"
17
+ },
18
+ "open": {
19
+ "type": "string",
20
+ "description": "打开方式",
21
+ "enum": [
22
+ "newWin",
23
+ "curWin",
24
+ "drawerWin"
25
+ ]
26
+ },
27
+ "show": {
28
+ "type": "boolean",
29
+ "description": "是否展示"
30
+ },
31
+ "type": {
32
+ "type": "string",
33
+ "description": "跳转类型",
34
+ "enum": [
35
+ "logging",
36
+ "container",
37
+ "processes",
38
+ "tracing",
39
+ "host",
40
+ "custom"
41
+ ]
42
+ },
43
+ "showChanged": {
44
+ "type": "boolean",
45
+ "description": "是否修改过显示状态"
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "charts/common/chart-links-schema.json",
4
+ "type": "array",
5
+ "description": "图表跳转链接列表",
6
+ "items": {
7
+ "$ref": "chart-link-item-schema.json"
8
+ }
9
+ }
@@ -25,8 +25,10 @@
25
25
  "heatmap",
26
26
  "topology",
27
27
  "sankey",
28
+ "change",
28
29
  "log",
29
30
  "object",
31
+ "monitor",
30
32
  "alarm",
31
33
  "text",
32
34
  "video",
@@ -34,4 +36,4 @@
34
36
  "command",
35
37
  "iframe"
36
38
  ]
37
- }
39
+ }
@@ -48,9 +48,16 @@
48
48
  }
49
49
  },
50
50
  "type": {
51
- "type": "string",
52
- "description": "固定字段",
53
- "const": "template"
51
+ "description": "仪表板主体类型,现有数据中常缺省,存在时固定为 template",
52
+ "anyOf": [
53
+ {
54
+ "type": "string",
55
+ "const": "template"
56
+ },
57
+ {
58
+ "type": "null"
59
+ }
60
+ ]
54
61
  }
55
62
  }
56
63
  },
@@ -70,4 +77,4 @@
70
77
  }
71
78
  }
72
79
  }
73
- }
80
+ }