Tony CHEMIT pushed to branch feature/issue_2755 at ultreiaio / ird-observe
Commits:
-
38a62dbb
by Tony Chemit at 2023-11-17T12:14:33+01:00
-
939468ef
by Tony Chemit at 2023-11-17T12:15:13+01:00
20 changed files:
- client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientConfig.java
- client/core/src/main/resources/observe-ui.properties
- client/datasource/actions/pom.xml
- client/datasource/actions/src/main/i18n/getters/java.getter
- + client/datasource/actions/src/main/i18n/templates/reportHtmlExport_en_GB.ftl
- + client/datasource/actions/src/main/i18n/templates/reportHtmlExport_es_ES.ftl
- + client/datasource/actions/src/main/i18n/templates/reportHtmlExport_fr_FR.ftl
- client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/ObserveKeyStrokesActions.java
- + client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/HtmlExportModel.java
- client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ReportModel.java
- client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ReportUI.jaxx
- client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ResultTableModel.java
- client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/actions/ExportToClipboard.java
- + client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/actions/ExportToHtml.java
- + client/datasource/actions/src/main/resources/icons/action-export-clipboard.png
- client/datasource/actions/src/main/resources/icons/action-export-csv.png
- + client/datasource/actions/src/main/resources/icons/action-export-html.png
- client/runner/src/main/i18n/translations/client-runner_en_GB.properties
- client/runner/src/main/i18n/translations/client-runner_es_ES.properties
- client/runner/src/main/i18n/translations/client-runner_fr_FR.properties
Changes:
| ... | ... | @@ -466,7 +466,7 @@ public class ClientConfig extends GeneratedClientConfig implements TripMapConfig |
| 466 | 466 | }
|
| 467 | 467 | |
| 468 | 468 | @Override
|
| 469 | - protected Supplier<Gson> getGsonSupplier() {
|
|
| 469 | + public Supplier<Gson> getGsonSupplier() {
|
|
| 470 | 470 | return gsonSupplier == null ? gsonSupplier = new DtoGsonSupplier(true) : gsonSupplier;
|
| 471 | 471 | }
|
| 472 | 472 |
| ... | ... | @@ -239,6 +239,8 @@ icon.action.wizard-refresh=action-wizard-refresh-16.png |
| 239 | 239 | icon.action.wizard-config=action-wizard-config-16.png
|
| 240 | 240 | icon.action.wizard-message=action-wizard-message-16.png
|
| 241 | 241 | icon.action.export-csv=action-export-csv.png
|
| 242 | +icon.action.export-html=action-export-html.png
|
|
| 243 | +icon.action.export-clipboard=action-export-clipboard.png
|
|
| 242 | 244 | # couleurs au format (r,g,b)
|
| 243 | 245 | icon.Table.removeIcon=action-delete.png
|
| 244 | 246 | color.Table.lastRowColor=255,255,0
|
| ... | ... | @@ -112,6 +112,10 @@ |
| 112 | 112 | <groupId>commons-io</groupId>
|
| 113 | 113 | <artifactId>commons-io</artifactId>
|
| 114 | 114 | </dependency>
|
| 115 | + <dependency>
|
|
| 116 | + <groupId>com.google.code.gson</groupId>
|
|
| 117 | + <artifactId>gson</artifactId>
|
|
| 118 | + </dependency>
|
|
| 115 | 119 | <dependency>
|
| 116 | 120 | <groupId>io.ultreia.java4all</groupId>
|
| 117 | 121 | <artifactId>application-template</artifactId>
|
| ... | ... | @@ -84,6 +84,9 @@ observe.ui.datasource.editor.actions.report.exportToClipboard |
| 84 | 84 | observe.ui.datasource.editor.actions.report.exportToCsv
|
| 85 | 85 | observe.ui.datasource.editor.actions.report.exportToCsv.done
|
| 86 | 86 | observe.ui.datasource.editor.actions.report.exportToCsv.tip
|
| 87 | +observe.ui.datasource.editor.actions.report.exportToHtml
|
|
| 88 | +observe.ui.datasource.editor.actions.report.exportToHtml.done
|
|
| 89 | +observe.ui.datasource.editor.actions.report.exportToHtml.tip
|
|
| 87 | 90 | observe.ui.datasource.editor.actions.report.no.report.found
|
| 88 | 91 | observe.ui.datasource.editor.actions.report.report.count.found
|
| 89 | 92 | observe.ui.datasource.editor.actions.report.title
|
| 1 | +<#-- @ftlvariable name=".data_model" type="fr.ird.observe.client.datasource.actions.report.HtmlExportModel" -->
|
|
| 2 | +<!DOCTYPE html>
|
|
| 3 | +<!--
|
|
| 4 | + #%L
|
|
| 5 | + ObServe Client :: DataSource :: Actions
|
|
| 6 | + %%
|
|
| 7 | + Copyright (C) 2008 - 2023 IRD, Ultreia.io
|
|
| 8 | + %%
|
|
| 9 | + This program is free software: you can redistribute it and/or modify
|
|
| 10 | + it under the terms of the GNU General Public License as
|
|
| 11 | + published by the Free Software Foundation, either version 3 of the
|
|
| 12 | + License, or (at your option) any later version.
|
|
| 13 | + |
|
| 14 | + This program is distributed in the hope that it will be useful,
|
|
| 15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 17 | + GNU General Public License for more details.
|
|
| 18 | + |
|
| 19 | + You should have received a copy of the GNU General Public
|
|
| 20 | + License along with this program. If not, see
|
|
| 21 | + <http://www.gnu.org/licenses/gpl-3.0.html>.
|
|
| 22 | + #L%
|
|
| 23 | + -->
|
|
| 24 | + |
|
| 25 | +<html lang="en">
|
|
| 26 | +<head>
|
|
| 27 | + <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"/>
|
|
| 28 | + <title>Report ${.data_model.selectedReport.name}</title>
|
|
| 29 | + <script src="https://unpkg.com/gridjs/dist/gridjs.umd.js"></script>
|
|
| 30 | + <style>
|
|
| 31 | + .config-panel {
|
|
| 32 | + padding: 10px;
|
|
| 33 | + margin: 10px 0;
|
|
| 34 | + background: #fcfcfc;
|
|
| 35 | + border: 1px solid #e9e9e9;
|
|
| 36 | + display: inline-block;
|
|
| 37 | + }
|
|
| 38 | + |
|
| 39 | + .config-panel label {
|
|
| 40 | + margin-right: 10px;
|
|
| 41 | + }
|
|
| 42 | + |
|
| 43 | + td.gridjs-td {
|
|
| 44 | + background-color: transparent;
|
|
| 45 | + }
|
|
| 46 | + |
|
| 47 | + tr:nth-child(even) {
|
|
| 48 | + background-color: #dddddd;
|
|
| 49 | + }
|
|
| 50 | + |
|
| 51 | + tr:hover td {
|
|
| 52 | + background-color: rgba(0, 0, 0, 0.1);
|
|
| 53 | + }
|
|
| 54 | + |
|
| 55 | + tr td:hover {
|
|
| 56 | + color: #fff;
|
|
| 57 | + }
|
|
| 58 | + |
|
| 59 | + th:hover {
|
|
| 60 | + background-color: #999;
|
|
| 61 | + color: #fff;
|
|
| 62 | + }
|
|
| 63 | + </style>
|
|
| 64 | + <script type="application/javascript">
|
|
| 65 | + |
|
| 66 | + function searchValue() {
|
|
| 67 | + return searchOption.checked;
|
|
| 68 | + }
|
|
| 69 | + |
|
| 70 | + function resizableValue() {
|
|
| 71 | + return resizableOption.checked;
|
|
| 72 | + }
|
|
| 73 | + |
|
| 74 | + function sortValue() {
|
|
| 75 | + return sortOption.checked;
|
|
| 76 | + }
|
|
| 77 | + |
|
| 78 | + function paginationValue() {
|
|
| 79 | + return paginationOption.checked ? {limit: paginationSizeOption.value} : false;
|
|
| 80 | + }
|
|
| 81 | + |
|
| 82 | + function toggleSearch(config, source) {
|
|
| 83 | + let newValue = source.checked;
|
|
| 84 | + // console.info("Toggle search to: " + newValue);
|
|
| 85 | + updateGrid(config);
|
|
| 86 | + }
|
|
| 87 | + |
|
| 88 | + function toggleResizable(config, source) {
|
|
| 89 | + let newValue = source.checked;
|
|
| 90 | + // console.info("Toggle resizable to: " + newValue);
|
|
| 91 | + updateGrid(config);
|
|
| 92 | + }
|
|
| 93 | + |
|
| 94 | + function toggleSort(config, source) {
|
|
| 95 | + let newValue = source.checked;
|
|
| 96 | + // console.info("Toggle sort to: " + newValue);
|
|
| 97 | + updateGrid(config);
|
|
| 98 | + }
|
|
| 99 | + |
|
| 100 | + function togglePagination(config, source) {
|
|
| 101 | + let newValue = source.checked;
|
|
| 102 | + // console.info("Toggle pagination to: " + newValue);
|
|
| 103 | + if (newValue) {
|
|
| 104 | + paginationSizeOption["disabled"] = null;
|
|
| 105 | + } else {
|
|
| 106 | + paginationSizeOption.disabled = true;
|
|
| 107 | + }
|
|
| 108 | + updateGrid(config);
|
|
| 109 | + }
|
|
| 110 | + |
|
| 111 | + function changePaginationSize(config, source) {
|
|
| 112 | + let newValue = source.value;
|
|
| 113 | + // console.info("Change pagination size to: " + newValue);
|
|
| 114 | + updateGrid(config);
|
|
| 115 | + }
|
|
| 116 | + |
|
| 117 | + function updateGrid(config) {
|
|
| 118 | + let newConfig = {
|
|
| 119 | + language: config.language,
|
|
| 120 | + data: config.data,
|
|
| 121 | + columns: config.columns,
|
|
| 122 | + search: searchValue(),
|
|
| 123 | + resizable: resizableValue(),
|
|
| 124 | + sort: sortValue(),
|
|
| 125 | + pagination: paginationValue()
|
|
| 126 | + };
|
|
| 127 | + gridContainerParent.innerHTML = "<div id=\"wrapper\"></div>";
|
|
| 128 | + // console.info(newConfig);
|
|
| 129 | + setTimeout(() => {
|
|
| 130 | + grid = new gridjs.Grid(newConfig).render(document.getElementById("wrapper"));
|
|
| 131 | + }, 50);
|
|
| 132 | + }
|
|
| 133 | + </script>
|
|
| 134 | +</head>
|
|
| 135 | +<body>
|
|
| 136 | +<h1>Report ${.data_model.selectedReport.name}</h1>
|
|
| 137 | +<h2>Configuration</h2>
|
|
| 138 | +<h3>Selected data:</h3>
|
|
| 139 | +<ul>
|
|
| 140 | + <li>
|
|
| 141 | + <#assign selectDataModel = .data_model.selectDataModel.selectionDataModel />
|
|
| 142 | + <#assign selectDataCount = selectDataModel.getSelectedCount() />
|
|
| 143 | + |
|
| 144 | + <#if selectDataCount == 1> 1 trip <#else> ${selectDataCount} trips</#if>.
|
|
| 145 | + <ul>
|
|
| 146 | + <#list selectDataModel.getSelectedLabels() as key, value>
|
|
| 147 | + <li>
|
|
| 148 | + ${key}
|
|
| 149 | + <ul>
|
|
| 150 | + <#list value as trip>
|
|
| 151 | + <li>${trip}</li>
|
|
| 152 | + </#list>
|
|
| 153 | + </ul>
|
|
| 154 | + </li>
|
|
| 155 | + </#list>
|
|
| 156 | + </ul>
|
|
| 157 | + </li>
|
|
| 158 | +</ul>
|
|
| 159 | +<h3>Selected report:</h3>
|
|
| 160 | + |
|
| 161 | +<#assign selectedReport = .data_model.selectedReport />
|
|
| 162 | +<p><b>${selectedReport.name}</b></p>
|
|
| 163 | +<ul>
|
|
| 164 | + <#list selectedReport.getVariables() as variable>
|
|
| 165 | + <li>
|
|
| 166 | + Variable ${variable.name} : ${variable.selectedValue}.
|
|
| 167 | + </li>
|
|
| 168 | + </#list>
|
|
| 169 | +</ul>
|
|
| 170 | +<h2>Result</h2>
|
|
| 171 | + |
|
| 172 | +<div class="config-panel">
|
|
| 173 | + <label><input id="search" type="checkbox" checked/> Search</label>|
|
|
| 174 | + <label><input id="resizable" type="checkbox" checked/> Resizable columns</label>|
|
|
| 175 | + <label><input id="sort" type="checkbox" checked/> Sort</label>|
|
|
| 176 | + <label><input id="pagination" type="checkbox"/> Pagination</label>|
|
|
| 177 | + <label>Page size <input id="paginationSize" type="number" disabled value="20"/></label>
|
|
| 178 | +</div>
|
|
| 179 | +<div id="wrapperParent">
|
|
| 180 | + <div id="wrapper"></div>
|
|
| 181 | +</div>
|
|
| 182 | +<script type="application/javascript">
|
|
| 183 | + const json = ${.data_model.json};
|
|
| 184 | + |
|
| 185 | + const gridContainerParent = document.getElementById("wrapperParent");
|
|
| 186 | + const searchOption = document.getElementById("search");
|
|
| 187 | + const resizableOption = document.getElementById("resizable");
|
|
| 188 | + const paginationOption = document.getElementById("pagination");
|
|
| 189 | + const paginationSizeOption = document.getElementById("paginationSize");
|
|
| 190 | + const sortOption = document.getElementById("sort");
|
|
| 191 | + |
|
| 192 | + let grid = new gridjs.Grid({
|
|
| 193 | + search: searchValue(),
|
|
| 194 | + resizable: resizableValue(),
|
|
| 195 | + sort: sortValue(),
|
|
| 196 | + pagination: paginationValue(),
|
|
| 197 | + <#--language: {-->
|
|
| 198 | + <#-- 'search': {-->
|
|
| 199 | + <#-- 'placeholder': '🔍 Recherche...'-->
|
|
| 200 | + <#-- },-->
|
|
| 201 | + <#-- sort: {-->
|
|
| 202 | + <#-- sortAsc: 'Tri ascendant',-->
|
|
| 203 | + <#-- sortDesc: 'Tri descendant',-->
|
|
| 204 | + <#-- },-->
|
|
| 205 | + <#-- pagination: {-->
|
|
| 206 | + <#-- previous: 'Précédent',-->
|
|
| 207 | + <#-- next: 'Suivant',-->
|
|
| 208 | + <#-- navigate: (page, pages) => `Page ${r"${page}"} sur ${r"${pages}"}`,-->
|
|
| 209 | + <#-- page: (page) => `Page ${r"${page}"}`,-->
|
|
| 210 | + <#-- showing: 'Affichage des lignes de',-->
|
|
| 211 | + <#-- of: 'sur',-->
|
|
| 212 | + <#-- to: 'à',-->
|
|
| 213 | + <#-- results: 'lignes.',-->
|
|
| 214 | + <#-- },-->
|
|
| 215 | + <#-- loading: 'Chargement...'-->
|
|
| 216 | + <#--},-->
|
|
| 217 | + columns: !!json.columnNames ? json.columnNames : [],
|
|
| 218 | + data: json.data.data
|
|
| 219 | + });
|
|
| 220 | + updateGrid(grid.config);
|
|
| 221 | + |
|
| 222 | + searchOption.addEventListener("change", function () {
|
|
| 223 | + toggleSearch(grid.config, this);
|
|
| 224 | + });
|
|
| 225 | + resizableOption.addEventListener("change", function () {
|
|
| 226 | + toggleResizable(grid.config, this);
|
|
| 227 | + });
|
|
| 228 | + sortOption.addEventListener("change", function () {
|
|
| 229 | + toggleSort(grid.config, this);
|
|
| 230 | + });
|
|
| 231 | + paginationOption.addEventListener("change", function () {
|
|
| 232 | + togglePagination(grid.config, this);
|
|
| 233 | + });
|
|
| 234 | + |
|
| 235 | + paginationSizeOption.addEventListener("change", function () {
|
|
| 236 | + changePaginationSize(grid.config, this);
|
|
| 237 | + });
|
|
| 238 | +</script>
|
|
| 239 | +</body>
|
|
| 240 | +</html> |
| 1 | +<#-- @ftlvariable name=".data_model" type="fr.ird.observe.client.datasource.actions.report.HtmlExportModel" -->
|
|
| 2 | +<!DOCTYPE html>
|
|
| 3 | +<!--
|
|
| 4 | + #%L
|
|
| 5 | + ObServe Client :: DataSource :: Actions
|
|
| 6 | + %%
|
|
| 7 | + Copyright (C) 2008 - 2023 IRD, Ultreia.io
|
|
| 8 | + %%
|
|
| 9 | + This program is free software: you can redistribute it and/or modify
|
|
| 10 | + it under the terms of the GNU General Public License as
|
|
| 11 | + published by the Free Software Foundation, either version 3 of the
|
|
| 12 | + License, or (at your option) any later version.
|
|
| 13 | + |
|
| 14 | + This program is distributed in the hope that it will be useful,
|
|
| 15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 17 | + GNU General Public License for more details.
|
|
| 18 | + |
|
| 19 | + You should have received a copy of the GNU General Public
|
|
| 20 | + License along with this program. If not, see
|
|
| 21 | + <http://www.gnu.org/licenses/gpl-3.0.html>.
|
|
| 22 | + #L%
|
|
| 23 | + -->
|
|
| 24 | +<#--TODO-->
|
|
| 25 | +<html lang="en">
|
|
| 26 | +<head>
|
|
| 27 | + <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"/>
|
|
| 28 | + <title>Report ${.data_model.selectedReport.name}</title>
|
|
| 29 | + <script src="https://unpkg.com/gridjs/dist/gridjs.umd.js"></script>
|
|
| 30 | + <style>
|
|
| 31 | + .config-panel {
|
|
| 32 | + padding: 10px;
|
|
| 33 | + margin: 10px 0;
|
|
| 34 | + background: #fcfcfc;
|
|
| 35 | + border: 1px solid #e9e9e9;
|
|
| 36 | + display: inline-block;
|
|
| 37 | + }
|
|
| 38 | + |
|
| 39 | + .config-panel label {
|
|
| 40 | + margin-right: 10px;
|
|
| 41 | + }
|
|
| 42 | + |
|
| 43 | + td.gridjs-td {
|
|
| 44 | + background-color: transparent;
|
|
| 45 | + }
|
|
| 46 | + |
|
| 47 | + tr:nth-child(even) {
|
|
| 48 | + background-color: #dddddd;
|
|
| 49 | + }
|
|
| 50 | + |
|
| 51 | + tr:hover td {
|
|
| 52 | + background-color: rgba(0, 0, 0, 0.1);
|
|
| 53 | + }
|
|
| 54 | + |
|
| 55 | + tr td:hover {
|
|
| 56 | + color: #fff;
|
|
| 57 | + }
|
|
| 58 | + |
|
| 59 | + th:hover {
|
|
| 60 | + background-color: #999;
|
|
| 61 | + color: #fff;
|
|
| 62 | + }
|
|
| 63 | + </style>
|
|
| 64 | + <script type="application/javascript">
|
|
| 65 | + |
|
| 66 | + function searchValue() {
|
|
| 67 | + return searchOption.checked;
|
|
| 68 | + }
|
|
| 69 | + |
|
| 70 | + function resizableValue() {
|
|
| 71 | + return resizableOption.checked;
|
|
| 72 | + }
|
|
| 73 | + |
|
| 74 | + function sortValue() {
|
|
| 75 | + return sortOption.checked;
|
|
| 76 | + }
|
|
| 77 | + |
|
| 78 | + function paginationValue() {
|
|
| 79 | + return paginationOption.checked ? {limit: paginationSizeOption.value} : false;
|
|
| 80 | + }
|
|
| 81 | + |
|
| 82 | + function toggleSearch(config, source) {
|
|
| 83 | + let newValue = source.checked;
|
|
| 84 | + // console.info("Toggle search to: " + newValue);
|
|
| 85 | + updateGrid(config);
|
|
| 86 | + }
|
|
| 87 | + |
|
| 88 | + function toggleResizable(config, source) {
|
|
| 89 | + let newValue = source.checked;
|
|
| 90 | + // console.info("Toggle resizable to: " + newValue);
|
|
| 91 | + updateGrid(config);
|
|
| 92 | + }
|
|
| 93 | + |
|
| 94 | + function toggleSort(config, source) {
|
|
| 95 | + let newValue = source.checked;
|
|
| 96 | + // console.info("Toggle sort to: " + newValue);
|
|
| 97 | + updateGrid(config);
|
|
| 98 | + }
|
|
| 99 | + |
|
| 100 | + function togglePagination(config, source) {
|
|
| 101 | + let newValue = source.checked;
|
|
| 102 | + // console.info("Toggle pagination to: " + newValue);
|
|
| 103 | + if (newValue) {
|
|
| 104 | + paginationSizeOption["disabled"] = null;
|
|
| 105 | + } else {
|
|
| 106 | + paginationSizeOption.disabled = true;
|
|
| 107 | + }
|
|
| 108 | + updateGrid(config);
|
|
| 109 | + }
|
|
| 110 | + |
|
| 111 | + function changePaginationSize(config, source) {
|
|
| 112 | + let newValue = source.value;
|
|
| 113 | + // console.info("Change pagination size to: " + newValue);
|
|
| 114 | + updateGrid(config);
|
|
| 115 | + }
|
|
| 116 | + |
|
| 117 | + function updateGrid(config) {
|
|
| 118 | + let newConfig = {
|
|
| 119 | + language: config.language,
|
|
| 120 | + data: config.data,
|
|
| 121 | + columns: config.columns,
|
|
| 122 | + search: searchValue(),
|
|
| 123 | + resizable: resizableValue(),
|
|
| 124 | + sort: sortValue(),
|
|
| 125 | + pagination: paginationValue()
|
|
| 126 | + };
|
|
| 127 | + gridContainerParent.innerHTML = "<div id=\"wrapper\"></div>";
|
|
| 128 | + // console.info(newConfig);
|
|
| 129 | + setTimeout(() => {
|
|
| 130 | + grid = new gridjs.Grid(newConfig).render(document.getElementById("wrapper"));
|
|
| 131 | + }, 50);
|
|
| 132 | + }
|
|
| 133 | + </script>
|
|
| 134 | +</head>
|
|
| 135 | +<body>
|
|
| 136 | +<h1>Report ${.data_model.selectedReport.name}</h1>
|
|
| 137 | +<h2>Configuration</h2>
|
|
| 138 | +<h3>Selected data:</h3>
|
|
| 139 | +<ul>
|
|
| 140 | + <li>
|
|
| 141 | + <#assign selectDataModel = .data_model.selectDataModel.selectionDataModel />
|
|
| 142 | + <#assign selectDataCount = selectDataModel.getSelectedCount() />
|
|
| 143 | + |
|
| 144 | + <#if selectDataCount == 1> 1 trip <#else> ${selectDataCount} trips</#if>.
|
|
| 145 | + <ul>
|
|
| 146 | + <#list selectDataModel.getSelectedLabels() as key, value>
|
|
| 147 | + <li>
|
|
| 148 | + ${key}
|
|
| 149 | + <ul>
|
|
| 150 | + <#list value as trip>
|
|
| 151 | + <li>${trip}</li>
|
|
| 152 | + </#list>
|
|
| 153 | + </ul>
|
|
| 154 | + </li>
|
|
| 155 | + </#list>
|
|
| 156 | + </ul>
|
|
| 157 | + </li>
|
|
| 158 | +</ul>
|
|
| 159 | +<h3>Selected report:</h3>
|
|
| 160 | + |
|
| 161 | +<#assign selectedReport = .data_model.selectedReport />
|
|
| 162 | +<p><b>${selectedReport.name}</b></p>
|
|
| 163 | +<ul>
|
|
| 164 | + <#list selectedReport.getVariables() as variable>
|
|
| 165 | + <li>
|
|
| 166 | + Variable ${variable.name} : ${variable.selectedValue}.
|
|
| 167 | + </li>
|
|
| 168 | + </#list>
|
|
| 169 | +</ul>
|
|
| 170 | +<h2>Result</h2>
|
|
| 171 | + |
|
| 172 | +<div class="config-panel">
|
|
| 173 | + <label><input id="search" type="checkbox" checked/> Search</label>|
|
|
| 174 | + <label><input id="resizable" type="checkbox" checked/> Resizable columns</label>|
|
|
| 175 | + <label><input id="sort" type="checkbox" checked/> Sort</label>|
|
|
| 176 | + <label><input id="pagination" type="checkbox"/> Pagination</label>|
|
|
| 177 | + <label>Page size <input id="paginationSize" type="number" disabled value="20"/></label>
|
|
| 178 | +</div>
|
|
| 179 | +<div id="wrapperParent">
|
|
| 180 | + <div id="wrapper"></div>
|
|
| 181 | +</div>
|
|
| 182 | +<script type="application/javascript">
|
|
| 183 | + const json = ${.data_model.json};
|
|
| 184 | + |
|
| 185 | + const gridContainerParent = document.getElementById("wrapperParent");
|
|
| 186 | + const searchOption = document.getElementById("search");
|
|
| 187 | + const resizableOption = document.getElementById("resizable");
|
|
| 188 | + const paginationOption = document.getElementById("pagination");
|
|
| 189 | + const paginationSizeOption = document.getElementById("paginationSize");
|
|
| 190 | + const sortOption = document.getElementById("sort");
|
|
| 191 | + |
|
| 192 | + let grid = new gridjs.Grid({
|
|
| 193 | + search: searchValue(),
|
|
| 194 | + resizable: resizableValue(),
|
|
| 195 | + sort: sortValue(),
|
|
| 196 | + pagination: paginationValue(),
|
|
| 197 | + <#--language: {-->
|
|
| 198 | + <#-- 'search': {-->
|
|
| 199 | + <#-- 'placeholder': '🔍 Recherche...'-->
|
|
| 200 | + <#-- },-->
|
|
| 201 | + <#-- sort: {-->
|
|
| 202 | + <#-- sortAsc: 'Tri ascendant',-->
|
|
| 203 | + <#-- sortDesc: 'Tri descendant',-->
|
|
| 204 | + <#-- },-->
|
|
| 205 | + <#-- pagination: {-->
|
|
| 206 | + <#-- previous: 'Précédent',-->
|
|
| 207 | + <#-- next: 'Suivant',-->
|
|
| 208 | + <#-- navigate: (page, pages) => `Page ${r"${page}"} sur ${r"${pages}"}`,-->
|
|
| 209 | + <#-- page: (page) => `Page ${r"${page}"}`,-->
|
|
| 210 | + <#-- showing: 'Affichage des lignes de',-->
|
|
| 211 | + <#-- of: 'sur',-->
|
|
| 212 | + <#-- to: 'à',-->
|
|
| 213 | + <#-- results: 'lignes.',-->
|
|
| 214 | + <#-- },-->
|
|
| 215 | + <#-- loading: 'Chargement...'-->
|
|
| 216 | + <#--},-->
|
|
| 217 | + columns: !!json.columnNames ? json.columnNames : [],
|
|
| 218 | + data: json.data.data
|
|
| 219 | + });
|
|
| 220 | + updateGrid(grid.config);
|
|
| 221 | + |
|
| 222 | + searchOption.addEventListener("change", function () {
|
|
| 223 | + toggleSearch(grid.config, this);
|
|
| 224 | + });
|
|
| 225 | + resizableOption.addEventListener("change", function () {
|
|
| 226 | + toggleResizable(grid.config, this);
|
|
| 227 | + });
|
|
| 228 | + sortOption.addEventListener("change", function () {
|
|
| 229 | + toggleSort(grid.config, this);
|
|
| 230 | + });
|
|
| 231 | + paginationOption.addEventListener("change", function () {
|
|
| 232 | + togglePagination(grid.config, this);
|
|
| 233 | + });
|
|
| 234 | + |
|
| 235 | + paginationSizeOption.addEventListener("change", function () {
|
|
| 236 | + changePaginationSize(grid.config, this);
|
|
| 237 | + });
|
|
| 238 | +</script>
|
|
| 239 | +</body>
|
|
| 240 | +</html> |
| 1 | +<#-- @ftlvariable name=".data_model" type="fr.ird.observe.client.datasource.actions.report.HtmlExportModel" -->
|
|
| 2 | +<!DOCTYPE html>
|
|
| 3 | +<!--
|
|
| 4 | + #%L
|
|
| 5 | + ObServe Client :: DataSource :: Actions
|
|
| 6 | + %%
|
|
| 7 | + Copyright (C) 2008 - 2023 IRD, Ultreia.io
|
|
| 8 | + %%
|
|
| 9 | + This program is free software: you can redistribute it and/or modify
|
|
| 10 | + it under the terms of the GNU General Public License as
|
|
| 11 | + published by the Free Software Foundation, either version 3 of the
|
|
| 12 | + License, or (at your option) any later version.
|
|
| 13 | + |
|
| 14 | + This program is distributed in the hope that it will be useful,
|
|
| 15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 17 | + GNU General Public License for more details.
|
|
| 18 | + |
|
| 19 | + You should have received a copy of the GNU General Public
|
|
| 20 | + License along with this program. If not, see
|
|
| 21 | + <http://www.gnu.org/licenses/gpl-3.0.html>.
|
|
| 22 | + #L%
|
|
| 23 | + -->
|
|
| 24 | + |
|
| 25 | +<html lang="fr">
|
|
| 26 | +<head>
|
|
| 27 | + <link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet"/>
|
|
| 28 | + <title>Rapport ${.data_model.selectedReport.name}</title>
|
|
| 29 | + <script src="https://unpkg.com/gridjs/dist/gridjs.umd.js"></script>
|
|
| 30 | + <style>
|
|
| 31 | + .config-panel {
|
|
| 32 | + padding: 10px;
|
|
| 33 | + margin: 10px 0;
|
|
| 34 | + background: #fcfcfc;
|
|
| 35 | + border: 1px solid #e9e9e9;
|
|
| 36 | + display: inline-block;
|
|
| 37 | + }
|
|
| 38 | + |
|
| 39 | + .config-panel label {
|
|
| 40 | + margin-right: 10px;
|
|
| 41 | + }
|
|
| 42 | + |
|
| 43 | + td.gridjs-td {
|
|
| 44 | + background-color: transparent;
|
|
| 45 | + }
|
|
| 46 | + |
|
| 47 | + tr:nth-child(even) {
|
|
| 48 | + background-color: #dddddd;
|
|
| 49 | + }
|
|
| 50 | + |
|
| 51 | + tr:hover td {
|
|
| 52 | + background-color: rgba(0, 0, 0, 0.1);
|
|
| 53 | + }
|
|
| 54 | + |
|
| 55 | + tr td:hover {
|
|
| 56 | + color: #fff;
|
|
| 57 | + }
|
|
| 58 | + |
|
| 59 | + th:hover {
|
|
| 60 | + background-color: #999;
|
|
| 61 | + color: #fff;
|
|
| 62 | + }
|
|
| 63 | + </style>
|
|
| 64 | + <script type="application/javascript">
|
|
| 65 | + |
|
| 66 | + function searchValue() {
|
|
| 67 | + return searchOption.checked;
|
|
| 68 | + }
|
|
| 69 | + |
|
| 70 | + function resizableValue() {
|
|
| 71 | + return resizableOption.checked;
|
|
| 72 | + }
|
|
| 73 | + |
|
| 74 | + function sortValue() {
|
|
| 75 | + return sortOption.checked;
|
|
| 76 | + }
|
|
| 77 | + |
|
| 78 | + function paginationValue() {
|
|
| 79 | + return paginationOption.checked ? {limit: paginationSizeOption.value} : false;
|
|
| 80 | + }
|
|
| 81 | + |
|
| 82 | + function toggleSearch(config, source) {
|
|
| 83 | + let newValue = source.checked;
|
|
| 84 | + // console.info("Toggle search to: " + newValue);
|
|
| 85 | + updateGrid(config);
|
|
| 86 | + }
|
|
| 87 | + |
|
| 88 | + function toggleResizable(config, source) {
|
|
| 89 | + let newValue = source.checked;
|
|
| 90 | + // console.info("Toggle resizable to: " + newValue);
|
|
| 91 | + updateGrid(config);
|
|
| 92 | + }
|
|
| 93 | + |
|
| 94 | + function toggleSort(config, source) {
|
|
| 95 | + let newValue = source.checked;
|
|
| 96 | + // console.info("Toggle sort to: " + newValue);
|
|
| 97 | + updateGrid(config);
|
|
| 98 | + }
|
|
| 99 | + |
|
| 100 | + function togglePagination(config, source) {
|
|
| 101 | + let newValue = source.checked;
|
|
| 102 | + // console.info("Toggle pagination to: " + newValue);
|
|
| 103 | + if (newValue) {
|
|
| 104 | + paginationSizeOption["disabled"] = null;
|
|
| 105 | + } else {
|
|
| 106 | + paginationSizeOption.disabled = true;
|
|
| 107 | + }
|
|
| 108 | + updateGrid(config);
|
|
| 109 | + }
|
|
| 110 | + |
|
| 111 | + function changePaginationSize(config, source) {
|
|
| 112 | + let newValue = source.value;
|
|
| 113 | + // console.info("Change pagination size to: " + newValue);
|
|
| 114 | + updateGrid(config);
|
|
| 115 | + }
|
|
| 116 | + |
|
| 117 | + function updateGrid(config) {
|
|
| 118 | + let newConfig = {
|
|
| 119 | + language: config.language,
|
|
| 120 | + data: config.data,
|
|
| 121 | + columns: config.columns,
|
|
| 122 | + search: searchValue(),
|
|
| 123 | + resizable: resizableValue(),
|
|
| 124 | + sort: sortValue(),
|
|
| 125 | + pagination: paginationValue()
|
|
| 126 | + };
|
|
| 127 | + gridContainerParent.innerHTML = "<div id=\"wrapper\"></div>";
|
|
| 128 | + // console.info(newConfig);
|
|
| 129 | + setTimeout(() => {
|
|
| 130 | + grid = new gridjs.Grid(newConfig).render(document.getElementById("wrapper"));
|
|
| 131 | + }, 50);
|
|
| 132 | + }
|
|
| 133 | + </script>
|
|
| 134 | +</head>
|
|
| 135 | +<body>
|
|
| 136 | +<h1>Rapport ${.data_model.selectedReport.name}</h1>
|
|
| 137 | +<h2>Configuration</h2>
|
|
| 138 | +<h3>Données sélectionnées :</h3>
|
|
| 139 | +<ul>
|
|
| 140 | + <li>
|
|
| 141 | + <#assign selectDataModel = .data_model.selectDataModel.selectionDataModel />
|
|
| 142 | + <#assign selectDataCount = selectDataModel.getSelectedCount() />
|
|
| 143 | + |
|
| 144 | + <#if selectDataCount == 1> 1 marée <#else> ${selectDataCount} marées</#if>.
|
|
| 145 | + <ul>
|
|
| 146 | + <#list selectDataModel.getSelectedLabels() as key, value>
|
|
| 147 | + <li>
|
|
| 148 | + ${key}
|
|
| 149 | + <ul>
|
|
| 150 | + <#list value as trip>
|
|
| 151 | + <li>${trip}</li>
|
|
| 152 | + </#list>
|
|
| 153 | + </ul>
|
|
| 154 | + </li>
|
|
| 155 | + </#list>
|
|
| 156 | + </ul>
|
|
| 157 | + </li>
|
|
| 158 | +</ul>
|
|
| 159 | +<h3>Rapport sélectionné :</h3>
|
|
| 160 | + |
|
| 161 | +<#assign selectedReport = .data_model.selectedReport />
|
|
| 162 | +<p><b>${selectedReport.name}</b></p>
|
|
| 163 | +<ul>
|
|
| 164 | + <#list selectedReport.getVariables() as variable>
|
|
| 165 | + <li>
|
|
| 166 | + Variable ${variable.name} : ${variable.selectedValue}.
|
|
| 167 | + </li>
|
|
| 168 | + </#list>
|
|
| 169 | +</ul>
|
|
| 170 | +<h2>Résultat</h2>
|
|
| 171 | + |
|
| 172 | +<div class="config-panel">
|
|
| 173 | + <label><input id="search" type="checkbox" checked/> Recherche</label>|
|
|
| 174 | + <label><input id="resizable" type="checkbox" checked/> Colonnes redimensionnables</label>|
|
|
| 175 | + <label><input id="sort" type="checkbox" checked/> Tri des colonnes</label>|
|
|
| 176 | + <label><input id="pagination" type="checkbox"/> Pagination</label>|
|
|
| 177 | + <label>Nombre de lignes par page <input id="paginationSize" type="number" disabled value="20"/></label>
|
|
| 178 | +</div>
|
|
| 179 | +<div id="wrapperParent">
|
|
| 180 | + <div id="wrapper"></div>
|
|
| 181 | +</div>
|
|
| 182 | +<script type="application/javascript">
|
|
| 183 | + const json = ${.data_model.json};
|
|
| 184 | + |
|
| 185 | + const gridContainerParent = document.getElementById("wrapperParent");
|
|
| 186 | + const searchOption = document.getElementById("search");
|
|
| 187 | + const resizableOption = document.getElementById("resizable");
|
|
| 188 | + const paginationOption = document.getElementById("pagination");
|
|
| 189 | + const paginationSizeOption = document.getElementById("paginationSize");
|
|
| 190 | + const sortOption = document.getElementById("sort");
|
|
| 191 | + |
|
| 192 | + let grid = new gridjs.Grid({
|
|
| 193 | + search: searchValue(),
|
|
| 194 | + resizable: resizableValue(),
|
|
| 195 | + sort: sortValue(),
|
|
| 196 | + pagination: paginationValue(),
|
|
| 197 | + language: {
|
|
| 198 | + 'search': {
|
|
| 199 | + 'placeholder': '🔍 Recherche...'
|
|
| 200 | + },
|
|
| 201 | + sort: {
|
|
| 202 | + sortAsc: 'Tri ascendant',
|
|
| 203 | + sortDesc: 'Tri descendant',
|
|
| 204 | + },
|
|
| 205 | + pagination: {
|
|
| 206 | + previous: 'Précédent',
|
|
| 207 | + next: 'Suivant',
|
|
| 208 | + navigate: (page, pages) => `Page ${r"${page}"} sur ${r"${pages}"}`,
|
|
| 209 | + page: (page) => `Page ${r"${page}"}`,
|
|
| 210 | + showing: 'Affichage des lignes de',
|
|
| 211 | + of: 'sur',
|
|
| 212 | + to: 'à',
|
|
| 213 | + results: 'lignes.',
|
|
| 214 | + },
|
|
| 215 | + loading: 'Chargement...'
|
|
| 216 | + },
|
|
| 217 | + columns: !!json.columnNames ? json.columnNames : [],
|
|
| 218 | + data: json.data.data
|
|
| 219 | + });
|
|
| 220 | + updateGrid(grid.config);
|
|
| 221 | + |
|
| 222 | + searchOption.addEventListener("change", function () {
|
|
| 223 | + toggleSearch(grid.config, this);
|
|
| 224 | + });
|
|
| 225 | + resizableOption.addEventListener("change", function () {
|
|
| 226 | + toggleResizable(grid.config, this);
|
|
| 227 | + });
|
|
| 228 | + sortOption.addEventListener("change", function () {
|
|
| 229 | + toggleSort(grid.config, this);
|
|
| 230 | + });
|
|
| 231 | + paginationOption.addEventListener("change", function () {
|
|
| 232 | + togglePagination(grid.config, this);
|
|
| 233 | + });
|
|
| 234 | + |
|
| 235 | + paginationSizeOption.addEventListener("change", function () {
|
|
| 236 | + changePaginationSize(grid.config, this);
|
|
| 237 | + });
|
|
| 238 | +</script>
|
|
| 239 | +</body>
|
|
| 240 | +</html> |
| ... | ... | @@ -42,6 +42,7 @@ public class ObserveKeyStrokesActions extends ObserveKeyStrokesEditorApi { |
| 42 | 42 | public static final KeyStroke KEY_STROKE_EXPORT_POPUP = KeyStroke.getKeyStroke("pressed F10");
|
| 43 | 43 | public static final KeyStroke KEY_STROKE_EXPORT_CLIPBOARD = KeyStroke.getKeyStroke("pressed F2");
|
| 44 | 44 | public static final KeyStroke KEY_STROKE_EXPORT_CSV = KeyStroke.getKeyStroke("pressed F3");
|
| 45 | + public static final KeyStroke KEY_STROKE_EXPORT_HTML = KeyStroke.getKeyStroke("pressed F4");
|
|
| 45 | 46 | |
| 46 | 47 | public static final KeyStroke KEY_STROKE_EXIT = KeyStroke.getKeyStroke("alt pressed F");
|
| 47 | 48 | } |
| 1 | +package fr.ird.observe.client.datasource.actions.report;
|
|
| 2 | + |
|
| 3 | +/*-
|
|
| 4 | + * #%L
|
|
| 5 | + * ObServe Client :: DataSource :: Actions
|
|
| 6 | + * %%
|
|
| 7 | + * Copyright (C) 2008 - 2023 IRD, Ultreia.io
|
|
| 8 | + * %%
|
|
| 9 | + * This program is free software: you can redistribute it and/or modify
|
|
| 10 | + * it under the terms of the GNU General Public License as
|
|
| 11 | + * published by the Free Software Foundation, either version 3 of the
|
|
| 12 | + * License, or (at your option) any later version.
|
|
| 13 | + *
|
|
| 14 | + * This program is distributed in the hope that it will be useful,
|
|
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 17 | + * GNU General Public License for more details.
|
|
| 18 | + *
|
|
| 19 | + * You should have received a copy of the GNU General Public
|
|
| 20 | + * License along with this program. If not, see
|
|
| 21 | + * <http://www.gnu.org/licenses/gpl-3.0.html>.
|
|
| 22 | + * #L%
|
|
| 23 | + */
|
|
| 24 | + |
|
| 25 | +import com.google.gson.Gson;
|
|
| 26 | +import fr.ird.observe.client.datasource.actions.config.SelectDataModel;
|
|
| 27 | +import fr.ird.observe.report.Report;
|
|
| 28 | +import io.ultreia.java4all.application.template.spi.GenerateTemplate;
|
|
| 29 | +import io.ultreia.java4all.util.matrix.DataMatrix;
|
|
| 30 | + |
|
| 31 | +import java.util.List;
|
|
| 32 | + |
|
| 33 | +/**
|
|
| 34 | + * The model used to generate data file in html export.
|
|
| 35 | + *
|
|
| 36 | + * Created at 15/11/2023.
|
|
| 37 | + *
|
|
| 38 | + * @author Tony Chemit - dev@tchemit.fr
|
|
| 39 | + * @since 9.3.0
|
|
| 40 | + */
|
|
| 41 | +@GenerateTemplate(template = "reportHtmlExport.ftl")
|
|
| 42 | +public class HtmlExportModel {
|
|
| 43 | + /**
|
|
| 44 | + * Selected report.
|
|
| 45 | + */
|
|
| 46 | + private final transient Report selectedReport;
|
|
| 47 | + /**
|
|
| 48 | + * Selected data model.
|
|
| 49 | + */
|
|
| 50 | + private final transient SelectDataModel selectDataModel;
|
|
| 51 | + |
|
| 52 | + private final List<String> columnNames;
|
|
| 53 | + private final List<String> rowNames;
|
|
| 54 | + private final DataMatrix data;
|
|
| 55 | + private final boolean withColumnHeader;
|
|
| 56 | + private final boolean withRowHeader;
|
|
| 57 | + private final transient String json;
|
|
| 58 | + |
|
| 59 | + public HtmlExportModel(Gson gson,
|
|
| 60 | + Report selectedReport,
|
|
| 61 | + SelectDataModel selectDataModel,
|
|
| 62 | + List<String> columnNames,
|
|
| 63 | + List<String> rowNames,
|
|
| 64 | + DataMatrix data,
|
|
| 65 | + boolean withColumnHeader,
|
|
| 66 | + boolean withRowHeader) {
|
|
| 67 | + this.selectedReport = selectedReport;
|
|
| 68 | + this.selectDataModel = selectDataModel;
|
|
| 69 | + this.columnNames = columnNames;
|
|
| 70 | + this.rowNames = rowNames;
|
|
| 71 | + this.data = data;
|
|
| 72 | + this.withColumnHeader = withColumnHeader;
|
|
| 73 | + this.withRowHeader = withRowHeader;
|
|
| 74 | + this.json = gson.toJson(this);
|
|
| 75 | + }
|
|
| 76 | + |
|
| 77 | + public String getJson() {
|
|
| 78 | + return json;
|
|
| 79 | + }
|
|
| 80 | + |
|
| 81 | + public Report getSelectedReport() {
|
|
| 82 | + return selectedReport;
|
|
| 83 | + }
|
|
| 84 | + |
|
| 85 | + public SelectDataModel getSelectDataModel() {
|
|
| 86 | + return selectDataModel;
|
|
| 87 | + }
|
|
| 88 | + |
|
| 89 | + public List<String> getColumnNames() {
|
|
| 90 | + return columnNames;
|
|
| 91 | + }
|
|
| 92 | + |
|
| 93 | + public List<String> getRowNames() {
|
|
| 94 | + return rowNames;
|
|
| 95 | + }
|
|
| 96 | + |
|
| 97 | + public DataMatrix getData() {
|
|
| 98 | + return data;
|
|
| 99 | + }
|
|
| 100 | + |
|
| 101 | + public boolean isWithColumnHeader() {
|
|
| 102 | + return withColumnHeader;
|
|
| 103 | + }
|
|
| 104 | + |
|
| 105 | + public boolean isWithRowHeader() {
|
|
| 106 | + return withRowHeader;
|
|
| 107 | + }
|
|
| 108 | +} |
| ... | ... | @@ -60,6 +60,7 @@ import java.io.File; |
| 60 | 60 | import java.io.IOException;
|
| 61 | 61 | import java.net.URL;
|
| 62 | 62 | import java.nio.file.Files;
|
| 63 | +import java.nio.file.Path;
|
|
| 63 | 64 | import java.util.ArrayList;
|
| 64 | 65 | import java.util.Collections;
|
| 65 | 66 | import java.util.Comparator;
|
| ... | ... | @@ -397,6 +398,10 @@ public class ReportModel extends AdminActionModel { |
| 397 | 398 | return new File(getClientConfig().getExportDirectory(), String.format("export-%1$s--%2$tF--%2$tk-%2$tM-%2$tS.csv", Objects.requireNonNull(getSelectedReport()).getId().replaceAll("\\.", "_"), new Date()));
|
| 398 | 399 | }
|
| 399 | 400 | |
| 401 | + public Path newExportHtmlDirectory() {
|
|
| 402 | + return getClientConfig().getExportDirectory().toPath().resolve( String.format("export-%1$s--%2$tF--%2$tk-%2$tM-%2$tS", Objects.requireNonNull(getSelectedReport()).getId().replaceAll("\\.", "_"), new Date()));
|
|
| 403 | + }
|
|
| 404 | + |
|
| 400 | 405 | void onReportsChanged(ReportUI ui, List<ReportDefinition> newValue) {
|
| 401 | 406 | log.debug(String.format("New reports : %s", newValue));
|
| 402 | 407 | newValue.sort(Comparator.comparing(ReportDefinition::getName));
|
| ... | ... | @@ -596,6 +601,11 @@ public class ReportModel extends AdminActionModel { |
| 596 | 601 | }
|
| 597 | 602 | }
|
| 598 | 603 | |
| 604 | + public HtmlExportModel toJsonModel() {
|
|
| 605 | + |
|
| 606 | + return new HtmlExportModel(getClientConfig().getGsonSupplier().get(), getSelectedReport(), selectDataModel, getResultModel().getColumnNames(), getResultModel().getRowNames(), getResultModel().getData(), getResultModel().isWithColumnHeader(), getResultModel().isWithRowHeader());
|
|
| 607 | + }
|
|
| 608 | + |
|
| 599 | 609 | private Map<String, FilterableComboBox<?>> initVariableComponents(ReportUI ui, Report report) {
|
| 600 | 610 | Map<String, FilterableComboBox<?>> result = new TreeMap<>();
|
| 601 | 611 | JPanel variablesPanel = ui.getReportVariableSelectorPanel();
|
| ... | ... | @@ -80,6 +80,7 @@ public void destroy() { |
| 80 | 80 | <JPopupMenu id='exportPopup'>
|
| 81 | 81 | <JMenuItem id='exportToClipboard' styleClass="enabledIfReportSelected"/>
|
| 82 | 82 | <JMenuItem id='exportToCsv' styleClass="enabledIfReportSelected"/>
|
| 83 | + <JMenuItem id='exportToHtml' styleClass="enabledIfReportSelected"/>
|
|
| 83 | 84 | </JPopupMenu>
|
| 84 | 85 | <JToolBar id='titleRightToolBar'>
|
| 85 | 86 | <JToggleButton id='toggleExport'/>
|
| ... | ... | @@ -236,6 +236,26 @@ public class ResultTableModel extends AbstractTableModel { |
| 236 | 236 | return data == null ? null : data.getValue(columnIndex, rowIndex);
|
| 237 | 237 | }
|
| 238 | 238 | |
| 239 | + public List<String> getColumnNames() {
|
|
| 240 | + return columnNames;
|
|
| 241 | + }
|
|
| 242 | + |
|
| 243 | + public List<String> getRowNames() {
|
|
| 244 | + return rowNames;
|
|
| 245 | + }
|
|
| 246 | + |
|
| 247 | + public DataMatrix getData() {
|
|
| 248 | + return data;
|
|
| 249 | + }
|
|
| 250 | + |
|
| 251 | + public boolean isWithColumnHeader() {
|
|
| 252 | + return withColumnHeader;
|
|
| 253 | + }
|
|
| 254 | + |
|
| 255 | + public boolean isWithRowHeader() {
|
|
| 256 | + return withRowHeader;
|
|
| 257 | + }
|
|
| 258 | + |
|
| 239 | 259 | public String getClipboardContent(boolean copyRowHeaders, boolean copyColumnHeaders) {
|
| 240 | 260 | return getDataContent(copyRowHeaders, copyColumnHeaders, true, '\t');
|
| 241 | 261 | }
|
| ... | ... | @@ -264,5 +284,4 @@ public class ResultTableModel extends AbstractTableModel { |
| 264 | 284 | result += data.getClipboardContent(copyRowHeaders || !withRowHeader, true, escapeCell, separator);
|
| 265 | 285 | return result;
|
| 266 | 286 | }
|
| 267 | - |
|
| 268 | 287 | } |
| ... | ... | @@ -43,7 +43,7 @@ public class ExportToClipboard extends AdminTabUIActionSupport<ReportUI> { |
| 43 | 43 | public ExportToClipboard() {
|
| 44 | 44 | super(t("observe.ui.datasource.editor.actions.report.exportToClipboard"),
|
| 45 | 45 | t("observe.ui.datasource.editor.actions.synchro.copy.tip"),
|
| 46 | - "report-copy",
|
|
| 46 | + "export-clipboard",
|
|
| 47 | 47 | ObserveKeyStrokesActions.KEY_STROKE_EXPORT_CLIPBOARD);
|
| 48 | 48 | setCheckMenuItemIsArmed(false);
|
| 49 | 49 | }
|
| 1 | +package fr.ird.observe.client.datasource.actions.report.actions;
|
|
| 2 | + |
|
| 3 | +/*-
|
|
| 4 | + * #%L
|
|
| 5 | + * ObServe Client :: DataSource :: Actions
|
|
| 6 | + * %%
|
|
| 7 | + * Copyright (C) 2008 - 2023 IRD, Ultreia.io
|
|
| 8 | + * %%
|
|
| 9 | + * This program is free software: you can redistribute it and/or modify
|
|
| 10 | + * it under the terms of the GNU General Public License as
|
|
| 11 | + * published by the Free Software Foundation, either version 3 of the
|
|
| 12 | + * License, or (at your option) any later version.
|
|
| 13 | + *
|
|
| 14 | + * This program is distributed in the hope that it will be useful,
|
|
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 17 | + * GNU General Public License for more details.
|
|
| 18 | + *
|
|
| 19 | + * You should have received a copy of the GNU General Public
|
|
| 20 | + * License along with this program. If not, see
|
|
| 21 | + * <http://www.gnu.org/licenses/gpl-3.0.html>.
|
|
| 22 | + * #L%
|
|
| 23 | + */
|
|
| 24 | + |
|
| 25 | +import fr.ird.observe.client.datasource.actions.ObserveKeyStrokesActions;
|
|
| 26 | +import fr.ird.observe.client.datasource.actions.actions.AdminTabUIActionSupport;
|
|
| 27 | +import fr.ird.observe.client.datasource.actions.report.HtmlExportModel;
|
|
| 28 | +import fr.ird.observe.client.datasource.actions.report.HtmlExportModelTemplate;
|
|
| 29 | +import fr.ird.observe.client.datasource.actions.report.ReportModel;
|
|
| 30 | +import fr.ird.observe.client.datasource.actions.report.ReportUI;
|
|
| 31 | +import fr.ird.observe.client.util.UIHelper;
|
|
| 32 | +import org.apache.logging.log4j.LogManager;
|
|
| 33 | +import org.apache.logging.log4j.Logger;
|
|
| 34 | + |
|
| 35 | +import java.awt.event.ActionEvent;
|
|
| 36 | +import java.io.IOException;
|
|
| 37 | +import java.nio.file.Files;
|
|
| 38 | +import java.nio.file.Path;
|
|
| 39 | + |
|
| 40 | +import static io.ultreia.java4all.i18n.I18n.t;
|
|
| 41 | + |
|
| 42 | +/**
|
|
| 43 | + * Created at 15/11/2023.
|
|
| 44 | + *
|
|
| 45 | + * @author Tony Chemit - dev@tchemit.fr
|
|
| 46 | + * @since 9.3.0
|
|
| 47 | + */
|
|
| 48 | +public class ExportToHtml extends AdminTabUIActionSupport<ReportUI> {
|
|
| 49 | + |
|
| 50 | + private static final Logger log = LogManager.getLogger(ExportToClipboard.class);
|
|
| 51 | + |
|
| 52 | + public ExportToHtml() {
|
|
| 53 | + super(t("observe.ui.datasource.editor.actions.report.exportToHtml"),
|
|
| 54 | + t("observe.ui.datasource.editor.actions.report.exportToHtml.tip"),
|
|
| 55 | + "export-html",
|
|
| 56 | + ObserveKeyStrokesActions.KEY_STROKE_EXPORT_HTML);
|
|
| 57 | + setCheckMenuItemIsArmed(false);
|
|
| 58 | + }
|
|
| 59 | + |
|
| 60 | + @Override
|
|
| 61 | + protected void doActionPerformed(ActionEvent e, ReportUI ui) {
|
|
| 62 | + try {
|
|
| 63 | + run();
|
|
| 64 | + } catch (IOException ex) {
|
|
| 65 | + throw new RuntimeException(ex);
|
|
| 66 | + }
|
|
| 67 | + }
|
|
| 68 | + |
|
| 69 | + |
|
| 70 | + private void run() throws IOException {
|
|
| 71 | + ReportModel stepModel = ui.getStepModel();
|
|
| 72 | + |
|
| 73 | + String reportId = stepModel.getSelectedReport().getId();
|
|
| 74 | + // generate result directory
|
|
| 75 | + Path exportDirectory = stepModel.newExportHtmlDirectory();
|
|
| 76 | + Files.createDirectories(exportDirectory);
|
|
| 77 | + |
|
| 78 | + // generate data file
|
|
| 79 | + Path dataFile = exportDirectory.resolve("data.json");
|
|
| 80 | + log.info("Generate data file for report ({}) at {}", reportId, dataFile);
|
|
| 81 | + HtmlExportModel dataModel = stepModel.toJsonModel();
|
|
| 82 | + String dataContent = dataModel.getJson();
|
|
| 83 | + Files.writeString(dataFile, dataContent);
|
|
| 84 | + |
|
| 85 | + // generate html file
|
|
| 86 | + Path htmlFile = exportDirectory.resolve("report.html");
|
|
| 87 | + log.info("Generate html file for report ({}) at {}", reportId, htmlFile);
|
|
| 88 | + String fileContent = HtmlExportModelTemplate.generate(dataModel);
|
|
| 89 | + Files.writeString(htmlFile, fileContent);
|
|
| 90 | + |
|
| 91 | + // open html file
|
|
| 92 | + UIHelper.openLink(htmlFile.toUri());
|
|
| 93 | + setUiStatus(t("observe.ui.datasource.editor.actions.report.exportToHtml.done", exportDirectory));
|
|
| 94 | + }
|
|
| 95 | +} |
| ... | ... | @@ -573,6 +573,9 @@ observe.ui.datasource.editor.actions.report.exportToClipboard=Clipboard |
| 573 | 573 | observe.ui.datasource.editor.actions.report.exportToCsv=CSV
|
| 574 | 574 | observe.ui.datasource.editor.actions.report.exportToCsv.done=Csv export done at %s
|
| 575 | 575 | observe.ui.datasource.editor.actions.report.exportToCsv.tip=Export to csv
|
| 576 | +observe.ui.datasource.editor.actions.report.exportToHtml=Html
|
|
| 577 | +observe.ui.datasource.editor.actions.report.exportToHtml.done=Html export done at %s
|
|
| 578 | +observe.ui.datasource.editor.actions.report.exportToHtml.tip=Export to html
|
|
| 576 | 579 | observe.ui.datasource.editor.actions.report.no.report.found=No report found.
|
| 577 | 580 | observe.ui.datasource.editor.actions.report.report.count.found=Found %s reports.
|
| 578 | 581 | observe.ui.datasource.editor.actions.report.report.description=Description of selected report
|
| ... | ... | @@ -573,6 +573,9 @@ observe.ui.datasource.editor.actions.report.exportToClipboard=Clipboard |
| 573 | 573 | observe.ui.datasource.editor.actions.report.exportToCsv=CSV
|
| 574 | 574 | observe.ui.datasource.editor.actions.report.exportToCsv.done=Csv export done at %s
|
| 575 | 575 | observe.ui.datasource.editor.actions.report.exportToCsv.tip=Export to csv
|
| 576 | +observe.ui.datasource.editor.actions.report.exportToHtml=Html
|
|
| 577 | +observe.ui.datasource.editor.actions.report.exportToHtml.done=Html export done at %s \#TODO
|
|
| 578 | +observe.ui.datasource.editor.actions.report.exportToHtml.tip=Export to html \#TODO
|
|
| 576 | 579 | observe.ui.datasource.editor.actions.report.no.report.found=No report found. \#TODO
|
| 577 | 580 | observe.ui.datasource.editor.actions.report.report.count.found=Found %s reports. \#TODO
|
| 578 | 581 | observe.ui.datasource.editor.actions.report.report.description=Descripción del informe seleccionado
|
| ... | ... | @@ -573,6 +573,9 @@ observe.ui.datasource.editor.actions.report.exportToClipboard=Presse papier |
| 573 | 573 | observe.ui.datasource.editor.actions.report.exportToCsv=Csv
|
| 574 | 574 | observe.ui.datasource.editor.actions.report.exportToCsv.done=Export csv sauvegardé dans le fichier %s
|
| 575 | 575 | observe.ui.datasource.editor.actions.report.exportToCsv.tip=Exporter au format Csv
|
| 576 | +observe.ui.datasource.editor.actions.report.exportToHtml=Html
|
|
| 577 | +observe.ui.datasource.editor.actions.report.exportToHtml.done=Export html sauvegardé dans le répertoire %s
|
|
| 578 | +observe.ui.datasource.editor.actions.report.exportToHtml.tip=Exporter au format Html
|
|
| 576 | 579 | observe.ui.datasource.editor.actions.report.no.report.found=Aucun rapport trouvé.
|
| 577 | 580 | observe.ui.datasource.editor.actions.report.report.count.found=%s rapports détectés.
|
| 578 | 581 | observe.ui.datasource.editor.actions.report.report.description=Description du rapport sélectionné
|