diff --git a/custom/util/grid.libsonnet b/custom/util/grid.libsonnet index bae4d109..fabbcda2 100644 --- a/custom/util/grid.libsonnet +++ b/custom/util/grid.libsonnet @@ -1,37 +1,13 @@ local d = import 'github.com/jsonnet-libs/docsonnet/doc-util/main.libsonnet'; local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; +local panelUtil = import './panel.libsonnet'; + { local root = self, - local rowPanelHeight = 1, local gridWidth = 24, - // Calculates the number of rows for a set of panels. - countRows(panels, panelWidth): - std.ceil(std.length(panels) / std.floor(gridWidth / panelWidth)), - - // Calculates gridPos for a panel based on its index, width and height. - gridPosForIndex(index, panelWidth, panelHeight, startY): { - local panelsPerRow = std.floor(gridWidth / panelWidth), - local row = std.floor(index / panelsPerRow), - local col = std.mod(index, panelsPerRow), - gridPos: { - w: panelWidth, - h: panelHeight, - x: panelWidth * col, - y: startY + (panelHeight * row) + row, - }, - }, - - // Configures gridPos for each panel in a grid with equal width and equal height. - makePanelGrid(panels, panelWidth, panelHeight, startY): - std.mapWithIndex( - function(i, panel) - panel + root.gridPosForIndex(i, panelWidth, panelHeight, startY), - panels - ), - '#makeGrid':: d.func.new( ||| `makeGrid` returns an array of `panels` organized in a grid with equal `panelWidth` @@ -52,90 +28,52 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ], ), makeGrid(panels, panelWidth=8, panelHeight=8, startY=0): - // Get indexes for all Row panels - local rowIndexes = - xtd.array.filterMapWithIndex( - function(i, p) p.type == 'row', - function(i, p) i, - panels, - ); + local sanitizePanels(ps) = std.map( + function(p) + local sanePanel = panelUtil.sanitizePanel(p); + ( + if p.type == 'row' + then sanePanel + { + panels: sanitizePanels(sanePanel.panels), + } + else sanePanel + { + gridPos+: { + h: panelHeight, + w: panelWidth, + }, + } + ), + ps + ); - // Group panels below each Row panel - local rowGroups = - std.mapWithIndex( - function(i, r) { - header: - { - // Set initial values to ensure a value is set - // may be overridden at per Row panel - collapsed: false, - panels: [], - } - + panels[r], - panels: - self.header.panels // prepend panels that are part of the Row panel - + (if i == std.length(rowIndexes) - 1 // last rowIndex - then panels[r + 1:] - else panels[r + 1:rowIndexes[i + 1]]), - rows: root.countRows(self.panels, panelWidth), - }, - rowIndexes - ); + local sanitizedPanels = sanitizePanels(panels); - // Loop over rowGroups - std.foldl( - function(acc, rowGroup) acc + { - local y = acc.nexty, - nexty: y // previous y - + (rowGroup.rows * panelHeight) // height of all rows - + rowGroup.rows // plus 1 for each row - + acc.lastRowPanelHeight, + local grouped = panelUtil.groupPanelsInRows(sanitizedPanels); - lastRowPanelHeight: rowPanelHeight, // set height for next round + local panelsBeforeRows = panelUtil.getPanelsBeforeNextRow(grouped); + local rowPanels = + std.filter( + function(p) p.type == 'row', + grouped + ); - // Create a grid per group - local panels = root.makePanelGrid(rowGroup.panels, panelWidth, panelHeight, y + 1), + local CalculateXforPanel(index, panel) = + local panelsPerRow = std.floor(gridWidth / panelWidth); + local col = std.mod(index, panelsPerRow); + panel + { gridPos+: { x: panelWidth * col } }; - panels+: - [ - // Add row header aka the Row panel - rowGroup.header + { - gridPos: { - w: gridWidth, // always full length - h: rowPanelHeight, // always 1 height - x: 0, // always at beginning - y: y, - }, - panels: - // If row is collapsed, then store panels inside Row panel - if rowGroup.header.collapsed - then panels - else [], - }, - ] - + ( - // If row is not collapsed, then expose panels directly - if !rowGroup.header.collapsed - then panels - else [] - ), - }, - rowGroups, - { - // Get panels that come before the rowGroups - local panelsBeforeRowGroups = - if std.length(rowIndexes) != 0 - then panels[0:rowIndexes[0]] - else panels, // matches all panels if no Row panels found - local rows = root.countRows(panelsBeforeRowGroups, panelWidth), - nexty: startY + (rows * panelHeight) + rows, + local panelsBeforeRowsWithX = std.mapWithIndex(CalculateXforPanel, panelsBeforeRows); - lastRowPanelHeight: 0, // starts without a row panel + local rowPanelsWithX = + std.map( + function(row) + row + { panels: std.mapWithIndex(CalculateXforPanel, row.panels) }, + rowPanels + ); - // Create a grid for the panels that come before the rowGroups - panels: root.makePanelGrid(panelsBeforeRowGroups, panelWidth, panelHeight, startY), - } - ).panels, + local uncollapsed = panelUtil.resolveCollapsedFlagOnRows(panelsBeforeRowsWithX + rowPanelsWithX); + + panelUtil.normalizeY(uncollapsed), '#wrapPanels':: d.func.new( ||| diff --git a/custom/util/panel.libsonnet b/custom/util/panel.libsonnet index dd250071..e2684dff 100644 --- a/custom/util/panel.libsonnet +++ b/custom/util/panel.libsonnet @@ -224,14 +224,15 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ] ), calculateLowestYforPanel(panel, panels): - local x1 = panel.gridPos.x; - local x2 = panel.gridPos.x + panel.gridPos.w; xtd.number.maxInArray( // the new position is highest value (max) on the Y-scale std.filterMap( function(p) // find panels that overlap on X-scale - p.gridPos.x == x1 - || xtd.number.inRange(p.gridPos.x, x1, x2) - || xtd.number.inRange((p.gridPos.x + p.gridPos.w), x1, x2), + local v1 = panel.gridPos.x; + local v2 = panel.gridPos.x + panel.gridPos.w; + local x1 = p.gridPos.x; + local x2 = p.gridPos.x + p.gridPos.w; + (v1 >= x1 && v1 < x2) + || (v2 >= x1 && v2 < x2), function(p) // return new position on Y-scale p.gridPos.y + p.gridPos.h, panels, diff --git a/examples/runtimeDashboard/output.json b/examples/runtimeDashboard/output.json index 6916cd27..e8453da6 100644 --- a/examples/runtimeDashboard/output.json +++ b/examples/runtimeDashboard/output.json @@ -232,7 +232,7 @@ "h": 8, "w": 8, "x": 0, - "y": 10 + "y": 9 }, "id": 5, "interval": "1m", @@ -282,7 +282,7 @@ "h": 8, "w": 8, "x": 8, - "y": 10 + "y": 9 }, "id": 6, "interval": "1m", @@ -316,7 +316,7 @@ "h": 1, "w": 24, "x": 0, - "y": 18 + "y": 17 }, "id": 7, "panels": [ @@ -329,7 +329,7 @@ "h": 8, "w": 8, "x": 0, - "y": 19 + "y": 0 }, "id": 8, "interval": "1m", @@ -409,7 +409,7 @@ "h": 8, "w": 8, "x": 8, - "y": 19 + "y": 0 }, "id": 9, "interval": "1m", @@ -474,7 +474,7 @@ "h": 8, "w": 8, "x": 16, - "y": 19 + "y": 0 }, "id": 10, "interval": "1m", @@ -521,7 +521,7 @@ "h": 8, "w": 8, "x": 0, - "y": 28 + "y": 0 }, "id": 11, "interval": "1m", @@ -559,7 +559,7 @@ "h": 1, "w": 24, "x": 0, - "y": 37 + "y": 18 }, "id": 12, "panels": [ @@ -572,7 +572,7 @@ "h": 8, "w": 8, "x": 0, - "y": 38 + "y": 0 }, "id": 13, "interval": "1m", @@ -652,7 +652,7 @@ "h": 8, "w": 8, "x": 8, - "y": 38 + "y": 0 }, "id": 14, "interval": "1m", diff --git a/gen/grafonnet-v10.0.0/custom/util/grid.libsonnet b/gen/grafonnet-v10.0.0/custom/util/grid.libsonnet index bae4d109..fabbcda2 100644 --- a/gen/grafonnet-v10.0.0/custom/util/grid.libsonnet +++ b/gen/grafonnet-v10.0.0/custom/util/grid.libsonnet @@ -1,37 +1,13 @@ local d = import 'github.com/jsonnet-libs/docsonnet/doc-util/main.libsonnet'; local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; +local panelUtil = import './panel.libsonnet'; + { local root = self, - local rowPanelHeight = 1, local gridWidth = 24, - // Calculates the number of rows for a set of panels. - countRows(panels, panelWidth): - std.ceil(std.length(panels) / std.floor(gridWidth / panelWidth)), - - // Calculates gridPos for a panel based on its index, width and height. - gridPosForIndex(index, panelWidth, panelHeight, startY): { - local panelsPerRow = std.floor(gridWidth / panelWidth), - local row = std.floor(index / panelsPerRow), - local col = std.mod(index, panelsPerRow), - gridPos: { - w: panelWidth, - h: panelHeight, - x: panelWidth * col, - y: startY + (panelHeight * row) + row, - }, - }, - - // Configures gridPos for each panel in a grid with equal width and equal height. - makePanelGrid(panels, panelWidth, panelHeight, startY): - std.mapWithIndex( - function(i, panel) - panel + root.gridPosForIndex(i, panelWidth, panelHeight, startY), - panels - ), - '#makeGrid':: d.func.new( ||| `makeGrid` returns an array of `panels` organized in a grid with equal `panelWidth` @@ -52,90 +28,52 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ], ), makeGrid(panels, panelWidth=8, panelHeight=8, startY=0): - // Get indexes for all Row panels - local rowIndexes = - xtd.array.filterMapWithIndex( - function(i, p) p.type == 'row', - function(i, p) i, - panels, - ); + local sanitizePanels(ps) = std.map( + function(p) + local sanePanel = panelUtil.sanitizePanel(p); + ( + if p.type == 'row' + then sanePanel + { + panels: sanitizePanels(sanePanel.panels), + } + else sanePanel + { + gridPos+: { + h: panelHeight, + w: panelWidth, + }, + } + ), + ps + ); - // Group panels below each Row panel - local rowGroups = - std.mapWithIndex( - function(i, r) { - header: - { - // Set initial values to ensure a value is set - // may be overridden at per Row panel - collapsed: false, - panels: [], - } - + panels[r], - panels: - self.header.panels // prepend panels that are part of the Row panel - + (if i == std.length(rowIndexes) - 1 // last rowIndex - then panels[r + 1:] - else panels[r + 1:rowIndexes[i + 1]]), - rows: root.countRows(self.panels, panelWidth), - }, - rowIndexes - ); + local sanitizedPanels = sanitizePanels(panels); - // Loop over rowGroups - std.foldl( - function(acc, rowGroup) acc + { - local y = acc.nexty, - nexty: y // previous y - + (rowGroup.rows * panelHeight) // height of all rows - + rowGroup.rows // plus 1 for each row - + acc.lastRowPanelHeight, + local grouped = panelUtil.groupPanelsInRows(sanitizedPanels); - lastRowPanelHeight: rowPanelHeight, // set height for next round + local panelsBeforeRows = panelUtil.getPanelsBeforeNextRow(grouped); + local rowPanels = + std.filter( + function(p) p.type == 'row', + grouped + ); - // Create a grid per group - local panels = root.makePanelGrid(rowGroup.panels, panelWidth, panelHeight, y + 1), + local CalculateXforPanel(index, panel) = + local panelsPerRow = std.floor(gridWidth / panelWidth); + local col = std.mod(index, panelsPerRow); + panel + { gridPos+: { x: panelWidth * col } }; - panels+: - [ - // Add row header aka the Row panel - rowGroup.header + { - gridPos: { - w: gridWidth, // always full length - h: rowPanelHeight, // always 1 height - x: 0, // always at beginning - y: y, - }, - panels: - // If row is collapsed, then store panels inside Row panel - if rowGroup.header.collapsed - then panels - else [], - }, - ] - + ( - // If row is not collapsed, then expose panels directly - if !rowGroup.header.collapsed - then panels - else [] - ), - }, - rowGroups, - { - // Get panels that come before the rowGroups - local panelsBeforeRowGroups = - if std.length(rowIndexes) != 0 - then panels[0:rowIndexes[0]] - else panels, // matches all panels if no Row panels found - local rows = root.countRows(panelsBeforeRowGroups, panelWidth), - nexty: startY + (rows * panelHeight) + rows, + local panelsBeforeRowsWithX = std.mapWithIndex(CalculateXforPanel, panelsBeforeRows); - lastRowPanelHeight: 0, // starts without a row panel + local rowPanelsWithX = + std.map( + function(row) + row + { panels: std.mapWithIndex(CalculateXforPanel, row.panels) }, + rowPanels + ); - // Create a grid for the panels that come before the rowGroups - panels: root.makePanelGrid(panelsBeforeRowGroups, panelWidth, panelHeight, startY), - } - ).panels, + local uncollapsed = panelUtil.resolveCollapsedFlagOnRows(panelsBeforeRowsWithX + rowPanelsWithX); + + panelUtil.normalizeY(uncollapsed), '#wrapPanels':: d.func.new( ||| diff --git a/gen/grafonnet-v10.0.0/custom/util/panel.libsonnet b/gen/grafonnet-v10.0.0/custom/util/panel.libsonnet index dd250071..e2684dff 100644 --- a/gen/grafonnet-v10.0.0/custom/util/panel.libsonnet +++ b/gen/grafonnet-v10.0.0/custom/util/panel.libsonnet @@ -224,14 +224,15 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ] ), calculateLowestYforPanel(panel, panels): - local x1 = panel.gridPos.x; - local x2 = panel.gridPos.x + panel.gridPos.w; xtd.number.maxInArray( // the new position is highest value (max) on the Y-scale std.filterMap( function(p) // find panels that overlap on X-scale - p.gridPos.x == x1 - || xtd.number.inRange(p.gridPos.x, x1, x2) - || xtd.number.inRange((p.gridPos.x + p.gridPos.w), x1, x2), + local v1 = panel.gridPos.x; + local v2 = panel.gridPos.x + panel.gridPos.w; + local x1 = p.gridPos.x; + local x2 = p.gridPos.x + p.gridPos.w; + (v1 >= x1 && v1 < x2) + || (v2 >= x1 && v2 < x2), function(p) // return new position on Y-scale p.gridPos.y + p.gridPos.h, panels, diff --git a/gen/grafonnet-v10.1.0/custom/util/grid.libsonnet b/gen/grafonnet-v10.1.0/custom/util/grid.libsonnet index bae4d109..fabbcda2 100644 --- a/gen/grafonnet-v10.1.0/custom/util/grid.libsonnet +++ b/gen/grafonnet-v10.1.0/custom/util/grid.libsonnet @@ -1,37 +1,13 @@ local d = import 'github.com/jsonnet-libs/docsonnet/doc-util/main.libsonnet'; local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; +local panelUtil = import './panel.libsonnet'; + { local root = self, - local rowPanelHeight = 1, local gridWidth = 24, - // Calculates the number of rows for a set of panels. - countRows(panels, panelWidth): - std.ceil(std.length(panels) / std.floor(gridWidth / panelWidth)), - - // Calculates gridPos for a panel based on its index, width and height. - gridPosForIndex(index, panelWidth, panelHeight, startY): { - local panelsPerRow = std.floor(gridWidth / panelWidth), - local row = std.floor(index / panelsPerRow), - local col = std.mod(index, panelsPerRow), - gridPos: { - w: panelWidth, - h: panelHeight, - x: panelWidth * col, - y: startY + (panelHeight * row) + row, - }, - }, - - // Configures gridPos for each panel in a grid with equal width and equal height. - makePanelGrid(panels, panelWidth, panelHeight, startY): - std.mapWithIndex( - function(i, panel) - panel + root.gridPosForIndex(i, panelWidth, panelHeight, startY), - panels - ), - '#makeGrid':: d.func.new( ||| `makeGrid` returns an array of `panels` organized in a grid with equal `panelWidth` @@ -52,90 +28,52 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ], ), makeGrid(panels, panelWidth=8, panelHeight=8, startY=0): - // Get indexes for all Row panels - local rowIndexes = - xtd.array.filterMapWithIndex( - function(i, p) p.type == 'row', - function(i, p) i, - panels, - ); + local sanitizePanels(ps) = std.map( + function(p) + local sanePanel = panelUtil.sanitizePanel(p); + ( + if p.type == 'row' + then sanePanel + { + panels: sanitizePanels(sanePanel.panels), + } + else sanePanel + { + gridPos+: { + h: panelHeight, + w: panelWidth, + }, + } + ), + ps + ); - // Group panels below each Row panel - local rowGroups = - std.mapWithIndex( - function(i, r) { - header: - { - // Set initial values to ensure a value is set - // may be overridden at per Row panel - collapsed: false, - panels: [], - } - + panels[r], - panels: - self.header.panels // prepend panels that are part of the Row panel - + (if i == std.length(rowIndexes) - 1 // last rowIndex - then panels[r + 1:] - else panels[r + 1:rowIndexes[i + 1]]), - rows: root.countRows(self.panels, panelWidth), - }, - rowIndexes - ); + local sanitizedPanels = sanitizePanels(panels); - // Loop over rowGroups - std.foldl( - function(acc, rowGroup) acc + { - local y = acc.nexty, - nexty: y // previous y - + (rowGroup.rows * panelHeight) // height of all rows - + rowGroup.rows // plus 1 for each row - + acc.lastRowPanelHeight, + local grouped = panelUtil.groupPanelsInRows(sanitizedPanels); - lastRowPanelHeight: rowPanelHeight, // set height for next round + local panelsBeforeRows = panelUtil.getPanelsBeforeNextRow(grouped); + local rowPanels = + std.filter( + function(p) p.type == 'row', + grouped + ); - // Create a grid per group - local panels = root.makePanelGrid(rowGroup.panels, panelWidth, panelHeight, y + 1), + local CalculateXforPanel(index, panel) = + local panelsPerRow = std.floor(gridWidth / panelWidth); + local col = std.mod(index, panelsPerRow); + panel + { gridPos+: { x: panelWidth * col } }; - panels+: - [ - // Add row header aka the Row panel - rowGroup.header + { - gridPos: { - w: gridWidth, // always full length - h: rowPanelHeight, // always 1 height - x: 0, // always at beginning - y: y, - }, - panels: - // If row is collapsed, then store panels inside Row panel - if rowGroup.header.collapsed - then panels - else [], - }, - ] - + ( - // If row is not collapsed, then expose panels directly - if !rowGroup.header.collapsed - then panels - else [] - ), - }, - rowGroups, - { - // Get panels that come before the rowGroups - local panelsBeforeRowGroups = - if std.length(rowIndexes) != 0 - then panels[0:rowIndexes[0]] - else panels, // matches all panels if no Row panels found - local rows = root.countRows(panelsBeforeRowGroups, panelWidth), - nexty: startY + (rows * panelHeight) + rows, + local panelsBeforeRowsWithX = std.mapWithIndex(CalculateXforPanel, panelsBeforeRows); - lastRowPanelHeight: 0, // starts without a row panel + local rowPanelsWithX = + std.map( + function(row) + row + { panels: std.mapWithIndex(CalculateXforPanel, row.panels) }, + rowPanels + ); - // Create a grid for the panels that come before the rowGroups - panels: root.makePanelGrid(panelsBeforeRowGroups, panelWidth, panelHeight, startY), - } - ).panels, + local uncollapsed = panelUtil.resolveCollapsedFlagOnRows(panelsBeforeRowsWithX + rowPanelsWithX); + + panelUtil.normalizeY(uncollapsed), '#wrapPanels':: d.func.new( ||| diff --git a/gen/grafonnet-v10.1.0/custom/util/panel.libsonnet b/gen/grafonnet-v10.1.0/custom/util/panel.libsonnet index dd250071..e2684dff 100644 --- a/gen/grafonnet-v10.1.0/custom/util/panel.libsonnet +++ b/gen/grafonnet-v10.1.0/custom/util/panel.libsonnet @@ -224,14 +224,15 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ] ), calculateLowestYforPanel(panel, panels): - local x1 = panel.gridPos.x; - local x2 = panel.gridPos.x + panel.gridPos.w; xtd.number.maxInArray( // the new position is highest value (max) on the Y-scale std.filterMap( function(p) // find panels that overlap on X-scale - p.gridPos.x == x1 - || xtd.number.inRange(p.gridPos.x, x1, x2) - || xtd.number.inRange((p.gridPos.x + p.gridPos.w), x1, x2), + local v1 = panel.gridPos.x; + local v2 = panel.gridPos.x + panel.gridPos.w; + local x1 = p.gridPos.x; + local x2 = p.gridPos.x + p.gridPos.w; + (v1 >= x1 && v1 < x2) + || (v2 >= x1 && v2 < x2), function(p) // return new position on Y-scale p.gridPos.y + p.gridPos.h, panels, diff --git a/gen/grafonnet-v9.4.0/custom/util/grid.libsonnet b/gen/grafonnet-v9.4.0/custom/util/grid.libsonnet index bae4d109..fabbcda2 100644 --- a/gen/grafonnet-v9.4.0/custom/util/grid.libsonnet +++ b/gen/grafonnet-v9.4.0/custom/util/grid.libsonnet @@ -1,37 +1,13 @@ local d = import 'github.com/jsonnet-libs/docsonnet/doc-util/main.libsonnet'; local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; +local panelUtil = import './panel.libsonnet'; + { local root = self, - local rowPanelHeight = 1, local gridWidth = 24, - // Calculates the number of rows for a set of panels. - countRows(panels, panelWidth): - std.ceil(std.length(panels) / std.floor(gridWidth / panelWidth)), - - // Calculates gridPos for a panel based on its index, width and height. - gridPosForIndex(index, panelWidth, panelHeight, startY): { - local panelsPerRow = std.floor(gridWidth / panelWidth), - local row = std.floor(index / panelsPerRow), - local col = std.mod(index, panelsPerRow), - gridPos: { - w: panelWidth, - h: panelHeight, - x: panelWidth * col, - y: startY + (panelHeight * row) + row, - }, - }, - - // Configures gridPos for each panel in a grid with equal width and equal height. - makePanelGrid(panels, panelWidth, panelHeight, startY): - std.mapWithIndex( - function(i, panel) - panel + root.gridPosForIndex(i, panelWidth, panelHeight, startY), - panels - ), - '#makeGrid':: d.func.new( ||| `makeGrid` returns an array of `panels` organized in a grid with equal `panelWidth` @@ -52,90 +28,52 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ], ), makeGrid(panels, panelWidth=8, panelHeight=8, startY=0): - // Get indexes for all Row panels - local rowIndexes = - xtd.array.filterMapWithIndex( - function(i, p) p.type == 'row', - function(i, p) i, - panels, - ); + local sanitizePanels(ps) = std.map( + function(p) + local sanePanel = panelUtil.sanitizePanel(p); + ( + if p.type == 'row' + then sanePanel + { + panels: sanitizePanels(sanePanel.panels), + } + else sanePanel + { + gridPos+: { + h: panelHeight, + w: panelWidth, + }, + } + ), + ps + ); - // Group panels below each Row panel - local rowGroups = - std.mapWithIndex( - function(i, r) { - header: - { - // Set initial values to ensure a value is set - // may be overridden at per Row panel - collapsed: false, - panels: [], - } - + panels[r], - panels: - self.header.panels // prepend panels that are part of the Row panel - + (if i == std.length(rowIndexes) - 1 // last rowIndex - then panels[r + 1:] - else panels[r + 1:rowIndexes[i + 1]]), - rows: root.countRows(self.panels, panelWidth), - }, - rowIndexes - ); + local sanitizedPanels = sanitizePanels(panels); - // Loop over rowGroups - std.foldl( - function(acc, rowGroup) acc + { - local y = acc.nexty, - nexty: y // previous y - + (rowGroup.rows * panelHeight) // height of all rows - + rowGroup.rows // plus 1 for each row - + acc.lastRowPanelHeight, + local grouped = panelUtil.groupPanelsInRows(sanitizedPanels); - lastRowPanelHeight: rowPanelHeight, // set height for next round + local panelsBeforeRows = panelUtil.getPanelsBeforeNextRow(grouped); + local rowPanels = + std.filter( + function(p) p.type == 'row', + grouped + ); - // Create a grid per group - local panels = root.makePanelGrid(rowGroup.panels, panelWidth, panelHeight, y + 1), + local CalculateXforPanel(index, panel) = + local panelsPerRow = std.floor(gridWidth / panelWidth); + local col = std.mod(index, panelsPerRow); + panel + { gridPos+: { x: panelWidth * col } }; - panels+: - [ - // Add row header aka the Row panel - rowGroup.header + { - gridPos: { - w: gridWidth, // always full length - h: rowPanelHeight, // always 1 height - x: 0, // always at beginning - y: y, - }, - panels: - // If row is collapsed, then store panels inside Row panel - if rowGroup.header.collapsed - then panels - else [], - }, - ] - + ( - // If row is not collapsed, then expose panels directly - if !rowGroup.header.collapsed - then panels - else [] - ), - }, - rowGroups, - { - // Get panels that come before the rowGroups - local panelsBeforeRowGroups = - if std.length(rowIndexes) != 0 - then panels[0:rowIndexes[0]] - else panels, // matches all panels if no Row panels found - local rows = root.countRows(panelsBeforeRowGroups, panelWidth), - nexty: startY + (rows * panelHeight) + rows, + local panelsBeforeRowsWithX = std.mapWithIndex(CalculateXforPanel, panelsBeforeRows); - lastRowPanelHeight: 0, // starts without a row panel + local rowPanelsWithX = + std.map( + function(row) + row + { panels: std.mapWithIndex(CalculateXforPanel, row.panels) }, + rowPanels + ); - // Create a grid for the panels that come before the rowGroups - panels: root.makePanelGrid(panelsBeforeRowGroups, panelWidth, panelHeight, startY), - } - ).panels, + local uncollapsed = panelUtil.resolveCollapsedFlagOnRows(panelsBeforeRowsWithX + rowPanelsWithX); + + panelUtil.normalizeY(uncollapsed), '#wrapPanels':: d.func.new( ||| diff --git a/gen/grafonnet-v9.4.0/custom/util/panel.libsonnet b/gen/grafonnet-v9.4.0/custom/util/panel.libsonnet index dd250071..e2684dff 100644 --- a/gen/grafonnet-v9.4.0/custom/util/panel.libsonnet +++ b/gen/grafonnet-v9.4.0/custom/util/panel.libsonnet @@ -224,14 +224,15 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ] ), calculateLowestYforPanel(panel, panels): - local x1 = panel.gridPos.x; - local x2 = panel.gridPos.x + panel.gridPos.w; xtd.number.maxInArray( // the new position is highest value (max) on the Y-scale std.filterMap( function(p) // find panels that overlap on X-scale - p.gridPos.x == x1 - || xtd.number.inRange(p.gridPos.x, x1, x2) - || xtd.number.inRange((p.gridPos.x + p.gridPos.w), x1, x2), + local v1 = panel.gridPos.x; + local v2 = panel.gridPos.x + panel.gridPos.w; + local x1 = p.gridPos.x; + local x2 = p.gridPos.x + p.gridPos.w; + (v1 >= x1 && v1 < x2) + || (v2 >= x1 && v2 < x2), function(p) // return new position on Y-scale p.gridPos.y + p.gridPos.h, panels, diff --git a/gen/grafonnet-v9.5.0/custom/util/grid.libsonnet b/gen/grafonnet-v9.5.0/custom/util/grid.libsonnet index bae4d109..fabbcda2 100644 --- a/gen/grafonnet-v9.5.0/custom/util/grid.libsonnet +++ b/gen/grafonnet-v9.5.0/custom/util/grid.libsonnet @@ -1,37 +1,13 @@ local d = import 'github.com/jsonnet-libs/docsonnet/doc-util/main.libsonnet'; local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; +local panelUtil = import './panel.libsonnet'; + { local root = self, - local rowPanelHeight = 1, local gridWidth = 24, - // Calculates the number of rows for a set of panels. - countRows(panels, panelWidth): - std.ceil(std.length(panels) / std.floor(gridWidth / panelWidth)), - - // Calculates gridPos for a panel based on its index, width and height. - gridPosForIndex(index, panelWidth, panelHeight, startY): { - local panelsPerRow = std.floor(gridWidth / panelWidth), - local row = std.floor(index / panelsPerRow), - local col = std.mod(index, panelsPerRow), - gridPos: { - w: panelWidth, - h: panelHeight, - x: panelWidth * col, - y: startY + (panelHeight * row) + row, - }, - }, - - // Configures gridPos for each panel in a grid with equal width and equal height. - makePanelGrid(panels, panelWidth, panelHeight, startY): - std.mapWithIndex( - function(i, panel) - panel + root.gridPosForIndex(i, panelWidth, panelHeight, startY), - panels - ), - '#makeGrid':: d.func.new( ||| `makeGrid` returns an array of `panels` organized in a grid with equal `panelWidth` @@ -52,90 +28,52 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ], ), makeGrid(panels, panelWidth=8, panelHeight=8, startY=0): - // Get indexes for all Row panels - local rowIndexes = - xtd.array.filterMapWithIndex( - function(i, p) p.type == 'row', - function(i, p) i, - panels, - ); + local sanitizePanels(ps) = std.map( + function(p) + local sanePanel = panelUtil.sanitizePanel(p); + ( + if p.type == 'row' + then sanePanel + { + panels: sanitizePanels(sanePanel.panels), + } + else sanePanel + { + gridPos+: { + h: panelHeight, + w: panelWidth, + }, + } + ), + ps + ); - // Group panels below each Row panel - local rowGroups = - std.mapWithIndex( - function(i, r) { - header: - { - // Set initial values to ensure a value is set - // may be overridden at per Row panel - collapsed: false, - panels: [], - } - + panels[r], - panels: - self.header.panels // prepend panels that are part of the Row panel - + (if i == std.length(rowIndexes) - 1 // last rowIndex - then panels[r + 1:] - else panels[r + 1:rowIndexes[i + 1]]), - rows: root.countRows(self.panels, panelWidth), - }, - rowIndexes - ); + local sanitizedPanels = sanitizePanels(panels); - // Loop over rowGroups - std.foldl( - function(acc, rowGroup) acc + { - local y = acc.nexty, - nexty: y // previous y - + (rowGroup.rows * panelHeight) // height of all rows - + rowGroup.rows // plus 1 for each row - + acc.lastRowPanelHeight, + local grouped = panelUtil.groupPanelsInRows(sanitizedPanels); - lastRowPanelHeight: rowPanelHeight, // set height for next round + local panelsBeforeRows = panelUtil.getPanelsBeforeNextRow(grouped); + local rowPanels = + std.filter( + function(p) p.type == 'row', + grouped + ); - // Create a grid per group - local panels = root.makePanelGrid(rowGroup.panels, panelWidth, panelHeight, y + 1), + local CalculateXforPanel(index, panel) = + local panelsPerRow = std.floor(gridWidth / panelWidth); + local col = std.mod(index, panelsPerRow); + panel + { gridPos+: { x: panelWidth * col } }; - panels+: - [ - // Add row header aka the Row panel - rowGroup.header + { - gridPos: { - w: gridWidth, // always full length - h: rowPanelHeight, // always 1 height - x: 0, // always at beginning - y: y, - }, - panels: - // If row is collapsed, then store panels inside Row panel - if rowGroup.header.collapsed - then panels - else [], - }, - ] - + ( - // If row is not collapsed, then expose panels directly - if !rowGroup.header.collapsed - then panels - else [] - ), - }, - rowGroups, - { - // Get panels that come before the rowGroups - local panelsBeforeRowGroups = - if std.length(rowIndexes) != 0 - then panels[0:rowIndexes[0]] - else panels, // matches all panels if no Row panels found - local rows = root.countRows(panelsBeforeRowGroups, panelWidth), - nexty: startY + (rows * panelHeight) + rows, + local panelsBeforeRowsWithX = std.mapWithIndex(CalculateXforPanel, panelsBeforeRows); - lastRowPanelHeight: 0, // starts without a row panel + local rowPanelsWithX = + std.map( + function(row) + row + { panels: std.mapWithIndex(CalculateXforPanel, row.panels) }, + rowPanels + ); - // Create a grid for the panels that come before the rowGroups - panels: root.makePanelGrid(panelsBeforeRowGroups, panelWidth, panelHeight, startY), - } - ).panels, + local uncollapsed = panelUtil.resolveCollapsedFlagOnRows(panelsBeforeRowsWithX + rowPanelsWithX); + + panelUtil.normalizeY(uncollapsed), '#wrapPanels':: d.func.new( ||| diff --git a/gen/grafonnet-v9.5.0/custom/util/panel.libsonnet b/gen/grafonnet-v9.5.0/custom/util/panel.libsonnet index dd250071..e2684dff 100644 --- a/gen/grafonnet-v9.5.0/custom/util/panel.libsonnet +++ b/gen/grafonnet-v9.5.0/custom/util/panel.libsonnet @@ -224,14 +224,15 @@ local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; ] ), calculateLowestYforPanel(panel, panels): - local x1 = panel.gridPos.x; - local x2 = panel.gridPos.x + panel.gridPos.w; xtd.number.maxInArray( // the new position is highest value (max) on the Y-scale std.filterMap( function(p) // find panels that overlap on X-scale - p.gridPos.x == x1 - || xtd.number.inRange(p.gridPos.x, x1, x2) - || xtd.number.inRange((p.gridPos.x + p.gridPos.w), x1, x2), + local v1 = panel.gridPos.x; + local v2 = panel.gridPos.x + panel.gridPos.w; + local x1 = p.gridPos.x; + local x2 = p.gridPos.x + p.gridPos.w; + (v1 >= x1 && v1 < x2) + || (v2 >= x1 && v2 < x2), function(p) // return new position on Y-scale p.gridPos.y + p.gridPos.h, panels, diff --git a/test/util_test.jsonnet b/test/util_test.jsonnet index e8226b5c..dbc1ee8c 100644 --- a/test/util_test.jsonnet +++ b/test/util_test.jsonnet @@ -439,3 +439,131 @@ test.new(std.thisFile) ) ) ) + +// util.grid.makeGrid ++ ( + local p1 = [ + g.panel.timeSeries.new('a'), + g.panel.timeSeries.new('b'), + g.panel.timeSeries.new('c'), + g.panel.timeSeries.new('d'), + g.panel.timeSeries.new('e'), + ]; + local p2 = [ + g.panel.timeSeries.new('a') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 0), + g.panel.timeSeries.new('b') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 0), + g.panel.timeSeries.new('c') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 16, 0), + g.panel.timeSeries.new('d') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 8), + g.panel.timeSeries.new('e') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 8), + ]; + + test.case.new( + name='util.grid.makeGrid -- just panels', + test=test.expect.eqDiff( + util.grid.makeGrid(p1), + p2, + ) + ) +) ++ ( + local p1 = [ + g.panel.timeSeries.new('a'), + g.panel.timeSeries.new('b'), + g.panel.row.new('row'), + g.panel.timeSeries.new('c'), + g.panel.timeSeries.new('d'), + g.panel.timeSeries.new('e'), + g.panel.row.new('rowCollapsed') + g.panel.row.withCollapsed(), + g.panel.timeSeries.new('f'), + g.panel.timeSeries.new('g'), + g.panel.timeSeries.new('h'), + ]; + local p2 = [ + g.panel.timeSeries.new('a') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 0), + g.panel.timeSeries.new('b') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 0), + g.panel.row.new('row') + + g.panel.row.withPanels([]) + + g.panel.row.withGridPos(8), + g.panel.timeSeries.new('c') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 9), + g.panel.timeSeries.new('d') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 9), + g.panel.timeSeries.new('e') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 16, 9), + g.panel.row.new('rowCollapsed') + + g.panel.row.withCollapsed() + + g.panel.row.withGridPos(17) + + g.panel.row.withPanels([ + g.panel.timeSeries.new('f') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 0), + g.panel.timeSeries.new('g') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 0), + g.panel.timeSeries.new('h') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 16, 0), + ]), + ]; + + test.case.new( + name='util.grid.makeGrid -- with rows', + test=test.expect.eqDiff( + util.grid.makeGrid(p1), + p2, + ) + ) +) ++ ( + local p1 = [ + g.panel.timeSeries.new('a'), + g.panel.timeSeries.new('b'), + g.panel.row.new('rowCollapsed') + g.panel.row.withCollapsed(), + g.panel.timeSeries.new('c'), + g.panel.timeSeries.new('d'), + g.panel.timeSeries.new('e'), + g.panel.row.new('row'), + g.panel.timeSeries.new('f'), + g.panel.timeSeries.new('g'), + g.panel.timeSeries.new('h'), + ]; + local p2 = [ + g.panel.timeSeries.new('a') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 0), + g.panel.timeSeries.new('b') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 0), + g.panel.row.new('rowCollapsed') + + g.panel.row.withCollapsed() + + g.panel.row.withPanels([]) + + g.panel.row.withGridPos(8) + + g.panel.row.withPanels([ + g.panel.timeSeries.new('c') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 0), + g.panel.timeSeries.new('d') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 0), + g.panel.timeSeries.new('e') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 16, 0), + ]), + g.panel.row.new('row') + + g.panel.row.withPanels([]) + + g.panel.row.withGridPos(9), + g.panel.timeSeries.new('f') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 0, 10), + g.panel.timeSeries.new('g') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 8, 10), + g.panel.timeSeries.new('h') + + g.panel.timeSeries.panelOptions.withGridPos(8, 8, 16, 10), + ]; + + test.case.new( + name='util.grid.makeGrid -- with collapsed row in middle', + test=test.expect.eqDiff( + util.grid.makeGrid(p1), + p2, + ) + ) +)