├── .editorconfig ├── .github └── workflows │ ├── build.yml │ └── codeql.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── SECURITY.md ├── assets ├── DeductThresholdDays.png ├── MissingValueLabel.PNG ├── MissingVarianceLabel.PNG ├── NaValueVariance.PNG ├── ShowLatestAvailable.PNG ├── StaleDataIcon.png ├── StaleDataIconContexted.png ├── TreatEmptyDisabled.PNG ├── TreatEmptyEnabled.PNG ├── ZeroLineAreaCorrect.PNG ├── ZeroLineAreaWrong.PNG ├── icon.svg └── screenshot.png ├── capabilities.json ├── eslint.config.mjs ├── fonts ├── PowerVisuals.eot ├── PowerVisuals.svg ├── PowerVisuals.ttf └── PowerVisuals.woff ├── karma.conf.ts ├── package-lock.json ├── package.json ├── pbiviz.json ├── specs ├── common.spec.ts ├── multiKpiBuilder.ts ├── multiKpiData.ts └── testWrapper.ts ├── src ├── columns │ └── columns.ts ├── converter │ ├── converter.ts │ ├── data │ │ ├── dataConverter.ts │ │ ├── dataFormatter.ts │ │ ├── dataOrderConverter.ts │ │ ├── dataOrderConverterWithDuplicates.ts │ │ ├── dataRepresentation.ts │ │ ├── dataRepresentationScale.ts │ │ └── dataSmooth.ts │ └── variance │ │ ├── createVarianceConverterByType.ts │ │ ├── differenceConverter.ts │ │ └── varianceConverter.ts ├── event │ └── eventName.ts ├── multiKpi.ts ├── services │ └── scaleService.ts ├── settings │ ├── descriptors │ │ ├── axisBaseDescriptor.ts │ │ ├── axisDescriptor.ts │ │ ├── baseDescriptor.ts │ │ ├── chartDescriptor.ts │ │ ├── container │ │ │ └── baseContainerDescriptor.ts │ │ ├── dateDescriptor.ts │ │ ├── descriptor.ts │ │ ├── formatDescriptor.ts │ │ ├── gridDescriptor.ts │ │ ├── kpi │ │ │ ├── kpiBaseDescriptor.ts │ │ │ ├── kpiDescriptor.ts │ │ │ └── kpiOnHoverDescriptor.ts │ │ ├── numericDescriptor.ts │ │ ├── printDescriptor.ts │ │ ├── sparkline │ │ │ ├── sparklineAxisDescriptor.ts │ │ │ ├── sparklineChartDescriptor.ts │ │ │ └── sparklineDescriptor.ts │ │ ├── sparklineNameDescriptor.ts │ │ ├── sparklineValueDescriptor.ts │ │ ├── staleDataDescriptor.ts │ │ ├── subtitleBaseDescriptor.ts │ │ ├── subtitleDescriptor.ts │ │ ├── textFormattingDescriptor.ts │ │ ├── tooltipDescriptor.ts │ │ ├── valuesDescriptor.ts │ │ └── varianceDescriptor.ts │ ├── seriesSettings.ts │ └── settings.ts ├── utils │ └── isValueValid.ts └── visualComponent │ ├── baseComponent.ts │ ├── baseContainerComponent.ts │ ├── mainChart │ ├── axisComponent.ts │ ├── chartComponent.ts │ ├── chartLabelBaseComponent.ts │ ├── chartLabelComponent.ts │ ├── hoverLabelComponent.ts │ └── mainChartComponent.ts │ ├── rootComponent.ts │ ├── sparkline │ ├── dotsComponent.ts │ ├── lineComponent.ts │ ├── multiLineComponent.ts │ ├── plotComponent.ts │ ├── sparklineComponent.ts │ ├── sparklineGroupComponent.ts │ └── svgComponent.ts │ ├── subtitleComponent.ts │ ├── subtitleWarningComponent.ts │ ├── verticalReferenceLineComponent.ts │ ├── visualComponent.ts │ ├── visualComponentBaseConstructorOptions.ts │ ├── visualComponentConstructorOptions.ts │ └── visualComponentRenderOptions.ts ├── stringResources └── en-US │ └── resources.resjson ├── styles └── styles.less ├── test.webpack.config.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | 10 | [*.json] 11 | indent_size = 2 12 | 13 | [*.less] 14 | indent_size = 4 15 | 16 | [*.ts] 17 | indent_size = 4 18 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ main, dev, certification] 6 | pull_request: 7 | branches: [ main, dev, certification ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: [18.x, 20.x] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm audit 23 | continue-on-error: true 24 | - run: npm outdated 25 | continue-on-error: true 26 | - run: npm ci 27 | - run: npm run eslint --if-present 28 | - run: npm run lint --if-present 29 | - run: npm run package 30 | - run: npm test 31 | env: 32 | CI: true 33 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [main, dev, certification] 6 | pull_request: 7 | branches: [main, dev, certification] 8 | schedule: 9 | - cron: '0 0 * * 3' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | timeout-minutes: 60 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | language: ['typescript'] 25 | 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v4 29 | with: 30 | fetch-depth: 2 31 | 32 | - name: Use Node.js 18 33 | uses: actions/setup-node@v2 34 | with: 35 | node-version: 18.x 36 | 37 | - name: Install Dependencies 38 | run: npm ci 39 | 40 | - name: Initialize CodeQL 41 | uses: github/codeql-action/init@v3 42 | with: 43 | languages: ${{ matrix.language }} 44 | 45 | - name: Autobuild 46 | uses: github/codeql-action/autobuild@v3 47 | 48 | - name: Perform CodeQL Analysis 49 | uses: github/codeql-action/analyze@v3 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .tmp 4 | dist 5 | typings 6 | .api 7 | *.log 8 | /coverage 9 | webpack.statistics.html 10 | webpack.statistics.*.html 11 | TESTS-report.xml 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.watcherExclude": { 3 | "**/.git/objects/**": true, 4 | "**/node_modules/**": true, 5 | ".tmp": true 6 | }, 7 | "files.exclude": { 8 | ".tmp": true 9 | }, 10 | "search.exclude": { 11 | ".tmp": true 12 | }, 13 | "json.schemas": [ 14 | { 15 | "fileMatch": [ 16 | "pbiviz.json" 17 | ], 18 | "url": "./node_modules/powerbi-visuals-api/schema.pbiviz.json" 19 | }, 20 | { 21 | "fileMatch": [ 22 | "capabilities.json" 23 | ], 24 | "url": "./node_modules/powerbi-visuals-api/schema.capabilities.json" 25 | }, 26 | { 27 | "fileMatch": [ 28 | "dependencies.json" 29 | ], 30 | "url": "./node_modules/powerbi-visuals-api/schema.dependencies.json" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.0.0.0 2 | * API 5.11.0 3 | * Migrate to formatting model 4 | * Add high contrast mode 5 | * Add localization 6 | * Update packages 7 | 8 | ## 2.3.1 9 | * FIX (Regression): Hovering on sparklines did not cause changing of main grap for preview 10 | 11 | ## 2.3.0 12 | * API 3.5.1 13 | * Packages update 14 | * Subtitle can be loaded form data also (will be merged with subtitle from options) 15 | * Some of options from Stale Data option group can be set up for a metric 16 | * New option "Auto Precision" that build values showing minimum 3 digits as 3.56 or 25.7 or 754 or 2345 17 | * Context menu support 18 | * FIXED: it is expected to see the line when values are the same but it will be shown a dot in sparklines and nothing in the main chart 19 | 20 | ## 2.2.1 21 | * Fix for last date visual issue 22 | 23 | ## 2.2.0 24 | * API 2.6.1 25 | * Packages update 26 | * Upgraded tooltips that are build with using of "powerbi-visuals-utils-tooltiputils" library 27 | * Principal tooltip was moved from the whole chart area into value and variant labels 28 | * Model of area filling was changed for values that are under zero 29 | * Was fixed a bag when cursor was shifted, if data of a chart started not from the beginning of a period 30 | * Was added a new option "Show Latest Available As Current Value" into "Values" option group to show a latter available value for each chart 31 | * A tooltip regarding stale data now shows info for each chart (if option "Show Latest Available As Current Value" is anbled) 32 | * Was added a new option "Deduct Threshold Days" into "Stale Data" option group to deduct threshold days from days that is showed in tooltips 33 | * "Missing Value Label" property inside "Values" and "Missing Variance Label" inside "Variance" option groups to set custom text for measures if value or variance doesn't exist 34 | * "Variance N/A Color" option was renamed to "Missing Variance Color" 35 | * "Variance N/A Font Size" option was renamed to "Missing Variance Font Size" 36 | * "Treat Empty Values As Zero" option was renamed to "Treat Empty/Missing Values As Zero" 37 | 38 | ## 2.1.1 39 | * API 2.5.0 40 | * Conditional loading of `core-js/stable` only for sandbox mode 41 | * `@babel/polyfill` replacement by `core-js/stable` 42 | 43 | ## 2.1.0 44 | * Adds Decimal Places, Precision and Format for variance values 45 | * Fixes auto font size issue 46 | * Adds Stale Data options (title pattern, threshold, color, and background) 47 | * Adds alignment for subtitle 48 | * Adds "On Hover Current Value" alignment 49 | * Allows calculating a difference instead of growth for percentage metrics 50 | * Allows to treat empty values as zero 51 | 52 | ## 2.0.0 53 | * API 2.2.0 54 | * PBIVIZ 3.x.x 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /assets/DeductThresholdDays.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/DeductThresholdDays.png -------------------------------------------------------------------------------- /assets/MissingValueLabel.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/MissingValueLabel.PNG -------------------------------------------------------------------------------- /assets/MissingVarianceLabel.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/MissingVarianceLabel.PNG -------------------------------------------------------------------------------- /assets/NaValueVariance.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/NaValueVariance.PNG -------------------------------------------------------------------------------- /assets/ShowLatestAvailable.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/ShowLatestAvailable.PNG -------------------------------------------------------------------------------- /assets/StaleDataIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/StaleDataIcon.png -------------------------------------------------------------------------------- /assets/StaleDataIconContexted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/StaleDataIconContexted.png -------------------------------------------------------------------------------- /assets/TreatEmptyDisabled.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/TreatEmptyDisabled.PNG -------------------------------------------------------------------------------- /assets/TreatEmptyEnabled.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/TreatEmptyEnabled.PNG -------------------------------------------------------------------------------- /assets/ZeroLineAreaCorrect.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/ZeroLineAreaCorrect.PNG -------------------------------------------------------------------------------- /assets/ZeroLineAreaWrong.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/ZeroLineAreaWrong.PNG -------------------------------------------------------------------------------- /assets/icon.svg: -------------------------------------------------------------------------------- 1 | Artboard 2 copy -------------------------------------------------------------------------------- /assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/assets/screenshot.png -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals"; 2 | import tseslint from 'typescript-eslint'; 3 | 4 | export default [ 5 | ...tseslint.configs.recommended, 6 | powerbiVisualsConfigs.configs.recommended, 7 | { 8 | ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**", "coverage/**", "specs/**", "test.webpack.config.js", "karma.conf.ts"], 9 | }, 10 | ]; -------------------------------------------------------------------------------- /fonts/PowerVisuals.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/fonts/PowerVisuals.eot -------------------------------------------------------------------------------- /fonts/PowerVisuals.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/fonts/PowerVisuals.ttf -------------------------------------------------------------------------------- /fonts/PowerVisuals.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/PowerBI-visuals-MultiKPI/4ade890445c91d8b1c5d6da00ee83174ca7a6570/fonts/PowerVisuals.woff -------------------------------------------------------------------------------- /karma.conf.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | "use strict"; 28 | 29 | process.env.CHROME_BIN = require("playwright-chromium").chromium.executablePath(); 30 | 31 | const path = require("path"); 32 | 33 | const webpackConfig = require("./test.webpack.config.js"); 34 | const tsconfig = require("./tsconfig.json"); 35 | const testRecursivePath = "specs/*.spec.ts"; 36 | const coverageFolder = "coverage"; 37 | 38 | module.exports = (config) => { 39 | config.set({ 40 | browserNoActivityTimeout: 100000, 41 | browsers: ["ChromeHeadless"], 42 | colors: true, 43 | coverageIstanbulReporter: { 44 | "combineBrowserReports": true, 45 | "dir": path.join(__dirname, coverageFolder), 46 | "fixWebpackSourcePaths": true, 47 | "report-config": { 48 | html: { 49 | subdir: "html-report", 50 | }, 51 | }, 52 | "reports": ["html", "lcovonly", "text-summary", "cobertura"], 53 | "verbose": false, 54 | }, 55 | coverageReporter: { 56 | dir: path.join(__dirname, coverageFolder), 57 | reporters: [ 58 | { type: "html", subdir: "html-report" }, 59 | { type: "lcov", subdir: "lcov" }, 60 | { type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" }, 61 | { type: "lcovonly", subdir: ".", file: "report-lcovonly.txt" }, 62 | { type: "text-summary", subdir: ".", file: "text-summary.txt" }, 63 | ], 64 | }, 65 | files: [ 66 | testRecursivePath, 67 | ], 68 | frameworks: ["jasmine"], 69 | junitReporter: { 70 | outputDir: path.join(__dirname, coverageFolder), 71 | outputFile: "TESTS-report.xml", 72 | useBrowserName: false, 73 | }, 74 | mime: { 75 | "text/x-typescript": ["ts", "tsx"], 76 | }, 77 | reporters: [ 78 | "progress", 79 | "junit", 80 | ], 81 | preprocessors: { 82 | [testRecursivePath]: ["webpack", "sourcemap"], 83 | }, 84 | singleRun: true, 85 | typescriptPreprocessor: { 86 | options: tsconfig.compilerOptions, 87 | }, 88 | webpack: webpackConfig, 89 | webpackMiddleware: { 90 | noInfo: true, 91 | }, 92 | }); 93 | }; 94 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "powerbi-visuals-multikpi", 3 | "version": "3.0.0.0", 4 | "description": "Shows a KPI metric along with other metrics as sparklines", 5 | "scripts": { 6 | "pbiviz": "pbiviz", 7 | "start": "pbiviz start", 8 | "package": "pbiviz package", 9 | "lint": "npx eslint .", 10 | "pretest": "pbiviz package --resources --no-minify --no-pbiviz", 11 | "test": "karma start", 12 | "debug": "karma start --browsers=Chrome --single-run=false", 13 | "cert": "pbiviz --install-cert" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/Microsoft/PowerBI-visuals-MultiKPI.git" 18 | }, 19 | "keywords": [ 20 | "powerbi-visuals", 21 | "Multi KPI", 22 | "KPI" 23 | ], 24 | "author": { 25 | "name": "Microsoft", 26 | "email": "pbicvsupport@microsoft.com" 27 | }, 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/Microsoft/PowerBI-visuals-MultiKPI/issues" 31 | }, 32 | "homepage": "https://github.com/Microsoft/PowerBI-visuals-MultiKPI#readme", 33 | "devDependencies": { 34 | "@types/d3-array": "^3.2.1", 35 | "@types/d3-axis": "^3.0.6", 36 | "@types/d3-dispatch": "^3.0.6", 37 | "@types/d3-scale": "^4.0.8", 38 | "@types/d3-selection": "^3.0.10", 39 | "@types/d3-shape": "^3.1.6", 40 | "@types/jasmine": "5.1.4", 41 | "@types/karma": "6.3.8", 42 | "coverage-istanbul-loader": "^3.0.5", 43 | "css-loader": "7.1.2", 44 | "eslint": "^8.57.1", 45 | "eslint-plugin-powerbi-visuals": "^1.0.0", 46 | "jasmine": "5.2.0", 47 | "karma": "6.4.4", 48 | "karma-chrome-launcher": "3.2.0", 49 | "karma-jasmine": "5.1.0", 50 | "karma-junit-reporter": "2.0.1", 51 | "karma-sourcemap-loader": "0.4.0", 52 | "karma-webpack": "5.0.1", 53 | "less": "4.2.0", 54 | "less-loader": "^12.2.0", 55 | "playwright-chromium": "^1.46.0", 56 | "powerbi-visuals-api": "5.11.0", 57 | "powerbi-visuals-tools": "^5.6.0", 58 | "powerbi-visuals-utils-testutils": "6.1.1", 59 | "style-loader": "4.0.0", 60 | "ts-loader": "9.5.1", 61 | "typescript": "^5.6.3", 62 | "webpack": "^5.93.0" 63 | }, 64 | "dependencies": { 65 | "@typescript-eslint/eslint-plugin": "^6.21.0", 66 | "@typescript-eslint/parser": "^6.21.0", 67 | "d3-array": "^3.2.4", 68 | "d3-axis": "^3.0.0", 69 | "d3-dispatch": "^3.0.1", 70 | "d3-scale": "^4.0.2", 71 | "d3-selection": "^3.0.0", 72 | "d3-shape": "^3.2.0", 73 | "powerbi-visuals-utils-colorutils": "6.0.4", 74 | "powerbi-visuals-utils-dataviewutils": "6.1.0", 75 | "powerbi-visuals-utils-formattingutils": "6.1.1", 76 | "powerbi-visuals-utils-svgutils": "6.0.4", 77 | "powerbi-visuals-utils-tooltiputils": "^6.0.4", 78 | "powerbi-visuals-utils-typeutils": "6.0.3", 79 | "regenerator-runtime": "^0.14.1", 80 | "typescript-eslint": "^8.9.0" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /pbiviz.json: -------------------------------------------------------------------------------- 1 | { 2 | "visual": { 3 | "name": "MultiKpi", 4 | "displayName": "Multi KPI 3.0.0.0", 5 | "guid": "multiKpiEA8DA325489E436991F0E411F2D85FF3", 6 | "visualClassName": "MultiKpi", 7 | "version": "3.0.0.0", 8 | "description": "Shows a KPI metric along with other metrics as sparklines", 9 | "supportUrl": "https://aka.ms/customvisualscommunity", 10 | "gitHubUrl": "https://github.com/Microsoft/PowerBI-visuals-MultiKPI" 11 | }, 12 | "apiVersion": "5.11.0", 13 | "author": { 14 | "name": "Microsoft", 15 | "email": "pbicvsupport@microsoft.com" 16 | }, 17 | "assets": { 18 | "icon": "./assets/icon.svg" 19 | }, 20 | "capabilities": "./capabilities.json" 21 | } 22 | -------------------------------------------------------------------------------- /specs/multiKpiBuilder.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { VisualBuilderBase } from "powerbi-visuals-utils-testutils"; 28 | 29 | import { MultiKpi } from "../src/multiKpi"; 30 | 31 | import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions; 32 | 33 | export class MultiKpiBuilder extends VisualBuilderBase { 34 | constructor(width: number, height: number) { 35 | super(width, height, "multiKpiEA8DA325489E436991F0E411F2D85FF3"); 36 | } 37 | 38 | protected build(options: VisualConstructorOptions): MultiKpi { 39 | return new MultiKpi(options); 40 | } 41 | 42 | public get instance(): MultiKpi { 43 | return this.visual; 44 | } 45 | 46 | public get root(): HTMLElement | null { 47 | return this.element.querySelector(".multiKpi_multiKpi"); 48 | } 49 | 50 | public get sparkline(): NodeListOf { 51 | return this.element.querySelectorAll(".multiKpi_sparklineComponent"); 52 | } 53 | 54 | public get sparklineSubtitle(): NodeListOf { 55 | return this.element.querySelectorAll(".multiKpi_subtitleComponent"); 56 | } 57 | 58 | public get line(): HTMLElement { 59 | return this.element.querySelector(".multiKpi_lineComponent"); 60 | } 61 | 62 | public get sparklineLine(): NodeListOf { 63 | return this.element.querySelectorAll(".multiKpi_line"); 64 | } 65 | 66 | public get mainChart(): HTMLElement | null { 67 | return this.element.querySelector(".multiKpi_mainChartComponent"); 68 | } 69 | 70 | public get mainChartNAVarance(): HTMLElement { 71 | return this.element.querySelector(".multiKpi_mainChartComponent .multiKpi_chartLabelBaseComponent_body_variance_na"); 72 | } 73 | 74 | public get subtitle(): HTMLElement | null { 75 | return this.element.querySelector(".multiKpi_subtitleWarningComponent"); 76 | } 77 | 78 | public get staleIcon(): HTMLElement | null { 79 | return this.element.querySelector(".multiKpi_subtitleWarningComponent .multiKpi_dataAge"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /specs/multiKpiData.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | 29 | import { getRandomNumbers, testDataViewBuilder } from "powerbi-visuals-utils-testutils"; 30 | import { valueType } from "powerbi-visuals-utils-typeutils"; 31 | 32 | import { 33 | dateColumn, 34 | valueColumn, 35 | subtitleColumn, 36 | } from "../src/columns/columns"; 37 | 38 | export class MultiKpiData extends testDataViewBuilder.TestDataViewBuilder { 39 | public amountOfSeries: number = 5; 40 | 41 | public dates: Date[] = []; 42 | public seriesValues: number[][] = []; 43 | 44 | constructor( 45 | withMisisngValues: boolean = false, 46 | brokenMetricIndex: number = 0, 47 | howOlderDatesAreInDays: number = 0) { 48 | super(); 49 | 50 | const today = new Date(); 51 | const hours: number = today.getHours(); 52 | const tomorrowShifter: number = hours > 11 ? 1 : 0; 53 | const tommorowOrShifted = new Date( 54 | today.getFullYear(), 55 | today.getMonth(), 56 | today.getDate() + (tomorrowShifter - howOlderDatesAreInDays), 57 | ); 58 | const twoWeeksBefore = new Date( 59 | tommorowOrShifted.getFullYear(), 60 | tommorowOrShifted.getMonth(), 61 | tommorowOrShifted.getDate() - 13, 62 | ); 63 | 64 | // Fill two weeks 65 | for (let i = 0; i < 14; i++) { 66 | this.dates.push(new Date(twoWeeksBefore.getFullYear(), twoWeeksBefore.getMonth(), twoWeeksBefore.getDate() + i)); 67 | } 68 | 69 | if (withMisisngValues) { 70 | for (let i: number = 0; i < this.amountOfSeries; i++) { 71 | if (i === 4) { 72 | const noDataArray: number[] = []; 73 | this.dates.forEach((d) => { 74 | noDataArray.push(undefined); 75 | }); 76 | this.seriesValues.push(noDataArray); 77 | } else if (i === brokenMetricIndex) { 78 | const valArr: number[] = getRandomNumbers(this.dates.length - 4, -150, 150); 79 | valArr.push(25); 80 | valArr.push(undefined); 81 | valArr.push(undefined); 82 | valArr.push(undefined); 83 | this.seriesValues.push(valArr); 84 | } else { 85 | this.seriesValues.push(getRandomNumbers( 86 | this.dates.length, 87 | -150, 88 | 150, 89 | )); 90 | } 91 | } 92 | } else { 93 | for (let i: number = 0; i < this.amountOfSeries; i++) { 94 | this.seriesValues.push(getRandomNumbers( 95 | this.dates.length, 96 | -150, 97 | 150, 98 | )); 99 | } 100 | } 101 | } 102 | 103 | public getDataView(columnNames?: string[]): powerbi.DataView { 104 | const datesCategory = this.buildDatesCategory(this.dates); 105 | const valuesCategory = this.buildValuesCategory(this.seriesValues); 106 | 107 | return this.createCategoricalDataViewBuilder( 108 | [datesCategory], 109 | valuesCategory, 110 | columnNames, 111 | ).build(); 112 | } 113 | 114 | public getDataViewWithSubtitle(columnNames?: string[]): powerbi.DataView { 115 | const datesCategory = this.buildDatesCategory(this.dates); 116 | const valuesCategory = this.buildValuesCategory(this.seriesValues); 117 | const repeatsNum: number = this.dates.length; 118 | let subtitleArr: string[] = []; 119 | for (let i = 0; i < repeatsNum; i++) { 120 | subtitleArr.push("Subtitle form data"); 121 | } 122 | 123 | valuesCategory.push({ 124 | source: { 125 | displayName: subtitleColumn.name, 126 | roles: { subtitleColumn: true }, 127 | type: valueType.ValueType.fromDescriptor({ text: true }), 128 | }, 129 | values: subtitleArr, 130 | }); 131 | 132 | return this.createCategoricalDataViewBuilder( 133 | [datesCategory], 134 | valuesCategory, 135 | columnNames, 136 | ).build(); 137 | } 138 | 139 | 140 | private buildDatesCategory(dates: Date[]): any { 141 | return { 142 | source: { 143 | displayName: dateColumn.name, 144 | format: "%M/%d/yyyy", 145 | roles: { dateColumn: true }, 146 | type: valueType.ValueType.fromDescriptor({ dateTime: true }), 147 | }, 148 | values: dates, 149 | } 150 | } 151 | 152 | private buildValuesCategory(seriesValues: number[][]): any { 153 | return seriesValues 154 | .map((values: number[], index: number) => { 155 | return { 156 | source: { 157 | displayName: valueColumn.name + index, 158 | roles: { valueColumn: true }, 159 | type: valueType.ValueType.fromDescriptor({ integer: true }), 160 | }, 161 | values, 162 | }; 163 | }); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /specs/testWrapper.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | 29 | import { MultiKpiData } from "./multiKpiData"; 30 | import { MultiKpiBuilder } from "./multiKpiBuilder"; 31 | 32 | export class TestWrapper { 33 | public dataView: powerbi.DataView; 34 | public dataViewBuilder: MultiKpiData; 35 | public visualBuilder: MultiKpiBuilder; 36 | 37 | constructor( 38 | withMisisngValues: boolean = false, 39 | brokenMetricIndex: number = 0, 40 | howOlderDatesAreInDays: number = 0, 41 | attachSubtitleData: boolean = false, 42 | width: number = 1024, 43 | height: number = 768) { 44 | 45 | this.visualBuilder = new MultiKpiBuilder(width, height); 46 | this.dataViewBuilder = new MultiKpiData( 47 | withMisisngValues, 48 | brokenMetricIndex, 49 | howOlderDatesAreInDays); 50 | 51 | if (attachSubtitleData) { 52 | this.dataView = this.dataViewBuilder.getDataViewWithSubtitle(); 53 | } else { 54 | this.dataView = this.dataViewBuilder.getDataView(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/columns/columns.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | export interface IVisualDataRole { 28 | displayName: string; 29 | name: string; 30 | } 31 | 32 | export const dateColumn: IVisualDataRole = { 33 | displayName: "Date", 34 | name: "dateColumn", 35 | }; 36 | 37 | export const valueColumn: IVisualDataRole = { 38 | displayName: "Values", 39 | name: "valueColumn", 40 | }; 41 | 42 | export const warningStateColumn: IVisualDataRole = { 43 | displayName: "Warning state", 44 | name: "warningStateColumn", 45 | }; 46 | 47 | export const tooltipColumn: IVisualDataRole = { 48 | displayName: "Tooltip", 49 | name: "tooltipColumn", 50 | }; 51 | 52 | export const changeStartDateColumn: IVisualDataRole = { 53 | displayName: "Change start date", 54 | name: "changeStartDateColumn", 55 | }; 56 | 57 | export const subtitleColumn: IVisualDataRole = { 58 | displayName: "Subtitle", 59 | name: "subtitleColumn", 60 | }; 61 | -------------------------------------------------------------------------------- /src/converter/converter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | export interface IConverter { 28 | convert(options: ConverterOptionsType): DataType; 29 | } 30 | -------------------------------------------------------------------------------- /src/converter/data/dataFormatter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { displayUnitSystemType, valueFormatter } from "powerbi-visuals-utils-formattingutils"; 28 | import { NumericDescriptor } from "../../settings/descriptors/numericDescriptor"; 29 | import { isValueValid } from "../../utils/isValueValid"; 30 | 31 | const wholeUnits: displayUnitSystemType.DisplayUnitSystemType = displayUnitSystemType.DisplayUnitSystemType.WholeUnits; 32 | 33 | export function getFormattedValueWithFallback(variance: number, settings: NumericDescriptor): string { 34 | if (!isValueValid(variance)) { 35 | return settings.noValueLabel.value || "N/A"; 36 | } 37 | 38 | return getFormattedValue(variance, settings); 39 | } 40 | 41 | export function getFormattedDate(date: Date, format: string = valueFormatter.DefaultDateFormat): string { 42 | return valueFormatter 43 | .create({ format }) 44 | .format(date); 45 | } 46 | 47 | export function getFormattedValue(value: number, settings: NumericDescriptor): string { 48 | return getValueFormatter(value, settings).format(value); 49 | } 50 | 51 | export function getValueFormatter(value: number, settings: NumericDescriptor): valueFormatter.IValueFormatter { 52 | return valueFormatter.create({ 53 | displayUnitSystemType: wholeUnits, 54 | format: settings.format.value, 55 | precision: detectPrecision(value, settings), 56 | value: settings.displayUnits.value || value, 57 | }); 58 | } 59 | 60 | export function detectPrecision(inputValue: number, settings: NumericDescriptor): number { 61 | if (settings.autoPrecision) { 62 | const format = settings.format.value; 63 | return valueFormatter.calculateExactDigitsPrecision(inputValue, format, +settings.displayUnits.value, 3); 64 | } 65 | 66 | return settings.precision.value; 67 | } 68 | -------------------------------------------------------------------------------- /src/converter/data/dataOrderConverter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { IConverter } from "../converter"; 28 | 29 | import { 30 | IDataRepresentation, 31 | IDataRepresentationSeries, 32 | } from "./dataRepresentation"; 33 | 34 | export interface IDataOrderConverterOptions { 35 | data: IDataRepresentation; 36 | firstSeriesName: string; 37 | } 38 | 39 | export class DataOrderConverter implements IConverter { 40 | public convert(options: IDataOrderConverterOptions): IDataRepresentation { 41 | const { data, firstSeriesName } = options; 42 | 43 | let selectedSeriesIndex: number = -1; 44 | 45 | const series: IDataRepresentationSeries[] = data.series.map(( 46 | seriesItem: IDataRepresentationSeries, 47 | seriesIndex: number, 48 | ) => { 49 | if (seriesItem.name === firstSeriesName) { 50 | selectedSeriesIndex = seriesIndex; 51 | } 52 | 53 | return seriesItem; 54 | }); 55 | 56 | if (selectedSeriesIndex >= 0) { 57 | [series[0], series[selectedSeriesIndex]] = [series[selectedSeriesIndex], series[0]]; 58 | } 59 | 60 | return { 61 | ...data, 62 | series, 63 | }; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/converter/data/dataOrderConverterWithDuplicates.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { IConverter } from "../converter"; 28 | 29 | import { 30 | IDataRepresentation, 31 | IDataRepresentationSeries, 32 | } from "./dataRepresentation"; 33 | 34 | import { IDataOrderConverterOptions } from "./dataOrderConverter"; 35 | 36 | export class DataOrderConverterWithDuplicates implements IConverter { 37 | public convert(options: IDataOrderConverterOptions): IDataRepresentation { 38 | const { data, firstSeriesName } = options; 39 | 40 | let selectedSeriesIndex: number = -1; 41 | 42 | const series: IDataRepresentationSeries[] = data.series.map(( 43 | seriesItem: IDataRepresentationSeries, 44 | seriesIndex: number, 45 | ) => { 46 | if (seriesItem.name === firstSeriesName) { 47 | selectedSeriesIndex = seriesIndex; 48 | } 49 | 50 | return seriesItem; 51 | }); 52 | 53 | if (selectedSeriesIndex >= 0) { 54 | series[0] = series[selectedSeriesIndex]; 55 | } 56 | 57 | return { 58 | ...data, 59 | series, 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/converter/data/dataRepresentation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IEnumMember = powerbi.IEnumMember; 29 | import IViewport = powerbi.IViewport; 30 | import ISelectionId = powerbi.visuals.ISelectionId; 31 | 32 | import { SeriesSettings } from "../../settings/seriesSettings"; 33 | import { DataRepresentationScale } from "./dataRepresentationScale"; 34 | 35 | export interface IDataRepresentationPoint { 36 | x: Date; 37 | y: number; 38 | index: number; 39 | } 40 | 41 | export enum DataRepresentationPointGradientType { 42 | line = "line", 43 | area = "area", 44 | } 45 | 46 | export interface IEnumMemberWithDisplayNameKey extends IEnumMember{ 47 | key: string; 48 | } 49 | 50 | export const dataRepresentationOptions : IEnumMemberWithDisplayNameKey[] = [ 51 | {value : DataRepresentationPointGradientType[DataRepresentationPointGradientType.area], displayName : "Area", key: "Visual_Area"}, 52 | {value : DataRepresentationPointGradientType[DataRepresentationPointGradientType.line], displayName : "Line", key: "Visual_Line"} 53 | ]; 54 | 55 | export type DataRepresentationAxisValueType = Date | number; 56 | 57 | export interface IDataRepresentationAxis { 58 | min: DataRepresentationAxisValueType; 59 | initialMin: DataRepresentationAxisValueType; 60 | max: DataRepresentationAxisValueType; 61 | initialMax: DataRepresentationAxisValueType; 62 | scale: DataRepresentationScale; 63 | } 64 | 65 | export interface IDataRepresentationSeries { 66 | name: string; 67 | index: number; 68 | points: IDataRepresentationPoint[]; // All data points as is 69 | smoothedPoints: IDataRepresentationPoint[]; // Interpolated data points 70 | current: IDataRepresentationPoint; 71 | x: IDataRepresentationAxis; 72 | y: IDataRepresentationAxis; 73 | ySparkline: IDataRepresentationAxis; 74 | variance: number; 75 | formattedVariance: string; 76 | formattedDate: string; 77 | dateDifference: number; 78 | staleDateDifference?: number; 79 | tooltip: string; 80 | formattedTooltip: string; 81 | selectionId: ISelectionId; 82 | settings: SeriesSettings; 83 | isLine: boolean; // There is a bag in SVG that hide line that has gradient attachment. The mark indicate to apply workaround 84 | } 85 | 86 | export enum ViewportSize { 87 | tiny = "tiny", 88 | small = "small", 89 | medium = "medium", 90 | normal = "normal", 91 | big = "big", 92 | huge = "huge", 93 | enormous = "enormous", 94 | } 95 | 96 | export interface IDataRepresentation { 97 | series: IDataRepresentationSeries[]; 98 | sortedSeries: IDataRepresentationSeries[]; 99 | warningState: number; 100 | latestDate: Date; 101 | staleDateDifference?: number; 102 | percentCalcDate: Date; 103 | subtitle?: string; 104 | viewport: IViewport; 105 | viewportSize: ViewportSize; 106 | } 107 | -------------------------------------------------------------------------------- /src/converter/data/dataRepresentationScale.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { 28 | scaleLinear, 29 | ScaleLinear, 30 | scaleTime, 31 | ScaleTime, 32 | } from "d3-scale"; 33 | 34 | import { DataRepresentationAxisValueType } from "../data/dataRepresentation"; 35 | 36 | export type DataRepresentationAxisScale = ScaleTime 37 | | ScaleLinear; 38 | 39 | export enum DataRepresentationTypeEnum { 40 | None, 41 | DateType, 42 | NumberType, 43 | StringType, 44 | } 45 | 46 | export class DataRepresentationScale { 47 | public static CREATE(): DataRepresentationScale { 48 | return new DataRepresentationScale(); 49 | } 50 | 51 | private baseScale: DataRepresentationAxisScale; 52 | private internalType: DataRepresentationTypeEnum; 53 | 54 | private constructor(scale: DataRepresentationAxisScale = null) { 55 | this.baseScale = scale; 56 | } 57 | 58 | public domain( 59 | values: DataRepresentationAxisValueType[], 60 | type: DataRepresentationTypeEnum, 61 | ): DataRepresentationScale { 62 | let scale: DataRepresentationAxisScale; 63 | 64 | if (values?.length) { 65 | switch (type) { 66 | case DataRepresentationTypeEnum.DateType: { 67 | scale = scaleTime(); 68 | break; 69 | } 70 | case DataRepresentationTypeEnum.NumberType: { 71 | scale = scaleLinear(); 72 | break; 73 | } 74 | } 75 | } 76 | 77 | if (scale) { 78 | scale.domain(values); 79 | } 80 | 81 | this.baseScale = scale; 82 | this.internalType = type; 83 | 84 | return this; 85 | } 86 | 87 | public getDomain(): DataRepresentationAxisValueType[] { 88 | if (!this.baseScale) { 89 | return []; 90 | } 91 | 92 | return this.baseScale.domain() || []; 93 | } 94 | 95 | public scale(value: DataRepresentationAxisValueType): number { 96 | if (!this.baseScale) { 97 | return 0; 98 | } 99 | 100 | return this.baseScale(value); 101 | } 102 | 103 | public copy(): DataRepresentationScale { 104 | return new DataRepresentationScale(this.baseScale?.copy()); 105 | } 106 | 107 | public range(rangeValues): DataRepresentationScale { 108 | if (this.baseScale) { 109 | this.baseScale.range(rangeValues); 110 | } 111 | 112 | return this; 113 | } 114 | 115 | public get type(): DataRepresentationTypeEnum { 116 | return this.internalType; 117 | } 118 | 119 | public invert(value: number): DataRepresentationAxisValueType { 120 | if (!this.baseScale) { 121 | return undefined; 122 | } 123 | 124 | return this.baseScale.invert(value); 125 | } 126 | 127 | public getScale(): DataRepresentationAxisScale { 128 | return this.baseScale; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/converter/variance/createVarianceConverterByType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { create as createDifferenceConverter } from "./differenceConverter"; 28 | import { create as createVarianceConverter } from "./varianceConverter"; 29 | 30 | export function createVarianceConverterByType(shouldUseDifferenceConverter: boolean) { 31 | return shouldUseDifferenceConverter 32 | ? createDifferenceConverter() 33 | : createVarianceConverter(); 34 | } 35 | -------------------------------------------------------------------------------- /src/converter/variance/differenceConverter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { IConverter } from "../converter"; 28 | import { IVarianceConverterOptions } from "./varianceConverter"; 29 | 30 | export class VarianceBasedOnDifferenceConverter implements IConverter { 31 | public convert(options: IVarianceConverterOptions): number { 32 | const { secondDataPoint, firstDataPoint } = options; 33 | 34 | if (firstDataPoint && secondDataPoint) { 35 | return secondDataPoint.y - firstDataPoint.y; 36 | } 37 | 38 | return NaN; 39 | } 40 | } 41 | 42 | let convert: IConverter; 43 | 44 | export function create(): IConverter { 45 | if (!convert) { 46 | convert = new VarianceBasedOnDifferenceConverter(); 47 | } 48 | 49 | return convert; 50 | } 51 | -------------------------------------------------------------------------------- /src/converter/variance/varianceConverter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { IConverter } from "../converter"; 28 | import { IDataRepresentationPoint } from "../data/dataRepresentation"; 29 | 30 | export interface IVarianceConverterOptions { 31 | firstDataPoint: IDataRepresentationPoint; 32 | secondDataPoint: IDataRepresentationPoint; 33 | } 34 | 35 | export class VarianceConverter implements IConverter { 36 | public convert(options: IVarianceConverterOptions): number { 37 | const { secondDataPoint, firstDataPoint } = options; 38 | 39 | return this.getPercentChange(firstDataPoint.y, secondDataPoint.y); 40 | } 41 | 42 | private getPercentChange(startValue: number, endValue: number): number { 43 | if (startValue === 0) { 44 | return NaN; 45 | } 46 | 47 | const diff: number = endValue - startValue; 48 | let percentChange: number = Math.abs(diff / startValue); 49 | 50 | if (endValue < startValue) { 51 | percentChange = percentChange * -1; 52 | } 53 | 54 | return percentChange; 55 | } 56 | } 57 | 58 | let converter: IConverter; 59 | 60 | export function create(): IConverter { 61 | if (!converter) { 62 | converter = new VarianceConverter(); 63 | } 64 | 65 | return converter; 66 | } 67 | -------------------------------------------------------------------------------- /src/event/eventName.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | export enum EventName { 28 | onChartChange = "onChartChange", 29 | onChartViewChange = "onChartViewChange", 30 | onChartViewReset = "onChartViewReset", 31 | onChartChangeHover = "onChartChangeHover", 32 | onChartChangeClick = "onChartChangeClick", 33 | onChartChangeStop = "onChartChangeStop", 34 | onMouseMove = "onMouseMove", 35 | onMouseOut = "onMouseOut", 36 | onCurrentDataPointIndexChange = "onCurrentDataPointIndexChange", 37 | onCurrentDataPointIndexReset = "onCurrentDataPointIndexReset", 38 | } 39 | -------------------------------------------------------------------------------- /src/services/scaleService.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | export class ScaleService { 31 | constructor(private rootElement: HTMLElement) { } 32 | 33 | public getScale(): IViewport { 34 | if (!this.rootElement) { 35 | return { 36 | height: 1, 37 | width: 1, 38 | }; 39 | } 40 | 41 | const rect: DOMRect = this.rootElement.getBoundingClientRect(); 42 | 43 | let clientWidth: number; 44 | let clientHeight: number; 45 | 46 | if (!this.rootElement.clientWidth || !this.rootElement.clientHeight) { 47 | const container: HTMLElement = (this.rootElement); 48 | 49 | clientWidth = +container.style.width; 50 | clientHeight = +container.style.height; 51 | } else { 52 | clientWidth = this.rootElement.clientWidth; 53 | clientHeight = this.rootElement.clientHeight; 54 | } 55 | 56 | return { 57 | height: rect.height / clientHeight, 58 | width: rect.width / clientWidth, 59 | }; 60 | } 61 | 62 | public destroy(): void { 63 | this.rootElement = null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/settings/descriptors/axisBaseDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import NumUpDown = formattingSettings.NumUpDown; 28 | import FormattingSettingsSlice = formattingSettings.Slice; 29 | 30 | import {BaseContainerDescriptor} from "../descriptors/container/baseContainerDescriptor"; 31 | import { TextFormattingDescriptor } from "./textFormattingDescriptor"; 32 | 33 | export class AxisBaseContainerItem extends TextFormattingDescriptor { 34 | public displayNameKey: string = "Visual_All"; 35 | public defaultDomainColor: string = "#4F4F4F" 36 | 37 | public axisLabelX: number = 3; 38 | public axisLabelY: number = 6; 39 | 40 | public min = new NumUpDown({ 41 | name: "min", 42 | displayNameKey: "Visual_Min", 43 | value: null 44 | }); 45 | 46 | public max = new NumUpDown({ 47 | name: "max", 48 | displayNameKey: "Visual_Max", 49 | value: null 50 | }); 51 | 52 | public slices: FormattingSettingsSlice[] = [ 53 | this.isShown, this.format, this.displayUnits, 54 | this.precision, this.font, this.color, 55 | this.min, this.max 56 | ]; 57 | 58 | constructor(defaultAxisContainerItem?: AxisBaseContainerItem){ 59 | super(defaultAxisContainerItem); 60 | 61 | if (defaultAxisContainerItem){ 62 | this.min.value = defaultAxisContainerItem.min.value; 63 | this.max.value = defaultAxisContainerItem.max.value; 64 | } 65 | } 66 | } 67 | 68 | export abstract class AxisBaseDescriptor extends BaseContainerDescriptor { 69 | constructor() { 70 | super(); 71 | this.defaultContainerItem.precision.value = 0; 72 | this.defaultContainerItem.font.fontFamily.value = "wf_standard-font, helvetica, arial, sans-serif"; 73 | this.defaultContainerItem.font.fontSize.value = 7.5; 74 | this.defaultContainerItem.color.value.value = "#4F4F4F"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/settings/descriptors/axisDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { AxisBaseContainerItem, AxisBaseDescriptor } from "./axisBaseDescriptor"; 27 | 28 | export class AxisDescriptor extends AxisBaseDescriptor { 29 | public name: string = "yAxis"; 30 | public displayNameKey: string = "Visual_YAxis"; 31 | 32 | public getNewContainerItem(defaultContainerItem: AxisBaseContainerItem): AxisBaseContainerItem { 33 | return new AxisBaseContainerItem(defaultContainerItem); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/settings/descriptors/baseDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsCard = formattingSettings.SimpleCard; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | 30 | export class BaseDescriptor extends FormattingSettingsCard { 31 | public isShown: ToggleSwitch = new ToggleSwitch({ 32 | name: "isShown", 33 | displayNameKey: "Visual_Show", 34 | value: true 35 | }); 36 | 37 | constructor(defaultBaseDescriptor?: BaseDescriptor){ 38 | super(); 39 | 40 | if (defaultBaseDescriptor){ 41 | this.isShown.value = defaultBaseDescriptor.isShown.value; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/settings/descriptors/chartDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import ILocalizationManager = powerbi.extensibility.ILocalizationManager; 28 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 29 | 30 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 31 | import FormattingSettingsSlice = formattingSettings.Slice; 32 | import ItemDropdown = formattingSettings.ItemDropdown; 33 | import ColorPicker = formattingSettings.ColorPicker; 34 | import ToggleSwitch = formattingSettings.ToggleSwitch; 35 | 36 | import { dataRepresentationOptions, IEnumMemberWithDisplayNameKey } from "../../converter/data/dataRepresentation"; 37 | import { BaseDescriptor } from "./baseDescriptor"; 38 | import { IDescriptor } from "./descriptor"; 39 | 40 | export class ChartDescriptor extends BaseDescriptor implements IDescriptor { 41 | public name: string = "chart"; 42 | public displayNameKey: string = "Visual_MainChart"; 43 | 44 | public defaultChartType: IEnumMemberWithDisplayNameKey = dataRepresentationOptions[0]; 45 | public defaultColor: string = "#c8d9ec"; 46 | public defaultAlternativeColor: string = "#f1f5fa"; 47 | public thickness: number = 2; 48 | 49 | private minThickness: number = 0.25; 50 | private maxThickness: number = 25; 51 | 52 | public chartType: ItemDropdown = new ItemDropdown({ 53 | name: "chartType", 54 | displayNameKey: "Visual_Type", 55 | items: dataRepresentationOptions, 56 | value: this.defaultChartType 57 | }); 58 | 59 | public color: ColorPicker = new ColorPicker({ 60 | name: "color", 61 | displayNameKey: "Visual_Color", 62 | value: {value: this.defaultColor} 63 | }); 64 | 65 | public alternativeColor: ColorPicker = new ColorPicker({ 66 | name: "alternativeColor", 67 | displayNameKey: "Visual_AlternativeColor", 68 | value: {value: this.defaultAlternativeColor} 69 | }); 70 | 71 | public shouldRenderZeroLine: ToggleSwitch = new ToggleSwitch({ 72 | name: "shouldRenderZeroLine", 73 | displayNameKey: "Visual_ZeroLine", 74 | value: false 75 | }); 76 | 77 | public slices: FormattingSettingsSlice[] = [this.chartType, this.color, this.alternativeColor, this.shouldRenderZeroLine]; 78 | 79 | public parse(): void { 80 | this.thickness = Math.max( 81 | this.minThickness, 82 | Math.min( 83 | this.maxThickness, 84 | this.thickness, 85 | ), 86 | ); 87 | } 88 | 89 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 90 | const isHighContrast: boolean = colorPalette.isHighContrast; 91 | 92 | this.slices.forEach((slice) => { 93 | if (slice instanceof ColorPicker){ 94 | slice.visible = isHighContrast ? false : slice.visible; 95 | slice.value = isHighContrast ? colorPalette.foreground : slice.value; 96 | } 97 | }) 98 | } 99 | 100 | public setLocalizedDisplayName(localizationManager: ILocalizationManager): void { 101 | dataRepresentationOptions.forEach(option => { 102 | option.displayName = localizationManager.getDisplayName(option.key) 103 | }); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/settings/descriptors/container/baseContainerDescriptor.ts: -------------------------------------------------------------------------------- 1 | import powerbi from "powerbi-visuals-api"; 2 | import ISelectionId = powerbi.visuals.ISelectionId; 3 | import DataViewMetadataColumn = powerbi.DataViewMetadataColumn; 4 | import Selector = powerbi.data.Selector; 5 | import FormattingComponent = powerbi.visuals.FormattingComponent; 6 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 7 | 8 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 9 | import FormattingSettingsCard = formattingSettings.SimpleCard; 10 | import FormattingSettingsContainer = formattingSettings.Container; 11 | import FormattingSettingsSlice = formattingSettings.Slice; 12 | import FontControl = formattingSettings.FontControl; 13 | import { ColorHelper } from "powerbi-visuals-utils-colorutils"; 14 | 15 | import { FormatDescriptor } from "../formatDescriptor"; 16 | import { BaseDescriptor } from "../baseDescriptor"; 17 | import { IDescriptor } from "../descriptor"; 18 | 19 | export type BaseContainerItemType = FormatDescriptor | BaseDescriptor; 20 | 21 | export abstract class BaseContainerDescriptor extends FormattingSettingsCard implements IDescriptor{ 22 | protected abstract getNewContainerItem(defaultContainerItem?: BaseContainerItem): BaseContainerItem; 23 | 24 | public defaultContainerItem: BaseContainerItem = this.getNewContainerItem(); 25 | 26 | public container: FormattingSettingsContainer = { 27 | displayNameKey: "Visual_ApplySettingsTo", 28 | containerItems: [this.defaultContainerItem] 29 | }; 30 | 31 | public createContainerItem(dataPoint: DataViewMetadataColumn, selectionId: ISelectionId): BaseContainerItem { 32 | const { displayName, objects, format } = dataPoint; 33 | 34 | const newContainerItem: BaseContainerItem = this.getNewContainerItem(this.defaultContainerItem); 35 | newContainerItem.displayName = displayName; 36 | newContainerItem.displayNameKey = null; 37 | 38 | if (newContainerItem instanceof FormatDescriptor){ 39 | newContainerItem.format.value = newContainerItem.format.value ?? format; 40 | } 41 | 42 | const selector: Selector = ColorHelper.normalizeSelector(selectionId?.getSelector()); 43 | newContainerItem.slices.forEach((slice: FormattingSettingsSlice) => { 44 | slice.setPropertiesValues(objects, this.name); 45 | this.setSliceSelector(slice, selector); 46 | }); 47 | 48 | return newContainerItem; 49 | } 50 | 51 | public populateContainer(containerItem: BaseContainerItem){ 52 | this.container.containerItems.push(containerItem); 53 | } 54 | 55 | public getCurrentContainer(containerName: string): BaseContainerItem { 56 | const currentContainer = this.container.containerItems.find(el => el.displayName === containerName); 57 | return (currentContainer as BaseContainerItem); 58 | } 59 | 60 | public parse(): void { 61 | this.container.containerItems.forEach((item) => { 62 | const settings = item as IDescriptor; 63 | if (settings.parse) { 64 | settings.parse(); 65 | } 66 | }); 67 | } 68 | 69 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 70 | this.container.containerItems.forEach((item) => { 71 | const settings = item as IDescriptor; 72 | if (settings.processHighContrastMode) { 73 | settings.processHighContrastMode(colorPalette); 74 | } 75 | }); 76 | } 77 | 78 | private setSliceSelector(slice: FormattingSettingsSlice, selector: Selector) { 79 | if (slice instanceof formattingSettings.CompositeSlice){ 80 | if (slice.type === FormattingComponent.FontControl){ 81 | const fontControlSlice: FontControl = slice as FontControl; 82 | fontControlSlice.fontFamily.selector = selector; 83 | fontControlSlice.fontSize.selector = selector; 84 | } 85 | } 86 | else { 87 | slice.selector = selector; 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /src/settings/descriptors/dateDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | 29 | import { FormatDescriptor } from "./formatDescriptor"; 30 | 31 | export class DateDescriptor extends FormatDescriptor { 32 | public name: string = "date"; 33 | public displayNameKey: string = "Visual_Date"; 34 | public slices: FormattingSettingsSlice[] = [this.format] 35 | 36 | constructor(){ 37 | super(); 38 | this.format.value = "%M/%d/yyyy"; 39 | } 40 | } -------------------------------------------------------------------------------- /src/settings/descriptors/descriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import ILocalizationManager = powerbi.extensibility.ILocalizationManager; 28 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 29 | 30 | export interface IDescriptor { 31 | parse?(): void; 32 | setDefault?(): void; 33 | setLocalizedDisplayName?(localizationManager: ILocalizationManager): void; 34 | processHighContrastMode?(colorPalette: ISandboxExtendedColorPalette): void; 35 | } 36 | -------------------------------------------------------------------------------- /src/settings/descriptors/formatDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import TextInput = formattingSettings.TextInput; 28 | 29 | import { BaseDescriptor } from "./baseDescriptor"; 30 | 31 | export class FormatDescriptor extends BaseDescriptor { 32 | public defaultPlaceholderFormat: string = "Auto"; 33 | 34 | public format: TextInput = new TextInput({ 35 | name: "format", 36 | displayNameKey: "Visual_Format", 37 | value: null, 38 | placeholder: this.defaultPlaceholderFormat 39 | }); 40 | 41 | constructor(defaultFormatDescriptor?: FormatDescriptor){ 42 | super(defaultFormatDescriptor); 43 | 44 | if (defaultFormatDescriptor){ 45 | this.format.value = defaultFormatDescriptor.format.value; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/settings/descriptors/gridDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import ValidatorType = powerbi.visuals.ValidatorType; 28 | 29 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 30 | import FormattingSettingsSlice = formattingSettings.Slice; 31 | import NumUpDown = formattingSettings.NumUpDown; 32 | import ToggleSwitch = formattingSettings.ToggleSwitch; 33 | 34 | import { BaseDescriptor } from "./baseDescriptor"; 35 | import { IDescriptor } from "./descriptor"; 36 | 37 | export class GridDescriptor extends BaseDescriptor implements IDescriptor{ 38 | public static MaxColumns: number = 15; 39 | public name: string = "grid"; 40 | public displayNameKey: string = "Visual_SparklineGrid"; 41 | 42 | private minColumns: number = 1; 43 | 44 | public columns: NumUpDown = new NumUpDown({ 45 | name: "columns", 46 | displayNameKey: "Visual_Columns", 47 | value: null, 48 | options: { 49 | minValue: { 50 | type: ValidatorType.Min, 51 | value: this.minColumns 52 | }, 53 | maxValue: { 54 | type: ValidatorType.Max, 55 | value: GridDescriptor.MaxColumns 56 | } 57 | } 58 | }); 59 | 60 | public toggleSparklineOnHover: ToggleSwitch = new ToggleSwitch({ 61 | name: "toggleSparklineOnHover", 62 | displayNameKey: "Visual_ToggleSparklineOnHover", 63 | descriptionKey: "Visual_ToggleSparklineOnHoverDescription", 64 | value: true 65 | }); 66 | 67 | public slices: FormattingSettingsSlice[] = [this.columns, this.toggleSparklineOnHover]; 68 | 69 | public parse(): void { 70 | this.columns.value = isNaN(this.columns.value) || this.columns.value === null 71 | ? this.columns.value 72 | : Math.max( 73 | Math.min(this.columns.value, GridDescriptor.MaxColumns), 74 | this.minColumns, 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/settings/descriptors/kpi/kpiDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { KpiBaseDescriptor } from "./kpiBaseDescriptor"; 28 | 29 | export class KpiDescriptor extends KpiBaseDescriptor { 30 | public name: string = "kpi"; 31 | public displayNameKey: string = "Visual_KPI"; 32 | 33 | constructor(){ 34 | super(); 35 | 36 | this.slices.push(this.startDate); 37 | } 38 | 39 | public get percentCalcDate(): Date { 40 | if (!this.startDate.value) { 41 | return undefined; 42 | } 43 | 44 | const date: Date = new Date(this.startDate.value); 45 | 46 | if (!date || isNaN(date.getTime())) { 47 | return undefined; 48 | } 49 | 50 | return date; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/settings/descriptors/kpi/kpiOnHoverDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import ValidatorType = powerbi.visuals.ValidatorType; 28 | 29 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 30 | import ToggleSwitch = formattingSettings.ToggleSwitch; 31 | import ColorPicker = formattingSettings.ColorPicker; 32 | import NumUpDown = formattingSettings.NumUpDown; 33 | 34 | import { KpiBaseDescriptor } from "./kpiBaseDescriptor"; 35 | 36 | export class KpiOnHoverDescriptor extends KpiBaseDescriptor { 37 | public name: string = "kpiOnHover"; 38 | public displayNameKey: string = "Visual_KPIOnHover"; 39 | 40 | public defaultCurrentValueFontSize: number = 11; 41 | public defaultCurrentValueColor: string = "#217CC9"; 42 | public defaultSeriesNameColor: string = "#4F4F4F"; 43 | 44 | public isCurrentValueShown: ToggleSwitch = new ToggleSwitch({ 45 | name: "isCurrentValueShown", 46 | displayNameKey: "Visual_CurrentValue", 47 | value: true 48 | }); 49 | 50 | public currentValueColor: ColorPicker = new ColorPicker({ 51 | name: "currentValueColor", 52 | displayNameKey: "Visual_CurrentValueColor", 53 | value: {value: this.defaultCurrentValueColor} 54 | }); 55 | 56 | public isCurrentValueLeftAligned: ToggleSwitch = new ToggleSwitch({ 57 | name: "isCurrentValueLeftAligned", 58 | displayNameKey: "Visual_CurrentValueIsLeftAlgned", 59 | value: true 60 | }); 61 | 62 | public currentValueFontSize: NumUpDown = new NumUpDown({ 63 | name: "currentValueFontSize", 64 | displayNameKey: "Visual_CurrentValueFontSize", 65 | value: this.defaultCurrentValueFontSize, 66 | options: { 67 | maxValue: { 68 | type: ValidatorType.Max, 69 | value: this.maxFontSize 70 | }, 71 | minValue: { 72 | type: ValidatorType.Min, 73 | value: this.minFontSize 74 | } 75 | } 76 | }); 77 | 78 | constructor() { 79 | super(); 80 | this.slices.push(this.isCurrentValueShown, this.currentValueFontSize, this.currentValueColor, this.isCurrentValueLeftAligned); 81 | 82 | this.seriesNameColor.value.value = this.defaultSeriesNameColor; 83 | this.valueColor.value.value = this.defaultSeriesNameColor; 84 | } 85 | 86 | public parse(): void { 87 | super.parse(); 88 | 89 | this.currentValueFontSize.value = this.getValidFontSize(this.currentValueFontSize.value); 90 | } 91 | 92 | onPreProcess(): void { 93 | super.onPreProcess(); 94 | 95 | const isSliceVisible: boolean = !this.autoAdjustFontSize.value; 96 | this.currentValueFontSize.visible = isSliceVisible; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/settings/descriptors/numericDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import NumUpDown = formattingSettings.NumUpDown; 28 | import AutoDropdown = formattingSettings.AutoDropdown; 29 | import TextInput = formattingSettings.TextInput; 30 | 31 | import { IDescriptor } from "./descriptor"; 32 | import { FormatDescriptor } from "./formatDescriptor"; 33 | 34 | export enum DisplayUnitsType { 35 | Auto = 0, 36 | None = 1, 37 | Thousands = 1000, 38 | Millions = 1000000, 39 | Billions = 1000000000, 40 | Trillions = 1000000000000 41 | } 42 | 43 | export class NumericDescriptor extends FormatDescriptor implements IDescriptor { 44 | public autoPrecision: boolean = false; 45 | public defaultNoValueLabel: string = "N/A"; 46 | 47 | protected minPrecision: number = 0; 48 | protected maxPrecision: number = 17; 49 | 50 | public noValueLabel: TextInput = new TextInput({ 51 | name: "noValueLabel", 52 | displayNameKey: "Visual_NoValueLabel", 53 | value: this.defaultNoValueLabel, 54 | placeholder: this.defaultNoValueLabel 55 | }); 56 | 57 | public displayUnits: AutoDropdown = new AutoDropdown({ 58 | name: "displayUnits", 59 | displayNameKey: "Visual_DisplayUnits", 60 | value: DisplayUnitsType.Auto 61 | }); 62 | 63 | public precision: NumUpDown = new NumUpDown({ 64 | name: "precision", 65 | displayNameKey: "Visual_Precision", 66 | value: 0, 67 | options: { 68 | minValue: { 69 | type: powerbi.visuals.ValidatorType.Min, 70 | value: this.minPrecision, 71 | }, 72 | maxValue: { 73 | type: powerbi.visuals.ValidatorType.Max, 74 | value: this.maxPrecision, 75 | }, 76 | } 77 | }); 78 | 79 | public parse(): void { 80 | this.precision.value = this.getValidPrecision(this.precision.value); 81 | } 82 | 83 | protected getValidPrecision(precision: number): number { 84 | if (isNaN(precision)) { 85 | return precision; 86 | } 87 | 88 | return Math.min( 89 | Math.max(this.minPrecision, precision), 90 | this.maxPrecision, 91 | ); 92 | } 93 | 94 | constructor(defaultNumericDescriptor?: NumericDescriptor){ 95 | super(defaultNumericDescriptor); 96 | 97 | if (defaultNumericDescriptor){ 98 | this.noValueLabel.value = defaultNumericDescriptor.noValueLabel.value; 99 | this.displayUnits.value = defaultNumericDescriptor.displayUnits.value; 100 | this.precision.value = defaultNumericDescriptor.precision.value; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/settings/descriptors/printDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsCard = formattingSettings.SimpleCard; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | import FormattingSettingsSlice = formattingSettings.Slice; 30 | 31 | export class PrintDescriptor extends FormattingSettingsCard { 32 | public name: string = "printMode"; 33 | public displayNameKey: string = "Visual_PrintMode"; 34 | public descriptionKey: string = "Visual_PrintModeDescription"; 35 | 36 | public show: ToggleSwitch = new ToggleSwitch({ 37 | name: "show", 38 | displayNameKey: "Visual_Show", 39 | value: true 40 | }); 41 | public topLevelSlice?: ToggleSwitch = this.show; 42 | public slices: FormattingSettingsSlice[] = [] 43 | 44 | constructor(){ 45 | super(); 46 | this.show.value = false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/settings/descriptors/sparkline/sparklineAxisDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import ToggleSwitch = formattingSettings.ToggleSwitch; 28 | 29 | import { AxisBaseContainerItem, AxisBaseDescriptor } from "../axisBaseDescriptor"; 30 | 31 | export class SparklineAxisContainerItem extends AxisBaseContainerItem { 32 | public name: string = "sparklineYAxis"; 33 | 34 | public shouldInheritValues: ToggleSwitch = new ToggleSwitch({ 35 | name: "shouldInheritValues", 36 | displayNameKey: "Visual_ShouldInheritValues", 37 | value: false 38 | }); 39 | 40 | constructor(defaultAxisContainerItem?: SparklineAxisContainerItem){ 41 | super(defaultAxisContainerItem); 42 | if (defaultAxisContainerItem){ 43 | this.shouldInheritValues.value = defaultAxisContainerItem.shouldInheritValues.value; 44 | } 45 | this.slices.push(this.shouldInheritValues); 46 | } 47 | } 48 | 49 | export class SparklineAxisDescriptor extends AxisBaseDescriptor { 50 | public name: string = "sparklineYAxis"; 51 | public displayNameKey: string = "Visual_SparklineYAxis"; 52 | 53 | public getNewContainerItem(defaultContainerItem: SparklineAxisContainerItem): SparklineAxisContainerItem { 54 | return new SparklineAxisContainerItem(defaultContainerItem); 55 | } 56 | 57 | constructor(){ 58 | super(); 59 | 60 | this.defaultContainerItem.axisLabelX = 8; 61 | this.defaultContainerItem.axisLabelY = 2; 62 | this.defaultContainerItem.isShown.value = false; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/settings/descriptors/sparkline/sparklineChartDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | import ColorPicker = formattingSettings.ColorPicker; 30 | 31 | import { BaseDescriptor } from "../baseDescriptor"; 32 | import { BaseContainerDescriptor } from "../container/baseContainerDescriptor"; 33 | 34 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 35 | 36 | export class SparklineChartContainerItem extends BaseDescriptor { 37 | public displayNameKey: string = "Visual_All"; 38 | 39 | public defaultColorValue: string = "#217cc9"; 40 | public defaultAlternativeColorValue: string = "#c7def1"; 41 | public defaultShouldInterpolate: boolean = true; 42 | public thickness: number = 1; 43 | public dotRadiusFactor: number = 2; 44 | 45 | private minThickness: number = 0.25; 46 | private maxThickness: number = 25; 47 | 48 | public color: ColorPicker = new ColorPicker({ 49 | name: "color", 50 | displayNameKey: "Visual_Color", 51 | value: {value:this.defaultColorValue} 52 | }); 53 | 54 | public alternativeColor: ColorPicker = new ColorPicker({ 55 | name: "alternativeColor", 56 | displayNameKey: "Visual_AlternativeColor", 57 | value: {value: this.defaultAlternativeColorValue} 58 | }); 59 | 60 | public shouldInterpolate: ToggleSwitch = new ToggleSwitch({ 61 | name: "shouldInterpolate", 62 | displayNameKey: "Visual_Interpolate", 63 | value: this.defaultShouldInterpolate 64 | }); 65 | 66 | public slices: FormattingSettingsSlice[] = [this.color, this.alternativeColor, this.shouldInterpolate]; 67 | 68 | public getRadius(): number { 69 | return this.thickness * this.dotRadiusFactor; 70 | } 71 | 72 | public parse(): void { 73 | this.thickness = Math.max( 74 | this.minThickness, 75 | Math.min( 76 | this.maxThickness, 77 | this.thickness, 78 | ), 79 | ); 80 | } 81 | 82 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 83 | const isHighContrast: boolean = colorPalette.isHighContrast; 84 | 85 | this.slices.forEach((slice) => { 86 | if (slice instanceof ColorPicker){ 87 | slice.visible = isHighContrast ? false : slice.visible; 88 | slice.value = isHighContrast ? colorPalette.foreground : slice.value; 89 | } 90 | }) 91 | } 92 | 93 | constructor(defaultSparklineChartContainerItem?: SparklineChartContainerItem){ 94 | super(defaultSparklineChartContainerItem); 95 | 96 | if(defaultSparklineChartContainerItem){ 97 | this.color.value = defaultSparklineChartContainerItem.color.value; 98 | this.alternativeColor.value = defaultSparklineChartContainerItem.alternativeColor.value; 99 | this.shouldInterpolate.value = defaultSparklineChartContainerItem.shouldInterpolate.value; 100 | } 101 | } 102 | } 103 | 104 | export class SparklineChartDescriptor extends BaseContainerDescriptor { 105 | public name: string = "sparklineChart"; 106 | public displayNameKey: string = "Visual_SparklineChart"; 107 | 108 | public getNewContainerItem(defaultContainerItem: SparklineChartContainerItem): SparklineChartContainerItem { 109 | return new SparklineChartContainerItem(defaultContainerItem); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/settings/descriptors/sparkline/sparklineDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import ValidatorType = powerbi.visuals.ValidatorType; 28 | 29 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 30 | import FormattingSettingsSlice = formattingSettings.Slice; 31 | import NumUpDown = formattingSettings.NumUpDown; 32 | 33 | import { BaseDescriptor } from "../baseDescriptor"; 34 | import { IDescriptor } from "../descriptor"; 35 | import { GridDescriptor } from "../gridDescriptor"; 36 | import { BaseContainerDescriptor } from "../container/baseContainerDescriptor"; 37 | 38 | export class SparklineContainerItem extends BaseDescriptor implements IDescriptor{ 39 | public displayNameKey: string = "Visual_All"; 40 | 41 | private minPosition: number = 1; 42 | private maxPosition: number = GridDescriptor.MaxColumns + 1; 43 | 44 | public position = new NumUpDown({ 45 | name: "position", 46 | displayNameKey: "Visual_Position", 47 | value: NaN, 48 | options: { 49 | maxValue: { 50 | type: ValidatorType.Max, 51 | value: this.maxPosition 52 | }, 53 | minValue: { 54 | type: ValidatorType.Min, 55 | value: this.minPosition 56 | } 57 | } 58 | }); 59 | 60 | public slices: FormattingSettingsSlice[] = [this.position]; 61 | 62 | public parse(): void { 63 | this.position.value = isNaN(this.position.value) || this.position.value === null 64 | ? this.position.value 65 | : Math.max( 66 | this.minPosition, 67 | Math.min( 68 | this.maxPosition, 69 | this.position.value, 70 | ), 71 | ); 72 | } 73 | 74 | constructor(defaultSparklineContainerItem?: SparklineContainerItem){ 75 | super(defaultSparklineContainerItem); 76 | 77 | if(defaultSparklineContainerItem){ 78 | this.position.value = defaultSparklineContainerItem.position.value; 79 | } 80 | } 81 | } 82 | 83 | export class SparklineDescriptor extends BaseContainerDescriptor { 84 | public name = "sparkline"; 85 | public displayNameKey = "Visual_Sparkline"; 86 | 87 | public getNewContainerItem(defaultContainerItem: SparklineContainerItem): SparklineContainerItem { 88 | return new SparklineContainerItem(defaultContainerItem); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/settings/descriptors/sparklineNameDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | 30 | import { SubtitleBaseContainerItem } from "./subtitleBaseDescriptor"; 31 | import { BaseContainerDescriptor } from "./container/baseContainerDescriptor"; 32 | 33 | export class SparklineNameContainerItem extends SubtitleBaseContainerItem { 34 | public name: string = "sparklineLabel"; 35 | public slices: FormattingSettingsSlice[] = [ 36 | this.isShown, this.autoAdjustFontSize, 37 | this.font, this.color, this.alignment 38 | ]; 39 | } 40 | 41 | export class SparklineNameDescriptor extends BaseContainerDescriptor { 42 | public name: string = "sparklineLabel"; 43 | public displayNameKey: string = "Visual_SparklineName"; 44 | 45 | topLevelSlice: ToggleSwitch = null; 46 | 47 | public getNewContainerItem(defaultContainerItem: SparklineNameContainerItem): SparklineNameContainerItem { 48 | return new SparklineNameContainerItem(defaultContainerItem); 49 | } 50 | 51 | constructor(){ 52 | super(); 53 | this.defaultContainerItem.autoAdjustFontSize.value = true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/settings/descriptors/sparklineValueDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | 29 | import { SubtitleBaseContainerItem } from "./subtitleBaseDescriptor"; 30 | import { BaseContainerDescriptor } from "./container/baseContainerDescriptor"; 31 | 32 | export class SparklineValueContainerItem extends SubtitleBaseContainerItem { 33 | public name: string = "sparklineValue"; 34 | 35 | public slices: FormattingSettingsSlice[] = [ 36 | this.isShown, this.format, this.displayUnits, 37 | this.precision, this.autoAdjustFontSize, 38 | this.font, this.color, this.alignment 39 | ]; 40 | } 41 | 42 | export class SparklineValueDescriptor extends BaseContainerDescriptor { 43 | public name: string = "sparklineValue"; 44 | public displayNameKey: string = "Visual_SparklineValue"; 45 | 46 | public getNewContainerItem(defaultContainerItem: SparklineValueContainerItem): SparklineValueContainerItem { 47 | return new SparklineValueContainerItem(defaultContainerItem); 48 | } 49 | 50 | constructor(){ 51 | super(); 52 | this.defaultContainerItem.autoAdjustFontSize.value = true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/settings/descriptors/staleDataDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | import NumUpDown = formattingSettings.NumUpDown; 30 | import ColorPicker = formattingSettings.ColorPicker; 31 | import TextInput = formattingSettings.TextInput; 32 | 33 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 34 | 35 | import { BaseDescriptor } from "./baseDescriptor"; 36 | 37 | export class StaleDataDescriptor extends BaseDescriptor { 38 | public name: string = "staleData"; 39 | public displayNameKey: string = "Visual_StaleData"; 40 | public descriptionKey: string = "Visual_StaleDataDescription"; 41 | 42 | public defaultColorValue: string = "#3599b8"; 43 | public defaultBackgroundValue: string = ""; 44 | 45 | public staleDataText: TextInput = new TextInput({ 46 | name: "staleDataText", 47 | displayNameKey: "Visual_Title", 48 | descriptionKey: "Visual_StaleDataTextDescription", 49 | value: "", 50 | placeholder: "" 51 | }); 52 | 53 | public staleDataThreshold: NumUpDown = new NumUpDown({ 54 | name: "staleDataThreshold", 55 | displayNameKey: "Visual_Threshold", 56 | descriptionKey: "Visual_ThresholdDescription", 57 | value: 0 58 | }); 59 | 60 | public color: ColorPicker = new ColorPicker({ 61 | name: "color", 62 | displayNameKey: "Visual_Color", 63 | value: {value: this.defaultColorValue} 64 | }); 65 | 66 | public backgroundColor: ColorPicker = new ColorPicker({ 67 | name: "background", 68 | displayNameKey: "Visual_BackgroundColor", 69 | value: {value: this.defaultBackgroundValue} 70 | }); 71 | 72 | public deductThresholdDays: ToggleSwitch = new ToggleSwitch({ 73 | name: "deductThresholdDays", 74 | displayNameKey: "Visual_DeductThresholdDays", 75 | value: false 76 | }); 77 | 78 | topLevelSlice: ToggleSwitch = this.isShown; 79 | 80 | public slices: FormattingSettingsSlice[] = [ 81 | this.staleDataText, this.deductThresholdDays, 82 | this.staleDataThreshold, this.color, this.backgroundColor 83 | ]; 84 | 85 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 86 | const isHighContrast: boolean = colorPalette.isHighContrast; 87 | 88 | this.color.visible = isHighContrast ? false : this.color.visible; 89 | this.color.value = isHighContrast ? colorPalette.foreground : this.color.value; 90 | 91 | this.backgroundColor.visible = isHighContrast ? false : this.backgroundColor.visible; 92 | this.backgroundColor.value = isHighContrast ? colorPalette.foreground : this.backgroundColor.value; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/settings/descriptors/subtitleBaseDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import TextInput = formattingSettings.TextInput; 28 | import ColorPicker = formattingSettings.ColorPicker; 29 | import ToggleSwitch = formattingSettings.ToggleSwitch; 30 | import AlignmentGroup = formattingSettings.AlignmentGroup; 31 | 32 | import { TextFormattingDescriptor } from "./textFormattingDescriptor"; 33 | 34 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 35 | 36 | export enum SubtitleAlignment { 37 | left = "left", 38 | center = "center", 39 | right = "right", 40 | } 41 | 42 | export class SubtitleBaseContainerItem extends TextFormattingDescriptor { 43 | public displayNameKey: string = "Visual_All"; 44 | 45 | public defaultTitleText: string = ""; 46 | public defaultBackgroundColor: string = ""; 47 | public defaultWarningText: string = ""; 48 | public defaultAlignment: SubtitleAlignment = SubtitleAlignment.left; 49 | public defaultFontColor: string = "#217cc9"; 50 | public defaultFontFamily: string = "wf_standard-font, helvetica, arial, sans-serif"; 51 | 52 | public paddingTop: number = 0; 53 | public paddingBottom: number = 0; 54 | 55 | public titleText: TextInput = new TextInput({ 56 | name: "titleText", 57 | displayNameKey: "Visual_TitleText", 58 | value: this.defaultTitleText, 59 | placeholder: this.defaultTitleText 60 | }); 61 | 62 | public backgroundColor: ColorPicker = new ColorPicker({ 63 | name: "background", 64 | displayNameKey: "Visual_BackgroundColor", 65 | value: {value: this.defaultBackgroundColor} 66 | }); 67 | 68 | public alignment: AlignmentGroup = new AlignmentGroup({ 69 | name: "alignment", 70 | displayNameKey: "Visual_Alignment", 71 | mode: powerbi.visuals.AlignmentGroupMode.Horizonal, 72 | value: SubtitleAlignment.center 73 | }); 74 | 75 | public warningText: TextInput = new TextInput({ 76 | name: "warningText", 77 | displayNameKey: "Visual_Warning", 78 | value: this.defaultWarningText, 79 | placeholder: this.defaultWarningText 80 | }); 81 | 82 | public show: ToggleSwitch = new ToggleSwitch({ 83 | name: "show", 84 | displayNameKey: "Visual_Show", 85 | value: true 86 | }); 87 | 88 | constructor(defaultSubtitleDescriptor?: SubtitleBaseContainerItem){ 89 | super(defaultSubtitleDescriptor); 90 | 91 | if (defaultSubtitleDescriptor){ 92 | this.titleText.value = defaultSubtitleDescriptor.titleText.value; 93 | this.backgroundColor.value = defaultSubtitleDescriptor.backgroundColor.value; 94 | this.alignment.value = defaultSubtitleDescriptor.alignment.value; 95 | this.warningText.value = defaultSubtitleDescriptor.warningText.value; 96 | this.show.value = defaultSubtitleDescriptor.show.value; 97 | } 98 | else { 99 | this.color.value.value = this.defaultFontColor; 100 | this.font.fontFamily.value = this.defaultFontFamily; 101 | } 102 | } 103 | 104 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 105 | super.processHighContrastMode(colorPalette); 106 | 107 | const isHighContrast: boolean = colorPalette.isHighContrast; 108 | this.backgroundColor.visible = isHighContrast ? false : this.backgroundColor.visible; 109 | this.backgroundColor.value = isHighContrast ? colorPalette.background : this.backgroundColor.value; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/settings/descriptors/subtitleDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | 30 | import { SubtitleAlignment, SubtitleBaseContainerItem } from "./subtitleBaseDescriptor"; 31 | 32 | export class SubtitleContainerItem extends SubtitleBaseContainerItem { 33 | public name: string = "subtitle"; 34 | public displayNameKey: string = "Visual_Subtitle"; 35 | 36 | public defaultWarningText: string = "Warning Message"; 37 | public staleDataText: string = ""; // We keep it here just for compatibility with old reports 38 | public defaultFontFamily: string = "Segoe UI, wf_segoe-ui_normal, helvetica, arial, sans-serif"; 39 | 40 | topLevelSlice: ToggleSwitch = this.show; 41 | public slices: FormattingSettingsSlice[] = [ 42 | this.font, this.color, this.titleText, 43 | this.backgroundColor, this.alignment, 44 | this.warningText 45 | ]; 46 | 47 | constructor(){ 48 | super(); 49 | this.show.value = false; 50 | this.alignment.value = SubtitleAlignment.left; 51 | this.font.fontSize.value = 8.25; 52 | this.font.fontFamily.value = this.defaultFontFamily; 53 | this.color.value.value = "#4F4F4F"; 54 | this.warningText.value = this.defaultWarningText; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/settings/descriptors/textFormattingDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { pixelConverter } from "powerbi-visuals-utils-typeutils"; 28 | 29 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 30 | import FontControl = formattingSettings.FontControl; 31 | import FontPicker = formattingSettings.FontPicker; 32 | import NumUpDown = formattingSettings.NumUpDown; 33 | import ColorPicker = formattingSettings.ColorPicker; 34 | import ToggleSwitch = formattingSettings.ToggleSwitch; 35 | 36 | import ValidatorType = powerbi.visuals.ValidatorType; 37 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 38 | 39 | import { NumericDescriptor } from "./numericDescriptor"; 40 | 41 | export class TextFormattingDescriptor extends NumericDescriptor { 42 | public defaultAutoAdjustFontSize: boolean = false; 43 | public autoFontSizeValue: number = 8; 44 | public defaultFontSize: number = 8; 45 | public defaultFontFamily: string = "Segoe UI, wf_segoe-ui_normal, helvetica, arial, sans-serif"; 46 | public defaultFontColor: string = "#666666"; 47 | 48 | protected minFontSize: number = 4; 49 | protected maxFontSize: number = 72; 50 | 51 | public fontSize: NumUpDown = new NumUpDown({ 52 | name: "fontSize", 53 | value: this.defaultFontSize, 54 | options: { 55 | minValue: { 56 | type: ValidatorType.Min, 57 | value: this.minFontSize, 58 | }, 59 | maxValue: { 60 | type: ValidatorType.Max, 61 | value: this.maxFontSize 62 | } 63 | } 64 | }); 65 | 66 | public fontFamily: FontPicker = new FontPicker({ 67 | name: "fontFamily", 68 | displayNameKey: "Visual_FontFamily", 69 | value: this.defaultFontFamily 70 | }); 71 | 72 | public isBold: ToggleSwitch = new ToggleSwitch({ 73 | name: "bold", 74 | value: false 75 | }); 76 | 77 | public isItalic: ToggleSwitch = new ToggleSwitch({ 78 | name: "italic", 79 | value: false 80 | }); 81 | 82 | public isUnderlined: ToggleSwitch = new ToggleSwitch({ 83 | name: "underline", 84 | value: false, 85 | }); 86 | 87 | public font: FontControl = new FontControl({ 88 | name: "font", 89 | displayNameKey: "Visual_Font", 90 | fontFamily: this.fontFamily, 91 | fontSize: this.fontSize, 92 | bold: this.isBold, 93 | italic: this.isItalic, 94 | underline: this.isUnderlined 95 | }); 96 | 97 | public color: ColorPicker = new ColorPicker({ 98 | name: "color", 99 | displayNameKey: "Visual_FontColor", 100 | value: { value: this.defaultFontColor } 101 | }); 102 | 103 | public autoAdjustFontSize: ToggleSwitch = new ToggleSwitch({ 104 | name: "autoAdjustFontSize", 105 | displayNameKey: "Visual_AutoFontSize", 106 | value: this.defaultAutoAdjustFontSize 107 | }); 108 | 109 | public parse(): void { 110 | super.parse(); 111 | this.font.fontSize.value = this.getValidFontSize(this.font.fontSize.value); 112 | } 113 | 114 | public processHighContrastMode(colorPalette: ISandboxExtendedColorPalette): void { 115 | const isHighContrast: boolean = colorPalette.isHighContrast; 116 | this.color.visible = isHighContrast ? false : this.color.visible; 117 | this.color.value = isHighContrast ? colorPalette.foreground : this.color.value; 118 | } 119 | 120 | public get fontSizePx(): string { 121 | return pixelConverter.toString(this.fontSizeInPx); 122 | } 123 | 124 | private get fontSizeInPx(): number { 125 | const fontSize: number = this.autoAdjustFontSize.value 126 | ? this.autoFontSizeValue 127 | : this.font.fontSize.value; 128 | 129 | return pixelConverter.fromPointToPixel(fontSize); 130 | } 131 | 132 | protected getValidFontSize(fontSize: number): number { 133 | return Math.max( 134 | this.minFontSize, 135 | Math.min( 136 | this.maxFontSize, 137 | fontSize, 138 | ), 139 | ); 140 | } 141 | 142 | constructor(defaultTextDescriptor?: TextFormattingDescriptor){ 143 | super(defaultTextDescriptor); 144 | 145 | if (defaultTextDescriptor){ 146 | this.fontSize.value = defaultTextDescriptor.fontSize.value; 147 | this.fontFamily.value = defaultTextDescriptor.fontFamily.value; 148 | this.isBold.value = defaultTextDescriptor.isBold.value; 149 | this.isItalic.value = defaultTextDescriptor.isItalic.value; 150 | this.isUnderlined.value = defaultTextDescriptor.isUnderlined.value; 151 | this.color.value = defaultTextDescriptor.color.value; 152 | this.autoAdjustFontSize.value = defaultTextDescriptor.autoAdjustFontSize.value; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/settings/descriptors/tooltipDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import TextInput = formattingSettings.TextInput; 29 | import ToggleSwitch = formattingSettings.ToggleSwitch; 30 | 31 | import { BaseDescriptor } from "./baseDescriptor"; 32 | import { BaseContainerDescriptor } from "./container/baseContainerDescriptor"; 33 | 34 | export class TooltipContainerItem extends BaseDescriptor { 35 | public displayNameKey: string = "Visual_All"; 36 | 37 | public label: TextInput = new TextInput({ 38 | name: "label", 39 | displayNameKey: "Visual_Label", 40 | value: null, 41 | placeholder: null 42 | }); 43 | 44 | public showDateDifference: ToggleSwitch = new ToggleSwitch({ 45 | name: "showDateDifference", 46 | displayNameKey: "Visual_DateDifference", 47 | value: true 48 | }); 49 | 50 | public showVariance: ToggleSwitch = new ToggleSwitch({ 51 | name: "showVariance", 52 | displayNameKey: "Visual_Variance", 53 | value: true 54 | }); 55 | 56 | public showDate: ToggleSwitch = new ToggleSwitch({ 57 | name: "showDate", 58 | displayNameKey: "Visual_Date", 59 | value: true 60 | }); 61 | 62 | public slices: FormattingSettingsSlice[] = [ 63 | this.isShown, this.label, this.showDateDifference, this.showVariance, this.showDate 64 | ]; 65 | 66 | constructor(defaultTooltipContainerItem?: TooltipContainerItem){ 67 | super(defaultTooltipContainerItem); 68 | 69 | if(defaultTooltipContainerItem){ 70 | this.label.value = defaultTooltipContainerItem.label.value; 71 | this.showDateDifference.value = defaultTooltipContainerItem.showDateDifference.value; 72 | this.showVariance.value = defaultTooltipContainerItem.showVariance.value; 73 | this.showDate.value = defaultTooltipContainerItem.showDate.value; 74 | } 75 | } 76 | } 77 | 78 | export class TooltipDescriptor extends BaseContainerDescriptor { 79 | public name: string = "tooltip"; 80 | public displayNameKey: string = "Visual_Tooltip"; 81 | 82 | public getNewContainerItem(defaultContainerItem: TooltipContainerItem): TooltipContainerItem { 83 | return new TooltipContainerItem(defaultContainerItem); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/settings/descriptors/valuesDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | 30 | import { NumericDescriptor } from "./numericDescriptor"; 31 | import { BaseContainerDescriptor } from "./container/baseContainerDescriptor"; 32 | 33 | export class ValuesContainerItem extends NumericDescriptor { 34 | public displayNameKey: string = "Visual_All"; 35 | 36 | public treatEmptyValuesAsZero: ToggleSwitch = new ToggleSwitch({ 37 | name: "treatEmptyValuesAsZero", 38 | displayNameKey: "Visual_TreatEmptyValuesAsZero", 39 | value: true 40 | }); 41 | 42 | public showLatterAvailableValue: ToggleSwitch = new ToggleSwitch({ 43 | name: "showLatterAvailableValue", 44 | displayNameKey: "Visual_ShowLatestAvailableValue", 45 | value: false 46 | }); 47 | 48 | public slices: FormattingSettingsSlice[] = [ 49 | this.format, this.noValueLabel, this.displayUnits, this.precision, 50 | this.treatEmptyValuesAsZero, this.showLatterAvailableValue 51 | ]; 52 | 53 | constructor(defaultValuesContainerItem?: ValuesContainerItem){ 54 | super(defaultValuesContainerItem); 55 | 56 | if (defaultValuesContainerItem){ 57 | this.treatEmptyValuesAsZero.value = defaultValuesContainerItem.treatEmptyValuesAsZero.value; 58 | this.showLatterAvailableValue.value = defaultValuesContainerItem.showLatterAvailableValue.value; 59 | } 60 | } 61 | } 62 | 63 | export class ValuesDescriptor extends BaseContainerDescriptor { 64 | public name: string = "values"; 65 | public displayNameKey: string = "Visual_Values"; 66 | 67 | public getNewContainerItem(defaultContainerItem: ValuesContainerItem): ValuesContainerItem { 68 | return new ValuesContainerItem(defaultContainerItem); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/settings/descriptors/varianceDescriptor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 27 | import FormattingSettingsSlice = formattingSettings.Slice; 28 | import ToggleSwitch = formattingSettings.ToggleSwitch; 29 | 30 | import { NumericDescriptor } from "./numericDescriptor"; 31 | import { BaseContainerDescriptor } from "./container/baseContainerDescriptor"; 32 | 33 | export class VarianceContainerItem extends NumericDescriptor { 34 | public displayNameKey: string = "Visual_All"; 35 | 36 | public shouldCalculateDifference: ToggleSwitch = new ToggleSwitch({ 37 | name: "shouldCalculateDifference", 38 | displayNameKey: "Visual_CalculateDifference", 39 | descriptionKey: "Visual_CalculateDifferenceDescription", 40 | value: false 41 | }); 42 | 43 | public slices: FormattingSettingsSlice[] = [ 44 | this.format, this.noValueLabel, this.displayUnits, 45 | this.precision, this.shouldCalculateDifference 46 | ]; 47 | 48 | constructor(defaultVarianceContainerItem?: VarianceContainerItem){ 49 | super(defaultVarianceContainerItem); 50 | this.noValueLabel.displayNameKey = "Visual_NoVarianceLabel"; 51 | 52 | if (defaultVarianceContainerItem){ 53 | this.shouldCalculateDifference.value = defaultVarianceContainerItem.shouldCalculateDifference.value; 54 | } 55 | } 56 | } 57 | 58 | export class VarianceDescriptor extends BaseContainerDescriptor { 59 | public name: string = "variance"; 60 | public displayNameKey: string = "Visual_Variance"; 61 | 62 | constructor(){ 63 | super(); 64 | this.defaultContainerItem.format.value = "+0.00%;-0.00%;0.00%"; 65 | this.defaultContainerItem.precision.value = 2; // It's different because we need to keep the existing behavior 66 | } 67 | 68 | public getNewContainerItem(defaultContainerItem: VarianceContainerItem): VarianceContainerItem { 69 | return new VarianceContainerItem(defaultContainerItem); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/settings/seriesSettings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import { SparklineAxisContainerItem } from "./descriptors/sparkline/sparklineAxisDescriptor"; 27 | import { SparklineChartContainerItem } from "./descriptors/sparkline/sparklineChartDescriptor"; 28 | import { SparklineContainerItem } from "./descriptors/sparkline/sparklineDescriptor"; 29 | import { TooltipContainerItem } from "./descriptors/tooltipDescriptor"; 30 | import { ValuesContainerItem } from "./descriptors/valuesDescriptor"; 31 | import { VarianceContainerItem } from "./descriptors/varianceDescriptor"; 32 | import { StaleDataDescriptor } from "./descriptors/staleDataDescriptor"; 33 | import { AxisBaseContainerItem } from "./descriptors/axisBaseDescriptor"; 34 | import { SparklineValueContainerItem } from "./descriptors/sparklineValueDescriptor"; 35 | import { SparklineNameContainerItem } from "./descriptors/sparklineNameDescriptor"; 36 | 37 | export class SeriesSettings { 38 | public values: ValuesContainerItem = new ValuesContainerItem(); 39 | public variance: VarianceContainerItem = new VarianceContainerItem(); 40 | public yAxis: AxisBaseContainerItem = new AxisBaseContainerItem(); 41 | public tooltip: TooltipContainerItem = new TooltipContainerItem(); 42 | public sparkline: SparklineContainerItem = new SparklineContainerItem(); 43 | public sparklineLabel: SparklineNameContainerItem = new SparklineNameContainerItem(); 44 | public sparklineChart: SparklineChartContainerItem = new SparklineChartContainerItem(); 45 | public sparklineYAxis: SparklineAxisContainerItem = new SparklineAxisContainerItem(); 46 | public sparklineValue: SparklineValueContainerItem = new SparklineValueContainerItem(); 47 | public staleData: StaleDataDescriptor = new StaleDataDescriptor(); 48 | } 49 | -------------------------------------------------------------------------------- /src/settings/settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | import powerbi from "powerbi-visuals-api"; 27 | import DataViewMetadataColumn = powerbi.DataViewMetadataColumn; 28 | import ISelectionId = powerbi.visuals.ISelectionId; 29 | import ILocalizationManager = powerbi.extensibility.ILocalizationManager; 30 | import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 31 | 32 | import { formattingSettings } from "powerbi-visuals-utils-formattingmodel"; 33 | import FormattingSettingsModel = formattingSettings.Model; 34 | import FormattingSettingsCard = formattingSettings.Cards; 35 | 36 | import { AxisDescriptor } from "./descriptors/axisDescriptor"; 37 | import { PrintDescriptor } from "./descriptors/printDescriptor"; 38 | import { ChartDescriptor } from "./descriptors/chartDescriptor"; 39 | import { DateDescriptor } from "./descriptors/dateDescriptor"; 40 | import { GridDescriptor } from "./descriptors/gridDescriptor"; 41 | import { KpiDescriptor } from "./descriptors/kpi/kpiDescriptor"; 42 | import { KpiOnHoverDescriptor } from "./descriptors/kpi/kpiOnHoverDescriptor"; 43 | import { SparklineNameDescriptor } from "./descriptors/sparklineNameDescriptor"; 44 | import { SparklineValueDescriptor } from "./descriptors/sparklineValueDescriptor"; 45 | import { SparklineAxisDescriptor } from "./descriptors/sparkline/sparklineAxisDescriptor"; 46 | import { SparklineChartDescriptor } from "./descriptors/sparkline/sparklineChartDescriptor"; 47 | import { SparklineDescriptor } from "./descriptors/sparkline/sparklineDescriptor"; 48 | import { StaleDataDescriptor } from "./descriptors/staleDataDescriptor"; 49 | import { SubtitleContainerItem } from "./descriptors/subtitleDescriptor"; 50 | import { TooltipDescriptor } from "./descriptors/tooltipDescriptor"; 51 | import { ValuesDescriptor } from "./descriptors/valuesDescriptor"; 52 | import { VarianceDescriptor } from "./descriptors/varianceDescriptor"; 53 | import { IDescriptor } from "./descriptors/descriptor"; 54 | import { BaseContainerDescriptor } from "./descriptors/container/baseContainerDescriptor"; 55 | import { SeriesSettings } from "./seriesSettings"; 56 | 57 | export class Settings extends FormattingSettingsModel { 58 | public date: DateDescriptor = new DateDescriptor(); 59 | public values: ValuesDescriptor = new ValuesDescriptor(); 60 | public variance: VarianceDescriptor = new VarianceDescriptor(); 61 | public yAxis: AxisDescriptor = new AxisDescriptor(); 62 | public chart: ChartDescriptor = new ChartDescriptor(); 63 | public tooltip: TooltipDescriptor = new TooltipDescriptor(); 64 | public kpi: KpiDescriptor = new KpiDescriptor(); 65 | public kpiOnHover: KpiOnHoverDescriptor = new KpiOnHoverDescriptor(); 66 | public grid: GridDescriptor = new GridDescriptor(); 67 | public sparkline: SparklineDescriptor = new SparklineDescriptor(); 68 | public sparklineLabel: SparklineNameDescriptor = new SparklineNameDescriptor(); 69 | public sparklineChart: SparklineChartDescriptor = new SparklineChartDescriptor(); 70 | public sparklineYAxis: SparklineAxisDescriptor = new SparklineAxisDescriptor(); 71 | public sparklineValue: SparklineValueDescriptor = new SparklineValueDescriptor(); 72 | public subtitle: SubtitleContainerItem = new SubtitleContainerItem(); 73 | public staleData: StaleDataDescriptor = new StaleDataDescriptor(); 74 | public printMode: PrintDescriptor = new PrintDescriptor(); 75 | 76 | public cards: FormattingSettingsCard[] = [ 77 | this.date, this.values, this.variance, 78 | this.yAxis, this.chart, this.tooltip, 79 | this.kpi, this.kpiOnHover, this.grid, this.sparkline, 80 | this.sparklineLabel, this.sparklineChart, 81 | this.sparklineValue, this.sparklineYAxis, 82 | this.subtitle, this.staleData, this.printMode 83 | ] 84 | 85 | public parse(colorPalette: ISandboxExtendedColorPalette, localizationManager: ILocalizationManager): void { 86 | if (this.staleData.staleDataText.value === "") { 87 | this.staleData.staleDataText.value = "Data is ${1} days late." + (this.subtitle.staleDataText || ""); 88 | } 89 | 90 | if (!this.subtitle.show.value) { 91 | this.staleData.isShown.value = false; 92 | } 93 | 94 | this.cards.forEach((card) => { 95 | const settings: IDescriptor = card as IDescriptor; 96 | 97 | if (settings.parse) { 98 | settings.parse(); 99 | } 100 | 101 | if (settings.processHighContrastMode) { 102 | settings.processHighContrastMode(colorPalette); 103 | } 104 | 105 | if (settings.setLocalizedDisplayName) { 106 | settings.setLocalizedDisplayName(localizationManager); 107 | } 108 | 109 | }); 110 | } 111 | 112 | public populateContainers(dataPoint: DataViewMetadataColumn, selectionId: ISelectionId): void { 113 | this.cards.forEach((card) => { 114 | if (card instanceof BaseContainerDescriptor){ 115 | const newContainerItem = card.createContainerItem(dataPoint, selectionId); 116 | card.populateContainer(newContainerItem); 117 | } 118 | }) 119 | } 120 | 121 | public getSettingsForSeries(seriesName: string): SeriesSettings { 122 | const currentSettings: SeriesSettings = new SeriesSettings(); 123 | this.cards.forEach((card) => { 124 | const settingName: string = card.name; 125 | if (card instanceof BaseContainerDescriptor){ 126 | currentSettings[settingName] = card.getCurrentContainer(seriesName); 127 | } 128 | }); 129 | 130 | currentSettings.staleData = this.staleData; 131 | return currentSettings; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/utils/isValueValid.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | export function isValueValid(value: number): boolean { 28 | return isFinite(value) && value != null; 29 | } 30 | -------------------------------------------------------------------------------- /src/visualComponent/baseContainerComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { BaseComponent } from "./baseComponent"; 28 | import { IVisualComponent } from "./visualComponent"; 29 | 30 | export abstract class BaseContainerComponent 31 | extends BaseComponent { 32 | 33 | protected components: IVisualComponent[] = []; 34 | 35 | public getComponents(): IVisualComponent[] { 36 | return this.components; 37 | } 38 | 39 | public clear(components: IVisualComponent[] = this.components): void { 40 | this.forEach( 41 | components, 42 | (component: IVisualComponent) => { 43 | component.clear(); 44 | }, 45 | ); 46 | 47 | super.clear(); 48 | } 49 | 50 | public destroy(components: IVisualComponent[] = this.components): void { 51 | this.forEach( 52 | components.splice(0, components.length), 53 | (component: IVisualComponent) => { 54 | component.destroy(); 55 | }, 56 | ); 57 | 58 | super.destroy(); 59 | } 60 | 61 | protected forEach( 62 | components: IVisualComponent[], 63 | iterator: ( 64 | component: IVisualComponent, 65 | index: number, 66 | ) => void, 67 | ): void { 68 | components.forEach((component: IVisualComponent, index: number) => { 69 | if (component) { 70 | iterator(component, index); 71 | } 72 | }); 73 | } 74 | 75 | protected initComponents( 76 | components: IVisualComponent[], 77 | expectedAmountOfComponents: number, 78 | initComponent: (index: number) => IVisualComponent, 79 | ): void { 80 | if (!components) { 81 | return; 82 | } 83 | 84 | components 85 | .splice(expectedAmountOfComponents) 86 | .forEach((component: IVisualComponent) => { 87 | component.clear(); 88 | component.destroy(); 89 | }); 90 | 91 | if (components.length < expectedAmountOfComponents) { 92 | for (let index: number = components.length; index < expectedAmountOfComponents; index++) { 93 | components.push(initComponent(index)); 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/visualComponent/mainChart/axisComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { axisRight } from "d3-axis"; 28 | import { ScaleLinear } from "d3-scale"; 29 | import { select as d3Select } from "d3-selection"; 30 | 31 | import powerbi from "powerbi-visuals-api"; 32 | import IViewport = powerbi.IViewport; 33 | 34 | import { valueFormatter } from "powerbi-visuals-utils-formattingutils"; 35 | 36 | import { 37 | IDataRepresentationAxis, 38 | IDataRepresentationSeries, 39 | } from "../../converter/data/dataRepresentation"; 40 | 41 | import { DataRepresentationScale } from "../../converter/data/dataRepresentationScale"; 42 | 43 | import { AxisBaseContainerItem } from "../../settings/descriptors/axisBaseDescriptor"; 44 | 45 | import { BaseComponent } from "../baseComponent"; 46 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 47 | import { detectPrecision } from "../../converter/data/dataFormatter"; 48 | 49 | export interface IAxisComponentRenderOptions { 50 | viewport: IViewport; 51 | settings: AxisBaseContainerItem; 52 | series: IDataRepresentationSeries; 53 | y: IDataRepresentationAxis; 54 | } 55 | 56 | export class AxisComponent extends BaseComponent { 57 | constructor(options: IVisualComponentConstructorOptions) { 58 | super(); 59 | 60 | this.constructorOptions = options; 61 | 62 | this.initElement( 63 | options.element, 64 | "axisComponent", 65 | "g", 66 | ); 67 | } 68 | 69 | public render(options: IAxisComponentRenderOptions): void { 70 | const { settings } = options; 71 | 72 | if (settings.isShown.value) { 73 | this.show(); 74 | this.renderComponent(options); 75 | } else { 76 | this.hide(); 77 | } 78 | } 79 | 80 | private renderComponent(options: IAxisComponentRenderOptions) { 81 | const { 82 | y, 83 | settings, 84 | viewport, 85 | } = options; 86 | 87 | const yScale: DataRepresentationScale = y.scale 88 | .copy() 89 | .range([viewport.height, 0]); 90 | 91 | const domain: number[] = (yScale.getDomain()); 92 | 93 | const axisValueFormatter: valueFormatter.IValueFormatter = valueFormatter.create({ 94 | displayUnitSystemType: 2, 95 | format: settings.format.value, 96 | precision: detectPrecision(domain[1] || domain[0], settings), 97 | value: settings.displayUnits.value || domain[1] || domain[0], 98 | }); 99 | 100 | const yAxis: (selection) => void = axisRight(>(yScale.getScale())) 101 | .tickValues(domain) 102 | .tickFormat((value: number) => { 103 | return axisValueFormatter.format(value); 104 | }); 105 | 106 | this.element.call(yAxis); 107 | 108 | this.element 109 | .selectAll(".tick text") 110 | .each(function enumerateEachTextTick(_, elementIndex: number) { 111 | d3Select(this) 112 | .attr("x", settings.axisLabelX) 113 | .attr("y", elementIndex 114 | ? settings.axisLabelY 115 | : -settings.axisLabelY) 116 | .style("fill", settings.color.value.value) 117 | .style("font-weight", settings.isBold.value ? "bold" : "normal") 118 | .style("font-style", settings.isItalic.value ? "italic" : "normal") 119 | .style("text-decoration", settings.isUnderlined.value ? "underline" : "none") 120 | }); 121 | 122 | const isHighContrast: boolean = this.constructorOptions.colorPalette.isHighContrast; 123 | this.element 124 | .select("path.domain") 125 | .style("stroke", isHighContrast ? settings.color.value.value : settings.defaultDomainColor); 126 | 127 | this.updateFormatting(this.element, settings); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/visualComponent/mainChart/chartLabelBaseComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | 29 | import { Selection as d3Selection, BaseType} from "d3-selection"; 30 | type Selection = d3Selection; 31 | 32 | import { CssConstants } from "powerbi-visuals-utils-svgutils"; 33 | import { pixelConverter } from "powerbi-visuals-utils-typeutils"; 34 | 35 | import { BaseComponent } from "../baseComponent"; 36 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 37 | 38 | import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem; 39 | 40 | export interface IRenderGroup { 41 | data: string; 42 | isShown: boolean; 43 | color?: string; 44 | selector?: CssConstants.ClassAndSelector; 45 | fontSizeInPt?: number; 46 | tooltipDataItems?: VisualTooltipDataItem[]; 47 | } 48 | 49 | export abstract class ChartLabelBaseComponent extends BaseComponent { 50 | protected className: string = "chartLabelBaseComponent"; 51 | 52 | protected headerSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix(`${this.className}_header`); 53 | protected bodySelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix(`${this.className}_body`); 54 | protected footerSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix(`${this.className}_footer`); 55 | 56 | protected varianceNotAvailableSelector: CssConstants.ClassAndSelector 57 | = this.getSelectorWithPrefix(`${this.className}_body_variance_na`); 58 | 59 | private itemSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix(`${this.className}_items`); 60 | 61 | constructor(options: IVisualComponentConstructorOptions) { 62 | super(); 63 | 64 | this.initElement( 65 | options.element, 66 | this.className, 67 | ); 68 | 69 | this.constructorOptions = { 70 | ...options, 71 | element: this.element, 72 | }; 73 | } 74 | 75 | protected renderGroup( 76 | selector: CssConstants.ClassAndSelector, 77 | renderGroupData: IRenderGroup[], 78 | ): void { 79 | const selection: Selection = this.element 80 | .selectAll(selector.selectorName) 81 | .data([renderGroupData]) 82 | .join("div") 83 | .classed(selector.className, true); 84 | 85 | const itemSelection: Selection = selection 86 | .selectAll(this.itemSelector.selectorName) 87 | .data((data: IRenderGroup[]) => { 88 | return data.filter((renderGroup: IRenderGroup) => { 89 | return renderGroup?.isShown; 90 | }); 91 | }) 92 | .join("div") 93 | .attr("class", (data: IRenderGroup) => { 94 | const baseSelector: string = this.itemSelector.className; 95 | 96 | return data.selector 97 | ? `${baseSelector} ${data.selector.className}` 98 | : baseSelector; 99 | }) 100 | .text((data: IRenderGroup) => data.data) 101 | .style("color", (data: IRenderGroup) => data.color) 102 | .style("font-size", (data: IRenderGroup) => { 103 | if (!data.fontSizeInPt || isNaN(data.fontSizeInPt)) { 104 | return null; 105 | } 106 | 107 | const fontSizeInPx: number = pixelConverter.fromPointToPixel(data.fontSizeInPt); 108 | 109 | return pixelConverter.toString(fontSizeInPx); 110 | }); 111 | 112 | this.constructorOptions.tooltipServiceWrapper.addTooltip( 113 | itemSelection, 114 | (data) => data.tooltipDataItems ? data.tooltipDataItems : null 115 | ); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/visualComponent/mainChart/chartLabelComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { FormatDescriptor } from "../../settings/descriptors/formatDescriptor"; 31 | import { KpiDescriptor } from "../../settings/descriptors/kpi/kpiDescriptor"; 32 | 33 | import { IDataRepresentationSeries } from "../../converter/data/dataRepresentation"; 34 | 35 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 36 | 37 | import { ChartLabelBaseComponent } from "./chartLabelBaseComponent"; 38 | 39 | import { getFormattedValueWithFallback } from "../../converter/data/dataFormatter"; 40 | import { EventName } from "../../event/eventName"; 41 | import { isValueValid } from "../../utils/isValueValid"; 42 | 43 | export interface IChartLabelComponentRenderOptions { 44 | dateSettings: FormatDescriptor; 45 | kpiSettings: KpiDescriptor; 46 | series: IDataRepresentationSeries; 47 | viewport: IViewport; 48 | } 49 | 50 | export class ChartLabelComponent extends ChartLabelBaseComponent { 51 | private componentClassName: string = "chartLabelComponent"; 52 | 53 | constructor(options: IVisualComponentConstructorOptions) { 54 | super(options); 55 | 56 | this.element.classed( 57 | this.getClassNameWithPrefix(this.componentClassName), 58 | true, 59 | ); 60 | 61 | this.constructorOptions.eventDispatcher.on( 62 | `${EventName.onMouseMove}.${this.componentClassName}`, 63 | this.hide.bind(this), 64 | ); 65 | 66 | this.constructorOptions.eventDispatcher.on( 67 | `${EventName.onMouseOut}.${this.componentClassName}`, 68 | this.show.bind(this), 69 | ); 70 | } 71 | 72 | public render(options: IChartLabelComponentRenderOptions): void { 73 | const { 74 | series, 75 | kpiSettings, 76 | } = options; 77 | 78 | this.updateFormatting(this.element, options.kpiSettings); 79 | 80 | if (!series || !series.points) { 81 | this.hide(); 82 | 83 | return; 84 | } else { 85 | this.show(); 86 | } 87 | 88 | const value: number = series.current ? series.current.y : NaN; 89 | 90 | this.renderGroup( 91 | this.headerSelector, 92 | [ 93 | { 94 | color: kpiSettings.seriesNameColor.value.value, 95 | data: series.name, 96 | fontSizeInPt: kpiSettings.autoAdjustFontSize.value 97 | ? null 98 | : kpiSettings.seriesNameFontSize.value, 99 | isShown: kpiSettings.isSeriesNameShown.value, 100 | }, 101 | ], 102 | ); 103 | 104 | const isVarianceValid: boolean = isValueValid(series.variance); 105 | 106 | this.renderGroup( 107 | this.bodySelector, 108 | [ 109 | { 110 | color: kpiSettings.valueColor.value.value, 111 | data: getFormattedValueWithFallback(value, series.settings.values), 112 | fontSizeInPt: kpiSettings.autoAdjustFontSize.value 113 | ? null 114 | : kpiSettings.valueFontSize.value, 115 | isShown: kpiSettings.isValueShown.value, 116 | }, 117 | { 118 | color: isVarianceValid 119 | ? kpiSettings.varianceColor.value.value 120 | : kpiSettings.varianceNotAvailableColor.value.value, 121 | data: `(${series.formattedVariance})`, 122 | fontSizeInPt: kpiSettings.autoAdjustFontSize.value 123 | ? null 124 | : isVarianceValid 125 | ? kpiSettings.varianceFontSize.value 126 | : kpiSettings.varianceNotAvailableFontSize.value, 127 | isShown: kpiSettings.isVarianceShown.value, 128 | selector: isVarianceValid || !kpiSettings.autoAdjustFontSize.value 129 | ? undefined 130 | : this.varianceNotAvailableSelector, 131 | }, 132 | ], 133 | ); 134 | 135 | this.renderGroup( 136 | this.footerSelector, 137 | [ 138 | { 139 | color: kpiSettings.dateColor.value.value, 140 | data: `${series.dateDifference} days`, 141 | fontSizeInPt: kpiSettings.autoAdjustFontSize.value 142 | ? null 143 | : kpiSettings.dateFontSize.value, 144 | isShown: kpiSettings.isDateShown.value, 145 | }, 146 | ], 147 | ); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/visualComponent/mainChart/mainChartComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { Dispatch } from "d3-dispatch"; 28 | import { pointer as d3Mouse } from "d3-selection"; 29 | 30 | import { BaseContainerComponent } from "../baseContainerComponent"; 31 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 32 | import { IVisualComponentRenderOptions } from "../visualComponentRenderOptions"; 33 | 34 | import { IVisualComponent } from "../visualComponent"; 35 | 36 | import { EventName } from "../../event/eventName"; 37 | 38 | import { 39 | ChartComponent, 40 | IChartComponentRenderOptions, 41 | } from "./chartComponent"; 42 | 43 | import { 44 | ChartLabelComponent, 45 | IChartLabelComponentRenderOptions, 46 | } from "./chartLabelComponent"; 47 | 48 | export type MainChartComponentsRenderOptions = IChartComponentRenderOptions | IChartLabelComponentRenderOptions; 49 | 50 | export class MainChartComponent extends BaseContainerComponent< 51 | IVisualComponentConstructorOptions, 52 | IVisualComponentRenderOptions, 53 | MainChartComponentsRenderOptions 54 | > { 55 | private chart: IVisualComponent; 56 | private chartLabel: IVisualComponent; 57 | 58 | constructor(options: IVisualComponentConstructorOptions) { 59 | super(); 60 | 61 | this.initElement( 62 | options.element, 63 | "mainChartComponent", 64 | ); 65 | 66 | this.constructorOptions = { 67 | ...options, 68 | element: this.element, 69 | }; 70 | 71 | this.chart = new ChartComponent(this.constructorOptions); 72 | this.chartLabel = new ChartLabelComponent(this.constructorOptions); 73 | 74 | this.components = [ 75 | this.chart, 76 | this.chartLabel, 77 | ]; 78 | 79 | this.initMouseEvents(); 80 | } 81 | 82 | public render(options: IVisualComponentRenderOptions): void { 83 | const { viewport } = options; 84 | 85 | this.updateSize(viewport.width, viewport.height); 86 | 87 | const data: IChartComponentRenderOptions = { 88 | series: options.data.series[0], 89 | settings: options.settings, 90 | viewport, 91 | viewportSize: options.data.viewportSize, 92 | }; 93 | 94 | this.chart.render(data); 95 | 96 | this.chartLabel.render({ 97 | dateSettings: options.settings.date, 98 | kpiSettings: options.settings.kpi, 99 | series: data.series, 100 | viewport, 101 | }); 102 | } 103 | 104 | private initMouseEvents(): void { 105 | const eventDispatcher: Dispatch = this.constructorOptions.eventDispatcher; 106 | 107 | function onMouseMove(event) { 108 | event.preventDefault(); 109 | event.stopPropagation(); 110 | event.stopImmediatePropagation(); 111 | eventDispatcher.call(EventName.onMouseMove, undefined, d3Mouse(event, this)); 112 | } 113 | 114 | this.element.on("mousemove", onMouseMove); 115 | this.element.on("touchmove", onMouseMove); 116 | this.element.on("touchstart", onMouseMove); 117 | 118 | function onMouseOut(event) { 119 | event.preventDefault(); 120 | event.stopPropagation(); 121 | event.stopImmediatePropagation(); 122 | 123 | eventDispatcher.call(EventName.onMouseOut); 124 | eventDispatcher.call(EventName.onChartChangeStop); 125 | eventDispatcher.call(EventName.onChartViewReset); 126 | } 127 | 128 | this.element.on("mouseout", onMouseOut); 129 | this.element.on("mouseleave", onMouseOut); 130 | this.element.on("touchleave", onMouseOut); 131 | 132 | this.element.on("mouseenter", () => { 133 | this.constructorOptions.eventDispatcher.call(EventName.onChartChangeStop); 134 | }); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/visualComponent/sparkline/dotsComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { CssConstants } from "powerbi-visuals-utils-svgutils"; 31 | 32 | import { 33 | IDataRepresentationAxis, 34 | IDataRepresentationPoint, 35 | } from "../../converter/data/dataRepresentation"; 36 | 37 | import { SparklineChartContainerItem } from "../../settings/descriptors/sparkline/sparklineChartDescriptor"; 38 | 39 | import { BaseComponent } from "../baseComponent"; 40 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 41 | 42 | import { DataRepresentationScale } from "../../converter/data/dataRepresentationScale"; 43 | 44 | import { isValueValid } from "../../utils/isValueValid"; 45 | 46 | export interface IDotsComponentRenderOptions { 47 | viewport: IViewport; 48 | x: IDataRepresentationAxis; 49 | y: IDataRepresentationAxis; 50 | points: IDataRepresentationPoint[]; 51 | settings: SparklineChartContainerItem; 52 | } 53 | 54 | export class DotsComponent extends BaseComponent { 55 | private dotSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix("dot"); 56 | 57 | constructor(options: IVisualComponentConstructorOptions) { 58 | super(); 59 | 60 | this.initElement( 61 | options.element, 62 | "dotsComponent", 63 | "g", 64 | ); 65 | } 66 | 67 | public render(options: IDotsComponentRenderOptions): void { 68 | const { 69 | x, 70 | y, 71 | points, 72 | viewport, 73 | settings, 74 | } = options; 75 | 76 | const xScale: DataRepresentationScale = x.scale 77 | .copy() 78 | .range([0, viewport.width]); 79 | 80 | const yScale: DataRepresentationScale = y.scale 81 | .copy() 82 | .range([viewport.height, 0]); 83 | 84 | // dots selection 85 | this.element 86 | .selectAll(this.dotSelector.selectorName) 87 | .data(points.filter((point: IDataRepresentationPoint) => { 88 | return point && isValueValid(point.y); 89 | })) 90 | .join("circle") 91 | .classed(this.dotSelector.className, true) 92 | .attr("cx", (point: IDataRepresentationPoint) => xScale.scale(point.x)) 93 | .attr("cy", (point: IDataRepresentationPoint) => yScale.scale(point.y)) 94 | .attr("r", settings.getRadius()) 95 | .style("fill", settings.color.value.value); 96 | } 97 | 98 | public clear(): void { 99 | this.element 100 | .selectAll("*") 101 | .remove(); 102 | } 103 | 104 | public destroy(): void { 105 | this.element = null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/visualComponent/sparkline/multiLineComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { BaseContainerComponent } from "../baseContainerComponent"; 28 | import { IVisualComponent } from "../visualComponent"; 29 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 30 | 31 | import { 32 | DataRepresentationPointGradientType, 33 | IDataRepresentationSeries, 34 | } from "../../converter/data/dataRepresentation"; 35 | 36 | import { 37 | ILineComponentRenderOptions, 38 | LineComponent, 39 | } from "./lineComponent"; 40 | 41 | import { ISparklineComponentRenderOptions } from "./sparklineComponent"; 42 | 43 | export class MultiLineComponent 44 | extends BaseContainerComponent { 45 | constructor(options: IVisualComponentConstructorOptions) { 46 | super(); 47 | 48 | this.initElement( 49 | options.element, 50 | "multiLineComponent", 51 | "g", 52 | ); 53 | 54 | this.constructorOptions = { 55 | ...options, 56 | element: this.element, 57 | }; 58 | } 59 | 60 | public render(options: ISparklineComponentRenderOptions): void { 61 | this.renderOptions = options; 62 | 63 | const { 64 | series, 65 | viewport, 66 | } = this.renderOptions; 67 | 68 | this.initComponents( 69 | this.components, 70 | series.length, 71 | () => { 72 | return new LineComponent(this.constructorOptions); 73 | }, 74 | ); 75 | 76 | this.forEach( 77 | this.components, 78 | (component: IVisualComponent, componentIndex: number) => { 79 | const currentSeries: IDataRepresentationSeries = series[componentIndex]; 80 | 81 | component.render({ 82 | alternativeColor: currentSeries.settings.sparklineChart.alternativeColor.value.value, 83 | color: currentSeries.settings.sparklineChart.color.value.value, 84 | current: currentSeries.current, 85 | isLine: currentSeries.isLine, 86 | points: currentSeries.smoothedPoints, 87 | thickness: currentSeries.settings.sparklineChart.thickness, 88 | type: DataRepresentationPointGradientType.line, 89 | viewport, 90 | x: currentSeries.x, 91 | y: currentSeries.ySparkline, 92 | }); 93 | }, 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/visualComponent/sparkline/plotComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { BaseContainerComponent } from "../baseContainerComponent"; 31 | import { ISparklineComponentRenderOptions } from "./sparklineComponent"; 32 | 33 | import { IVisualComponent } from "../visualComponent"; 34 | 35 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 36 | import { SvgComponent } from "./svgComponent"; 37 | 38 | export class PlotComponent 39 | extends BaseContainerComponent { 40 | constructor(options: IVisualComponentConstructorOptions) { 41 | super(); 42 | 43 | this.initElement( 44 | options.element, 45 | "plot", 46 | ); 47 | 48 | this.constructorOptions = { 49 | ...options, 50 | element: this.element, 51 | }; 52 | 53 | this.components = [ 54 | new SvgComponent(this.constructorOptions), 55 | ]; 56 | } 57 | 58 | public render(options: ISparklineComponentRenderOptions): void { 59 | const { viewport } = options; 60 | 61 | this.updateSize(viewport.width, viewport.height); 62 | 63 | const componentViewport: IViewport = { ...viewport }; 64 | 65 | this.forEach( 66 | this.components, 67 | (component: IVisualComponent) => { 68 | component.render({ 69 | ...options, 70 | viewport: { ...componentViewport }, 71 | }); 72 | 73 | const margins: IViewport = component.getViewport(); 74 | 75 | componentViewport.height -= margins.height; 76 | }, 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/visualComponent/sparkline/sparklineGroupComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { IMargin } from "powerbi-visuals-utils-svgutils"; 28 | 29 | import { pixelConverter } from "powerbi-visuals-utils-typeutils"; 30 | 31 | import { BaseContainerComponent } from "../baseContainerComponent"; 32 | import { IVisualComponent } from "../visualComponent"; 33 | import { IVisualComponentConstructorOptions } from "../visualComponentConstructorOptions"; 34 | import { IVisualComponentRenderOptions } from "../visualComponentRenderOptions"; 35 | 36 | import { 37 | ISparklineComponentRenderOptions, 38 | SparklineComponent, 39 | } from "./sparklineComponent"; 40 | 41 | import { IDataRepresentationSeries } from "../../converter/data/dataRepresentation"; 42 | 43 | export class SparklineGroupComponent 44 | extends BaseContainerComponent { 45 | private className: string = "sparklineGroupComponent"; 46 | 47 | private minAmountOfSeries: number = 1; 48 | 49 | private padding: IMargin = { 50 | bottom: 0, 51 | left: 8, 52 | right: 0, 53 | top: 5, 54 | }; 55 | 56 | private renderingDelay: number = 10; 57 | private renderingTimers: number[] = []; 58 | 59 | constructor(options: IVisualComponentConstructorOptions) { 60 | super(); 61 | 62 | this.initElement(options.element, this.className); 63 | 64 | this.constructorOptions = { 65 | ...options, 66 | element: this.element, 67 | }; 68 | } 69 | 70 | public render(options: IVisualComponentRenderOptions): void { 71 | this.renderOptions = options; 72 | 73 | const { 74 | data: { series }, 75 | settings: { grid }, 76 | } = this.renderOptions; 77 | 78 | const seriesLength: number = series.length; 79 | 80 | const amountOfComponents: number = isNaN(grid.columns.value) || !grid.columns.value 81 | ? seriesLength 82 | : grid.columns.value; 83 | 84 | this.element.style( 85 | "padding", 86 | `${pixelConverter.toString(this.padding.top)} 0 ${pixelConverter.toString(this.padding.bottom)} 0`, 87 | ); 88 | 89 | this.initComponents( 90 | this.components, 91 | amountOfComponents, 92 | (componentIndex: number) => { 93 | return new SparklineComponent({ 94 | ...this.constructorOptions, 95 | id: componentIndex, 96 | }); 97 | }, 98 | ); 99 | 100 | const paddingWidth: number = amountOfComponents > this.minAmountOfSeries 101 | ? this.padding.left * (amountOfComponents - 1) 102 | : 0; 103 | 104 | const height: number = Math.max(0, options.viewport.height - this.padding.top - this.padding.bottom); 105 | const width: number = Math.max(0, (options.viewport.width - paddingWidth) / amountOfComponents); 106 | 107 | this.forEach( 108 | this.components, 109 | (component: IVisualComponent, componentIndex: number) => { 110 | const data: IDataRepresentationSeries = series[componentIndex]; 111 | 112 | const position: number = data?.settings?.sparkline.position.value 113 | ? data.settings.sparkline.position.value 114 | : data 115 | ? data.index 116 | : componentIndex; 117 | 118 | this.renderComponent( 119 | component, 120 | { 121 | current: data, 122 | dataRepresentation: options.data, 123 | position, 124 | series: [data], 125 | viewport: { height, width }, 126 | }, 127 | componentIndex, 128 | ); 129 | }, 130 | ); 131 | } 132 | 133 | private renderComponent( 134 | component: IVisualComponent, 135 | options: RenderOptions, 136 | index: number, 137 | ) { 138 | if (this.renderingTimers[index]) { 139 | clearTimeout(this.renderingTimers[index]); 140 | } 141 | 142 | this.renderingTimers[index] = (setTimeout( 143 | component.render.bind(component, options), 144 | this.renderingDelay, 145 | )); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/visualComponent/subtitleComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { CssConstants } from "powerbi-visuals-utils-svgutils"; 31 | import { pixelConverter } from "powerbi-visuals-utils-typeutils"; 32 | 33 | import { BaseComponent } from "./baseComponent"; 34 | import { IVisualComponentConstructorOptions } from "./visualComponentConstructorOptions"; 35 | import { SubtitleBaseContainerItem } from "../settings/descriptors/subtitleBaseDescriptor"; 36 | 37 | export interface ISubtitleComponentRenderOptions { 38 | subtitleSettings: SubtitleBaseContainerItem; 39 | subtitle?: string; 40 | } 41 | 42 | export class SubtitleComponent extends BaseComponent { 43 | protected subtitleSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix("subtitle"); 44 | 45 | private className: string = "subtitleComponent"; 46 | 47 | constructor(options: IVisualComponentConstructorOptions) { 48 | super(); 49 | 50 | this.initElement( 51 | options.element, 52 | this.className, 53 | ); 54 | 55 | this.constructorOptions = { 56 | ...options, 57 | element: this.element, 58 | }; 59 | } 60 | 61 | public render(options: ISubtitleComponentRenderOptions): void { 62 | const { subtitleSettings: settings, subtitle } = options; 63 | 64 | if (settings.show.value && settings.isShown.value) { 65 | this.show(); 66 | this.renderComponent(settings, subtitle); 67 | } else { 68 | this.hide(); 69 | } 70 | } 71 | 72 | public getViewport(): IViewport { 73 | const height: number = this.element && this.isShown 74 | ? ((this.element.node())).clientHeight 75 | : 0; 76 | 77 | return { 78 | height, 79 | width: this.width, 80 | }; 81 | } 82 | 83 | private renderComponent(settings: SubtitleBaseContainerItem, subtitle?: string): void { 84 | const subtitleText: string = `${settings.titleText.value}${(subtitle ?? "")}`; 85 | 86 | // subtitle selection 87 | this.element 88 | .selectAll(this.subtitleSelector.selectorName) 89 | .data(settings.show.value && settings.isShown.value ? [[]] : []) 90 | .join("div") 91 | .classed(this.subtitleSelector.className, true) 92 | .text(subtitleText) 93 | .style("text-align", settings.alignment.value); 94 | 95 | this.updateFormatting(this.element, settings); 96 | 97 | this.element 98 | .style("background-color", settings.backgroundColor.value.value) 99 | .style("padding-top", settings.paddingTop ? 100 | pixelConverter.toString(settings.paddingTop) 101 | : null, 102 | ) 103 | .style("padding-bottom", settings.paddingBottom 104 | ? pixelConverter.toString(settings.paddingBottom) 105 | : null, 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/visualComponent/verticalReferenceLineComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { CssConstants } from "powerbi-visuals-utils-svgutils"; 31 | 32 | import { BaseComponent } from "./baseComponent"; 33 | 34 | import { 35 | IDataRepresentationPoint, 36 | IDataRepresentationSeries, 37 | } from "../converter/data/dataRepresentation"; 38 | 39 | import { FormatDescriptor } from "../settings/descriptors/formatDescriptor"; 40 | import { KpiDescriptor } from "../settings/descriptors/kpi/kpiDescriptor"; 41 | 42 | import { IVisualComponentConstructorOptions } from "./visualComponentConstructorOptions"; 43 | 44 | import { DataRepresentationScale } from "../converter/data/dataRepresentationScale"; 45 | 46 | export interface IVerticalReferenceLineComponentRenderOptions { 47 | offset: number; 48 | viewport: IViewport; 49 | series: IDataRepresentationSeries; 50 | dataPoint: IDataRepresentationPoint; 51 | kpiSettings: KpiDescriptor; 52 | dateSettings: FormatDescriptor; 53 | } 54 | 55 | export class VerticalReferenceLineComponent 56 | extends BaseComponent { 57 | private lineSelector: CssConstants.ClassAndSelector = this.getSelectorWithPrefix("verticalLine"); 58 | 59 | constructor(options: IVisualComponentConstructorOptions) { 60 | super(); 61 | 62 | this.initElement( 63 | options.element, 64 | "verticalLineComponent", 65 | "g", 66 | ); 67 | } 68 | 69 | public render(options: IVerticalReferenceLineComponentRenderOptions): void { 70 | const { 71 | offset, 72 | viewport, 73 | series: { x }, 74 | dataPoint, 75 | } = options; 76 | 77 | const xScale: DataRepresentationScale = x.scale 78 | .copy() 79 | .range([offset, viewport.width]); 80 | 81 | const xPosition: number = xScale.scale(dataPoint?.x); 82 | 83 | // line selection 84 | this.element 85 | .selectAll(this.lineSelector.selectorName) 86 | .data(dataPoint ? [dataPoint] : []) 87 | .join("line") 88 | .classed(this.lineSelector.className, true) 89 | .attr("x1", xPosition) 90 | .attr("x2", xPosition) 91 | .attr("y1", 0) 92 | .attr("y2", viewport.height); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/visualComponent/visualComponent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | export interface IVisualComponent { 31 | isShown?: boolean; 32 | 33 | render(options: RenderOptionsType): void; 34 | clear(): void; 35 | destroy(): void; 36 | hide?(): void; 37 | show?(): void; 38 | toggle?(): void; 39 | getViewport?(): IViewport; 40 | getComponents?(): IVisualComponent[] 41 | } 42 | -------------------------------------------------------------------------------- /src/visualComponent/visualComponentBaseConstructorOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { Selection as d3Selection, BaseType} from "d3-selection"; 28 | type Selection = d3Selection; 29 | 30 | export interface IVisualComponentBaseConstructorOptions { 31 | element?: Selection; 32 | } 33 | -------------------------------------------------------------------------------- /src/visualComponent/visualComponentConstructorOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import { Dispatch } from "d3-dispatch"; 28 | import powerbi from "powerbi-visuals-api"; 29 | import IColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette; 30 | 31 | import { ScaleService } from "../services/scaleService"; 32 | import { Settings } from "../settings/settings"; 33 | import { IVisualComponentBaseConstructorOptions } from "./visualComponentBaseConstructorOptions"; 34 | import { ITooltipServiceWrapper } from "powerbi-visuals-utils-tooltiputils"; 35 | 36 | export interface IVisualComponentConstructorOptions extends IVisualComponentBaseConstructorOptions { 37 | eventDispatcher?: Dispatch; // TODO 38 | id?: number | string; 39 | scaleService?: ScaleService; 40 | colorPalette?: IColorPalette; 41 | getSettings?: () => Settings; 42 | tooltipServiceWrapper?: ITooltipServiceWrapper; 43 | } 44 | -------------------------------------------------------------------------------- /src/visualComponent/visualComponentRenderOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | import powerbi from "powerbi-visuals-api"; 28 | import IViewport = powerbi.IViewport; 29 | 30 | import { IDataRepresentation } from "../converter/data/dataRepresentation"; 31 | import { Settings } from "../settings/settings"; 32 | 33 | export interface IVisualComponentRenderOptions { 34 | settings: Settings; 35 | viewport: IViewport; 36 | data: IDataRepresentation; 37 | } 38 | -------------------------------------------------------------------------------- /stringResources/en-US/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "Visual_Alignment": "Alignment", 3 | "Visual_All": "All", 4 | "Visual_AlternativeColor": "Alternative color", 5 | "Visual_ApplySettingsTo": "Apply settings to", 6 | "Visual_Area": "Area", 7 | "Visual_AutoFontSize": "Auto font size", 8 | "Visual_AutoPrecision": "Auto precision", 9 | "Visual_BackgroundColor": "Background color", 10 | "Visual_BackgroundColorAll": "Background color (for all only)", 11 | "Visual_CalculateDifference": "Calculate difference", 12 | "Visual_CalculateDifferenceDescription": "Calculates a difference instead of growth", 13 | "Visual_ChangeStartDate": "Change start date", 14 | "Visual_Color": "Color", 15 | "Visual_ColorAll": "Color (for all only)", 16 | "Visual_Columns": "Columns", 17 | "Visual_CurrentValue": "Current value", 18 | "Visual_CurrentValueColor": "Current value color", 19 | "Visual_CurrentValueFontSize": "Current value font size", 20 | "Visual_CurrentValueIsLeftAlgned": "Current value is left aligned", 21 | "Visual_Date": "Date", 22 | "Visual_DateColor": "Date color", 23 | "Visual_DateDifference": "Date difference", 24 | "Visual_DateFontSize": "Date font size", 25 | "Visual_DeductThresholdDays": "Deduct threshold days", 26 | "Visual_DisplayUnits": "Display units", 27 | "Visual_Font": "Font", 28 | "Visual_FontColor": "Font color", 29 | "Visual_FontFamily": "Font family", 30 | "Visual_Format": "Format", 31 | "Visual_Interpolate": "Interpolate", 32 | "Visual_KPI": "KPI", 33 | "Visual_KPIOnHover": "KPI on hover", 34 | "Visual_Label": "Label", 35 | "Visual_Line": "Line", 36 | "Visual_Long_Description": "The Multi KPI custom visual is for presenting a key performance indicator (KPI) along with a variety of supporting information, including:\n[#LI]Title, Subtitle[/#LI]\n[#LI]Sparklines[/#LI]\n[#LI]Current date and KPI status (value, date, variance)[/#LI]\nSome of the key features include:\n[#LI]KPI trend over time: hover-over the main chart to see a KPI for each date.[/#LI]\n[#LI]Rich Formatting Options: set alternate titles, and tooltips, font sizes, colors, background colors.[/#LI]\n[#LI]Numerous Chart Features: multi KPI support number types, precision, Y-axis tick marks, and hover-over tooltips.[/#LI]\n[#LI]Sparkline Interpolation: Interpolate sparkline values to get rid of noisy points.[/#LI]\n[#LI]Auto-Scaling: design a larger tile in your report with rich details. After pinning it to a Power BI Dashboard, you may resize it to smaller versions of the tile without losing essential details.[/#LI]", 37 | "Visual_MainChart": "Main chart", 38 | "Visual_Max": "Max", 39 | "Visual_Min": "Min", 40 | "Visual_MissingVarianceColor": "Missing variance color", 41 | "Visual_MissingVarianceFontSize": "Missing variance font size", 42 | "Visual_Name": "Name", 43 | "Visual_NameColor": "Name color", 44 | "Visual_NoValueLabel": "Missing value label", 45 | "Visual_NoVarianceLabel": "Missing variance label", 46 | "Visual_Position": "Position", 47 | "Visual_Precision": "Precision", 48 | "Visual_PrintMode": "Print mode", 49 | "Visual_PrintModeDescription": "Print Mode forces black color in Snapshot Service and Browser Print View", 50 | "Visual_SeriesNameFontSize": "Series name font size", 51 | "Visual_Short_Description": "A powerful Multi KPI visualization, of a key KPI along with multiple sparklines of supporting data", 52 | "Visual_ShouldInheritValues": "Inherit Min/Max from Y Axis", 53 | "Visual_Show": "Show", 54 | "Visual_ShowLatestAvailableValue": "Show latest available as current value", 55 | "Visual_Sparkline": "Sparkline", 56 | "Visual_SparklineChart": "Sparkline chart", 57 | "Visual_SparklineGrid": "Sparkline grid", 58 | "Visual_SparklineName": "Sparkline name", 59 | "Visual_SparklineValue": "Sparkline value", 60 | "Visual_SparklineYAxis": "Sparkline Y-axis", 61 | "Visual_StaleData": "Stale data", 62 | "Visual_StaleDataDescription": "To turn on Stale Data make sure to turn on Subtitle first", 63 | "Visual_StaleDataTextDescription": "Use ${1} to indicate where to put a date difference to indicate how old data is", 64 | "Visual_Subtitle": "Subtitle", 65 | "Visual_Threshold": "Threshold (days)", 66 | "Visual_ThresholdDescription": "Data is stale if data is older than some number of days from now", 67 | "Visual_Title": "Title", 68 | "Visual_TitleText": "Title text", 69 | "Visual_ToggleSparklineOnHover": "Toggle sparkline on hover", 70 | "Visual_ToggleSparklineOnHoverDescription": "Toggle Sparkline to the main chart on hover event", 71 | "Visual_Tooltip": "Tooltip", 72 | "Visual_TreatEmptyValuesAsZero": "Treat empty/missing values as zero", 73 | "Visual_Type": "Type", 74 | "Visual_Value": "Value", 75 | "Visual_ValueColor": "Value color", 76 | "Visual_ValueFontSize": "Value font size", 77 | "Visual_Values": "Values", 78 | "Visual_Variance": "Variance", 79 | "Visual_VarianceColor": "Variance color", 80 | "Visual_VarianceFontSize": "Variance font size", 81 | "Visual_Warning": "Warning", 82 | "Visual_YAxis": "Y-axis", 83 | "Visual_ZeroLine": "Zero line" 84 | } -------------------------------------------------------------------------------- /test.webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require("webpack"); 3 | 4 | module.exports = { 5 | devtool: 'inline-source-map', 6 | mode: 'development', 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.ts$/, 11 | use: 'ts-loader', 12 | exclude: /(dist|coverage|karma.conf.ts)/ 13 | }, 14 | { 15 | test: /\.ts$/i, 16 | enforce: 'post', 17 | include: /(src)/, 18 | exclude: /(node_modules|resources\/js\/vendor)/, 19 | loader: 'coverage-istanbul-loader', 20 | options: { esModules: true } 21 | }, 22 | { 23 | test: /\.less$/, 24 | use: [{ 25 | loader: 'style-loader' 26 | }, 27 | { 28 | loader: 'css-loader' 29 | }, 30 | { 31 | loader: 'less-loader', 32 | options: { 33 | lessOptions: { 34 | paths: [path.resolve(__dirname, 'node_modules')] 35 | } 36 | } 37 | } 38 | ] 39 | } 40 | ] 41 | }, 42 | externals: { 43 | "powerbi-visuals-api": '{}' 44 | }, 45 | resolve: { 46 | extensions: ['.tsx', '.ts', '.js', '.css'] 47 | }, 48 | output: { 49 | path: path.resolve(__dirname, ".tmp") 50 | }, 51 | plugins: [ 52 | new webpack.ProvidePlugin({ 53 | 'powerbi-visuals-api': null 54 | }), 55 | ], 56 | }; 57 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": false, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "module": "es6", 7 | "target": "ES6", 8 | "sourceMap": true, 9 | "outDir": "./.tmp/build/", 10 | "moduleResolution": "node", 11 | "declaration": true, 12 | "lib": [ 13 | "es2017", 14 | "dom" 15 | ] 16 | }, 17 | "files": [ 18 | "src/multiKpi.ts" 19 | ] 20 | } 21 | --------------------------------------------------------------------------------