From cee3ab18b5d33d98547bce022b24557a9e0efed7 Mon Sep 17 00:00:00 2001 From: SharathAlur Date: Tue, 3 Sep 2019 19:05:10 +0530 Subject: [PATCH] New: No Data View (fixes #39) (#68) * New: No Data View (fixes #39) * New: No Data View (fixes #39) * New: No Data View (fixes #39) Address review comment * New: No Data View (fixes #39) Add necessary Tests * New: No Data View (fixes #39) Code cleanup * New: No Data View (fixes #39) Code cleanup and documentation * New: No Data View (fixes #39) Update font-size to fit to all screen sizes * New: No Data View (fixes #39) Update example * New: No Data View (fixes #39) Update test to use the constants * New: No Data View (fixes #39) Revert the chage added by mistake --- CONTRIBUTORS.md | 1 + dev/app.js | 8 +- dev/examples/controls/line.js | 8 ++ dev/examples/data.js | 58 +++++++++++ docs/README.md | 3 +- docs/core/GraphAPI.md | 27 ++--- package.json | 2 +- src/main/js/controls/Gantt/GanttConfig.js | 2 +- .../controls/Gantt/helpers/creationHelpers.js | 2 +- src/main/js/controls/Graph/Graph.js | 18 +++- src/main/js/controls/Graph/GraphConfig.js | 4 +- src/main/js/controls/Graph/helpers/helpers.js | 82 ++++++++++++++- .../js/controls/Timeline/TimelineConfig.js | 2 +- .../Timeline/helpers/creationHelpers.js | 2 +- src/main/js/helpers/axis.js | 4 +- src/main/js/helpers/constants.js | 4 +- src/main/js/helpers/styles.js | 4 + src/main/js/locale/de-DE.js | 3 +- src/main/js/locale/en-AU.js | 3 +- src/main/js/locale/en-CA.js | 3 +- src/main/js/locale/en-GB.js | 3 +- src/main/js/locale/en-US.js | 3 +- src/main/js/locale/es-ES.js | 3 +- src/main/js/locale/fr-FR.js | 3 +- src/main/js/locale/ja-JP.js | 3 +- src/main/js/locale/pt-BR.js | 3 +- src/main/less/colors.less | 1 + src/main/less/core.less | 11 +++ src/test/unit/controls/Graph/Graph-spec.js | 99 ++++++++++++++++++- 29 files changed, 333 insertions(+), 36 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index bb1266e58..a36f99625 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -4,6 +4,7 @@ Cerner Corporation - Dinesh Singh [@Dinesh94Singh] - Veronica Mazur [@veronimazur] - Swati Kode [@swatikode] +- Sharath M H [@SharathAlur] [@abhijit945]: https://github.com/abhijit945 [@dinesh94singh]: https://github.com/Dinesh94Singh diff --git a/dev/app.js b/dev/app.js index bac259345..6b16d4a6f 100644 --- a/dev/app.js +++ b/dev/app.js @@ -70,7 +70,8 @@ import { renderLineYHidden, renderMultiLine, renderMultiLineRegion, - renderMultiLineIdenticalDatasetRegion + renderMultiLineIdenticalDatasetRegion, + renderNoDataView } from "./examples/controls/line"; import { renderMultiPairedResultRegion, @@ -156,6 +157,11 @@ renderSiteApp( pathname: "/line/shapes-hidden", content: renderLineShapesHidden, title: "Shapes Hidden" + }, + { + pathname: "/line/no-data", + content: renderNoDataView, + title: "No Data" } ] }, diff --git a/dev/examples/controls/line.js b/dev/examples/controls/line.js index a001e31eb..d94a03dfe 100644 --- a/dev/examples/controls/line.js +++ b/dev/examples/controls/line.js @@ -419,3 +419,11 @@ export const renderLineXOrientationTop = (id) => { ); return lineDefault; }; +export const renderNoDataView = (id) => { + const axisData = utils.deepClone(getDemoData(`#${id}`, "NO_DATA_VIEW")); + const lineDefault = Carbon.api.graph(axisData); + lineDefault.loadContent( + Carbon.api.line(getDemoData(`#${id}`, "NO_DATA_VIEW").data[0]) + ); + return lineDefault; +}; diff --git a/dev/examples/data.js b/dev/examples/data.js index ffb1ad69a..7e20cc552 100644 --- a/dev/examples/data.js +++ b/dev/examples/data.js @@ -1665,6 +1665,64 @@ const DATA = [ showVGrid: true, showHGrid: true }) + }, + { + NO_DATA_VIEW: (id) => ({ + bindTo: id, + bindLegendTo: null, + axis: { + x: { + show: true, + label: "Data", + lowerLimit: 80, + upperLimit: 280, + ticks: { + show: true, // TODO Future implementation + count: 10, // TODO Future implementation + format: "", + values: [] + } + }, + y: { + show: true, + label: "Line Set A", + lowerLimit: 0, + upperLimit: 20 + }, + y2: { + show: false, + label: "Line Set B", + lowerLimit: 0, + upperLimit: 250 + } + }, + data: [ + { + key: "uid_1", + label: { + display: "Data Label 1" + }, + color: Carbon.helpers.COLORS.BLACK, + onClick: loadPopup, + values: [] + }, + { + key: "uid_2", + label: { + display: "Data Label 2" + }, + shape: Carbon.helpers.SHAPES.TRIANGLE, + color: Carbon.helpers.COLORS.BLUE, + onClick: loadPopup, + values: [] + } + ], + showLabel: true, + showLegend: true, + showShapes: true, + showVGrid: true, + showHGrid: true + }) } ]; export const getDemoData = (id, type) => { diff --git a/docs/README.md b/docs/README.md index 509927bfb..f5724b1a7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -210,7 +210,8 @@ const locale_custom = { "Okt", "Nov", "Dez" - ] + ], + noData: "No Data" }; ``` diff --git a/docs/core/GraphAPI.md b/docs/core/GraphAPI.md index b6b0c20c2..686a82c33 100644 --- a/docs/core/GraphAPI.md +++ b/docs/core/GraphAPI.md @@ -31,19 +31,20 @@ GraphAPI is a set of graphs that share a common set of base visualization struct ### Optional -| Property Name | Expected | Default | Description | -| ------------- | -------- | --------------------------------------------- | ------------------------------------------------------------------------------------ | -| bindLegendTo | string | null | If DOM id provided, binds legend into that container (Example: `"#legendContainer"`) | -| locale | object | LOCALE.en_US | Locale object for X-Axis tick values | -| dimension | object | {} | Refer [Dimension](#dimension) | -| throttle | number | (1000/60) => time in ms | Delay between resize of a browser window | -| showLabel | boolean | true | Toggle to show axes labels | -| showLegend | boolean | true | Toggle to show graph legend | -| showShapes | boolean | true | Toggle to show shapes in the line graph | -| showVGrid | boolean | true | Toggle to show vertical grid | -| showHGrid | boolean | true | Toggle to show horizontal grid | -| dateline | array | [] | Refer [Dateline](../helpers/Dateline.md) | -| padding | object | `{ top: 10, bottom: 5, left: 30, right: 50 }` | Refer [Padding](../controls/Padding.md) | +| Property Name | Expected | Default | Description | +| -------------- | -------- | --------------------------------------------- | ------------------------------------------------------------------------------------ | +| bindLegendTo | string | null | If DOM id provided, binds legend into that container (Example: `"#legendContainer"`) | +| locale | object | LOCALE.en_US | Locale object for X-Axis tick values | +| dimension | object | {} | Refer [Dimension](#dimension) | +| throttle | number | (1000/60) => time in ms | Delay between resize of a browser window | +| showLabel | boolean | true | Toggle to show axes labels | +| showLegend | boolean | true | Toggle to show graph legend | +| showShapes | boolean | true | Toggle to show shapes in the line graph | +| showVGrid | boolean | true | Toggle to show vertical grid | +| showHGrid | boolean | true | Toggle to show horizontal grid | +| dateline | array | [] | Refer [Dateline](../helpers/Dateline.md) | +| padding | object | `{ top: 10, bottom: 5, left: 30, right: 50 }` | Refer [Padding](../controls/Padding.md) | +| showNoDataText | boolean | true | Toggle to show no data text | ## Dimension diff --git a/package.json b/package.json index d1e917f19..aaeb72d65 100644 --- a/package.json +++ b/package.json @@ -166,4 +166,4 @@ "test": "karma start ./build/karma/karma.config.js --single-run --no-auto-watch", "test:persist": "karma start ./build/karma/karma.config.js --no-single-run" } -} +} \ No newline at end of file diff --git a/src/main/js/controls/Gantt/GanttConfig.js b/src/main/js/controls/Gantt/GanttConfig.js index bd7c99326..314f94cea 100644 --- a/src/main/js/controls/Gantt/GanttConfig.js +++ b/src/main/js/controls/Gantt/GanttConfig.js @@ -163,7 +163,7 @@ export const processInput = (input, config) => { x: {}, y: {} }; - config.locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); + config.d3Locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); config.throttle = getDefaultValue( input.throttle, constants.RESIZE_THROTTLE diff --git a/src/main/js/controls/Gantt/helpers/creationHelpers.js b/src/main/js/controls/Gantt/helpers/creationHelpers.js index 03affad0c..1386e2fd4 100644 --- a/src/main/js/controls/Gantt/helpers/creationHelpers.js +++ b/src/main/js/controls/Gantt/helpers/creationHelpers.js @@ -232,7 +232,7 @@ const getAxesScale = (axis, scale, config) => { config.axis.x.ticks.values, getXAxisWidth(config), getAxisTickFormat( - config.locale, + config.d3Locale, config.axis.x.ticks.format, config.axis.x.type ), diff --git a/src/main/js/controls/Graph/Graph.js b/src/main/js/controls/Graph/Graph.js index ebf3a45a2..e5db13221 100644 --- a/src/main/js/controls/Graph/Graph.js +++ b/src/main/js/controls/Graph/Graph.js @@ -30,7 +30,9 @@ import { scaleGraph, setAxisPadding, translateGraph, - updateAxesDomain + updateAxesDomain, + removeNoDataView, + drawNoDataView } from "./helpers/helpers"; /** @@ -260,6 +262,9 @@ class Graph extends Construct { : containerSVG ); } + if (this.config.showNoDataText) { + drawNoDataView(this.config, this.svg); + } attachEventHandlers(this); return this.svg; } @@ -310,6 +315,9 @@ class Graph extends Construct { ) { redrawDatelineContent(this.scale, this.config, this.svg); } + if (utils.notEmpty(content.config.values)) { + removeNoDataView(this.svg); + } this.resize(); return this; } @@ -330,6 +338,14 @@ class Graph extends Construct { this.content.splice(index, 1); this.contentTargets.splice(index, 1); content.unload(this); + if ( + this.config.showNoDataText && + this.content.every((content) => + utils.isEmpty(content.config.values) + ) + ) { + drawNoDataView(this.config, this.svg); + } this.resize(); return this; } diff --git a/src/main/js/controls/Graph/GraphConfig.js b/src/main/js/controls/Graph/GraphConfig.js index d23f0bd55..96aa9c4d3 100644 --- a/src/main/js/controls/Graph/GraphConfig.js +++ b/src/main/js/controls/Graph/GraphConfig.js @@ -85,7 +85,9 @@ export const processInput = (input, config, type) => { config.axis = _axis; config.dateline = getDefaultValue(utils.deepClone(input.dateline), []); config.padding = getPadding(config, input.padding); - config.locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); + config.locale = getDefaultValue(input.locale, DEFAULT_LOCALE); + config.showNoDataText = getDefaultValue(input.showNoDataText, true); + config.d3Locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); config.throttle = getDefaultValue( input.throttle, constants.RESIZE_THROTTLE diff --git a/src/main/js/controls/Graph/helpers/helpers.js b/src/main/js/controls/Graph/helpers/helpers.js index 1293ad16b..4bff650bf 100644 --- a/src/main/js/controls/Graph/helpers/helpers.js +++ b/src/main/js/controls/Graph/helpers/helpers.js @@ -544,6 +544,7 @@ const translateGraph = (control) => { control.svg, getYAxisYPosition ); + translateNoDataView(control.config, control.svg); }; /** * Pads the domain with some buffer that gets calculated based on input values. @@ -675,6 +676,83 @@ const setAxisPadding = (axisPadding, { config }) => { axisPadding[yAxis] = config.axisPadding; } }; +/** + * Removes the No Data View from the node + * + * @private + * @param {d3.selection} svg - d3 selection node of svg. + * @returns {undefined} - returns nothing + */ +const removeNoDataView = (svg) => { + d3RemoveElement(svg, `.${styles.noDataContainer}`); +}; +/** + * Append No Data View to the graph node. + * + * @private + * @param {object} config - config object derived from input JSON + * @param {d3.selection} svg - d3 selection node of svg. + * @returns {d3.selection} d3 selection node of svg. + */ +const drawNoDataView = (config, svg) => { + const noDataViewHeight = + getYAxisHeight(config) / constants.NO_DATA_VIEW_PROPORTION; + + const noDataViewContainer = svg + .append("g") + .classed(styles.noDataContainer, true); + + noDataViewContainer + .append("rect") + .classed(styles.noDataOverlay, true) + .attr(constants.X_AXIS, getXAxisXPosition(config)) + .attr( + constants.Y_AXIS, + calculateVerticalPadding(config) + noDataViewHeight + ) + .attr("height", noDataViewHeight) + .attr("width", getXAxisWidth(config)); + noDataViewContainer + .append("text") + .classed(styles.noDataLabel, true) + .attr("x", getXAxisLabelXPosition(config)) + .attr( + "y", + getYAxisLabelYPosition(config) + constants.NO_DATA_LABEL_PADDING + ) + .append("tspan") + .text(config.locale.noData); + + return svg; +}; + +/** + * Translates no data view rectangle and the label + * based on the current positioning on resize. + * + * @private + * @param {object} config - config object derived from input JSON + * @param {d3.selection} svg - d3 selection node of svg. + * @returns {undefined} - returns nothing + */ +const translateNoDataView = (config, svg) => { + svg.select(`.${styles.noDataOverlay}`) + .transition() + .call(constants.d3Transition) + .attr( + "height", + getYAxisHeight(config) / constants.NO_DATA_VIEW_PROPORTION + ) + .attr("width", getXAxisWidth(config)); + svg.select(`.${styles.noDataLabel}`) + .transition() + .call(constants.d3Transition) + .attr("x", getXAxisLabelXPosition(config)) + .attr( + "y", + getYAxisLabelYPosition(config) + constants.NO_DATA_LABEL_PADDING + ); +}; export { translateAxes, @@ -699,5 +777,7 @@ export { detachEventHandlers, d3RemoveElement, setAxisPadding, - getAxisInfoRowLabelHeight + getAxisInfoRowLabelHeight, + removeNoDataView, + drawNoDataView }; diff --git a/src/main/js/controls/Timeline/TimelineConfig.js b/src/main/js/controls/Timeline/TimelineConfig.js index 711020c28..77ab2b804 100644 --- a/src/main/js/controls/Timeline/TimelineConfig.js +++ b/src/main/js/controls/Timeline/TimelineConfig.js @@ -26,7 +26,7 @@ export const processInput = (input, config) => { config.axis = { x: {} }; - config.locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); + config.d3Locale = d3.locale(getDefaultValue(input.locale, DEFAULT_LOCALE)); config.throttle = getDefaultValue( input.throttle, constants.RESIZE_THROTTLE diff --git a/src/main/js/controls/Timeline/helpers/creationHelpers.js b/src/main/js/controls/Timeline/helpers/creationHelpers.js index 9c79ab4c2..80ecccf22 100644 --- a/src/main/js/controls/Timeline/helpers/creationHelpers.js +++ b/src/main/js/controls/Timeline/helpers/creationHelpers.js @@ -137,7 +137,7 @@ const getAxesScale = (axis, scale, config) => { config.axis.x.ticks.values, getXAxisWidth(config), getAxisTickFormat( - config.locale, + config.d3Locale, config.axis.x.ticks.format, config.axis.x.type ) diff --git a/src/main/js/helpers/axis.js b/src/main/js/helpers/axis.js index 58d593fc2..f4b2f4bf8 100644 --- a/src/main/js/helpers/axis.js +++ b/src/main/js/helpers/axis.js @@ -175,7 +175,7 @@ const getAxesScale = (axis, scale, config) => { config.axis.x.ticks.values, getXAxisWidth(config), getAxisTickFormat( - config.locale, + config.d3Locale, config.axis.x.ticks.format, config.axis.x.type ), @@ -313,7 +313,7 @@ const prepareHorizontalAxis = (scale, tickValues, config, orientation) => tickValues, getXAxisWidth(config), getAxisTickFormat( - config.locale, + config.d3Locale, config.axis.x.ticks.format, config.axis.x.type ), diff --git a/src/main/js/helpers/constants.js b/src/main/js/helpers/constants.js index fcee9ea48..83c56c077 100644 --- a/src/main/js/helpers/constants.js +++ b/src/main/js/helpers/constants.js @@ -238,5 +238,7 @@ export default { TICK_ORIENTATION: { TOP: -1, BOTTOM: 1 - } + }, + NO_DATA_VIEW_PROPORTION: 3, + NO_DATA_LABEL_PADDING: 15 }; diff --git a/src/main/js/helpers/styles.js b/src/main/js/helpers/styles.js index 3fefde1d2..b471ecd53 100644 --- a/src/main/js/helpers/styles.js +++ b/src/main/js/helpers/styles.js @@ -43,6 +43,10 @@ export default { datelineGroup: "carbon-dateline-group", datelinePoint: "carbon-dateline-point", dateline: "carbon-dateline", + noDataContainer: "carbon-no-data-container", + noDataLabel: "carbon-no-data-label", + noDataOverlay: "carbon-no-data-overlay", + /** * Line */ diff --git a/src/main/js/locale/de-DE.js b/src/main/js/locale/de-DE.js index d42882ec9..fb6352add 100644 --- a/src/main/js/locale/de-DE.js +++ b/src/main/js/locale/de-DE.js @@ -45,5 +45,6 @@ export default { "Okt", "Nov", "Dez" - ] + ], + noData: "Keine Daten" }; diff --git a/src/main/js/locale/en-AU.js b/src/main/js/locale/en-AU.js index 02399e5d6..210d8fe0e 100644 --- a/src/main/js/locale/en-AU.js +++ b/src/main/js/locale/en-AU.js @@ -45,5 +45,6 @@ export default { "Oct", "Nov", "Dec" - ] + ], + noData: "No Data" }; diff --git a/src/main/js/locale/en-CA.js b/src/main/js/locale/en-CA.js index 882df3f83..33b3980cf 100644 --- a/src/main/js/locale/en-CA.js +++ b/src/main/js/locale/en-CA.js @@ -45,5 +45,6 @@ export default { "Oct", "Nov", "Dec" - ] + ], + noData: "No Data" }; diff --git a/src/main/js/locale/en-GB.js b/src/main/js/locale/en-GB.js index 3864b7972..c4c209583 100644 --- a/src/main/js/locale/en-GB.js +++ b/src/main/js/locale/en-GB.js @@ -45,5 +45,6 @@ export default { "Oct", "Nov", "Dec" - ] + ], + noData: "No Data" }; diff --git a/src/main/js/locale/en-US.js b/src/main/js/locale/en-US.js index bfd6b6c22..b1c67765b 100644 --- a/src/main/js/locale/en-US.js +++ b/src/main/js/locale/en-US.js @@ -45,5 +45,6 @@ export default { "Oct", "Nov", "Dec" - ] + ], + noData: "No Data" }; diff --git a/src/main/js/locale/es-ES.js b/src/main/js/locale/es-ES.js index d01003dc6..99ac3638f 100644 --- a/src/main/js/locale/es-ES.js +++ b/src/main/js/locale/es-ES.js @@ -45,5 +45,6 @@ export default { "oct", "nov", "dic" - ] + ], + noData: "Sin datos" }; diff --git a/src/main/js/locale/fr-FR.js b/src/main/js/locale/fr-FR.js index dff3d9a79..0f86c7e14 100644 --- a/src/main/js/locale/fr-FR.js +++ b/src/main/js/locale/fr-FR.js @@ -45,5 +45,6 @@ export default { "oct.", "nov.", "déc." - ] + ], + noData: "Aucune donnée" }; diff --git a/src/main/js/locale/ja-JP.js b/src/main/js/locale/ja-JP.js index b3de3edb2..13ae74f9d 100644 --- a/src/main/js/locale/ja-JP.js +++ b/src/main/js/locale/ja-JP.js @@ -45,5 +45,6 @@ export default { "10月", "11月", "12月" - ] + ], + noData: "データなし" }; diff --git a/src/main/js/locale/pt-BR.js b/src/main/js/locale/pt-BR.js index c41d0b4c8..257155646 100644 --- a/src/main/js/locale/pt-BR.js +++ b/src/main/js/locale/pt-BR.js @@ -45,5 +45,6 @@ export default { "Out", "Nov", "Dez" - ] + ], + noData: "Sem dados" }; diff --git a/src/main/less/colors.less b/src/main/less/colors.less index 9dc1e40a1..0ea06a391 100644 --- a/src/main/less/colors.less +++ b/src/main/less/colors.less @@ -12,3 +12,4 @@ @blue10: #ebf6fd; @red85: #c00; @yellow60: #ffc20a; +@grey55: #868a8c; diff --git a/src/main/less/core.less b/src/main/less/core.less index b67045741..74b7476ac 100644 --- a/src/main/less/core.less +++ b/src/main/less/core.less @@ -279,3 +279,14 @@ svg:not(:root) { } } } + +.carbon-no-data-label { + font-size: 1.25rem; + text-anchor: middle; + fill: @grey65; +} + +.carbon-no-data-overlay { + fill: @white; + opacity: 0.6; +} diff --git a/src/test/unit/controls/Graph/Graph-spec.js b/src/test/unit/controls/Graph/Graph-spec.js index 18a41e0eb..a5035ff61 100644 --- a/src/test/unit/controls/Graph/Graph-spec.js +++ b/src/test/unit/controls/Graph/Graph-spec.js @@ -5,7 +5,9 @@ import Graph from "../../../../main/js/controls/Graph/index"; import Line from "../../../../main/js/controls/Line/Line"; import { getXAxisWidth, - getYAxisHeight + getYAxisHeight, + getXAxisLabelXPosition, + getYAxisLabelYPosition } from "../../../../main/js/helpers/axis"; import constants, { AXES_ORIENTATION, @@ -233,6 +235,10 @@ describe("Graph", () => { ); }).toThrowError(errors.THROW_MSG_NO_AXIS_LABEL_INFO); }); + it("If showNoDataText is not present, default value of showNoDataText is set to true", () => { + const graph = new Graph(getAxes(axisDefault)); + expect(graph.config.showNoDataText).toEqual(true); + }); }); it("Throws error on empty input", () => { expect(() => { @@ -294,9 +300,11 @@ describe("Graph", () => { expect(graph.config.bindTo).toEqual(input.bindTo); expect(graph.config.axis).not.toBeNull(); expect(graph.config.locale).not.toBeNull(); + expect(graph.config.d3Locale).not.toBeNull(); expect(graph.config.throttle).toEqual(constants.RESIZE_THROTTLE); expect(graph.config.showLabel).toEqual(true); expect(graph.config.showLegend).toEqual(true); + expect(graph.config.showNoDataText).toEqual(true); expect(graph.config.showShapes).toEqual(true); expect(graph.config.showHGrid).toEqual(true); expect(graph.config.showVGrid).toEqual(true); @@ -383,9 +391,11 @@ describe("Graph", () => { expect(graph.config.bindTo).toEqual(input.bindTo); expect(graph.config.axis).not.toBeNull(); expect(graph.config.locale).not.toBeNull(); + expect(graph.config.d3Locale).not.toBeNull(); expect(graph.config.throttle).toEqual(constants.RESIZE_THROTTLE); expect(graph.config.showLabel).toEqual(true); expect(graph.config.showLegend).toEqual(true); + expect(graph.config.showNoDataText).toEqual(true); expect(graph.config.showShapes).toEqual(true); expect(graph.config.showHGrid).toEqual(true); expect(graph.config.showVGrid).toEqual(true); @@ -2515,6 +2525,32 @@ describe("Graph", () => { done(); }); }); + it("No data view aligns correctly", (done) => { + graphContainer.setAttribute("style", "width: 800px; height: 200px"); + graph.resize(); + triggerEvent(window, "resize", () => { + const noDataContainer = fetchElementByClass( + styles.noDataOverlay + ); + expect(toNumber(noDataContainer.getAttribute("height"))).toBe( + getYAxisHeight(graph.config) / + constants.NO_DATA_VIEW_PROPORTION + ); + expect(toNumber(noDataContainer.getAttribute("width"))).toBe( + getXAxisWidth(graph.config) + ); + + const noDataLabel = fetchElementByClass(styles.noDataLabel); + expect(toNumber(noDataLabel.getAttribute("x"))).toBe( + getXAxisLabelXPosition(graph.config) + ); + expect(toNumber(noDataLabel.getAttribute("y"))).toBe( + getYAxisLabelYPosition(graph.config) + + constants.NO_DATA_LABEL_PADDING + ); + done(); + }); + }); /** * BF12182018.01 - Verify the consumer has the option to provide custom padding for the graph-container. */ @@ -2842,9 +2878,11 @@ describe("Graph", () => { expect(graph.config.bindTo).toEqual(input.bindTo); expect(graph.config.axis).not.toBeNull(); expect(graph.config.locale).not.toBeNull(); + expect(graph.config.d3Locale).not.toBeNull(); expect(graph.config.throttle).toEqual(constants.RESIZE_THROTTLE); expect(graph.config.showLabel).toEqual(true); expect(graph.config.showLegend).toEqual(true); + expect(graph.config.showNoDataText).toEqual(true); expect(graph.config.showShapes).toEqual(true); expect(graph.config.showHGrid).toEqual(true); expect(graph.config.showVGrid).toEqual(true); @@ -2926,4 +2964,63 @@ describe("Graph", () => { expect(toNumber(translate[1], 10)).toBeCloserTo(10); }); }); + describe("No Data", () => { + describe("Will be displayed", () => { + it("If showNoDataText is set to true or undefined", () => { + graph = new Graph(getAxes(axisDefault)); + const noDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noDataTextElement).not.toBeNull(); + }); + it("If showNoDataText is set to true or undefined and the value of the data is not present", () => { + const primaryContent = new Line(getData()); + graph = new Graph(getAxes(axisDefault)); + graph.loadContent(primaryContent); + const noDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noDataTextElement).not.toBeNull(); + }); + it("if data is unloaded and no more data present on the screen to display", () => { + const primaryContent = new Line(getData(valuesDefault)); + graph = new Graph(getAxes(axisDefault)); + graph.loadContent(primaryContent); + const noNoDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noNoDataTextElement).toBeNull(); + graph.unloadContent(primaryContent); + const noDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noDataTextElement).not.toBeNull(); + }); + }); + describe("Will not be displayed", () => { + it("if showNoDataText is set to false", () => { + graph = new Graph( + Object.assign( + { + showNoDataText: false + }, + getAxes(axisDefault) + ) + ); + const noDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noDataTextElement).toBeNull(); + }); + it("if loaded data contains value", () => { + const primaryContent = new Line(getData(valuesDefault)); + graph = new Graph(getAxes(axisDefault)); + graph.loadContent(primaryContent); + const noDataTextElement = fetchElementByClass( + styles.noDataContainer + ); + expect(noDataTextElement).toBeNull(); + }); + }); + }); });