├── .config ├── checkstyle │ ├── checkstyle.xml │ └── suppressions.xml └── pmd │ └── ruleset.xml ├── .gitattributes ├── .github ├── .lycheeignore ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── enhancement.yml │ └── question.yml ├── labels.yml └── workflows │ ├── broken-links.yml │ ├── check-build.yml │ ├── release.yml │ ├── sonar.yml │ ├── sync-labels.yml │ ├── test-deploy.yml │ └── update-from-template.yml ├── .gitignore ├── .idea ├── checkstyle-idea.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── externalDependencies.xml ├── inspectionProfiles │ └── Project_Default.xml └── saveactions_settings.xml ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── .run └── Run Demo.run.xml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── assets ├── demo.avif └── preview.gif ├── mvnw ├── mvnw.cmd ├── pom.xml ├── renovate.json5 ├── vaadin-grid-exporter-demo ├── pom.xml └── src │ └── main │ ├── java │ └── software │ │ └── xdev │ │ └── vaadin │ │ ├── Application.java │ │ └── gridexport │ │ └── example │ │ ├── DemoView.java │ │ ├── jsonext │ │ ├── JsonConfig.java │ │ ├── JsonConfigComponent.java │ │ ├── JsonFormat.java │ │ └── JsonGridExporterProvider.java │ │ └── pre_defined_title │ │ └── PredefinedTitleProvider.java │ └── resources │ └── application.yml └── vaadin-grid-exporter ├── pom.xml └── src ├── main ├── java │ └── software │ │ └── xdev │ │ └── vaadin │ │ └── grid_exporter │ │ ├── GridExportLocalizationConfig.java │ │ ├── GridExporter.java │ │ ├── GridExporterProvider.java │ │ ├── Translator.java │ │ ├── column │ │ ├── ColumnConfiguration.java │ │ ├── ColumnConfigurationBuilder.java │ │ ├── ColumnConfigurationHeaderResolvingStrategyBuilder.java │ │ └── headerresolving │ │ │ ├── ColumnHeaderResolvingStrategy.java │ │ │ ├── ManualColumnHeaderResolvingStrategy.java │ │ │ └── VaadinColumnHeaderResolvingStrategy.java │ │ ├── components │ │ └── wizard │ │ │ ├── WizardState.java │ │ │ ├── WizardStyles.java │ │ │ ├── buttonbar │ │ │ ├── AbstractWizardButtonBar.java │ │ │ ├── WizardButtonBar.java │ │ │ └── WizardButtonBarWithAnchor.java │ │ │ ├── panel │ │ │ ├── WizardPanel.java │ │ │ └── WizardPanelActions.java │ │ │ └── step │ │ │ ├── WizardPanelStepChangedEvent.java │ │ │ ├── WizardStep.java │ │ │ ├── WizardStepComposite.java │ │ │ └── WizardStepState.java │ │ ├── format │ │ ├── AbstractFormat.java │ │ ├── Format.java │ │ ├── SpecificConfig.java │ │ └── SpecificConfigComponent.java │ │ ├── grid │ │ └── GridDataExtractor.java │ │ ├── jasper │ │ ├── DynamicExporter.java │ │ ├── JasperGridExporterProvider.java │ │ ├── JasperGridReportStyles.java │ │ ├── config │ │ │ ├── JasperConfigsLocalization.java │ │ │ ├── encoding │ │ │ │ ├── EncodingConfig.java │ │ │ │ ├── EncodingConfigComponent.java │ │ │ │ └── ExportEncoding.java │ │ │ ├── header │ │ │ │ ├── HeaderConfig.java │ │ │ │ └── HeaderConfigComponent.java │ │ │ ├── highlight │ │ │ │ ├── HighlightConfig.java │ │ │ │ └── HighlightConfigComponent.java │ │ │ ├── page │ │ │ │ ├── PageConfig.java │ │ │ │ └── PageConfigComponent.java │ │ │ ├── separator │ │ │ │ ├── CSVSeparatorConfig.java │ │ │ │ └── CSVSeparatorConfigComponent.java │ │ │ └── title │ │ │ │ ├── TitleConfig.java │ │ │ │ └── TitleConfigComponent.java │ │ └── format │ │ │ ├── AbstractJasperReportFormat.java │ │ │ ├── AbstractJasperReportSpreadsheetFormat.java │ │ │ ├── AbstractJasperReportWordProcessingFormat.java │ │ │ ├── CsvFormat.java │ │ │ ├── DocxFormat.java │ │ │ ├── HtmlFormat.java │ │ │ ├── OdsFormat.java │ │ │ ├── OdtFormat.java │ │ │ ├── PdfFormat.java │ │ │ ├── PptxFormat.java │ │ │ ├── RtfFormat.java │ │ │ ├── TextFormat.java │ │ │ └── XlsxFormat.java │ │ └── wizard │ │ ├── GridExporterWizard.java │ │ ├── GridExporterWizardState.java │ │ └── steps │ │ ├── AbstractGridExportWizardStepComposite.java │ │ ├── FormatStep.java │ │ ├── GeneralStep.java │ │ └── PreviewStep.java └── resources │ └── META-INF │ └── resources │ └── frontend │ └── styles │ └── wizard.css └── test └── java └── software └── xdev └── vaadin └── grid_exporter ├── column └── headerresolving │ └── VaadinColumnHeaderResolvingStrategyTest.java └── grid └── GridDataExtractorReflectionTest.java /.config/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Force sh files to have LF 5 | *.sh text eol=lf 6 | 7 | # Force MVN Wrapper Linux files LF 8 | mvnw text eol=lf 9 | .mvn/wrapper/maven-wrapper.properties text eol=lf 10 | -------------------------------------------------------------------------------- /.github/.lycheeignore: -------------------------------------------------------------------------------- 1 | # Ignorefile for broken link check 2 | localhost 3 | mvnrepository.com 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug 2 | description: Create a bug report for something that is broken 3 | labels: [bug] 4 | type: bug 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for reporting a bug. 10 | 11 | Please fill in as much information as possible about your bug so that we don't have to play "information ping-pong" and can help you immediately. 12 | 13 | - type: checkboxes 14 | id: checklist 15 | attributes: 16 | label: "Checklist" 17 | options: 18 | - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/vaadin-grid-exporter/releases/latest)" 19 | required: true 20 | - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/vaadin-grid-exporter/issues) or [closed](https://github.com/xdev-software/vaadin-grid-exporter/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." 21 | required: true 22 | - label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise." 23 | required: true 24 | - label: "This issue contains only one bug." 25 | required: true 26 | 27 | - type: input 28 | id: app-version 29 | attributes: 30 | label: Affected version 31 | description: "In which version did you encounter the bug?" 32 | placeholder: "x.x.x" 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | id: description 38 | attributes: 39 | label: Description of the problem 40 | description: | 41 | Describe as exactly as possible what is not working. 42 | validations: 43 | required: true 44 | 45 | - type: textarea 46 | id: steps-to-reproduce 47 | attributes: 48 | label: Steps to reproduce the bug 49 | description: | 50 | What did you do for the bug to show up? 51 | 52 | If you can't cause the bug to show up again reliably (and hence don't have a proper set of steps to give us), please still try to give as many details as possible on how you think you encountered the bug. 53 | placeholder: | 54 | 1. Use '...' 55 | 2. Do '...' 56 | validations: 57 | required: true 58 | 59 | - type: textarea 60 | id: additional-information 61 | attributes: 62 | label: Additional information 63 | description: | 64 | Any other relevant information you'd like to include 65 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: 💬 Contact support 3 | url: https://xdev.software/en/services/support 4 | about: "If you need support as soon as possible or/and you can't wait for any pull request" 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature/Enhancement 2 | description: Suggest a new feature or enhancement 3 | labels: [enhancement] 4 | type: feature 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for suggesting a new feature/enhancement. 10 | 11 | - type: checkboxes 12 | id: checklist 13 | attributes: 14 | label: "Checklist" 15 | options: 16 | - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/vaadin-grid-exporter/issues) or [closed](https://github.com/xdev-software/vaadin-grid-exporter/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." 17 | required: true 18 | - label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise." 19 | required: true 20 | - label: "This issue contains only one feature request/enhancement." 21 | required: true 22 | 23 | - type: textarea 24 | id: description 25 | attributes: 26 | label: Description 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | id: additional-information 32 | attributes: 33 | label: Additional information 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: ❓ Question 2 | description: Ask a question 3 | labels: [question] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to fill out this form! 9 | 10 | - type: checkboxes 11 | id: checklist 12 | attributes: 13 | label: "Checklist" 14 | options: 15 | - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/vaadin-grid-exporter/issues) or [closed](https://github.com/xdev-software/vaadin-grid-exporter/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." 16 | required: true 17 | - label: "I have taken the time to fill in all the required details. I understand that the question will be dismissed otherwise." 18 | required: true 19 | 20 | - type: textarea 21 | id: what-is-the-question 22 | attributes: 23 | label: What is/are your question(s)? 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | id: additional-information 29 | attributes: 30 | label: Additional information 31 | description: "Any other information you'd like to include - for instance logs, screenshots, etc." 32 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # Default 2 | ## Required for template 3 | - name: bug 4 | description: "Something isn't working" 5 | color: 'd73a4a' 6 | - name: enhancement 7 | description: New feature or request 8 | color: '#a2eeef' 9 | - name: question 10 | description: Information is requested 11 | color: '#d876e3' 12 | ## Others 13 | - name: duplicate 14 | description: This already exists 15 | color: '#cfd3d7' 16 | - name: good first issue 17 | description: Good for newcomers 18 | color: '#7057ff' 19 | - name: help wanted 20 | description: Extra attention is needed 21 | color: '#008672' 22 | - name: invalid 23 | description: "This doesn't seem right" 24 | color: '#e4e669' 25 | # Custom 26 | - name: automated 27 | description: Created by an automation 28 | color: '#000000' 29 | - name: "can't reproduce" 30 | color: '#e95f2c' 31 | - name: customer-requested 32 | description: Was requested by a customer of us 33 | color: '#068374' 34 | - name: stale 35 | color: '#ededed' 36 | - name: waiting-for-response 37 | description: If no response is received after a certain time the issue will be closed 38 | color: '#202020' 39 | -------------------------------------------------------------------------------- /.github/workflows/broken-links.yml: -------------------------------------------------------------------------------- 1 | name: Broken links 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "23 23 * * 0" 7 | 8 | permissions: 9 | issues: write 10 | 11 | jobs: 12 | link-checker: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 15 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - run: mv .github/.lycheeignore .lycheeignore 19 | 20 | - name: Link Checker 21 | id: lychee 22 | uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2 23 | with: 24 | fail: false # Don't fail on broken links, create an issue instead 25 | 26 | - name: Find already existing issue 27 | id: find-issue 28 | run: | 29 | echo "number=$(gh issue list -l 'bug' -l 'automated' -L 1 -S 'in:title \"Link Checker Report\"' -s 'open' --json 'number' --jq '.[].number')" >> $GITHUB_OUTPUT 30 | env: 31 | GH_TOKEN: ${{ github.token }} 32 | 33 | - name: Close issue if everything is fine 34 | if: env.lychee_exit_code == 0 && steps.find-issue.outputs.number != '' 35 | run: gh issue close -r 'not planned' ${{ steps.find-issue.outputs.number }} 36 | env: 37 | GH_TOKEN: ${{ github.token }} 38 | 39 | - name: Create Issue From File 40 | if: env.lychee_exit_code != 0 41 | uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd # v5 42 | with: 43 | issue-number: ${{ steps.find-issue.outputs.number }} 44 | title: Link Checker Report 45 | content-filepath: ./lychee/out.md 46 | labels: bug, automated 47 | -------------------------------------------------------------------------------- /.github/workflows/check-build.yml: -------------------------------------------------------------------------------- 1 | name: Check Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ develop ] 7 | paths-ignore: 8 | - '**.md' 9 | - '.config/**' 10 | - '.github/**' 11 | - '.idea/**' 12 | - 'assets/**' 13 | pull_request: 14 | branches: [ develop ] 15 | paths-ignore: 16 | - '**.md' 17 | - '.config/**' 18 | - '.github/**' 19 | - '.idea/**' 20 | - 'assets/**' 21 | 22 | env: 23 | PRIMARY_MAVEN_MODULE: ${{ github.event.repository.name }} 24 | DEMO_MAVEN_MODULE: ${{ github.event.repository.name }}-demo 25 | 26 | jobs: 27 | build: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 30 30 | 31 | strategy: 32 | matrix: 33 | java: [17, 21] 34 | distribution: [temurin] 35 | 36 | steps: 37 | - uses: actions/checkout@v4 38 | 39 | - name: Set up JDK 40 | uses: actions/setup-java@v4 41 | with: 42 | distribution: ${{ matrix.distribution }} 43 | java-version: ${{ matrix.java }} 44 | cache: 'maven' 45 | 46 | - name: Build with Maven 47 | run: ./mvnw -B clean package -Pproduction 48 | 49 | - name: Check for uncommited changes 50 | run: | 51 | if [[ "$(git status --porcelain)" != "" ]]; then 52 | echo ---------------------------------------- 53 | echo git status 54 | echo ---------------------------------------- 55 | git status 56 | echo ---------------------------------------- 57 | echo git diff 58 | echo ---------------------------------------- 59 | git diff 60 | echo ---------------------------------------- 61 | echo Troubleshooting 62 | echo ---------------------------------------- 63 | echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && ./mvnw -B clean package -Pproduction" 64 | exit 1 65 | fi 66 | 67 | - name: Upload demo files 68 | uses: actions/upload-artifact@v4 69 | with: 70 | name: demo-files-java-${{ matrix.java }} 71 | path: ${{ env.DEMO_MAVEN_MODULE }}/target/${{ env.DEMO_MAVEN_MODULE }}.jar 72 | if-no-files-found: error 73 | 74 | checkstyle: 75 | runs-on: ubuntu-latest 76 | if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} 77 | timeout-minutes: 15 78 | 79 | strategy: 80 | matrix: 81 | java: [17] 82 | distribution: [temurin] 83 | 84 | steps: 85 | - uses: actions/checkout@v4 86 | 87 | - name: Set up JDK 88 | uses: actions/setup-java@v4 89 | with: 90 | distribution: ${{ matrix.distribution }} 91 | java-version: ${{ matrix.java }} 92 | cache: 'maven' 93 | 94 | - name: Run Checkstyle 95 | run: ./mvnw -B checkstyle:check -P checkstyle -T2C 96 | 97 | pmd: 98 | runs-on: ubuntu-latest 99 | if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} 100 | timeout-minutes: 15 101 | 102 | strategy: 103 | matrix: 104 | java: [17] 105 | distribution: [temurin] 106 | 107 | steps: 108 | - uses: actions/checkout@v4 109 | 110 | - name: Set up JDK 111 | uses: actions/setup-java@v4 112 | with: 113 | distribution: ${{ matrix.distribution }} 114 | java-version: ${{ matrix.java }} 115 | cache: 'maven' 116 | 117 | - name: Run PMD 118 | run: ./mvnw -B test pmd:aggregate-pmd-no-fork pmd:check -P pmd -DskipTests -T2C 119 | 120 | - name: Run CPD (Copy Paste Detector) 121 | run: ./mvnw -B pmd:aggregate-cpd pmd:cpd-check -P pmd -DskipTests -T2C 122 | 123 | - name: Upload report 124 | if: always() 125 | uses: actions/upload-artifact@v4 126 | with: 127 | name: pmd-report 128 | if-no-files-found: ignore 129 | path: | 130 | target/reports/** 131 | -------------------------------------------------------------------------------- /.github/workflows/sonar.yml: -------------------------------------------------------------------------------- 1 | name: Sonar 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ develop ] 7 | paths-ignore: 8 | - '**.md' 9 | - '.config/**' 10 | - '.github/**' 11 | - '.idea/**' 12 | - 'assets/**' 13 | pull_request: 14 | branches: [ develop ] 15 | paths-ignore: 16 | - '**.md' 17 | - '.config/**' 18 | - '.github/**' 19 | - '.idea/**' 20 | - 'assets/**' 21 | 22 | env: 23 | SONARCLOUD_ORG: ${{ github.event.organization.login }} 24 | SONARCLOUD_HOST: https://sonarcloud.io 25 | 26 | jobs: 27 | token-check: 28 | runs-on: ubuntu-latest 29 | if: ${{ !(github.event_name == 'pull_request' && startsWith(github.head_ref, 'renovate/')) }} 30 | timeout-minutes: 5 31 | outputs: 32 | hasToken: ${{ steps.check-token.outputs.has }} 33 | steps: 34 | - id: check-token 35 | run: | 36 | [ -z $SONAR_TOKEN ] && echo "has=false" || echo "has=true" >> "$GITHUB_OUTPUT" 37 | env: 38 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 39 | 40 | sonar-scan: 41 | runs-on: ubuntu-latest 42 | needs: token-check 43 | if: ${{ needs.token-check.outputs.hasToken }} 44 | timeout-minutes: 30 45 | steps: 46 | - uses: actions/checkout@v4 47 | with: 48 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 49 | 50 | - name: Set up JDK 51 | uses: actions/setup-java@v4 52 | with: 53 | distribution: 'temurin' 54 | java-version: 17 55 | 56 | - name: Cache SonarCloud packages 57 | uses: actions/cache@v4 58 | with: 59 | path: ~/.sonar/cache 60 | key: ${{ runner.os }}-sonar 61 | restore-keys: ${{ runner.os }}-sonar 62 | 63 | - name: Cache Maven packages 64 | uses: actions/cache@v4 65 | with: 66 | path: ~/.m2 67 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 68 | restore-keys: ${{ runner.os }}-m2 69 | 70 | - name: Build with Maven 71 | run: | 72 | ./mvnw -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ 73 | -DskipTests \ 74 | -Dsonar.projectKey=${{ env.SONARCLOUD_ORG }}_${{ github.event.repository.name }} \ 75 | -Dsonar.organization=${{ env.SONARCLOUD_ORG }} \ 76 | -Dsonar.host.url=${{ env.SONARCLOUD_HOST }} 77 | env: 78 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 79 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 80 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync labels 2 | 3 | on: 4 | push: 5 | branches: develop 6 | paths: 7 | - .github/labels.yml 8 | 9 | workflow_dispatch: 10 | 11 | permissions: 12 | issues: write 13 | 14 | jobs: 15 | labels: 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 10 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | sparse-checkout: .github/labels.yml 22 | 23 | - uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2 24 | with: 25 | config-file: .github/labels.yml 26 | -------------------------------------------------------------------------------- /.github/workflows/test-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Test Deployment 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | env: 7 | PRIMARY_MAVEN_MODULE: ${{ github.event.repository.name }} 8 | 9 | jobs: 10 | publish-maven: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 60 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up JDK 17 | uses: actions/setup-java@v4 18 | with: # running setup-java again overwrites the settings.xml 19 | distribution: 'temurin' 20 | java-version: '17' 21 | server-id: sonatype-central-portal 22 | server-username: MAVEN_CENTRAL_USERNAME 23 | server-password: MAVEN_CENTRAL_TOKEN 24 | gpg-passphrase: MAVEN_GPG_PASSPHRASE 25 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} 26 | 27 | - name: Publish to Central Portal 28 | run: ../mvnw -B deploy -P publish-sonatype-central-portal -DskipTests 29 | working-directory: ${{ env.PRIMARY_MAVEN_MODULE }} 30 | env: 31 | MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_USERNAME }} 32 | MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_MAVEN_CENTRAL_PORTAL_TOKEN }} 33 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 12 | .mvn/wrapper/maven-wrapper.jar 13 | 14 | 15 | # Compiled class file 16 | *.class 17 | 18 | # Log file 19 | *.log 20 | 21 | # BlueJ files 22 | *.ctxt 23 | 24 | # Mobile Tools for Java (J2ME) 25 | .mtj.tmp/ 26 | 27 | # Package/Binary Files don't belong into a git repo 28 | *.jar 29 | *.war 30 | *.nar 31 | *.ear 32 | *.zip 33 | *.tar.gz 34 | *.rar 35 | *.dll 36 | *.exe 37 | *.bin 38 | 39 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 40 | hs_err_pid* 41 | 42 | # JRebel 43 | **/resources/rebel.xml 44 | **/resources/rebel-remote.xml 45 | 46 | # eclispe stuff for root 47 | /.settings/ 48 | /.classpath 49 | /.project 50 | 51 | 52 | # eclispe stuff for modules 53 | /*/.metadata/ 54 | /*/.apt_generated_tests/ 55 | /*/.settings/ 56 | /*/.classpath 57 | /*/.project 58 | /*/RemoteSystemsTempFiles/ 59 | 60 | 61 | #vaadin/node webpack/frontend stuff 62 | # Ignore Node 63 | node/ 64 | 65 | # The following files are generated/updated by vaadin-maven-plugin 66 | node_modules/ 67 | 68 | # Vaadin 69 | package.json 70 | package-lock.json 71 | webpack.generated.js 72 | webpack.config.js 73 | tsconfig.json 74 | types.d.ts 75 | vite.config.ts 76 | vite.generated.ts 77 | /*/src/main/frontend/generated/ 78 | /*/src/main/frontend/index.html 79 | /*/src/main/dev-bundle/ 80 | /*/src/main/bundles/ 81 | *.lock 82 | 83 | #custom 84 | .flattened-pom.xml 85 | .tern-project 86 | 87 | # == IntelliJ == 88 | *.iml 89 | *.ipr 90 | 91 | # Some files are user/installation independent and are used for configuring the IDE 92 | # See also https://stackoverflow.com/a/35279076 93 | 94 | .idea/* 95 | !.idea/saveactions_settings.xml 96 | !.idea/checkstyle-idea.xml 97 | !.idea/externalDependencies.xml 98 | 99 | !.idea/inspectionProfiles/ 100 | .idea/inspectionProfiles/* 101 | !.idea/inspectionProfiles/Project_Default.xml 102 | 103 | !.idea/codeStyles/ 104 | .idea/codeStyles/* 105 | !.idea/codeStyles/codeStyleConfig.xml 106 | !.idea/codeStyles/Project.xml 107 | -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10.21.0 5 | JavaOnlyWithTests 6 | true 7 | true 8 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 99 | 100 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/saveactions_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 18 | -------------------------------------------------------------------------------- /.run/Run Demo.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 3.2.7 2 | * Migrated deployment to _Sonatype Maven Central Portal_ [#155](https://github.com/xdev-software/standard-maven-template/issues/155) 3 | * Updated dependencies 4 | 5 | # 3.2.6 6 | * Fix naming so that Vaadin Directory sync works [#318](https://github.com/xdev-software/vaadin-addon-template/issues/318) 7 | * Updated dependencies 8 | 9 | # 3.2.5 10 | * Make it possible to better customize ``SpecificConfigComponent`` 11 | 12 | # 3.2.4 13 | * Updated dependencies 14 | 15 | # 3.2.3 16 | * Added dedicated method for adding steps to WizardPanel to make overriding it easier #269 17 | * Updated dependencies 18 | 19 | # 3.2.2 20 | * Fix column order being ignored #256 21 | 22 | # 3.2.1 23 | * Fix cells truncating data #229 24 | * Updated dependencies 25 | 26 | # 3.2.0 27 | * Updated to Vaadin 24.4 28 | 29 | # 3.1.0 30 | * Update to [JasperReports 7](https://github.com/xdev-software/dynamicreports-core-for-grid-exporter/blob/develop/CHANGELOG.md#200) 31 | * Updated dependencies 32 | 33 | # 3.0.3 34 | * ⚠️ GroupId changed from ``com.xdev-software`` to ``software.xdev`` 35 | * Updated dependencies 36 | 37 | # 3.0.2 38 | * Fixed not working translations on preview step #153 39 | * Updated dependencies 40 | 41 | # 3.0.1 42 | * Fixed compilation problems due to missing ``ecj`` dependency #98 43 | * Updated dependencies 44 | 45 | # 3.0.0 46 | ⚠️This release contains breaking changes 47 | 48 | * Adds support for Vaadin 24+, drops support for Vaadin 23
49 | If you are still using Vaadin 23, use the ``3.x`` versions. 50 | * Requires Java 17+ 51 | * Replaced the underlying reporting framework ``dynamicreports`` with [our fork of it](https://github.com/xdev-software/dynamicreports-core-for-grid-exporter) which is specially designed for this project 52 | * Differences from the original project are roughly described in the [changelog](https://github.com/xdev-software/dynamicreports-core-for-grid-exporter/blob/develop/CHANGELOG.md). 53 | * Removed ``XML`` from the default formats because the exported data was unusable 54 | * Replaced ``VaadinInternalRenderingColumnHeaderResolvingStrategy`` with ``VaadinColumnHeaderResolvingStrategy`` 55 | * Updated dependencies 56 | 57 | # 2.0.0 58 | * Undocked from RapidClipse 59 | * Changed package from ``com.rapidclipse.framework.server.reports`` to ``software.xdev.vaadin.grid_exporter`` 60 | * Restructured the UI 61 | * Using a step-by-step-wizard like layout 62 | * Made formats configurable via UI 63 | * Refactored software architecture to make the component more expandable 64 | * Removed ``XLS`` from default formats due to not included dependency which causes a crash (``XLSX`` still works) 65 | * Updated dependencies 66 | 67 | Example usage: 68 | 69 | | v1 | v2 | 70 | | --- | --- | 71 | | ``GridExportDialog.open(grid)`` | ``GridExporter.newWithDefaults(grid).open()`` | 72 | 73 | # 1.0.3 74 | * Removed unused code 75 | 76 | # 1.0.2 77 | * Updated dependencies 78 | * Vaadin 23.2 79 | 80 | # 1.0.1 81 | * Removed unnecessary code and dependencies; Updated jasperreports to latest version 82 | 83 | # 1.0.0 84 | Initial release 85 | 86 | * Forked project from the RapidClipse Framework (Version 11.0) 87 | * Updated to Vaadin 23 88 | * Removed unnecessary code and dependencies 89 | * Removed requirement that Grid columns need keys 90 | * Reworked localization - can now be explicitly set using ``GridExportLocalizationConfig`` 91 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | We would absolutely love to get the community involved, and we welcome any form of contributions – comments and questions on different communication channels, issues and pull request and anything that you build and share using our components. 4 | 5 | ### Communication channels 6 | * Communication is primarily done using issues. 7 | * If you need support as soon as possible and you can't wait for any pull request, feel free to use [our support](https://xdev.software/en/services/support). 8 | * As a last resort measure or on otherwise important matter you may also [contact us directly](https://xdev.software/en/about-us/contact). 9 | 10 | ### Ways to help 11 | * **Report bugs**
Create an issue or send a pull request 12 | * **Send pull requests**
If you want to contribute code, check out the development instructions below. 13 | * However when contributing larger new features, please first discuss the change you wish to make via issue with the owners of this repository before making it.
Otherwise your work might be rejected and your effort was pointless. 14 | 15 | We also encourage you to read the [contribution instructions by GitHub](https://docs.github.com/en/get-started/quickstart/contributing-to-projects). 16 | 17 | ## Developing 18 | 19 | ### Software Requirements 20 | You should have the following things installed: 21 | * Git 22 | * Java 21 - should be as unmodified as possible (Recommended: [Eclipse Adoptium](https://adoptium.net/temurin/releases/)) 23 | * Maven (Note that the [Maven Wrapper](https://maven.apache.org/wrapper/) is shipped with the repo) 24 | 25 | ### Recommended setup 26 | * Install ``IntelliJ`` (Community Edition is sufficient) 27 | * Install the following plugins: 28 | * [Save Actions](https://plugins.jetbrains.com/plugin/22113) - Provides save actions, like running the formatter or adding ``final`` to fields 29 | * [SonarLint](https://plugins.jetbrains.com/plugin/7973-sonarlint) - CodeStyle/CodeAnalysis 30 | * You may consider disabling telemetry in the settings under ``Tools > Sonarlint -> About`` 31 | * [Checkstyle-IDEA](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) - CodeStyle/CodeAnalysis 32 | * Import the project 33 | * Ensure that everything is encoded in ``UTF-8`` 34 | * Ensure that the JDK/Java-Version is correct 35 | * To enable AUTOMATIC reloading/restarting while developing and running the app do this (further information in " 36 | SpringBoot-Devtools" section below; [Source](https://stackoverflow.com/q/33349456)): 37 | * ``Settings > Build, Execution, Deployment > Compiler``:
38 | Enable [``Build project automatically``](https://www.jetbrains.com/help/idea/compiling-applications.html#auto-build) 39 | * ``Settings > Advanced Settings``:
40 | Enable [``Allow auto-make to start even if developed application is currently running``](https://www.jetbrains.com/help/idea/advanced-settings.html#advanced_compiler) 41 | * To launch the Demo execute the predefined (launch) configuration ``Run Demo`` 42 | 43 | #### [SpringBoot-Developer-Tools](https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.devtools) 44 | ... should automatically be enabled.
45 | If you are changing a file and build the project, parts of the app get restarted.
46 | Bigger changes may require a complete restart. 47 | * [Vaadin automatically reloads the UI on each restart](https://vaadin.com/docs/latest/configuration/live-reload/spring-boot).
48 | You can control this behavior with the ``vaadin.devmode.liveReload.enabled`` property (default: ``true``). 49 | 50 | ## Releasing [![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/vaadin-grid-exporter/release.yml?branch=master)](https://github.com/xdev-software/vaadin-grid-exporter/actions/workflows/release.yml) 51 | 52 | Before releasing: 53 | * Consider doing a [test-deployment](https://github.com/xdev-software/vaadin-grid-exporter/actions/workflows/test-deploy.yml?query=branch%3Adevelop) before actually releasing. 54 | * Check the [changelog](CHANGELOG.md) 55 | 56 | If the ``develop`` is ready for release, create a pull request to the ``master``-Branch and merge the changes 57 | 58 | When the release is finished do the following: 59 | * Merge the auto-generated PR (with the incremented version number) back into the ``develop`` 60 | * Ensure that [Vaadin Directory](https://vaadin.com/directory) syncs the update and maybe update the component / version there 61 | 62 | ### Release failures 63 | 64 | There are 2 modes of release failure: 65 | 1. The remote server was e.g. down and non of the artifacts got published 66 | 2. There was a build failure during release and only parts of the artifacts got released 67 | 68 | In case 1 we can re-release the existing version,
in case 2 we have to release a new version when we can't get the artifacts deleted (as is the case with Maven Central) 69 | 70 | #### How-to: Re-Releasing an existing version 71 | 72 | 1. Delete the release on GitHub 73 | 2. Delete the release Git tag from the repo (locally and remote!) 74 | 3. Delete the ``master``-Branch and re-create it from the ``develop`` branch (or reset it to the state before the release-workflow commits have been done) 75 | * This requires __temporarily__ removing the branch protection 76 | * Once this was done a new release is triggered immediately! 77 | 78 | #### How-to: Releasing a new version 79 | 80 | 1. Merge the ``master`` branch back into ``develop`` (or another temporary branch) 81 | 2. Make sure all master branch versions are prepared for a new release
e.g. if the broken release was ``1.0.0`` the version should now be at ``1.0.1-SNAPSHOT`` - the ``SNAPSHOT`` is important for the workflow! 82 | 3. Mark the broken release as broken e.g. inside the Changelog, GitHub Release page, etc.
83 | You can use something like this: 84 | ``` 85 | > [!WARNING] 86 | > This release is broken as my cat accidentally clicked the abort button during the process 87 | ``` 88 | 4. Merge the changes back into the ``master`` branch to trigger a new release 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Published on Vaadin Directory](https://img.shields.io/badge/Vaadin%20Directory-published-00b4f0?logo=vaadin)](https://vaadin.com/directory/component/gridexporter-for-vaadin) 2 | [![Latest version](https://img.shields.io/maven-central/v/software.xdev/vaadin-grid-exporter?logo=apache%20maven)](https://mvnrepository.com/artifact/software.xdev/vaadin-grid-exporter) 3 | [![Build](https://img.shields.io/github/actions/workflow/status/xdev-software/vaadin-grid-exporter/check-build.yml?branch=develop)](https://github.com/xdev-software/vaadin-grid-exporter/actions/workflows/check-build.yml?query=branch%3Adevelop) 4 | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=xdev-software_vaadin-grid-exporter&metric=alert_status)](https://sonarcloud.io/dashboard?id=xdev-software_vaadin-grid-exporter) 5 | ![Vaadin 24+](https://img.shields.io/badge/Vaadin%20Platform/Flow-24+-00b4f0) 6 | 7 | # GridExporter for Vaadin 8 | 9 | The Vaadin Grid Exporter can convert nearly any Vaadin Grid to a variety of formats.
10 | This way you don't have to copy the Grid contents manually or print the whole website with the Grid. 11 | 12 | Out of the box supported formats: 13 | * CSV 14 | * Word (DOCX) 15 | * HTML 16 | * ODS 17 | * ODT 18 | * PDF 19 | * PowerPoint (PPTX) 20 | * RTF 21 | * Plain text 22 | * Excel (XLSX) 23 | 24 | _These formats are exported using [dynamicreports](https://github.com/xdev-software/dynamicreports-core-for-grid-exporter)._ 25 | 26 | It's also easy to extend the Exporter to support your custom format. 27 | 28 | ![demo](assets/preview.gif) 29 | 30 | > [!NOTE] 31 | >
Disclaimer about the scope of this component (click to expand) 32 | > 33 | > Although the GridExporter can handle most use-cases, extreme scenarios will likely impact performance, usability and might require some hacks.
34 | > For such cases custom written exports are recommended e.g. by utilizing JasperReports directly.
35 | > If you need help implementing these feel free to [contact us](#support) or open a [question](https://github.com/xdev-software/vaadin-grid-exporter/issues/new?assignees=&labels=question&projects=&template=question.yml) if you are not sure that the GridExporter is a good option for your scenario. 36 | > 37 | >
38 | 39 | ## Usage 40 | 41 | Default usage: 42 | 43 | ```java 44 | GridExporter 45 | .newWithDefaults(this.grExamples) 46 | .open(); 47 | ``` 48 | 49 | Custom format (see [JsonGridExporterProvider from Demo](vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/jsonext/JsonGridExporterProvider.java)): 50 | 51 | ```java 52 | GridExporter 53 | .newWithDefaults(this.grExamples) 54 | .loadFromProvider(new JsonGridExporterProvider()) 55 | .open(); 56 | ``` 57 | 58 | ## Installation 59 | 60 | [Installation guide for the latest release](https://github.com/xdev-software/vaadin-grid-exporter/releases/latest#Installation) 61 | 62 | ### Comaptibility with ``CSP`` (Content-Security-Policy) and ``X-Frame-Options`` 63 | 64 | > [!TIP] 65 | > In Spring Security the [default value of ``X-Frame-Options`` is ``DENY``](https://docs.spring.io/spring-security/reference/features/exploits/headers.html#headers-frame-options) which will break the preview if not changed. 66 | 67 | To show the preview the [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) or the [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) (deprecated in favor of CSP) must be configured in a way that they allow showing same-site elements. 68 | 69 | This can be achieved by: 70 | * setting the CSP to include at least ``frame-ancestors 'self'`` and maybe additionally ``object-src 'self'`` 71 | * setting ``X-Frame-Options`` to ``SAMESITE``.
If you use Spring Security without a CSP the easiest way to set this is: 72 | ```java 73 | http.headers(c -> c.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)); 74 | ``` 75 | 76 | > [!NOTE] 77 | > Depending on the browser the settings sometimes have slightly different effects.
78 | > For example Firefox blocks the preview due to privacy reasons when ``X-Frame-Option=DENY`` and ``Content-Security-Policy=frame-ancestors 'self'; object-src 'self'; ...`` but Chrome does not. 79 | 80 | ### Compatibility with Vaadin 81 | 82 | | Vaadin version | GridExporter version | 83 | | --- | --- | 84 | | Vaadin 24+ (latest) | ``3+`` | 85 | | Vaadin 23 | ``2.x`` | 86 | 87 | ### Compatibility with JasperReports 88 | 89 | Starting with version [3.1.0](./CHANGELOG.md#310) JasperReports 7 is required. 90 | 91 | ### Spring-Boot 92 | * You may have to include ``software/xdev`` inside [``vaadin.allowed-packages``](https://vaadin.com/docs/latest/integrations/spring/configuration#configure-the-scanning-of-packages) 93 | 94 | ## Run the Demo 95 | * Checkout the repo 96 | * Run ``mvn install && mvn -f vaadin-grid-exporter-demo spring-boot:run`` 97 | * Open http://localhost:8080 98 | 99 |
100 | Show example 101 | 102 | ![demo](assets/demo.avif) 103 |
104 | 105 | ## Support 106 | If you need support as soon as possible and you can't wait for any pull request, feel free to use [our support](https://xdev.software/en/services/support). 107 | 108 | ## Contributing 109 | See the [contributing guide](./CONTRIBUTING.md) for detailed instructions on how to get started with our project. 110 | 111 | ## Dependencies and Licenses 112 | View the [license of the current project](LICENSE) or the [summary including all dependencies](https://xdev-software.github.io/vaadin-grid-exporter/dependencies) 113 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report a security vulnerability [on GitHub Security Advisories](https://github.com/xdev-software/vaadin-grid-exporter/security/advisories/new). 6 | -------------------------------------------------------------------------------- /assets/demo.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdev-software/vaadin-grid-exporter/0482ab482093e0c17e07ebcb8dcb02103c6d3a13/assets/demo.avif -------------------------------------------------------------------------------- /assets/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdev-software/vaadin-grid-exporter/0482ab482093e0c17e07ebcb8dcb02103c6d3a13/assets/preview.gif -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | software.xdev 8 | vaadin-grid-exporter-root 9 | 3.2.8-SNAPSHOT 10 | pom 11 | 12 | 13 | XDEV Software 14 | https://xdev.software 15 | 16 | 17 | 18 | vaadin-grid-exporter 19 | vaadin-grid-exporter-demo 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 26 | 27 | 28 | 29 | Apache-2.0 30 | https://www.apache.org/licenses/LICENSE-2.0.txt 31 | repo 32 | 33 | 34 | 35 | 36 | 37 | checkstyle 38 | 39 | 40 | 41 | org.apache.maven.plugins 42 | maven-checkstyle-plugin 43 | 3.6.0 44 | 45 | 46 | com.puppycrawl.tools 47 | checkstyle 48 | 10.24.0 49 | 50 | 51 | 52 | .config/checkstyle/checkstyle.xml 53 | true 54 | 55 | 56 | 57 | 58 | check 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | pmd 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-pmd-plugin 73 | 3.26.0 74 | 75 | true 76 | true 77 | 78 | .config/pmd/ruleset.xml 79 | 80 | 81 | 82 | 83 | net.sourceforge.pmd 84 | pmd-core 85 | 7.13.0 86 | 87 | 88 | net.sourceforge.pmd 89 | pmd-java 90 | 7.13.0 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | org.apache.maven.plugins 101 | maven-jxr-plugin 102 | 3.6.0 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "rebaseWhen": "behind-base-branch", 4 | "packageRules": [ 5 | { 6 | "description": "Ignore project internal dependencies", 7 | "packagePattern": "^software.xdev:vaadin-grid-exporter", 8 | "datasources": [ 9 | "maven" 10 | ], 11 | "enabled": false 12 | }, 13 | { 14 | "description": "Group net.sourceforge.pmd", 15 | "matchPackagePatterns": [ 16 | "^net.sourceforge.pmd" 17 | ], 18 | "datasources": [ 19 | "maven" 20 | ], 21 | "groupName": "net.sourceforge.pmd" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | software.xdev 9 | vaadin-grid-exporter-root 10 | 3.2.8-SNAPSHOT 11 | 12 | 13 | vaadin-grid-exporter-demo 14 | 3.2.8-SNAPSHOT 15 | jar 16 | 17 | 18 | XDEV Software 19 | https://xdev.software 20 | 21 | 22 | 23 | 17 24 | ${javaVersion} 25 | 26 | UTF-8 27 | UTF-8 28 | 29 | software.xdev.vaadin.Application 30 | 31 | 32 | 24.7.4 33 | 34 | 3.4.5 35 | 36 | 37 | 38 | 39 | 40 | com.vaadin 41 | vaadin-bom 42 | pom 43 | import 44 | ${vaadin.version} 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-dependencies 53 | ${org.springframework.boot.version} 54 | pom 55 | import 56 | 57 | 58 | 59 | 60 | 61 | 62 | com.vaadin 63 | vaadin-core 64 | 65 | 66 | com.vaadin 67 | hilla-dev 68 | 69 | 70 | 71 | 72 | software.xdev 73 | vaadin-grid-exporter 74 | ${project.version} 75 | 76 | 77 | 78 | 79 | com.vaadin 80 | vaadin-spring-boot-starter 81 | 82 | 83 | com.vaadin 84 | hilla 85 | 86 | 87 | 88 | 89 | 90 | org.yaml 91 | snakeyaml 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-devtools 96 | true 97 | 98 | 99 | 100 | 101 | com.fasterxml.jackson.core 102 | jackson-databind 103 | 104 | 105 | 106 | 107 | ${project.artifactId} 108 | 109 | 110 | 111 | 112 | org.springframework.boot 113 | spring-boot-maven-plugin 114 | ${org.springframework.boot.version} 115 | 116 | 117 | 118 | 119 | 120 | 121 | com.vaadin 122 | vaadin-maven-plugin 123 | ${vaadin.version} 124 | 125 | 126 | 127 | prepare-frontend 128 | 129 | 130 | 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-compiler-plugin 135 | 3.14.0 136 | 137 | ${maven.compiler.release} 138 | 139 | -proc:none 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | production 149 | 150 | 151 | 152 | com.vaadin 153 | vaadin-core 154 | 155 | 156 | com.vaadin 157 | vaadin-dev 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | com.vaadin 166 | vaadin-maven-plugin 167 | ${vaadin.version} 168 | 169 | 170 | 171 | prepare-frontend 172 | build-frontend 173 | 174 | 175 | 176 | 177 | 178 | org.springframework.boot 179 | spring-boot-maven-plugin 180 | 181 | ${mainClass} 182 | 183 | 184 | 185 | repackage 186 | 187 | repackage 188 | 189 | package 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/Application.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 6 | 7 | import com.vaadin.flow.component.page.AppShellConfigurator; 8 | import com.vaadin.flow.component.page.Push; 9 | import com.vaadin.flow.spring.annotation.EnableVaadin; 10 | 11 | 12 | @SuppressWarnings({"checkstyle:HideUtilityClassConstructor", "PMD.UseUtilityClass"}) 13 | @SpringBootApplication 14 | @EnableVaadin 15 | @Push 16 | public class Application extends SpringBootServletInitializer implements AppShellConfigurator 17 | { 18 | public static void main(final String[] args) 19 | { 20 | SpringApplication.run(Application.class, args); 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/DemoView.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example; 2 | 3 | import com.vaadin.flow.component.AttachEvent; 4 | import com.vaadin.flow.component.Composite; 5 | import com.vaadin.flow.component.button.Button; 6 | import com.vaadin.flow.component.grid.Grid; 7 | import com.vaadin.flow.component.grid.GridVariant; 8 | import com.vaadin.flow.component.icon.VaadinIcon; 9 | import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 10 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 11 | import com.vaadin.flow.data.renderer.ComponentRenderer; 12 | import com.vaadin.flow.router.PageTitle; 13 | import com.vaadin.flow.router.Route; 14 | 15 | import software.xdev.vaadin.grid_exporter.GridExportLocalizationConfig; 16 | import software.xdev.vaadin.grid_exporter.GridExporter; 17 | import software.xdev.vaadin.grid_exporter.jasper.config.JasperConfigsLocalization; 18 | import software.xdev.vaadin.gridexport.example.jsonext.JsonGridExporterProvider; 19 | import software.xdev.vaadin.gridexport.example.pre_defined_title.PredefinedTitleProvider; 20 | 21 | 22 | @PageTitle("GridExport Examples") 23 | @Route("") 24 | public class DemoView extends Composite 25 | { 26 | private final Grid grExamples = new Grid<>(); 27 | 28 | public DemoView() 29 | { 30 | final HorizontalLayout hlButtonContainer = new HorizontalLayout(); 31 | hlButtonContainer.setPadding(false); 32 | hlButtonContainer.add( 33 | new Button( 34 | "Export", 35 | VaadinIcon.PRINT.create(), 36 | e -> GridExporter.newWithDefaults(this.grExamples) 37 | .open()), 38 | new Button( 39 | "Export (German translation)", 40 | VaadinIcon.PRINT.create(), 41 | e -> GridExporter.newWithDefaults(this.grExamples) 42 | .withLocalizationConfig(germanLocalizationConfig()) 43 | .open()), 44 | new Button( 45 | "Export (JSON)", 46 | VaadinIcon.PRINT.create(), 47 | e -> GridExporter.newWithDefaults(this.grExamples) 48 | .loadFromProvider(new JsonGridExporterProvider()) 49 | .open()), 50 | new Button( 51 | "Export (Predefined title)", 52 | VaadinIcon.PRINT.create(), 53 | e -> new GridExporter<>(this.grExamples) 54 | .loadFromProvider(new PredefinedTitleProvider("Custom title!")) 55 | .open()) 56 | ); 57 | 58 | this.grExamples 59 | .addColumn(Example::route) 60 | .setHeader("Route") 61 | .setFlexGrow(1); 62 | 63 | this.grExamples 64 | .addColumn(Example::name) 65 | .setHeader("Name") 66 | .setFlexGrow(1); 67 | 68 | this.grExamples 69 | .addColumn(Example::desc) 70 | .setHeader("Description") 71 | .setFlexGrow(1); 72 | 73 | this.grExamples 74 | .addColumn(new ComponentRenderer<>(x -> new Button("Dummy open button"))) 75 | .setAutoWidth(true) 76 | .setFlexGrow(0); 77 | 78 | this.grExamples.setSizeFull(); 79 | this.grExamples.addThemeVariants(GridVariant.LUMO_COMPACT); 80 | 81 | this.getContent().add( 82 | hlButtonContainer, 83 | this.grExamples); 84 | this.getContent().setHeightFull(); 85 | } 86 | 87 | @Override 88 | protected void onAttach(final AttachEvent attachEvent) 89 | { 90 | this.grExamples.setItems( 91 | new Example("styled", "Styled-Demo", "dark mode 🌑 and more"), 92 | new Example("parameter", "Parameter-Demo", "configuration is stored in QueryParameters"), 93 | new Example("localized", "Localized-Demo", "🌐 simple localization"), 94 | new Example("customized", "Customized-Demo", "usage of a customized DateRange") 95 | ); 96 | } 97 | 98 | record Example(String route, String name, String desc) 99 | { 100 | } 101 | 102 | static GridExportLocalizationConfig germanLocalizationConfig() 103 | { 104 | return new GridExportLocalizationConfig() 105 | .with(GridExportLocalizationConfig.EXPORT_GRID, "Tabelle exportieren") 106 | .with(GridExportLocalizationConfig.CANCEL, "Abbrechen") 107 | .with(GridExportLocalizationConfig.PREVIOUS, "Zurück") 108 | .with(GridExportLocalizationConfig.NEXT, "Weiter") 109 | .with(GridExportLocalizationConfig.DOWNLOAD, "Herunterladen") 110 | .with(GridExportLocalizationConfig.GENERAL, "Generell") 111 | .with(GridExportLocalizationConfig.FILENAME, "Dateiname") 112 | .with(GridExportLocalizationConfig.COLUMNS, "Spalten") 113 | .with(GridExportLocalizationConfig.NAME, "Name") 114 | .with(GridExportLocalizationConfig.POSITION, "Position") 115 | .with(GridExportLocalizationConfig.ALREADY_PRESENT, "Bereits vorhanden") 116 | .with(GridExportLocalizationConfig.FORMAT, "Format") 117 | .with(GridExportLocalizationConfig.PREVIEW, "Vorschau") 118 | .with(GridExportLocalizationConfig.UNABLE_TO_SHOW_PREVIEW, "Vorschau kann nicht angezeigt werden") 119 | .with(JasperConfigsLocalization.ENCODING, "Enkodierung") 120 | .with(JasperConfigsLocalization.WITH_BOM, "mit BOM") 121 | .with(JasperConfigsLocalization.HEADER, "Header") 122 | .with(JasperConfigsLocalization.EXPORT_HEADER, "Kopfzeilen exportieren") 123 | .with(JasperConfigsLocalization.HIGHLIGHTING, "Hervorhebungen") 124 | .with(JasperConfigsLocalization.HIGHLIGHT_ROWS, "Zeilen hervorheben") 125 | .with(JasperConfigsLocalization.PAGE, "Seite") 126 | .with(JasperConfigsLocalization.FORMAT_PAGE_TYPE, "Format / Seitentyp") 127 | .with(JasperConfigsLocalization.ORIENTATION, "Orientierung") 128 | .with(JasperConfigsLocalization.ORIENTATION_PORTRAIT, "Hochformat") 129 | .with(JasperConfigsLocalization.ORIENTATION_LANDSCAPE, "Querformat") 130 | .with(JasperConfigsLocalization.SHOW_PAGE_NUMBERS, "Seitennummerierung") 131 | .with(JasperConfigsLocalization.MARGIN, "Rand") 132 | .with(JasperConfigsLocalization.SEPARATOR, "Trennzeichen") 133 | .with(JasperConfigsLocalization.TITLE, "Titel"); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/jsonext/JsonConfig.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example.jsonext; 2 | 3 | import software.xdev.vaadin.grid_exporter.format.SpecificConfig; 4 | 5 | 6 | public class JsonConfig implements SpecificConfig 7 | { 8 | protected boolean usePrettyPrint = true; 9 | 10 | protected boolean withKeys = true; 11 | 12 | public boolean isUsePrettyPrint() 13 | { 14 | return this.usePrettyPrint; 15 | } 16 | 17 | public void setUsePrettyPrint(final boolean usePrettyPrint) 18 | { 19 | this.usePrettyPrint = usePrettyPrint; 20 | } 21 | 22 | public boolean isWithKeys() 23 | { 24 | return this.withKeys; 25 | } 26 | 27 | public void setWithKeys(final boolean withKeys) 28 | { 29 | this.withKeys = withKeys; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/jsonext/JsonConfigComponent.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example.jsonext; 2 | 3 | import static java.util.Map.entry; 4 | 5 | import java.util.Map; 6 | 7 | import com.vaadin.flow.component.checkbox.Checkbox; 8 | 9 | import software.xdev.vaadin.grid_exporter.Translator; 10 | import software.xdev.vaadin.grid_exporter.format.SpecificConfigComponent; 11 | 12 | 13 | public class JsonConfigComponent extends SpecificConfigComponent 14 | { 15 | public static final String JSON = "json"; 16 | 17 | public static final String USE_PRETTY_PRINT = "use_pretty_print"; 18 | 19 | public static final String WITH_KEYS = "with_keys"; 20 | 21 | // Key, Default Value 22 | public static final Map DEFAULT_VALUES = Map.ofEntries( 23 | entry(JSON, "JSON"), 24 | entry(USE_PRETTY_PRINT, "Use pretty print"), 25 | entry(WITH_KEYS, "Export with keys") 26 | ); 27 | 28 | protected final Checkbox chbxUsePrettyPrint = new Checkbox(); 29 | 30 | protected final Checkbox chbxWithKeys = new Checkbox(); 31 | 32 | protected JsonConfigComponent(final Translator translator) 33 | { 34 | super(translator, JsonConfig::new, JSON); 35 | 36 | this.initUI(); 37 | 38 | this.registerBindings(); 39 | } 40 | 41 | protected void initUI() 42 | { 43 | this.chbxUsePrettyPrint.setLabel(this.translate(USE_PRETTY_PRINT)); 44 | 45 | this.chbxWithKeys.setLabel(this.translate(WITH_KEYS)); 46 | 47 | this.getContent().add(this.chbxUsePrettyPrint, this.chbxWithKeys); 48 | } 49 | 50 | protected void registerBindings() 51 | { 52 | this.binder.forField(this.chbxUsePrettyPrint) 53 | .bind(JsonConfig::isUsePrettyPrint, JsonConfig::setUsePrettyPrint); 54 | 55 | this.binder.forField(this.chbxWithKeys) 56 | .bind(JsonConfig::isWithKeys, JsonConfig::setWithKeys); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/jsonext/JsonFormat.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example.jsonext; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.ObjectWriter; 9 | 10 | import software.xdev.vaadin.grid_exporter.column.ColumnConfiguration; 11 | import software.xdev.vaadin.grid_exporter.format.AbstractFormat; 12 | import software.xdev.vaadin.grid_exporter.format.SpecificConfig; 13 | import software.xdev.vaadin.grid_exporter.grid.GridDataExtractor; 14 | 15 | 16 | public class JsonFormat extends AbstractFormat 17 | { 18 | public JsonFormat() 19 | { 20 | super("JSON", "json", "application/json"); 21 | this.withConfigComponents( 22 | JsonConfigComponent::new 23 | ); 24 | } 25 | 26 | @SuppressWarnings("java:S112") // IDK 27 | @Override 28 | public byte[] export( 29 | final GridDataExtractor gridDataExtractor, 30 | final List> columnsToExport, 31 | final List configs) 32 | { 33 | final ObjectMapper mapper = new ObjectMapper(); 34 | // pretty writer 35 | final ObjectWriter writer = 36 | this.getValueFrom(configs, JsonConfig.class, JsonConfig::isUsePrettyPrint) 37 | .orElse(false) 38 | ? mapper.writerWithDefaultPrettyPrinter() 39 | : mapper.writer(); 40 | 41 | try 42 | { 43 | final List> rowData = 44 | gridDataExtractor.getSortedAndFilteredData(columnsToExport); 45 | return writer.writeValueAsBytes( 46 | this.getValueFrom(configs, JsonConfig.class, JsonConfig::isWithKeys) 47 | .orElse(false) 48 | // Create a key-value Map 49 | ? rowData.stream() 50 | .map(list -> columnsToExport.stream().collect(Collectors.toMap( 51 | ColumnConfiguration::getHeader, 52 | i -> list.get(columnsToExport.indexOf(i)))) 53 | ) 54 | .toList() 55 | : rowData); 56 | } 57 | catch(final JsonProcessingException e) 58 | { 59 | throw new RuntimeException(e); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/jsonext/JsonGridExporterProvider.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example.jsonext; 2 | 3 | import software.xdev.vaadin.grid_exporter.GridExporterProvider; 4 | 5 | 6 | public class JsonGridExporterProvider extends GridExporterProvider 7 | { 8 | public JsonGridExporterProvider() 9 | { 10 | super(JsonConfigComponent.DEFAULT_VALUES, new JsonFormat()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/java/software/xdev/vaadin/gridexport/example/pre_defined_title/PredefinedTitleProvider.java: -------------------------------------------------------------------------------- 1 | package software.xdev.vaadin.gridexport.example.pre_defined_title; 2 | 3 | import java.util.List; 4 | 5 | import software.xdev.dynamicreports.jasper.builder.JasperReportBuilder; 6 | import software.xdev.dynamicreports.jasper.builder.export.Exporters; 7 | import software.xdev.dynamicreports.jasper.builder.export.JasperPdfExporterBuilder; 8 | import software.xdev.vaadin.grid_exporter.GridExporterProvider; 9 | import software.xdev.vaadin.grid_exporter.Translator; 10 | import software.xdev.vaadin.grid_exporter.jasper.config.JasperConfigsLocalization; 11 | import software.xdev.vaadin.grid_exporter.jasper.config.header.HeaderConfigComponent; 12 | import software.xdev.vaadin.grid_exporter.jasper.config.highlight.HighlightConfigComponent; 13 | import software.xdev.vaadin.grid_exporter.jasper.config.page.PageConfigComponent; 14 | import software.xdev.vaadin.grid_exporter.jasper.config.title.TitleConfig; 15 | import software.xdev.vaadin.grid_exporter.jasper.config.title.TitleConfigComponent; 16 | import software.xdev.vaadin.grid_exporter.jasper.format.AbstractJasperReportFormat; 17 | 18 | 19 | public class PredefinedTitleProvider extends GridExporterProvider 20 | { 21 | public PredefinedTitleProvider(final String predefinedTitle) 22 | { 23 | super( 24 | JasperConfigsLocalization.DEFAULT_VALUES, 25 | List.of( 26 | new PredefinedTitlePdfFormat(predefinedTitle) 27 | )); 28 | } 29 | 30 | public static class PredefinedTitlePdfFormat extends AbstractJasperReportFormat 31 | { 32 | public PredefinedTitlePdfFormat(final String defaultTitle) 33 | { 34 | super( 35 | "PDF", 36 | "pdf", 37 | "application/pdf", 38 | true, 39 | true, 40 | JasperReportBuilder::toPdf, 41 | Exporters::pdfExporter 42 | ); 43 | this.withConfigComponents( 44 | translator -> new PreDefinedTitleConfigComponent(translator, defaultTitle), 45 | HeaderConfigComponent::new, 46 | HighlightConfigComponent::new, 47 | PageConfigComponent::new 48 | ); 49 | } 50 | } 51 | 52 | 53 | public static class PreDefinedTitleConfigComponent extends TitleConfigComponent 54 | { 55 | public PreDefinedTitleConfigComponent(final Translator translator, final String defaultTitle) 56 | { 57 | super(translator); 58 | this.setNewConfigSupplier(() -> { 59 | final TitleConfig titleConfig = new TitleConfig(); 60 | titleConfig.setTitle(defaultTitle); 61 | return titleConfig; 62 | }); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /vaadin-grid-exporter-demo/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | vaadin: 2 | allowed-packages: software/xdev,com/vaadin/flow 3 | devmode: 4 | usageStatistics: 5 | enabled: false 6 | 7 | spring: 8 | devtools: 9 | restart: 10 | poll-interval: 2s 11 | quiet-period: 1s 12 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/GridExportLocalizationConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter; 17 | 18 | import static java.util.Map.entry; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.function.BiFunction; 23 | 24 | import com.vaadin.flow.component.Component; 25 | 26 | 27 | /** 28 | * Makes i18n possible for the component. As defaults the english language is used. 29 | */ 30 | public class GridExportLocalizationConfig 31 | { 32 | public static final String PREFIX = "gridexporter."; 33 | 34 | public static final String EXPORT_GRID = PREFIX + "export_grid"; 35 | 36 | public static final String CANCEL = PREFIX + "cancel"; 37 | public static final String PREVIOUS = PREFIX + "previous"; 38 | public static final String NEXT = PREFIX + "next"; 39 | public static final String DOWNLOAD = PREFIX + "download"; 40 | 41 | public static final String GENERAL = PREFIX + "general"; 42 | public static final String FILENAME = PREFIX + "filename"; 43 | public static final String COLUMNS = PREFIX + "columns"; 44 | public static final String NAME = PREFIX + "name"; 45 | public static final String POSITION = PREFIX + "position"; 46 | public static final String ALREADY_PRESENT = PREFIX + "already_present"; 47 | 48 | public static final String FORMAT = PREFIX + "format"; 49 | 50 | public static final String PREVIEW = PREFIX + "preview"; 51 | 52 | public static final String UNABLE_TO_SHOW_PREVIEW = PREFIX + "unable_to_show_preview"; 53 | 54 | // Key, Default Value 55 | public static final Map DEFAULT_VALUES = Map.ofEntries( 56 | entry(EXPORT_GRID, "Export Grid"), 57 | // Buttons 58 | entry(CANCEL, "Cancel"), 59 | entry(PREVIOUS, "Previous"), 60 | entry(NEXT, "Next"), 61 | entry(DOWNLOAD, "Download"), 62 | // Steps 63 | entry(GENERAL, "General"), 64 | entry(FILENAME, "Filename"), 65 | entry(COLUMNS, "Columns"), 66 | entry(NAME, "Name"), 67 | entry(POSITION, "Position"), 68 | entry(ALREADY_PRESENT, "Already present"), 69 | entry(FORMAT, "Format"), 70 | entry(PREVIEW, "Preview"), 71 | entry(UNABLE_TO_SHOW_PREVIEW, "Unable to show preview") 72 | ); 73 | 74 | // Key, Resolver 75 | protected final Map> keyResolvers = new HashMap<>(); 76 | 77 | public GridExportLocalizationConfig withAll(final Map keyValues) 78 | { 79 | keyValues.forEach(this::with); 80 | return this; 81 | } 82 | 83 | public GridExportLocalizationConfig with(final String key, final String value) 84 | { 85 | this.getKeyResolvers().put(key, (c, k) -> value); 86 | return this; 87 | } 88 | 89 | public GridExportLocalizationConfig withTranslation(final String key, final String i18nKey) 90 | { 91 | this.getKeyResolvers().put( 92 | key, 93 | (c, k) -> c.getTranslation(i18nKey)); 94 | return this; 95 | } 96 | 97 | public String getTranslation(final String key, final Component caller) 98 | { 99 | final BiFunction resolver = this.getKeyResolvers().get(key); 100 | if(resolver == null) 101 | { 102 | final String defaultValue = DEFAULT_VALUES.get(key); 103 | return defaultValue != null ? defaultValue : key; 104 | } 105 | return resolver.apply(caller, key); 106 | } 107 | 108 | public Map> getKeyResolvers() 109 | { 110 | return this.keyResolvers; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/GridExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter; 17 | 18 | import java.time.LocalDateTime; 19 | import java.time.ZoneOffset; 20 | import java.time.format.DateTimeFormatter; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.Objects; 25 | import java.util.function.Function; 26 | import java.util.function.Predicate; 27 | 28 | import com.vaadin.flow.component.grid.Grid; 29 | 30 | import software.xdev.vaadin.grid_exporter.column.ColumnConfiguration; 31 | import software.xdev.vaadin.grid_exporter.column.ColumnConfigurationBuilder; 32 | import software.xdev.vaadin.grid_exporter.column.ColumnConfigurationHeaderResolvingStrategyBuilder; 33 | import software.xdev.vaadin.grid_exporter.format.Format; 34 | import software.xdev.vaadin.grid_exporter.grid.GridDataExtractor; 35 | import software.xdev.vaadin.grid_exporter.jasper.JasperGridExporterProvider; 36 | import software.xdev.vaadin.grid_exporter.wizard.GridExporterWizard; 37 | import software.xdev.vaadin.grid_exporter.wizard.GridExporterWizardState; 38 | 39 | 40 | /** 41 | * Opens a wizard to export a Grid. 42 | * 43 | * @param The grid bean type 44 | */ 45 | public class GridExporter 46 | { 47 | protected final Grid grid; 48 | 49 | protected GridExportLocalizationConfig localizationConfig = new GridExportLocalizationConfig(); 50 | 51 | protected Predicate> columnFilter = col -> true; 52 | 53 | protected ColumnConfigurationBuilder columnConfigurationBuilder = new ColumnConfigurationBuilder() 54 | .withColumnConfigHeaderResolvingStrategyBuilder( 55 | ColumnConfigurationHeaderResolvingStrategyBuilder::withVaadinInternalHeaderStrategy); 56 | 57 | protected String fileName = "Report_" + DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm") 58 | .format(LocalDateTime.now(ZoneOffset.UTC)); 59 | 60 | protected List availableFormats = new ArrayList<>(); 61 | 62 | protected Format preSelectedFormat; 63 | 64 | protected Function, GridDataExtractor> gridDataExtractorSupplier = GridDataExtractor::new; 65 | 66 | public GridExporter(final Grid grid) 67 | { 68 | this.grid = Objects.requireNonNull(grid); 69 | } 70 | 71 | public GridExporter loadFromProvider(final GridExporterProvider provider) 72 | { 73 | this.localizationConfig.withAll(provider.getDefaultTranslationKeyValues()); 74 | this.availableFormats.addAll(provider.getFormats()); 75 | return this; 76 | } 77 | 78 | public GridExporter withLocalizationConfig(final GridExportLocalizationConfig localizationConfig) 79 | { 80 | this.localizationConfig = localizationConfig; 81 | return this; 82 | } 83 | 84 | public GridExporter withColumnFilter(final Predicate> columnFilter) 85 | { 86 | this.columnFilter = columnFilter; 87 | return this; 88 | } 89 | 90 | public GridExporter withColumnConfigurationBuilder(final ColumnConfigurationBuilder columnConfigurationBuilder) 91 | { 92 | this.columnConfigurationBuilder = columnConfigurationBuilder; 93 | return this; 94 | } 95 | 96 | public GridExporter withFileName(final String fileName) 97 | { 98 | this.fileName = Objects.requireNonNull(fileName); 99 | return this; 100 | } 101 | 102 | public GridExporter withAvailableFormats(final Format... availableFormats) 103 | { 104 | return this.withAvailableFormats(Arrays.asList(availableFormats)); 105 | } 106 | 107 | public GridExporter withAvailableFormats(final List availableFormats) 108 | { 109 | Objects.requireNonNull(availableFormats); 110 | if(availableFormats.isEmpty()) 111 | { 112 | throw new IllegalStateException("Available formats is empty"); 113 | } 114 | 115 | this.availableFormats = new ArrayList<>(availableFormats); 116 | return this; 117 | } 118 | 119 | public GridExporter addAvailableFormat(final Format availableFormat) 120 | { 121 | Objects.requireNonNull(availableFormat); 122 | this.availableFormats.add(availableFormat); 123 | return this; 124 | } 125 | 126 | public GridExporter withPreSelectedFormat(final Format preSelectedFormat) 127 | { 128 | Objects.requireNonNull(preSelectedFormat); 129 | if(!this.availableFormats.contains(preSelectedFormat)) 130 | { 131 | throw new IllegalArgumentException("Available formats must contain Preselected format"); 132 | } 133 | this.preSelectedFormat = preSelectedFormat; 134 | return this; 135 | } 136 | 137 | public GridExporter withGridDataExtractorSupplier( 138 | final Function, GridDataExtractor> dataExtractorSupplier) 139 | { 140 | this.gridDataExtractorSupplier = Objects.requireNonNull(dataExtractorSupplier); 141 | return this; 142 | } 143 | 144 | protected List> generateAvailableColumns() 145 | { 146 | return this.grid.getColumns().stream() 147 | .filter(this.columnFilter) 148 | .map(this.columnConfigurationBuilder::build) 149 | .toList(); 150 | } 151 | 152 | /** 153 | * Opens the {@link GridExporterWizard}. 154 | */ 155 | public void open() 156 | { 157 | final GridExporterWizardState state = new GridExporterWizardState<>( 158 | this.gridDataExtractorSupplier.apply(this.grid), 159 | this.availableFormats, 160 | this.generateAvailableColumns()); 161 | state.setFileName(this.fileName); 162 | 163 | if(this.preSelectedFormat == null) 164 | { 165 | this.preSelectedFormat = this.availableFormats.get(0); 166 | } 167 | state.setSelectedFormat(this.preSelectedFormat); 168 | 169 | new GridExporterWizard<>(state, this.localizationConfig).open(); 170 | } 171 | 172 | /** 173 | * Creates a new {@link GridExporter} with the default JasperReports exports. 174 | *

175 | * Note: This may be removed or split into a separate module in the future. 176 | *

177 | */ 178 | public static GridExporter newWithDefaults(final Grid grid) 179 | { 180 | return new GridExporter<>(grid) 181 | .loadFromProvider(new JasperGridExporterProvider()); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/GridExporterProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | import software.xdev.vaadin.grid_exporter.format.Format; 23 | 24 | 25 | /** 26 | * Provides data to the {@link GridExporter}. 27 | *

28 | * Can be used for extensions. 29 | *

30 | */ 31 | public class GridExporterProvider 32 | { 33 | protected final Map defaultTranslationKeyValues; 34 | protected final List formats; 35 | 36 | public GridExporterProvider(final Map defaultTranslationKeyValues, final Format... formats) 37 | { 38 | this(defaultTranslationKeyValues, Arrays.asList(formats)); 39 | } 40 | 41 | public GridExporterProvider(final Map defaultTranslationKeyValues, final List formats) 42 | { 43 | this.defaultTranslationKeyValues = defaultTranslationKeyValues; 44 | this.formats = formats; 45 | } 46 | 47 | public Map getDefaultTranslationKeyValues() 48 | { 49 | return this.defaultTranslationKeyValues; 50 | } 51 | 52 | public List getFormats() 53 | { 54 | return this.formats; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/Translator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter; 17 | 18 | /** 19 | * Simple interface to translate a given key into some language. 20 | */ 21 | @FunctionalInterface 22 | public interface Translator 23 | { 24 | /** 25 | * @param key to translate 26 | * @return translated String 27 | */ 28 | String translate(final String key); 29 | } 30 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/ColumnConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column; 17 | 18 | import java.util.Objects; 19 | 20 | import com.vaadin.flow.component.grid.Grid.Column; 21 | import com.vaadin.flow.function.SerializableFunction; 22 | 23 | 24 | public class ColumnConfiguration 25 | { 26 | protected final Column gridColumn; 27 | protected String header; 28 | 29 | public ColumnConfiguration( 30 | final Column gridColumn, 31 | final SerializableFunction, String> headerResolver) 32 | { 33 | this.gridColumn = gridColumn; 34 | this.header = Objects.requireNonNullElse(headerResolver.apply(gridColumn), ""); 35 | } 36 | 37 | public Column getGridColumn() 38 | { 39 | return this.gridColumn; 40 | } 41 | 42 | public String getHeader() 43 | { 44 | return this.header; 45 | } 46 | 47 | public ColumnConfiguration setHeader(final String header) 48 | { 49 | this.header = Objects.requireNonNull(header); 50 | return this; 51 | } 52 | 53 | @Override 54 | public boolean equals(final Object o) 55 | { 56 | if(this == o) 57 | { 58 | return true; 59 | } 60 | if(!(o instanceof final ColumnConfiguration that)) 61 | { 62 | return false; 63 | } 64 | return Objects.equals(this.gridColumn, that.gridColumn); 65 | } 66 | 67 | @Override 68 | public int hashCode() 69 | { 70 | return Objects.hash(this.gridColumn); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/ColumnConfigurationBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column; 17 | 18 | 19 | 20 | import java.util.function.Consumer; 21 | 22 | import com.vaadin.flow.component.grid.Grid.Column; 23 | 24 | 25 | /** 26 | * Used for (initially) building a {@link ColumnConfiguration} 27 | */ 28 | public class ColumnConfigurationBuilder 29 | { 30 | protected final ColumnConfigurationHeaderResolvingStrategyBuilder columnConfigHeaderResolvingStrategyBuilder = 31 | new ColumnConfigurationHeaderResolvingStrategyBuilder(); 32 | 33 | public ColumnConfigurationBuilder withColumnConfigHeaderResolvingStrategyBuilder( 34 | final Consumer configureBuilderFunc) 35 | { 36 | configureBuilderFunc.accept(this.columnConfigHeaderResolvingStrategyBuilder); 37 | return this; 38 | } 39 | 40 | public ColumnConfiguration build(final Column gridColumn) 41 | { 42 | return new ColumnConfiguration<>(gridColumn, this.columnConfigHeaderResolvingStrategyBuilder.build()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/ColumnConfigurationHeaderResolvingStrategyBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.Optional; 22 | import java.util.function.Function; 23 | 24 | import com.vaadin.flow.component.grid.Grid.Column; 25 | import com.vaadin.flow.function.SerializableFunction; 26 | 27 | import software.xdev.vaadin.grid_exporter.column.headerresolving.ColumnHeaderResolvingStrategy; 28 | import software.xdev.vaadin.grid_exporter.column.headerresolving.ManualColumnHeaderResolvingStrategy; 29 | import software.xdev.vaadin.grid_exporter.column.headerresolving.VaadinColumnHeaderResolvingStrategy; 30 | 31 | 32 | /** 33 | * Builds a function (from multiple strategies) that resolves the text for a column.
If no strategies are specified 34 | * the fallback {@link Column#getKey()} is used. 35 | */ 36 | public class ColumnConfigurationHeaderResolvingStrategyBuilder 37 | { 38 | protected final List strategies = new ArrayList<>(); 39 | 40 | /** 41 | * Uses the {@link VaadinColumnHeaderResolvingStrategy} 42 | */ 43 | public ColumnConfigurationHeaderResolvingStrategyBuilder withVaadinInternalHeaderStrategy() 44 | { 45 | return this.withStrategy(new VaadinColumnHeaderResolvingStrategy()); 46 | } 47 | 48 | /** 49 | * Uses the {@link ManualColumnHeaderResolvingStrategy} 50 | */ 51 | public ColumnConfigurationHeaderResolvingStrategyBuilder withManualColumnHeaderStrategy( 52 | final Function, I> identifierResolver, 53 | final Map> headerTextResolverMap) 54 | { 55 | return this.withStrategy(new ManualColumnHeaderResolvingStrategy<>(identifierResolver, headerTextResolverMap)); 56 | } 57 | 58 | /** 59 | * Adds a new {@link ColumnHeaderResolvingStrategy}.
This strategy will be added at the end of the strategy 60 | * list. 61 | */ 62 | public ColumnConfigurationHeaderResolvingStrategyBuilder withStrategy(final ColumnHeaderResolvingStrategy strategy) 63 | { 64 | this.strategies.add(strategy); 65 | return this; 66 | } 67 | 68 | /** 69 | * Adds a new {@link ColumnHeaderResolvingStrategy}.
70 | * This strategy will be added at the start of the strategy list. 71 | */ 72 | public ColumnConfigurationHeaderResolvingStrategyBuilder 73 | withFirstStrategy(final ColumnHeaderResolvingStrategy strategy) 74 | { 75 | this.strategies.add(0, strategy); 76 | return this; 77 | } 78 | 79 | /** 80 | * Clears all existing strategies 81 | */ 82 | public ColumnConfigurationHeaderResolvingStrategyBuilder clearAllStrategies() 83 | { 84 | this.strategies.clear(); 85 | return this; 86 | } 87 | 88 | @SuppressWarnings("java:S1452") // Not exposed to the user and otherwise compilation failure 89 | public SerializableFunction, String> build() 90 | { 91 | return col -> 92 | { 93 | for(final ColumnHeaderResolvingStrategy resolvingFunction : this.strategies) 94 | { 95 | final Optional optResolvedValue = resolvingFunction.resolve(col); 96 | if(optResolvedValue.isPresent()) 97 | { 98 | return optResolvedValue.get(); 99 | } 100 | } 101 | 102 | // Fallback 103 | return col.getKey() != null ? col.getKey() : ""; 104 | }; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/headerresolving/ColumnHeaderResolvingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column.headerresolving; 17 | 18 | 19 | 20 | import java.util.Optional; 21 | 22 | import com.vaadin.flow.component.grid.Grid.Column; 23 | 24 | 25 | /** 26 | * Can be implemented to create a new strategy that resolves a {@link Column} header 27 | */ 28 | public interface ColumnHeaderResolvingStrategy 29 | { 30 | /** 31 | * Resolves the text for a column header 32 | * 33 | * @param column 34 | * The column for which the header text should be resolved 35 | * @return 36 | * {@link Optional#empty()} when the text could not be resolved and the next function should be used.
37 | * If a value was found the Optional contains the string. 38 | */ 39 | Optional resolve(Column column); 40 | } 41 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/headerresolving/ManualColumnHeaderResolvingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column.headerresolving; 17 | 18 | import java.util.Map; 19 | import java.util.Optional; 20 | import java.util.function.Function; 21 | 22 | import com.vaadin.flow.component.grid.Grid.Column; 23 | 24 | 25 | /** 26 | * Resolves the header-text by using the unique identification {@linkplain I} and find the corresponding resolving 27 | * function for the identification in a map. 28 | *
29 | * This function is the used to resolve the header-text. 30 | *

31 | * Example: 32 | *
33 | * {@code new ManualColumnHeaderResolvingStrategy(col -> col.getKey(), Map.of("name", k -> "Username", "pw", k -> 34 | * "Password"))} 35 | *

36 | * 37 | * @param The identifier of the column, e.g. the key or the column itself 38 | */ 39 | public class ManualColumnHeaderResolvingStrategy implements ColumnHeaderResolvingStrategy 40 | { 41 | protected final Function, I> identifierResolver; 42 | protected final Map> headerTextResolverMap; 43 | 44 | public ManualColumnHeaderResolvingStrategy( 45 | final Function, I> identifierResolver, 46 | final Map> headerTextResolverMap) 47 | { 48 | this.identifierResolver = identifierResolver; 49 | this.headerTextResolverMap = headerTextResolverMap; 50 | } 51 | 52 | @Override 53 | public Optional resolve(final Column column) 54 | { 55 | final I identifier = this.identifierResolver.apply(column); 56 | 57 | final Function resolveFunction = this.headerTextResolverMap.get(identifier); 58 | if(resolveFunction == null) 59 | { 60 | return Optional.empty(); 61 | } 62 | 63 | return Optional.ofNullable(resolveFunction.apply(identifier)); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/column/headerresolving/VaadinColumnHeaderResolvingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.column.headerresolving; 17 | 18 | import java.util.Optional; 19 | 20 | import com.vaadin.flow.component.Component; 21 | import com.vaadin.flow.component.grid.Grid.Column; 22 | import com.vaadin.flow.dom.Element; 23 | 24 | 25 | /** 26 | * Tries to get the header using Vaadin Column API methods 27 | *

28 | * Note: This might fail when the vaadin version changes 29 | */ 30 | public class VaadinColumnHeaderResolvingStrategy implements ColumnHeaderResolvingStrategy 31 | { 32 | @Override 33 | public Optional resolve(final Column column) 34 | { 35 | try 36 | { 37 | final Optional optHeaderComponentText = Optional.ofNullable(column.getHeaderComponent()) 38 | .map(Component::getElement) 39 | .map(Element::getText); 40 | if(optHeaderComponentText.isPresent()) 41 | { 42 | return optHeaderComponentText; 43 | } 44 | 45 | return Optional.ofNullable(column.getHeaderText()); 46 | } 47 | catch(final Exception e) 48 | { 49 | return Optional.empty(); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/components/wizard/WizardState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.components.wizard; 17 | 18 | public interface WizardState 19 | { 20 | // just marker 21 | } 22 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/components/wizard/WizardStyles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.components.wizard; 17 | 18 | public final class WizardStyles 19 | { 20 | private WizardStyles() 21 | { 22 | // No impl 23 | } 24 | 25 | public static final String LOCATION = "./styles/wizard.css"; 26 | 27 | // region WizardPanel 28 | 29 | public static final String WIZARD_PANEL = "wizard-panel"; 30 | 31 | public static final String WIZARD_PANEL_TABS = WIZARD_PANEL + "-tabs"; 32 | 33 | public static final String WIZARD_PANEL_CONTENT = WIZARD_PANEL + "-content"; 34 | 35 | // endregion 36 | // region WizardButtonBar 37 | 38 | public static final String WIZARD_BUTTON_BAR = "wizard-button-bar"; 39 | 40 | public static final String WIZARD_BUTTON_BAR_BTN_CANCEL = WIZARD_BUTTON_BAR + "-cancel"; 41 | public static final String WIZARD_BUTTON_BAR_BTN_PREVIOUS = WIZARD_BUTTON_BAR + "-previous"; 42 | public static final String WIZARD_BUTTON_BAR_BTN_NEXT = WIZARD_BUTTON_BAR + "-next"; 43 | public static final String WIZARD_BUTTON_BAR_BTN_DONE = WIZARD_BUTTON_BAR + "-done"; 44 | 45 | // endregion 46 | } 47 | -------------------------------------------------------------------------------- /vaadin-grid-exporter/src/main/java/software/xdev/vaadin/grid_exporter/components/wizard/buttonbar/AbstractWizardButtonBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2022 XDEV Software (https://xdev.software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package software.xdev.vaadin.grid_exporter.components.wizard.buttonbar; 17 | 18 | import java.util.Objects; 19 | import java.util.function.Consumer; 20 | import java.util.function.Function; 21 | import java.util.stream.Stream; 22 | 23 | import com.vaadin.flow.component.Composite; 24 | import com.vaadin.flow.component.HasSize; 25 | import com.vaadin.flow.component.HasStyle; 26 | import com.vaadin.flow.component.button.Button; 27 | import com.vaadin.flow.component.button.ButtonVariant; 28 | import com.vaadin.flow.component.dependency.CssImport; 29 | import com.vaadin.flow.component.orderedlayout.FlexComponent; 30 | import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 31 | import com.vaadin.flow.shared.Registration; 32 | 33 | import software.xdev.vaadin.grid_exporter.components.wizard.WizardStyles; 34 | import software.xdev.vaadin.grid_exporter.components.wizard.panel.WizardPanelActions; 35 | import software.xdev.vaadin.grid_exporter.components.wizard.step.WizardStepState; 36 | 37 | 38 | @CssImport(WizardStyles.LOCATION) 39 | public abstract class AbstractWizardButtonBar

> extends Composite 40 | implements HasSize, HasStyle 41 | { 42 | protected final Button btnCancel = new Button("Cancel"); 43 | protected final Button btnPrevious = new Button("Back"); 44 | protected final Button btnNext = new Button("Next"); 45 | protected final Button btnDone = new Button("Done"); 46 | 47 | protected final HorizontalLayout hlEndButtons = new HorizontalLayout(); 48 | 49 | protected void init(final WizardPanelActions panel) 50 | { 51 | Objects.requireNonNull(panel); 52 | 53 | this.initUI(); 54 | this.registerListeners(panel); 55 | 56 | // Set initial state 57 | this.updateFromStepState(new WizardStepState(0, 0)); 58 | } 59 | 60 | protected void initUI() 61 | { 62 | this.btnCancel.addClassName(WizardStyles.WIZARD_BUTTON_BAR_BTN_CANCEL); 63 | this.btnPrevious.addClassName(WizardStyles.WIZARD_BUTTON_BAR_BTN_PREVIOUS); 64 | this.btnNext.addClassName(WizardStyles.WIZARD_BUTTON_BAR_BTN_NEXT); 65 | this.btnDone.addClassName(WizardStyles.WIZARD_BUTTON_BAR_BTN_DONE); 66 | 67 | Stream.of(this.btnCancel, this.btnPrevious, this.btnNext, this.btnDone) 68 | .forEach(btn -> btn.setDisableOnClick(true)); 69 | 70 | Stream.of(this.btnNext, this.btnDone) 71 | .forEach(btn -> btn.addThemeVariants(ButtonVariant.LUMO_PRIMARY)); 72 | 73 | this.hlEndButtons.setPadding(false); 74 | this.hlEndButtons.add(this.btnPrevious, this.btnNext, this.btnDone); 75 | 76 | this.getContent().addClassName(WizardStyles.WIZARD_BUTTON_BAR); 77 | this.getContent().setPadding(false); 78 | this.getContent().setWidthFull(); 79 | this.getContent().setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN); 80 | this.getContent().add(this.btnCancel, this.hlEndButtons); 81 | } 82 | 83 | protected void registerListeners(final WizardPanelActions panel) 84 | { 85 | this.addButtonClickEvent(this.getBtnPrevious(), panel::showPreviousStep); 86 | this.addButtonClickEvent(this.getBtnNext(), panel::showNextStep); 87 | 88 | panel.addStepStateChangedListener(this::updateFromStepState); 89 | } 90 | 91 | protected Registration addButtonClickEvent(final Button button, final Consumer isFromClientConsumer) 92 | { 93 | return button.addClickListener(ev -> 94 | { 95 | isFromClientConsumer.accept(ev.isFromClient()); 96 | ev.getSource().setEnabled(true); 97 | }); 98 | } 99 | 100 | protected void updateFromStepState(final WizardStepState stepState) 101 | { 102 | this.getBtnPrevious().setEnabled(!stepState.isFirstStep()); 103 | 104 | this.getBtnNext().setVisible(!stepState.isLastStep()); 105 | this.getBtnDone().setVisible(stepState.isLastStep()); 106 | } 107 | 108 | // region Getter for Buttons 109 | 110 | public Button getBtnCancel() 111 | { 112 | return this.btnCancel; 113 | } 114 | 115 | public Button getBtnPrevious() 116 | { 117 | return this.btnPrevious; 118 | } 119 | 120 | public Button getBtnNext() 121 | { 122 | return this.btnNext; 123 | } 124 | 125 | public Button getBtnDone() 126 | { 127 | return this.btnDone; 128 | } 129 | 130 | // endregion 131 | 132 | public P configureButton( 133 | final Function selfButtonSupplier, 134 | final Consumer