--- #------------------------------------------------------------------------------ # YAML Aliases to simplify maintenance anchorLinks: - link: &grafana-home url: "https://grafana.com/" params: "time" - thresholds: &thresholds-high - {color: "green", level: 100} - {color: "orange", level: 400} - {color: "red", level: 700} - thresholds: &thresholds-slow - {color: "green", level: 0} - {color: "orange", level: 80} - {color: "red", level: 150} # ----------------------------------------------------------------------------- # Panel Config cellIdPreamble: "cell-" gradientMode: "hue" cells: #---------------------------------------------------------------------------- # The clock consists of two hands and a face (surrounding circle). The face is # used to store the rotation origin to use for the hands. All three cells share # the same 'clock' namespace. The hand stroke colors could be driven from bespoke # values, but in this example they are being sourced from the cell dataRef. # The constant 'handDRef' shows how to decouple the source data from the actual # formulas. There is only one clock in this example, but the formulas and drives # could be used by multiple clocks via yaml anchors with different data injected # via these constants. clockFace: bespoke: namespace: "clock" drives: # Capture the clock origin - elementName: "ellipse" attribsGet: clockOriginX: "cx" clockOriginY: "cy" clockLongHand: dataRef: "test-data-large-sin" strokeColor: thresholds: *thresholds-high bespoke: namespace: "clock" constants: handDRef: "test-data-large-cos" formulas: - "longHandAngle = string(data[handDRef])" - "shortHandAngle = string(data[handDRef] / 12)" drives: # Note color thresholds are using large-sin but the rotation is using the large-cos dataRef - elementName: "path" attribsSet: transform: "concat('rotate(', longHandAngle, ' ', clockOriginX, ' ', clockOriginY, ')')" clockShortHand: dataRef: "test-data-large-cos" strokeColor: thresholds: *thresholds-high bespoke: namespace: "clock" drives: - elementName: "path" attribsSet: transform: "concat('rotate(', shortHandAngle, ' ', clockOriginX, ' ', clockOriginY, ')')" #---------------------------------------------------------------------------- # The connector shows how arror direction can be driven using the visibility # attribute on the different path elements. In this example the drive is re-used # for both connectors using a yaml anchor. connector1: &connector dataRef: "test-data-large-sin" bespoke: drives: # Three path elements exist. The first is the line and the 2nd, 3rd are the arrow heads. Drive the # arrow head visibility off of data so only one is visible at a time. - elementName: "path" elementPosition: 2 attribsSet: visibility: "data['test-data-large-sin'] >= 500 ? 'hidden' : 'visible'" - elementName: "path" elementPosition: 3 attribsSet: visibility: "data['test-data-large-sin'] < 500 ? 'hidden' : 'visible'" connector2: *connector connector3: *connector connector4: *connector connector5: *connector #---------------------------------------------------------------------------- # The range ring shows how an element can be scaled whilst maintaining the label position. # The 'utils.log()'' formula is commented out, but uncomment it to view the data available # in this scope. This also shows the label value and labelColor being driven from the # ringBoundary variable calculated in the mathjs formula. rangeRing: bespokeDataRef: "ringBoundary" label: separator: "replace" units: "ops" labelColor: thresholds: *thresholds-high bespoke: dataRefs: - "test-data-large-sin" formulas: - "scale = string(0.5 + max(0.0, min(1.0, data['test-data-large-sin'] / 1000)))" - "ringBoundary = round(data['test-data-large-sin'] / 200) * 200" #- "utils.log('log scale and data to console:', scale, ringBoundary, data)" drives: # Capture the range-ring origin on the 'ellipse' element - elementName: "ellipse" attribsGet: rangeRingOriginX: "cx" rangeRingOriginY: "cy" # Scale the range-ring on the outer 'g' around the ellipse origin. Scaling on the outer 'g' ensures # everything within such as the label is kept coherently positioned. - elementName: "g" elementPosition: 1 attribsSet: transform: "concat('scale(', scale, ' ', scale, ')')" 'transform-origin': "concat(rangeRingOriginX, ' ', rangeRingOriginY)" #---------------------------------------------------------------------------- # The propeller consists of an 'ellipse' hub and two 'path' blades. The hub provides # the rotation origin. By rotating on the outer 'g' it demonstratres how the fill-level # drive is kept coherent with the propeller position. prop_center: bespoke: namespace: "propeller" drives: - elementName: "ellipse" attribsGet: propOriginX: "cx" propOriginY: "cy" prop_blade_1: dataRef: "test-data-large-cos" fillColor: thresholds: *thresholds-high fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 1000 fillDirection: 'bottomToTop' bespoke: namespace: "propeller" drives: # Rotate the outer 'g' using transform. This ensures the inner clip-path setup for the fillLevel drive remains # coherently positioned as the blade rotates. - elementName: "g" elementPosition: 1 attribsSet: transform: &propBladeTransform "concat('rotate(', string(data['test-data-large-cos']), ' ', propOriginX, ' ', propOriginY, ')')" prop_blade_2: dataRef: "test-data-large-cos" fillColor: thresholds: *thresholds-high fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 1000 fillDirection: 'topToBottom' bespoke: namespace: "propeller" drives: - elementName: "g" elementPosition: 1 attribsSet: transform: *propBladeTransform #---------------------------------------------------------------------------- # The four boxes demonstrate fill-level direction. Arranged at the points of a # clock the fill-levels go in and out in symetry. box9: dataRef: "test-data-small-sin" label: separator: "replace" units: "pps" fillColor: thresholds: *thresholds-slow fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 200 fillDirection: 'leftToRight' link: *grafana-home box12: dataRef: "test-data-small-sin" label: separator: "replace" units: "pps" fillColor: thresholds: *thresholds-slow fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 200 fillDirection: 'topToBottom' link: *grafana-home box3: dataRef: "test-data-small-sin" label: separator: "replace" units: "pps" fillColor: thresholds: *thresholds-slow fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 200 fillDirection: 'rightToLeft' link: *grafana-home box6: dataRef: "test-data-small-sin" label: separator: "replace" units: "pps" fillColor: thresholds: *thresholds-slow fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 200 fillDirection: 'bottomToTop' link: *grafana-home #---------------------------------------------------------------------------- # The three vessels show how all shapes, even shapes defined via a 'path' can # have a controllable fill-level. vessel1: &vessel dataRef: "test-data-small-sin" label: separator: "replace" units: "pps" fillColor: thresholds: *thresholds-slow fillLevel: thresholdLwrFillPercent: 0 thresholdUprFillPercent: 100 thresholdLwrValue: 0 thresholdUprValue: 200 fillDirection: 'bottomToTop' link: *grafana-home vessel2: *vessel vessel3: *vessel