How to download report?

image

image

image

image
image

<?xml version="1.0" encoding="UTF-8" standalone="no"?>






















    <collection id="usersDc_entitybox"
                class="com.company.tegastest.entity.User" >
        <loader id="usersDl_entitybox"
                readOnly="true">
            <query>
                <![CDATA[select e from User e]]>
            </query>
        </loader>
        <fetchPlan extends="_base"/>
    </collection>

    <collection id="module1Dc" class="com.company.tegastest.entity.ActivityLog">
        <loader id="module1Dl">
            <query>
                <![CDATA[select e from ActivityLog e]]>
            </query>
        </loader>
        <fetchPlan extends="_base"/>
    </collection>

    <collection id="module2Dc" class="com.company.tegastest.entity.ActivityLog"/>
    <collection id="module3Dc" class="com.company.tegastest.entity.ActivityLog"/>
    <collection id="module4Dc" class="com.company.tegastest.entity.ActivityLog"/>
</data>
<facets>
    <dataLoadCoordinator auto="true"/>
    <urlQueryParameters>
        <pagination component="pagination1"/>
        <pagination component="pagination2"/>
        <pagination component="pagination3"/>
        <pagination component="pagination4"/>
    </urlQueryParameters>
</facets>
<layout classNames="layout-dashboard" width="100%" padding="false">
    <vbox classNames="vbox-dashboard">

        <h3 id="dashboard_h3_main" text="Dashboard"/>

        <div classNames="auditTrail-form-table">
            <vbox>

                <hbox classNames="hbox-table-dashboard" width="100%" justifyContent="BETWEEN" padding="true">
                    <h3 id="dashboard_h3_table" text="Audit Trail"/>
                </hbox>
                <tabSheet classNames="tabsheet-dashboard" width="100%" >
                    <tab id="tab1" label="Log in/Log out history" classNames="tab-dashboard">

                        <vbox>
                            <hbox width="100%">
                                <textField id="dashboard_searchFieldPlate1" placeholder="Action by..." label="Search" width="55%"
                                           classNames="dashboard-searchFieldPlate"/>

                                <comboBox id="action_userComboBox_audit" label="Action" placeholder="ALL" width="15%"/>
                                <datePicker id="datepicker_audit" label="Date"  width="15%"/>
                                <button id="data1_bttn" text="Download Report" action="dataGrid1.rf"/>
                            </hbox>
                            <dataGrid dataContainer="module1Dc" width="100%" height="100%" minHeight="15em" pageSize="5" id="dataGrid1">
                                <columns>
                                    <column property="activity" header="Action"/>
                                    <column property="actionBy" header="Action by"/>
                                    <column property="user" header="User Role"/>
                                    <column property="actionDate" header="Date/Time"/>
                                </columns>

                                <actions>
                                    <action id="rf" type="report_runListEntityReport"/>
                                </actions>
                            </dataGrid>
                            <simplePagination id="pagination1" dataLoader="activityDl" alignSelf="CENTER" itemsPerPageDefaultValue="5"/>
                        </vbox>

                    </tab>
                    <tab id="tab2" label="Submission history">

                        <vbox>
                            <textField id="dashboard_searchFieldPlate2" placeholder="Enter Company Name..." label="Search" width="50%"
                                       classNames="dashboard-searchFieldPlate"/>
                            <dataGrid dataContainer="module2Dc" width="100%" height="100%" minHeight="15em" pageSize="5" id="dataGrid2">
                                <columns>
                                    <column property="actionBy" header="Action by"/>
                                    <column property="user" header="User Role"/>
                                    <column property="actionDate" header="Date/Time"/>
                                </columns>
                            </dataGrid>
                            <simplePagination id="pagination2" dataLoader="activityDl" alignSelf="CENTER" itemsPerPageDefaultValue="5"/>
                        </vbox>

                    </tab>
                    <tab id="tab3" label="Approval/Rejected/Blacklist">

                        <vbox>
                            <textField id="dashboard_searchFieldPlate3" placeholder="Enter Company Name..." label="Search" width="50%"
                                       classNames="dashboard-searchFieldPlate"/>
                            <dataGrid dataContainer="module3Dc" width="100%" height="100%" minHeight="15em" pageSize="5" id="dataGrid3">
                                <columns>
                                    <column property="actionBy" header="Action by"/>
                                    <column property="user" header="User Role"/>
                                    <column property="actionDate" header="Date/Time"/>
                                </columns>
                            </dataGrid>
                            <simplePagination id="pagination3" dataLoader="activityDl" alignSelf="CENTER" itemsPerPageDefaultValue="5"/>
                        </vbox>

                    </tab>
                    <tab id="tab4" label="Registration/Profile Edit">

                        <vbox>
                            <textField id="dashboard_searchFieldPlate4" placeholder="Enter Company Name..." label="Search" width="50%"
                                       classNames="dashboard-searchFieldPlate"/>
                            <dataGrid dataContainer="module4Dc" width="100%" height="100%" minHeight="15em" pageSize="5" id="dataGrid4">
                                <columns>
                                    <column property="actionBy" header="Action by"/>
                                    <column property="user" header="User Role"/>
                                    <column property="actionDate" header="Date/Time"/>
                                </columns>
                            </dataGrid>
                            <simplePagination id="pagination4" dataLoader="activityDl" alignSelf="CENTER" itemsPerPageDefaultValue="5"/>
                        </vbox>

                    </tab>
                </tabSheet>
            </vbox>
        </div>

    </vbox>

    <footer classNames="footer-dashboard" width="100%">
        <hbox width="100%" justifyContent="BETWEEN" padding="true">
            <hbox>
                <nativeLabel id="dashboard_textfield_footer" classNames="dashboard-textfield-footer"
                             text="Copyright © 2023 | Tabung Gagasan Ekonomi Anak Sarawak (TEGAS)"/>
            </hbox>

            <hbox>

                <hbox>
                    <anchor href="https://www.facebook.com/tegastf" target="BLANK">
                        <image resource="icons/Icon facebook.svg"/>
                    </anchor>
                    <anchor href="https://www.instagram.com/tegas_sarawak" target="BLANK">
                        <image resource="icons/Icon Instagram.svg"/>
                    </anchor>
                </hbox>

            </hbox>
        </hbox>
    </footer>
</layout>

package com.company.tegastest.view.audittrail;

import com.company.tegastest.entity.ActivityLog;
import com.company.tegastest.view.main.MainView;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.router.Route;
import io.jmix.core.DataManager;
import io.jmix.flowui.component.datepicker.TypedDatePicker;
import io.jmix.flowui.component.grid.DataGrid;
import io.jmix.flowui.component.textfield.TypedTextField;
import io.jmix.flowui.model.CollectionContainer;
import io.jmix.flowui.view.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

@Route(value = “audit-trail-view”, layout = MainView.class)
@ViewController(id = “AuditTrailView”)
@ViewDescriptor(path = “audit-trail-view.xml”)
public class AuditTrailView extends StandardView {

// --- Injected Components ---
@Autowired
private DataManager dataManager;

// Filter Components
@ViewComponent
private TypedTextField<String> dashboard_searchFieldPlate1;
@ViewComponent
private ComboBox<String> action_userComboBox_audit;


// Data Containers
@ViewComponent
private CollectionContainer<ActivityLog> module1Dc;
@ViewComponent
private CollectionContainer<ActivityLog> module2Dc;
@ViewComponent
private CollectionContainer<ActivityLog> module3Dc;
@ViewComponent
private CollectionContainer<ActivityLog> module4Dc;

// Data Grids
@ViewComponent
private DataGrid<ActivityLog> dataGrid1;
@ViewComponent
private DataGrid<ActivityLog> dataGrid2;
@ViewComponent
private DataGrid<ActivityLog> dataGrid3;
@ViewComponent
private DataGrid<ActivityLog> dataGrid4;
@ViewComponent
private TypedDatePicker<Comparable> datepicker_audit;

@Subscribe
public void onInit(InitEvent event) {
    // Populate the action combo box with items
    action_userComboBox_audit.setItems(
            "Login", "Logout", "Submit", "Approve", "Reject",
            "Blacklist", "Suspend", "Unsuspend", "Register", "Edit"
    );

    // Add a generated column to display the friendly action name in each grid
    setupCustomGridColumns();

    // Set up listeners for all filter components
    setupFilterListeners();

    // Perform the initial data load with no filters active
    applyFilters();
}

/**
 * Sets up listeners for all filter components. When any filter value changes,
 * the central applyFilters() method is called.
 */
private void setupFilterListeners() {
    dashboard_searchFieldPlate1.addTypedValueChangeListener(e -> applyFilters());
    action_userComboBox_audit.addValueChangeListener(e -> applyFilters());
    datepicker_audit.addValueChangeListener(e -> applyFilters());
}

/**
 * Central method to apply all active filters. It retrieves the current values
 * from the filter components and reloads the data for all modules.
 */
private void applyFilters() {
    String searchText = dashboard_searchFieldPlate1.getValue();
    String selectedAction = action_userComboBox_audit.getValue();
    LocalDate selectedDate = datepicker_audit.getValue();

    loadModuleLogs(1, module1Dc, searchText, selectedAction, selectedDate);
    loadModuleLogs(2, module2Dc, searchText, selectedAction, selectedDate);
    loadModuleLogs(3, module3Dc, searchText, selectedAction, selectedDate);
    loadModuleLogs(4, module4Dc, searchText, selectedAction, selectedDate);
}

/**
 * Loads logs for a specific module, dynamically building a query
 * based on the active filters.
 */
private void loadModuleLogs(int moduleId, CollectionContainer<ActivityLog> container,
                            String searchText, String selectedAction, LocalDate selectedDate) {

    StringBuilder query = new StringBuilder("select a from ActivityLog a where a.module = :module");
    Map<String, Object> params = new HashMap<>();
    params.put("module", moduleId);

    boolean hasSearchText = searchText != null && !searchText.trim().isEmpty();
    boolean hasSelectedAction = selectedAction != null && !selectedAction.isEmpty();
    boolean hasSelectedDate = selectedDate != null;

    // --- Apply Search Text Filter (Action By) ---
    if (hasSearchText) {
        query.append(" and lower(a.actionBy) like :searchText");
        params.put("searchText", "%" + searchText.toLowerCase().trim() + "%");
    }

    // --- Apply Date Filter ---
    if (hasSelectedDate) {
        ZonedDateTime startOfDay = selectedDate.atStartOfDay(ZoneId.systemDefault());
        ZonedDateTime endOfDay = selectedDate.atTime(LocalTime.MAX).atZone(ZoneId.systemDefault());
        query.append(" and a.actionDate >= :startDate and a.actionDate <= :endDate");
        params.put("startDate", Date.from(startOfDay.toInstant()));
        params.put("endDate", Date.from(endOfDay.toInstant()));
    }

    query.append(" order by a.actionDate desc");

    List<ActivityLog> logs = dataManager.load(ActivityLog.class)
            .query(query.toString())
            .parameters(params)
            .list();

    // --- Apply Action Filter (In-Memory) ---
    // This is done in memory because the action name is resolved from a code
    if (hasSelectedAction) {
        logs = logs.stream()
                .filter(log -> selectedAction.equals(resolveActivityName(log.getModule(), log.getActivity())))
                .toList();
    }

    container.setItems(logs);
}

private void setupCustomGridColumns() {
    DataGrid<ActivityLog>[] grids = new DataGrid[]{dataGrid1, dataGrid2, dataGrid3, dataGrid4};
    for (DataGrid<ActivityLog> grid : grids) {
        grid.addColumn(log -> resolveActivityName(log.getModule(), log.getActivity()))
                .setHeader("Action")
                .setSortable(true)
                .setAutoWidth(true);
    }
}

private String resolveActivityName(Integer module, Integer activityCode) {
    if (module == null || activityCode == null) return "";
    return switch (module) {
        case 1 -> switch (activityCode) {
            case 1 -> "Login";
            case 2 -> "Logout";
            default -> "Unknown";
        };
        case 2 -> switch (activityCode) {
            case 3 -> "Submit";
            default -> "Unknown";
        };
        case 3 -> switch (activityCode) {
            case 4 -> "Approve";
            case 5 -> "Reject";
            case 6 -> "Blacklist";
            case 9 -> "Suspend";
            case 10 -> "Unsuspend";
            default -> "Unknown";
        };
        case 4 -> switch (activityCode) {
            case 7 -> "Register";
            case 8 -> "Edit";
            default -> "Unknown";
        };
        default -> "Unknown Module";
    };
}

}