Tony CHEMIT pushed to branch feature/issue_2755 at ultreiaio / ird-observe

Commits:

20 changed files:

Changes:

  • client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientConfig.java
    ... ... @@ -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
     
    

  • client/core/src/main/resources/observe-ui.properties
    ... ... @@ -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
    

  • client/datasource/actions/pom.xml
    ... ... @@ -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>
    

  • client/datasource/actions/src/main/i18n/getters/java.getter
    ... ... @@ -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
    

  • client/datasource/actions/src/main/i18n/templates/reportHtmlExport_en_GB.ftl
    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&nbsp;<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>

  • client/datasource/actions/src/main/i18n/templates/reportHtmlExport_es_ES.ftl
    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&nbsp;<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>

  • client/datasource/actions/src/main/i18n/templates/reportHtmlExport_fr_FR.ftl
    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&nbsp;<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>

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/ObserveKeyStrokesActions.java
    ... ... @@ -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
     }

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/HtmlExportModel.java
    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
    +}

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ReportModel.java
    ... ... @@ -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();
    

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ReportUI.jaxx
    ... ... @@ -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'/>
    

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/ResultTableModel.java
    ... ... @@ -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
     }

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/actions/ExportToClipboard.java
    ... ... @@ -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
         }
    

  • client/datasource/actions/src/main/java/fr/ird/observe/client/datasource/actions/report/actions/ExportToHtml.java
    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
    +}

  • client/datasource/actions/src/main/resources/icons/action-export-clipboard.png
    No preview for this file type
  • client/datasource/actions/src/main/resources/icons/action-export-csv.png
    No preview for this file type
  • client/datasource/actions/src/main/resources/icons/action-export-html.png
    No preview for this file type
  • client/runner/src/main/i18n/translations/client-runner_en_GB.properties
    ... ... @@ -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
    

  • client/runner/src/main/i18n/translations/client-runner_es_ES.properties
    ... ... @@ -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
    

  • client/runner/src/main/i18n/translations/client-runner_fr_FR.properties
    ... ... @@ -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é