diff --git a/package-lock.json b/package-lock.json index 63cd0bf..45072e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1396,9 +1396,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -2092,9 +2092,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -4288,20 +4288,22 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5278,9 +5280,9 @@ } }, "node_modules/jasmine/node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5700,9 +5702,9 @@ } }, "node_modules/karma-webpack/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, "license": "MIT", "dependencies": { @@ -5889,9 +5891,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -6672,9 +6674,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/path/node_modules/inherits": { @@ -6738,9 +6740,10 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -8040,18 +8043,44 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "dev": true, + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "debug": "~4.4.1" }, "engines": { "node": ">=10.0.0" } }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -8459,9 +8488,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" diff --git a/package.json b/package.json index 8c7854d..a2ecec9 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "package": "pbiviz package", "eslint": "npx eslint . --ext .js,.jsx,.ts,.tsx", "test": "karma start", - "cert": "pbiviz --create-cert" + "cert": "pbiviz --create-cert", + "debug": "karma start --browsers=Chrome --single-run=false" }, "author": { "name": "Microsoft", diff --git a/src/visual.ts b/src/visual.ts index 4e69ca8..0fa6c36 100644 --- a/src/visual.ts +++ b/src/visual.ts @@ -775,24 +775,6 @@ export class DotPlot implements IVisual { xAxisProperties.axis.tickValues(tickValues); - const tickWidth: number = (tickValues.length > DotPlot.MinAmountOfTicks - ? scale(tickValues[1]) - scale(tickValues[0]) - : pixelSpan) - DotPlot.TickWidthOffset; - - xAxisProperties.axis.tickFormat((index: number) => { - if (!this.formattingSettings.categoryAxis.show.value || !this.data.dataGroups[index]) { - return DotPlot.DefaultTickValue; - } - - const textProperties: TextProperties = DotPlot.getCategoryTextProperties( - this.data.dataGroups[index].category.value); - - return textMeasurementService.getTailoredTextOrDefault( - textProperties, - tickWidth - ); - }); - if (this.formattingSettings.categoryAxis.show.value) { // Should handle the label, units of the label and the axis style xAxisProperties.axisLabel = this.data.categoryAxisName; @@ -825,20 +807,30 @@ export class DotPlot implements IVisual { } if (this.formattingSettings.categoryAxis.show.value) { + const pixelSpan: number = this.dataViewport.width - this.data.maxLabelWidth; + const scale: any = this.xAxisProperties.axis.scale(); + const tickValues: any[] = this.xAxisProperties.axis.tickValues(); + const tickWidth: number = (tickValues.length > DotPlot.MinAmountOfTicks + ? scale(tickValues[1]) - scale(tickValues[0]) + : pixelSpan) - DotPlot.TickWidthOffset; + this.xAxisSelection.selectAll(DotPlot.TickTextSelector.selectorName) .text((index: number) => { return this.data.dataGroups[index] - && this.data.dataGroups[index].category.value; - }); - } else { - this.xAxisSelection.selectAll(DotPlot.TickTextSelector.selectorName) - .append("title") - .text((index: number) => { - return this.data.dataGroups[index] - && this.data.dataGroups[index].category.value; - }); + && textMeasurementService.getTailoredTextOrDefault( + DotPlot.getCategoryTextProperties(this.data.dataGroups[index].category.value), + tickWidth + ); + }) } + this.xAxisSelection.selectAll(DotPlot.TickTextSelector.selectorName) + .append("title") + .text((index: number) => { + return this.data.dataGroups[index] + && this.data.dataGroups[index].category.value; + }); + this.xAxisSelection .selectAll("line") .style("opacity", this.formattingSettings.categoryAxis.show.value diff --git a/test/visualData.ts b/test/visualData.ts index a244445..61495e7 100644 --- a/test/visualData.ts +++ b/test/visualData.ts @@ -38,13 +38,13 @@ export class DotPlotData extends TestDataViewBuilder { public static ColumnValues: string = "Value"; public static ValuesCategoryLongNames: string[] = [ - "Sir Demetrius", - "Sir Montgomery", - "Sir Remington", - "Sir Forrester", - "Sir Christopher", - "Miss Annabelle", - "Miss Emmaline" + "Very long label that should be truncated", + "Extremely long label that should be truncated", + "Quite a long label that should be truncated", + "Long label that should be truncated", + "Label that should be truncated", + "Short label", + "Label that should be truncated", ]; public valuesCategory: string[] = [ diff --git a/test/visualTest.ts b/test/visualTest.ts index d51c48f..6c06f40 100644 --- a/test/visualTest.ts +++ b/test/visualTest.ts @@ -81,6 +81,18 @@ describe("DotPlot", () => { }); }); + it("xAxis tick labels are truncated if they don't fit", done => { + defaultDataViewBuilder.valuesCategory = DotPlotData.ValuesCategoryLongNames; + dataView = defaultDataViewBuilder.getDataView(); + + visualBuilder.updateRenderTimeout(dataView, () => { + expect(visualBuilder.xAxisTickText + .some((textElement: SVGTextElement) => textElement.textContent!.includes("..."))).toBe(true); + + done(); + }); + }); + it("should correctly render duplicates in categories", done => { dataView.categorical!.categories![0].values[1] = dataView.categorical!.categories![0].values[0]; @@ -264,7 +276,7 @@ describe("DotPlot", () => { }; }); - it("show", () => { + fit("show", () => { (dataView.metadata.objects as any).categoryAxis.show = true; visualBuilder.updateFlushAllD3Transitions(dataView); @@ -279,7 +291,6 @@ describe("DotPlot", () => { visualBuilder.xAxisTicks .map(e => e.querySelector("text")!) .forEach((e: SVGTextElement) => { - expect(e.children.length).toBe(0); expect(e.tagName).not.toBe("title"); expect(e.textContent!).toBeTruthy(); });