From 60339aff31b32edbfd7913a6278032d91da2d073 Mon Sep 17 00:00:00 2001 From: srmukher <120183316+srmukher@users.noreply.github.com> Date: Wed, 17 Jan 2024 15:31:11 +0530 Subject: [PATCH 1/5] Removing publish to site job from workflow (#34) * Cleaning up UnitTestApp module * Revert "Cleaning up UnitTestApp module" This reverts commit 3c42278091b2de194b01df3a354b70b87c7d6808. * Removing publish to site job from workflow * Disabling the publish to site job --- .github/workflows/testCoverage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testCoverage.yml b/.github/workflows/testCoverage.yml index 2ad5dd35bc..51458e8ab4 100644 --- a/.github/workflows/testCoverage.yml +++ b/.github/workflows/testCoverage.yml @@ -129,6 +129,7 @@ jobs: echo "$table" publish_to_site: + if: false needs: run_tests runs-on: 'ubuntu-latest' steps: @@ -196,4 +197,4 @@ jobs: uses: actions/deploy-pages@v4 - name: Url after deployment - run: echo "${{ steps.deployment.outputs.page_url }}" + run: echo "${{ steps.deployment.outputs.page_url }}" \ No newline at end of file From 7fe0d3a4282b19ced2db1aa46a7e60966e3c53fc Mon Sep 17 00:00:00 2001 From: Shubhabrata Ghosh <35366351+Shubhabrata08@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:11:19 +0530 Subject: [PATCH 2/5] Auto deploy test coverage to docsite (#21) * deploy: 2606de2de6c6cfd4e8b36a81364f857fdaa98662 * yml change * testing action * testing action * testing action * Testing * testing * test * testing auto commit * minor fix * Minor fix * directory fix * Disp dir * dir change * small fix * commit test * dir disp * dir fix * testing dir * dir fix * git stat * commit test * view moved coverage * auto commit fix * Apply automatic changes * branch fix * Delete artifact * Apply automatic changes * risky commit * Add deployment script * checkout main while deploying * Remove old artifacts * change permissions * branch change * branch set to main * list files post commit * Delete build files * Restore docusaurus config * Script cleanup * Remove push trigger * test commit * comment time taking tests * test glob pattern artifact download * retest * use of pattern * commit testCoverage report to main * Rename txt to md * md renaming * change foldername * new branch for testCov deployment * Rename md doc foldername * change pull command * yml syntax fix * Add rename feature * Add push to cov branch * Fix upstream * Stuff * Syntax fix * rename fix * syntax fix * rename filenames * rename fix * Linting md * Clear stuff * branch wizardry * more branch wizardry * No more branch wizardry * Enable all tests * restore matrix * disable matrix * rename messup fixed * matrix change * rename fix * echo logging * yay log * Fix rename * reactivate matrix * Folder restructuring * deployment wizardry * fix deployent wizardry * Push artifact to repo * discard second repo solution * separate branch for artifacts * Comment artifact downloads * Shift pull statement * remove old artifacts * Setup multi commit * some branch wizardry * Add link to website * Fix filename * debug report file * Fix sed commands * Add coverage percentage value * add status badge * Fix badge variable * Fix trimming * Fix Line 2 * Reset workflow for all OS * fix workflow repo input params --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Shubhabrata08 --- .github/workflows/testCoverage.yml | 227 ++++++++++++++++++++++------- 1 file changed, 177 insertions(+), 50 deletions(-) diff --git a/.github/workflows/testCoverage.yml b/.github/workflows/testCoverage.yml index 51458e8ab4..81faac60be 100644 --- a/.github/workflows/testCoverage.yml +++ b/.github/workflows/testCoverage.yml @@ -1,4 +1,4 @@ -name: 'Test coverage' +name: "Test coverage" on: schedule: - cron: "0 */8 * * *" @@ -16,10 +16,10 @@ on: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: - contents: read + contents: write pages: write id-token: write - + jobs: run_tests: strategy: @@ -32,13 +32,13 @@ jobs: windows_artifact_name: ${{ steps.windows.outputs.COVERAGE_FILENAME_WINDOWS }} macos_artifact_name: ${{ steps.macos.outputs.COVERAGE_FILENAME_MACOS }} - steps: + steps: - name: Checkout [master] uses: actions/checkout@v4 - name: Checkout [react-charting] uses: actions/checkout@v4 - with: + with: repository: ${{ github.event.inputs.repo || 'microsoft/fluentui' }} ref: ${{ github.event.inputs.branch || 'master' }} path: repo1 @@ -50,24 +50,24 @@ jobs: run: ls ./repo1 - name: Install packages - run: yarn --cwd ./tools/UnitTestApp && yarn --cwd ./repo1 && yarn --cwd ./repo1/packages/react-charting + run: yarn --cwd ./tools/UnitTestApp && yarn --cwd ./repo1 && yarn --cwd ./repo1/packages/react-charting - name: Change function visibility from private to public id: setup uses: ./tools/UnitTestApp/ChangeFunctionVisibility with: osType: ${{ matrix.os }} - + - name: Build - run: yarn --cwd ./repo1 buildto @fluentui/react-charting + run: yarn --cwd ./repo1 buildto @fluentui/react-charting - name: Run the tests in windows - if: matrix.os == 'windows-latest' + if: matrix.os == 'windows-latest' run: cd ./repo1/packages/react-charting && powershell -Command "(Get-Content -Path ./config/tests.js) -replace 'PROD', 'TEST' | Set-Content -Path ./config/tests.js" && yarn jest --coverage --coverageDirectory ./coverage/${{matrix.os}} --verbose --coverageReporters=html --coverageReporters=text > coverageReport.txt continue-on-error: true - name: Run a single test in windows - if: matrix.os == 'windows-latest' + if: matrix.os == 'windows-latest' run: cd ./repo1/packages/react-charting && powershell -Command "(Get-Content -Path ./config/tests.js) -replace 'PROD', 'TEST' | Set-Content -Path ./config/tests.js" && yarn jest ./src/components/VerticalBarChart --coverage --coverageDirectory ./coverage/${{matrix.os}}_VerticalBarChart --verbose --coverageReporters=html continue-on-error: true @@ -83,14 +83,14 @@ jobs: - name: Generate coverage file name in windows id: windows - if: matrix.os == 'windows-latest' + if: matrix.os == 'windows-latest' run: | - $NOW=& Get-Date -format yyyy-MM-dd - echo "COVERAGE_FILENAME=test_coverage_${{ matrix.os }}_$NOW" >> $env:GITHUB_ENV + $NOW=& Get-Date -format yyyy-MM-dd + echo "COVERAGE_FILENAME=test_coverage_${{ matrix.os }}_$NOW" >> $env:GITHUB_ENV - name: Generate coverage file name - run: | - echo "COVERAGE_FILENAME=test_coverage_${{ matrix.os }}_$(date +'%Y-%m-%d_%H-%M-%S')" >> $GITHUB_ENV + run: | + echo "COVERAGE_FILENAME=test_coverage_${{ matrix.os }}_$(date +'%Y-%m-%d_%H-%M-%S')" >> $GITHUB_ENV - name: Save coverage folder uses: actions/upload-artifact@v4 @@ -114,49 +114,74 @@ jobs: - name: Extract the coverage summary table if: matrix.os != 'windows-latest' run: | - cd ./repo1/packages/react-charting - file_contents=$(cat coverageReport.txt) - table=$(echo "$file_contents" | awk '/----/,/^$/' | sed '1d;$d') - echo "$table" + cd ./repo1/packages/react-charting + file_contents=$(cat coverageReport.txt) + table=$(echo "$file_contents" | awk '/----/,/^$/' | sed '1d;$d') + echo "$table" - name: Extract the coverage summary table in windows if: matrix.os == 'windows-latest' run: | - cd ./repo1/packages/react-charting - $fileContents = Get-Content -Raw -Path "coverageReport.txt" - $tableRegex = "(?ms)----.*?^$" - $table = [regex]::Match($fileContents, $tableRegex) - echo "$table" - - publish_to_site: - if: false + cd ./repo1/packages/react-charting + $fileContents = Get-Content -Raw -Path "coverageReport.txt" + $tableRegex = "(?ms)----.*?^$" + $table = [regex]::Match($fileContents, $tableRegex) + echo "$table" + + push_artifacts_to_repo: needs: run_tests - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" + permissions: + contents: write + steps: - name: Download all artifacts to publish together uses: actions/download-artifact@v4 with: - name: 'ubuntu-latest' - path: './coverage/ubuntu-latest' + name: "ubuntu-latest" + path: "./coverage/ubuntu-latest" - name: Download all artifacts to publish together uses: actions/download-artifact@v4 with: - name: 'macos-latest' - path: './coverage/macos-latest' + name: "macos-latest" + path: "./coverage/macos-latest" - name: Download all artifacts to publish together uses: actions/download-artifact@v4 with: - name: 'windows-latest' - path: './coverage/windows-latest' + name: "windows-latest" + path: "./coverage/windows-latest" - name: Download all artifacts to publish together uses: actions/download-artifact@v4 with: - name: 'coverage_VBC' - path: './coverage/coverage_VBC' + name: "coverage_VBC" + path: "./coverage/coverage_VBC" + - name: Download all artifacts to publish together + uses: actions/download-artifact@v4 + with: + name: ${{env.COVERAGE_FILENAME_MACOS}} + path: './coverage/coverageFileMacOS' + - name: Download all artifacts to publish together + uses: actions/download-artifact@v4 + with: + name: ${{env.COVERAGE_FILENAME_UBUNTU}} + path: "./coverage/coverageFileUbuntu" + - name: Download all artifacts to publish together + uses: actions/download-artifact@v4 + with: + name: ${{env.COVERAGE_FILENAME_WINDOWS}} + path: './coverage/coverageFileWindows' + - name: Download all artifacts to publish together + uses: actions/download-artifact@v4 + with: + pattern: test_coverage_* + path: "./coverage/coverageFiles" + + - name: "Check coverage file" + run: cd ./coverage/coverageFiles && ls -a - name: Rename folders run: | cd ./coverage @@ -173,28 +198,130 @@ jobs: done shell: bash - - name: Show the coverage folder - run: | - cd ./coverage - ls - - name: Generate html to show the latest coverages for all os types run: | - cd ./coverage - echo "Contributor Readiness

View contributor guides and full test coverage reports

" >> index.html + cd ./coverage + echo "Contributor Readiness

View contributor guides and full test coverage reports

" >> index.html shell: bash - name: Setup Pages uses: actions/configure-pages@v4 - + - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: './coverage' + path: "./coverage" + + - name: Directory disp + run: ls -a + + - name: Checkout [main] + uses: actions/checkout@v4 + with: + path: repo + ref: main + + - name: Remove old artifacts + run: | + rm -rf ./repo/docs/coverageFiles + cd ./repo/docs + ls -a + shell: bash + - name: Rename all txt reports to md and remove unnecessary lines + run: | + cd ./coverage/coverageFiles + for f in $(find ./ -name '*.txt'); do + sed -i '/PASS/d' "$f" + sed -i '/FAIL/d' "$f" + sed -i '/yarn/d' "$f" + sed -i '/jest/d' "$f" + sed -i '1d' "$f" + statementCoveragePercent=$(echo $(awk '/All files/ {print}' $f) | awk -F'|' '{print $2}') + statementCoveragePercentTrimmed=$(echo "$statementCoveragePercent" | awk '{$1=$1; print}') + sed -i "1i\![Test Coverage Badge](https://img.shields.io/badge/Test_Coverage-$statementCoveragePercentTrimmed-mediumgreen)\n" "$f" + sed -i '2i\ ' "$f" + sed -i '3i\[Click here for a detailed report](https://fluentui-charting-test-coverage.netlify.app/)' "$f" + dir_path=$(dirname "$f") + file_name=$(basename "$f") + new_file_name="TestCoverageReport.md" + mv -- "$f" "$dir_path/$new_file_name" + done + ls -lR + + - name: Move coverage to docs + run: ls -a && mv -f coverage/coverageFiles repo/docs && cd repo/docs && ls -a + - name: Rename folder names for reports + run: | + cd ./repo/docs/coverageFiles + ls -lR + for dir in *; do + if [[ $dir == *"ubuntu"* ]]; then + mv "$dir/TestCoverageReport.md" "Ubuntu Test Coverage Report.md" + rm -rf $dir + elif [[ $dir == *"macos"* ]]; then + mv "$dir/TestCoverageReport.md" "MacOS Test Coverage Report.md" + rm -rf $dir + elif [[ $dir == *"windows"* ]]; then + mv "$dir/TestCoverageReport.md" "Windows Test Coverage Report.md" + rm -rf $dir + fi + done + ls -lR + shell: bash + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + repository: repo + branch: main + - name: Change branch to test-coverage-artifacts and move new artifacts to folder + run: | + cd repo + if [ `git branch | grep test-coverage-artifacts` ] + then + git checkout test-coverage-artifacts + git pull origin test-coverage-artifacts + else + git checkout -b test-coverage-artifacts + fi + rm -rf ./* + cd .. + mv -f ./coverage/* ./repo/ + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + repository: repo + branch: test-coverage-artifacts + push_options: "--force" + - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 + deploy: + needs: push_artifacts_to_repo + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v4 + with: + ref: main + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: yarn + - name: List files in docs + run: cd docs && ls -a + - name: Install dependencies + run: cd apps/docsite && yarn install --frozen-lockfile + - name: Build website + run: cd apps/docsite && yarn build - - name: Url after deployment - run: echo "${{ steps.deployment.outputs.page_url }}" \ No newline at end of file + # Popular action to deploy to GitHub Pages: + # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + # Build output to publish to the `gh-pages` branch: + publish_dir: ./apps/docsite/build + # The following lines assign commit authorship to the official + # GH-Actions bot for deploys to `gh-pages` branch: + # https://github.com/actions/checkout/issues/13#issuecomment-724415212 + # The GH actions bot is used by default if you didn't specify the two fields. + # You can swap them out with your own user credentials. + user_name: github-actions[bot] + user_email: 41898282+github-actions[bot]@users.noreply.github.com From de0c28f7a0d3341ff5d0d517cf075db35154e9bb Mon Sep 17 00:00:00 2001 From: "Atishay Jain (from Dev Box)" Date: Thu, 25 Jan 2024 23:33:31 +0530 Subject: [PATCH 3/5] Add heatmap chart to testing v9 theme --- .../src/components/ChartWrapper.tsx | 2 + .../components/HeatMapChartBasic.Example.tsx | 353 ++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 tools/v9-migration/src/components/HeatMapChartBasic.Example.tsx diff --git a/tools/v9-migration/src/components/ChartWrapper.tsx b/tools/v9-migration/src/components/ChartWrapper.tsx index ef6669ca0f..29f42626ff 100644 --- a/tools/v9-migration/src/components/ChartWrapper.tsx +++ b/tools/v9-migration/src/components/ChartWrapper.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { Theme,webDarkTheme,webLightTheme } from '@fluentui/react-components'; import { LineChartBasicExample } from './LineChartBasicExample'; import { HorizontalBarChartBasicExample } from './HorizontalBarChart.Basic.Example'; +import { HeatMapChartBasicExample } from './HeatMapChartBasic.Example'; import * as d3Color from 'd3-color'; @@ -25,6 +26,7 @@ export function ChartWrapper() { + ); diff --git a/tools/v9-migration/src/components/HeatMapChartBasic.Example.tsx b/tools/v9-migration/src/components/HeatMapChartBasic.Example.tsx new file mode 100644 index 0000000000..79304738e3 --- /dev/null +++ b/tools/v9-migration/src/components/HeatMapChartBasic.Example.tsx @@ -0,0 +1,353 @@ +import * as React from 'react'; +import { HeatMapChart, IHeatMapChartProps, DataVizPalette, getColorFromToken } from '@fluentui/react-charting'; + +interface IHeatMapChartBasicExampleState { + width: number; + height: number; +} + +export class HeatMapChartBasicExample extends React.Component<{}, IHeatMapChartBasicExampleState> { + constructor(props: any) { + super(props); + this.state = { + width: 450, + height: 350, + }; + } + public render(): React.ReactNode { + const rootStyle = { width: `${this.state.width}px`, height: `${this.state.height}px` }; + const yPointMapping: { [key: string]: string } = { + p1: 'Ohio', + p2: 'Alaska', + p3: 'Texas', + p4: 'DC', + p5: 'NYC', + }; + const yPoint: string[] = ['p1', 'p2', 'p3', 'p4', 'p5']; + + const xPoint: Date[] = [ + new Date('2020-03-03'), // 0 + new Date('2020-03-04'), // 1 + new Date('2020-03-05'), // 2 + new Date('2020-03-06'), // 3 + new Date('2020-03-07'), // 4 + new Date('2020-03-08'), // 5 + new Date('2020-03-09'), // 6 + new Date('2020-03-10'), // 7 + ]; + const HeatMapData: IHeatMapChartProps['data'] = [ + { + value: 100, + legend: 'Excellent (0-200)', + data: [ + { + x: xPoint[2], + y: yPoint[2], + value: 46, + rectText: 46, + ratio: [46, 2391], + descriptionMessage: 'air quality seems to be excellent today', + }, + ], + }, + { + value: 250, + legend: 'Good (201-300)', + data: [ + { + x: xPoint[0], + y: yPoint[1], + value: 265, + rectText: 265, + ratio: [265, 2479], + descriptionMessage: 'today we have good air quality in Alaska', + }, + { + x: xPoint[1], + y: yPoint[0], + value: 250, + rectText: 250, + ratio: [250, 2043], + descriptionMessage: 'a sudden rise of 150 units in Ohio today', + }, + { + x: xPoint[2], + y: yPoint[0], + value: 235, + rectText: 235, + ratio: [235, 2043], + descriptionMessage: 'air quality seems to have decreased by only 15 units from yesterday', + }, + { + x: xPoint[6], + y: yPoint[2], + value: 300, + rectText: 300, + ratio: [300, 2391], + descriptionMessage: 'air comes to control a little bit more than yesterday', + }, + { + x: xPoint[0], + y: yPoint[3], + value: 290, + rectText: 290, + ratio: [290, 2462], + descriptionMessage: '1st day in the week, DC witnesses good air quality', + }, + { + x: xPoint[4], + y: yPoint[4], + value: 280, + rectText: 280, + ratio: [280, 2486], + descriptionMessage: `Air quality index decreases by exactly 300 units, + giving the people of NYC good hope`, + }, + { + x: xPoint[5], + y: yPoint[3], + value: 300, + rectText: 300, + ratio: [300, 2462], + descriptionMessage: '60 units decreased from yesterday.', + }, + ], + }, + { + value: 350, + legend: 'Medium (301-400)', + data: [ + { + x: xPoint[1], + y: yPoint[1], + value: 345, + rectText: 345, + ratio: [345, 2479], + descriptionMessage: 'Alaska has just reported nearly 100 units hike in air quality', + }, + { + x: xPoint[6], + y: yPoint[1], + value: 325, + rectText: 325, + ratio: [325, 2479], + descriptionMessage: `Alaska to 300`, + }, + { + x: xPoint[5], + y: yPoint[2], + value: 390, + rectText: 390, + ratio: [390, 2391], + descriptionMessage: 'air comes to control a little bit', + }, + { + x: xPoint[1], + y: yPoint[3], + value: 385, + rectText: 385, + ratio: [385, 2462], + descriptionMessage: 'Washington DC witnesses a hike of nearly 100 units in air quality', + }, + { + x: xPoint[4], + y: yPoint[3], + value: 360, + rectText: 360, + ratio: [360, 2462], + descriptionMessage: 'a 200% hike in the air quality index', + }, + { + x: xPoint[1], + y: yPoint[2], + value: 400, + rectText: 400, + ratio: [400, 2391], + descriptionMessage: 'a sudden spike in the badness of the air quality', + }, + { + x: xPoint[3], + y: yPoint[0], + value: 400, + rectText: 400, + ratio: [400, 2043], + descriptionMessage: 'situation got worse in air quality due to industrial smoke', + }, + ], + }, + { + value: 450, + legend: 'Danger (401-500)', + data: [ + { + x: xPoint[4], + y: yPoint[0], + value: 423, + rectText: 423, + ratio: [423, 2043], + descriptionMessage: 'we can see an increase of 23 units', + }, + { + x: xPoint[2], + y: yPoint[1], + value: 463, + rectText: 463, + ratio: [463, 2479], + descriptionMessage: 'day by day, situation is getting worse in Alaska', + }, + { + x: xPoint[3], + y: yPoint[2], + value: 480, + rectText: 480, + ratio: [480, 2391], + descriptionMessage: 'same story, today also air quality decreases. a bad day in Texas', + }, + { + x: xPoint[2], + y: yPoint[3], + value: 491, + rectText: 491, + ratio: [491, 2462], + descriptionMessage: 'Day by day, 100 units are increasing in air quality', + }, + { + x: xPoint[1], + y: yPoint[4], + value: 433, + rectText: 433, + ratio: [433, 2486], + descriptionMessage: `They say good things stay for a short time, today + this saying became reality. New York has witnessed nearly 300% bad air quality`, + }, + { + x: xPoint[5], + y: yPoint[4], + value: 473, + rectText: 473, + ratio: [473, 2486], + descriptionMessage: `Today is the same fate as the 2nd day. still, air quality + stays above 400`, + }, + ], + }, + { + value: 550, + legend: 'Very Danger (501-600)', + data: [ + { + x: xPoint[5], + y: yPoint[0], + value: 600, + rectText: 600, + ratio: [600, 2043], + descriptionMessage: 'looks like god has cursed us with poisonous air. worst air quality index', + }, + { + x: xPoint[5], + y: yPoint[1], + value: 536, + rectText: 536, + ratio: [536, 2479], + descriptionMessage: `shh!, all the hopes were washed away in the rain yesterday, + with another hike of 400% in air quality`, + }, + { + x: xPoint[3], + y: yPoint[1], + value: 520, + rectText: 520, + ratio: [520, 2479], + descriptionMessage: 'Alaska planning to build air purifier to control the air quality', + }, + { + x: xPoint[4], + y: yPoint[2], + value: 525, + rectText: 525, + ratio: [525, 2391], + descriptionMessage: 'air worsens badly today due to farmers burning the harvest', + }, + { + x: xPoint[6], + y: yPoint[3], + value: 560, + rectText: 560, + ratio: [560, 2462], + descriptionMessage: `Due to industrial pollution and the + burning of harvest, it resulted in bad air quality in Washington DC`, + }, + { + x: xPoint[3], + y: yPoint[4], + value: 580, + rectText: 580, + ratio: [580, 2486], + descriptionMessage: `Air quality index is becoming worse day by day, leaving the + people of NYC in very bad medical conditions.`, + }, + { + x: xPoint[6], + y: yPoint[4], + value: 590, + rectText: 590, + ratio: [590, 2486], + descriptionMessage: `finally, the weekend ends with very bad air quality in New York City`, + }, + ], + }, + ]; + return ( + <> + + + + +

Heat map explaining the Air Quality Index

+
+ yPointMapping[point as string]} + xAxisNumberFormatString=".7s" + yAxisNumberFormatString=".3s" + width={this.state.width} + height={this.state.height} + domainValuesForColorScale={[0, 200, 400, 600]} + rangeValuesForColorScale={[ + getColorFromToken(DataVizPalette.success), + getColorFromToken(DataVizPalette.warning), + getColorFromToken(DataVizPalette.error), + getColorFromToken(DataVizPalette.highError), + ]} + enableReflow={true} + /> +
+ + ); + } + private _onWidthChange = (e: React.ChangeEvent) => { + this.setState({ width: parseInt(e.target.value, 10) }); + }; + private _onHeightChange = (e: React.ChangeEvent) => { + this.setState({ height: parseInt(e.target.value, 10) }); + }; +} From b8d06b926f32013cb2dbf9d3184092cd9c4f754a Mon Sep 17 00:00:00 2001 From: Shubhabrata Ghosh <35366351+Shubhabrata08@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:02:55 +0530 Subject: [PATCH 4/5] Add dynamic link to homepage (#36) --- apps/docsite/src/pages/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/docsite/src/pages/index.tsx b/apps/docsite/src/pages/index.tsx index a49b555213..ac26f2c494 100644 --- a/apps/docsite/src/pages/index.tsx +++ b/apps/docsite/src/pages/index.tsx @@ -6,6 +6,7 @@ import HomepageFeatures from '@site/src/components/HomepageFeatures'; import Heading from '@theme/Heading'; import styles from './index.module.css'; +import sidebars from '@site/sidebars'; function HomepageHeader() { const {siteConfig} = useDocusaurusContext(); @@ -19,7 +20,7 @@ function HomepageHeader() {
+ to={`/docs/${sidebars.tutorialSidebar[0]}`}> Getting Started 🚈
From 53946acfb07f3bb82bf82bc3befc8a6ee8af3946 Mon Sep 17 00:00:00 2001 From: krkshitij <110246001+krkshitij@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:19:04 +0530 Subject: [PATCH 5/5] Add contributor guides (#37) * add contributor guides * fix errors * update docsite links * add width to small image --- docs/Charting-Concepts/GaugeChart.md | 217 ++++++++++++++++++ docs/Charting-Concepts/HeatMapChart.md | 143 ++++++++++++ docs/Charting-Concepts/HorizontalBarChart.md | 159 +++++++++++++ docs/Charting-Concepts/StackedBarChart.md | 178 ++++++++++++++ .../Test Plans/HeatMapChart/ComponentTests.md | 30 +++ docs/assets/images/gaugechart-dev-design.png | Bin 0 -> 70445 bytes .../images/gaugechart-test-coverage.png | Bin 0 -> 155107 bytes .../images/heatmapchart-test-coverage.png | Bin 0 -> 187099 bytes .../horizontalbarchart-test-coverage.png | Bin 0 -> 213759 bytes .../images/stackedbarchart-test-coverage.png | Bin 0 -> 315377 bytes 10 files changed, 727 insertions(+) create mode 100644 docs/Charting-Concepts/GaugeChart.md create mode 100644 docs/Charting-Concepts/HeatMapChart.md create mode 100644 docs/Charting-Concepts/HorizontalBarChart.md create mode 100644 docs/Charting-Concepts/StackedBarChart.md create mode 100644 docs/Test Plans/HeatMapChart/ComponentTests.md create mode 100644 docs/assets/images/gaugechart-dev-design.png create mode 100644 docs/assets/images/gaugechart-test-coverage.png create mode 100644 docs/assets/images/heatmapchart-test-coverage.png create mode 100644 docs/assets/images/horizontalbarchart-test-coverage.png create mode 100644 docs/assets/images/stackedbarchart-test-coverage.png diff --git a/docs/Charting-Concepts/GaugeChart.md b/docs/Charting-Concepts/GaugeChart.md new file mode 100644 index 0000000000..abfe452e48 --- /dev/null +++ b/docs/Charting-Concepts/GaugeChart.md @@ -0,0 +1,217 @@ +# Contributor guide: Gauge Chart + +Gauge chart measures the progress of a metric against its target and its primary components are a speedometer and a needle. The speedometer usually consists of color-coded segments progressing value from left to right. + +## Use cases + +Gauge chart offers a quick and intuitive way to evaluate a single value within a specific range and its relation to targets or thresholds. Here are some common use cases for gauge chart: + +- Performance Monitoring: Track metrics like sales or customer satisfaction against predefined benchmarks. +- KPI Tracking: Monitor progress towards goals by displaying key performance indicators. +- Health and Fitness: Display health parameters such as heart rate or steps taken. +- Survey Feedback: Visualize satisfaction scores or survey feedback. +- Resource Allocation: Show resource distribution across different categories. +- Risk Assessment: Assess risk levels or safety ratings. +- Project Progress: Represent project or task completion percentage. +- Quality Control: Monitor defect or error rates. + +## Dev Design details + +Gauge chart dev design + +The Gauge chart comprises the following components and subcomponents: + +**GaugeChart**: This is the main component responsible for rendering and managing subcomponents such as chart title, limits (min and max values), segments, needle, chart value, sublabel, and other components. It handles user interactions and provides the overall functionality of the chart. + +**FocusZone**: This component facilitates focus navigation within the Gauge chart. It allows users to navigate between focusable subcomponents, such as segments and the needle, using the arrow and tab keys. + +**SVGTooltipText**: This component is used to render the chart value and sublabel as SVG text elements with an optional tooltip. The tooltip is triggered when the content overflows and appears when users hover over or focus on the element. + +**Legends**: Legends are a list of strings that identify each segment in the Gauge chart. The Legends component renders a button for each legend, enabling users to highlight the corresponding segment by hovering over or selecting the legend. + +**Callout**: This component functions as an anchored tip, offering additional information about the segment, needle, or chart value that is currently hovered over or focused without blocking the user. + +**Segments**: These are the color-coded intervals that indicate different levels or categories. + +**Needle**: It indicates the current value of the chart within a range. + +## Mathematical/Geometrical concepts + +- Segments in the chart are generated using the [arc](https://github.com/d3/d3-shape#arcs) utility from the [d3-shape](https://github.com/d3/d3-shape) library. This utility returns an arc generator that produces path data based on specified angle and radius values. The arcs are always centred at coordinates \{0, 0}, so a transform is applied to move the arc to a different position. +- Here, an angle of 0 radians corresponds to the positive y-axis. The arc is created in a clockwise direction if the signed difference between the start and end angles is positive. The angular span of each segment is determined by the ratio of its individual size to the total size of all segments. +- The [pad angle](https://github.com/d3/d3-shape#arc_padAngle) is converted to a fixed linear distance separating adjacent arcs, defined as padRadius * padAngle. As per the design doc, the desired distance between adjacent arcs is 2px, referred to as ARC_PADDING. To maintain this distance between the outer boundaries of the arcs, padRadius is kept the same as outerRadius, and padAngle is calculated as ARC_PADDING / padRadius. Note that if the inner radius or angular span is small relative to the pad angle, it may not be possible to maintain parallel edges between adjacent arcs. + +## Performance + +## Accessibility + +The following subcomponents are accessible using a screen reader: + +1. **Chart \**: The following attributes provide an accessible name describing the contents of the chart. + - `role` = "presentation" + - `aria-label` = "This is a gauge chart with \{numSegments} section represented." + +1. **Min value \**: It is already accessible to screen readers, but the content doesn’t convey complete information. The following attributes specify a different accessible name for the min value. + - `role` = "img" + - `aria-label` = "Min value: \{minValue}" + +1. **Max value \**: It is already accessible to screen readers, but the content doesn’t convey complete information. The following attributes specify a different accessible name for the max value. + - `role` = "img" + - `aria-label` = "Max value: \{adjustedMaxValue}" + +1. **Segments \**: The following attributes provide an accessible name describing the segment. + - `role` = "img" + - `aria-label` = + "\{segmentLegend}, \{segmentStart} - \{segmentEnd}" when variant is GaugeChartVariant.MultipleSegments, or + "\{segmentLegend}, \{segmentSize} out of \{totalSizeOfSegments} or \{segmentSizeInPercent}%" when variant is GaugeChartVariant.SingleSegment. + + Users can provide a custom accessible name or description for a segment using its accessibilityData prop. + +1. **Chart value \**: It is already accessible to screen readers, but the content doesn’t convey complete information. The following attributes specify a different accessible name for the chart value. + - `role` = "img" + - `aria-label` = "Current value: \{formattedChartValue}" + +1. **Sublabel \**: It is already accessible to screen readers. The following attributes provide an accessible name for the sublabel. + - `role` = "img" + - `aria-label` = the sublabel itself + +## Testing + +![Test coverage report](../assets/images/gaugechart-test-coverage.png) + +[GaugeChart test plan](../Test%20Plans/GaugeChart/ComponentTests.md) + +## Variants + +Here are the props available for customizing the gauge chart: + +- **width** and **height**: These props determine the diameter of the gauge. If not provided, a default diameter of 140px is used. + +- **chartTitle**: Use this prop to render a title above the gauge. + +- **chartValue**: This required prop controls the rotation of the needle. If the chart value is less than the minimum, the needle points to the min value. Similarly, if it exceeds the maximum, the needle points to the max value. + +- **segments**: Use this required prop to divide the gauge into colored sections. The segments can have fixed sizes or vary with the chart value to create a sweeping effect. Negative segment sizes are treated as 0. + +- **minValue**: Use this prop if the minimum value of the gauge is different from 0. + +- **maxValue**: Use this prop to render a placeholder segment when the difference between the max and min values is larger than the total size of the segments. If the difference is smaller, the max value will be adjusted so that the total size of the segments matches the difference. + +- **sublabel**: Use this prop to render additional text below the chart value. + +- **hideMinMax**: Set this prop to true to hide the min and max values of the gauge. + +- **chartValueFormat**: This prop controls how the chart value is displayed. Set it to one of the following options: + - A custom formatter function that returns a string representing the chart value. + - *GaugeValueFormat.Fraction*: Renders the chart value as a fraction. + - *GaugeValueFormat.Percentage*: Renders the chart value as a percentage. This is the default format. + + Note: If the min value is non-zero and no formatter function is provided, the chart value will be rendered as a number. + +- **variant**: This prop determines the presentation style of the gauge chart. Set it to one of the following options: + - *GaugeChartVariant.SingleSegment*: Displays and announces the segment sizes as percentages. + - *GaugeChartVariant.MultipleSegments*: Displays and announces the segment sizes as ranges. This is the default variant. + +For more details, see [Fluent UI - Controls - React - GaugeChart](https://developer.microsoft.com/en-us/fluentui#/controls/web/gaugechart) + +## Theming + +- The styles file contains a function called getStyles, which returns styles for different areas or subcomponents of the chart based on the props passed to it. The base component is wrapped with the styled HOC, which passes the theme (set by the user) and the concatenated styles (obtained from the styling function and any additional styles provided by the user) as props to the base component. Within the base component, the styles are applied to corresponding elements after converting them into class names. This conversion is done by passing theme and other style props as arguments to the function returned by the classNamesFunction utility. To learn more about component styling, refer [this](https://github.com/microsoft/fluentui/wiki/Component-Styling). +- For each segment in the chart, the color prop is optional. If the color prop is not defined, a color is selected from the qualitative palette using the getNextColor utility. However, if the color prop is defined, the getColorFromToken utility is used to determine the appropriate CSS color. If the value of the color prop is a theme-specific color token from the DataVizPalette, the utility will return the corresponding CSS color. Otherwise, if the color prop is already a valid CSS color, it will be returned as is. + +## Debugging + +## Error scenarios + +## Localization aspects + +Currently, the chart supports localization only for the callout content. + +## Some notable PRs and their brief description + +[Add gauge chart by krkshitij · Pull Request #27170 · microsoft/fluentui (github.com)](https://github.com/microsoft/fluentui/pull/27170) + +## Future improvements + +1. Add min width and height +1. Show message when chart is empty + +## Rendering details + +- The calculation of margins for the Gauge chart takes into account the presence of the chart title, sublabel, and limits (min and max values) to ensure that they do not overlap with the segments. Additionally, there is an extra margin of 16px around the gauge, referred to as GAUGE_MARGIN. +- Assuming that the legends do not wrap, the legends container is considered to have a fixed height of 24px. This helps calculate the available height for the \ element. +- The outer radius of the gauge is calculated based on the width and height props. If these props are not provided, the viewable width and height of the root div when the component mounts are used instead. +- According to the design doc, the font size of the chart value and the arc width vary depending on the size of the gauge chart. We cannot use CSS media queries in this case because the styles would be conditionally applied based on browser and operating system parameters. Instead, we use the BREAKPOINTS constant to determine the appropriate inner radius of the gauge and the font size of the chart value. +- If the difference between the max and min values exceeds the total size of all segments, a placeholder segment is rendered with a value equal to the difference. However, if the difference is smaller, the maximum value is adjusted to the correct value. +- The sweep fraction is calculated using the chart value, min value, and adjusted max value to determine the rotation of the needle. +- The min and max values are formatted with SI prefixes, as mentioned in the design doc. This formatting ensures that the values do not exceed 6 characters, equivalent to a width of 36px, referred to as LABEL_WIDTH. +- By default, the focus outline for segments is rectangular in shape. So the default outline is removed, and a custom outline is shown or hidden based on focus and blur events by adjusting the stroke width. + +## Interactions + +The chart is wrapped with a FocusZone component to allow focus on its interactive subcomponents. The following subcomponents are accessible using the keyboard: + +1. **Segments \** + - `data-is-focusable`: True + - `onFocus`: Shows a callout near the element containing the chart value and all segments, along with their respective ranges + - `onBlur`: Hides the callout if it is visible + +1. **Needle \** + - `data-is-focusable`: True + - `onFocus`: Shows a callout near the element containing the chart value and all segments, along with their respective ranges + - `onBlur`: Hides the callout if it is visible + +1. **Chart value \** + - `data-is-focusable`: True if the text content overflows the specified width and height + - `onFocus`: Shows a tooltip with the complete content + - `onBlur`: Hides the tooltip if it is visible + +1. **Legend \
** (CartesianChart) + - `onMouseLeave`: Hides the callout if it is visible. + +1. **Legend \