diff --git a/cypress/fixtures/flows/dashboard-gauge-half-fit.json b/cypress/fixtures/flows/dashboard-gauge-half-fit.json new file mode 100644 index 000000000..b22191fc2 --- /dev/null +++ b/cypress/fixtures/flows/dashboard-gauge-half-fit.json @@ -0,0 +1,147 @@ +[ + { + "id": "ghf-tab", + "type": "tab", + "label": "Gauge Half Fit", + "disabled": false, + "info": "" + }, + { + "id": "dashboard-ui-base", + "type": "ui-base", + "name": "UI Name", + "path": "/dashboard", + "includeClientData": true, + "acceptsClientConfig": ["ui-notification", "ui-control"] + }, + { + "id": "dashboard-ui-theme", + "type": "ui-theme", + "name": "Theme", + "colors": { + "surface": "#ffffff", + "primary": "#0094ce", + "bgPage": "#eeeeee", + "groupBg": "#ffffff", + "groupOutline": "#cccccc" + } + }, + { + "id": "dashboard-ui-page-1", + "type": "ui-page", + "name": "Page 1", + "ui": "dashboard-ui-base", + "path": "/page1", + "icon": "home", + "layout": "grid", + "theme": "dashboard-ui-theme", + "order": 1, + "className": "", + "visible": "true", + "disabled": false + }, + { + "id": "dashboard-ui-group", + "type": "ui-group", + "name": "Half", + "page": "dashboard-ui-page-1", + "width": "6", + "height": "1", + "order": 1, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-gauge-half-tall", + "type": "ui-gauge", + "z": "ghf-tab", + "group": "dashboard-ui-group", + "name": "Tall", + "order": 1, + "value": "payload", + "valueType": "msg", + "width": "2", + "height": "5", + "gtype": "gauge-half", + "gstyle": "needle", + "title": "Tall half", + "alwaysShowTitle": true, + "floatingTitlePosition": "top-left", + "units": "%", + "icon": "", + "prefix": "", + "suffix": "", + "segments": [ + { "from": "0", "color": "#53a51c", "text": "", "textType": "label" }, + { "from": "60", "color": "#f6c000", "text": "", "textType": "label" }, + { "from": "80", "color": "#ca3838", "text": "", "textType": "label" } + ], + "min": "0", + "max": "100", + "sizeThickness": "16", + "sizeGap": "4", + "sizeKeyThickness": "8", + "styleRounded": true, + "styleGlow": false, + "className": "", + "x": 400, + "y": 120, + "wires": [[]] + }, + { + "id": "dashboard-ui-gauge-34-tall", + "type": "ui-gauge", + "z": "ghf-tab", + "group": "dashboard-ui-group", + "name": "Tall34", + "order": 2, + "value": "payload", + "valueType": "msg", + "width": "2", + "height": "5", + "gtype": "gauge-34", + "gstyle": "needle", + "title": "Tall 34", + "alwaysShowTitle": true, + "floatingTitlePosition": "top-left", + "units": "%", + "icon": "", + "prefix": "", + "suffix": "", + "segments": [ + { "from": "0", "color": "#53a51c", "text": "", "textType": "label" }, + { "from": "60", "color": "#f6c000", "text": "", "textType": "label" }, + { "from": "80", "color": "#ca3838", "text": "", "textType": "label" } + ], + "min": "0", + "max": "100", + "sizeThickness": "16", + "sizeGap": "4", + "sizeKeyThickness": "8", + "styleRounded": true, + "styleGlow": false, + "className": "", + "x": 400, + "y": 200, + "wires": [[]] + }, + { + "id": "ghf-inject", + "type": "inject", + "z": "ghf-tab", + "name": "Set 65", + "props": [{ "p": "payload" }], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.1", + "topic": "", + "payload": "65", + "payloadType": "num", + "x": 180, + "y": 120, + "wires": [["dashboard-ui-gauge-half-tall", "dashboard-ui-gauge-34-tall"]] + } +] diff --git a/cypress/tests/widgets/gauge-half-fit.spec.js b/cypress/tests/widgets/gauge-half-fit.spec.js new file mode 100644 index 000000000..e39ba470b --- /dev/null +++ b/cypress/tests/widgets/gauge-half-fit.spec.js @@ -0,0 +1,36 @@ +describe('Node-RED Dashboard 2.0 - Gauge dial fit (#1607)', () => { + beforeEach(() => { + cy.deployFixture('dashboard-gauge-half-fit') + cy.visit('/dashboard/page1') + }) + + it('sizes the half-gauge to its arc, not the whole tall cell', () => { + const widget = '#nrdb-ui-widget-dashboard-ui-gauge-half-tall' + cy.get(widget).find('svg').should('be.visible') + // eslint-disable-next-line promise/always-return, promise/catch-or-return + cy.get(widget).then(($w) => { + const cell = $w[0].getBoundingClientRect().height + const svg = $w[0].querySelector('svg') + const svgH = svg.getBoundingClientRect().height + const svgW = svg.getBoundingClientRect().width + // the arc is ~w/2 tall; the svg should hug that (+ label room), not stretch to the cell + expect(svgH, 'svg sized to the arc, not the cell').to.be.lessThan(svgW / 2 + 40) + expect(svgH, 'svg does not fill the tall cell').to.be.lessThan(cell - 40) + }) + }) + + it('sizes the 34 dial to its arc, not the whole tall cell', () => { + const widget = '#nrdb-ui-widget-dashboard-ui-gauge-34-tall' + cy.get(widget).find('svg').should('be.visible') + // eslint-disable-next-line promise/always-return, promise/catch-or-return + cy.get(widget).then(($w) => { + const cell = $w[0].getBoundingClientRect().height + const svg = $w[0].querySelector('svg') + const svgH = svg.getBoundingClientRect().height + const svgW = svg.getBoundingClientRect().width + // the dial is ~min(w,h)=w tall here; the svg should hug that, not stretch to the cell + expect(svgH, 'svg sized to the dial, not the cell').to.be.lessThan(svgW + 40) + expect(svgH, 'svg does not fill the tall cell').to.be.lessThan(cell - 40) + }) + }) +}) diff --git a/ui/src/widgets/ui-gauge/types/UIGaugeDial.vue b/ui/src/widgets/ui-gauge/types/UIGaugeDial.vue index e9b0db162..266f21656 100644 --- a/ui/src/widgets/ui-gauge/types/UIGaugeDial.vue +++ b/ui/src/widgets/ui-gauge/types/UIGaugeDial.vue @@ -144,12 +144,26 @@ export default { this.$refs.gauge.setAttribute('width', w) + let gaugeArea if (this.props.gtype === 'gauge-half') { const minDimension = Math.min(w / 2, h) this.r = minDimension + this.sizes.fudge + gaugeArea = minDimension } else { const minDimension = Math.min(w, h) this.r = minDimension / 2 + gaugeArea = minDimension + } + + const limit = this.$refs['limits-min'] + const labelRoom = limit ? Math.ceil(limit.getBBox().height) : 16 + if (gaugeArea + labelRoom < h) { + this.height = gaugeArea + this.$refs.gauge.style.flexGrow = '0' + this.$refs.gauge.setAttribute('height', gaugeArea + labelRoom) + } else { + this.$refs.gauge.style.flexGrow = '' + this.$refs.gauge.setAttribute('height', '100%') } }, update (value, duration = 1000) {