new dataview version

This commit is contained in:
Ralph Soika 2026-06-08 12:19:48 +02:00
parent 69456a28a0
commit 049bf8fea9
4 changed files with 225 additions and 88 deletions

View file

@ -43,8 +43,7 @@ import jakarta.servlet.http.HttpServletRequest;
/** /**
* The DataViewFormSectionController provides methods to display a data view in * The DataViewFormSectionController provides methods to display a data view in
* as a * a custom form section
* custom form section
* *
* @see pages/workitems/sections/dataview.xhtml * @see pages/workitems/sections/dataview.xhtml
* @author rsoika * @author rsoika
@ -147,6 +146,7 @@ public class DataViewSectionController implements Serializable {
if (_dataViewName != null) { if (_dataViewName != null) {
logger.info("...build new dataSet by options: " + options); logger.info("...build new dataSet by options: " + options);
dataSet = new DataViewSectionDataSet(_dataViewName, workflowController.getWorkitem(), dataViewService); dataSet = new DataViewSectionDataSet(_dataViewName, workflowController.getWorkitem(), dataViewService);
dataSets.put(options, dataSet); dataSets.put(options, dataSet);
} }
} }

View file

@ -3,6 +3,7 @@ package org.imixs.workflow.office.forms;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.imixs.workflow.FileData; import org.imixs.workflow.FileData;
@ -34,6 +35,8 @@ public class DataViewSectionDataSet implements Serializable {
private int pageSize = 10; private int pageSize = 10;
private int pageIndex = 0; private int pageIndex = 0;
private String viewId;
private DataViewService dataViewService; private DataViewService dataViewService;
private ItemCollection workitem; private ItemCollection workitem;
@ -43,8 +46,13 @@ public class DataViewSectionDataSet implements Serializable {
this.workitem = workitem; this.workitem = workitem;
this.dataViewService = dataViewService; this.dataViewService = dataViewService;
dataViewDefinition = dataViewService.loadDataViewDefinition(dataViewName); // Generate a unique view ID for JSF component identification
this.viewId = "dv_" + UUID.randomUUID().toString().replace("-", "");
dataViewDefinition = dataViewService.loadDataViewDefinition(dataViewName);
if (dataViewDefinition == null) {
return;
}
boolean debug = dataViewDefinition.getItemValueBoolean("debug"); boolean debug = dataViewDefinition.getItemValueBoolean("debug");
if (debug) { if (debug) {
logger.info("resolve query by dataView '" + dataViewName + "'"); logger.info("resolve query by dataView '" + dataViewName + "'");
@ -55,10 +63,21 @@ public class DataViewSectionDataSet implements Serializable {
// resove query by dataView // resove query by dataView
query = this.dataViewService.parseQuery(dataViewDefinition, this.workitem); query = this.dataViewService.parseQuery(dataViewDefinition, this.workitem);
sortBy = dataViewDefinition.getItemValueString("sort.by");
sortReverse = dataViewDefinition.getItemValueBoolean("sort.reverse");
loadData(); loadData();
} }
/**
* return unique data view id for jsf pages
*
* @return
*/
public String getViewId() {
return viewId;
}
public void forward() { public void forward() {
if (!isEndOfList()) { if (!isEndOfList()) {
pageIndex++; pageIndex++;

View file

@ -4,97 +4,97 @@
xmlns:marty="http://java.sun.com/jsf/composite/marty"> xmlns:marty="http://java.sun.com/jsf/composite/marty">
<!-- preload view options --> <!-- preload view options -->
<f:view>
<h:panelGroup styleClass="imixs-view imixs-search" layout="block" id="dataview_result_id"
rendered="#{dataViewSectionController.hasDataSet(options)}">
<ui:param name="dataViewDataSet" value="#{dataViewSectionController.loadDataSet(options)}" /> <ui:param name="dataViewDataSet" value="#{dataViewSectionController.loadDataSet(options)}" />
<ui:param name="searchPage" <h:panelGroup styleClass="imixs-view imixs-search" layout="block" id="#{dataViewDataSet.viewId}"
value="#{(dataViewDataSet.getPageIndex()+1)}/#{(dataViewDataSet.getTotalPages())}" /> rendered="#{dataViewSectionController.hasDataSet(options)}">
<table class="imixsdatatable imixs-orderitems">
<tr> <ui:param name="searchPage"
<ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef"> value="#{(dataViewDataSet.getPageIndex()+1)}/#{(dataViewDataSet.getTotalPages())}" />
<th>#{columnDef.item['item.label']}</th> <table class="imixsdatatable imixs-orderitems">
</ui:repeat>
</tr>
<ui:repeat value="#{dataViewDataSet.data}" var="record">
<tr> <tr>
<ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef"> <ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef">
<td> <th>#{columnDef.item['item.label']}</th>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:anyURI'}">
<h:link outcome="/pages/workitems/workitem.xhtml?faces-redirect=true"
styleClass="imixs-viewentry-main-link">
<h:outputText value="#{record.item[columnDef.item['item.name']]}" />
<f:param name="id" value="#{record.item['$uniqueid']}" />
</h:link>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:string'}">
<h:outputText value="#{record.item[columnDef.item['item.name']]}" />
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:date'}"
styleClass="align-center">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.datePatternShort}" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:double'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:float'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:dateTime'}">
<f:facet name="header">#{columnDef.item['item.label']}</f:facet>
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePatternShort}" />
</h:outputText>
</ui:fragment>
</td>
</ui:repeat> </ui:repeat>
</tr> </tr>
</ui:repeat> <ui:repeat value="#{dataViewDataSet.data}" var="record">
</table> <tr>
<!-- navigation --> <ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef">
<div <td>
style="background-color: #f9f9f9; font-size:0.85rem; border-bottom: 1px solid var(--input-border);border-left: 1px solid var(--input-border);border-right: 1px solid var(--input-border); height: 30px; display: flex; justify-content: space-between; align-items: center;padding: 5px 10px;"> <ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:anyURI'}">
<span style="display: flex; align-items: center;gap: 10px;"> <h:link outcome="/pages/workitems/workitem.xhtml?faces-redirect=true"
<h:commandLink title="Excel Export" rendered="false" actionListener="#{dataGroupController.export()}" styleClass="imixs-viewentry-main-link">
onclick="handleSubmit(this)"> <h:outputText value="#{record.item[columnDef.item['item.name']]}" />
<i class="fa-solid fa-file-csv"></i> <f:param name="id" value="#{record.item['$uniqueid']}" />
</h:commandLink> </h:link>
<h:commandLink title="Excel Export" rendered="#{dataViewDataSet.hasPoiExport()}" </ui:fragment>
actionListener="#{dataViewDataSet.export()}" onclick="handleSubmit(this)">
<span class="typcn typcn-vendor-microsoft"></span>
</h:commandLink>
</span>
<span style="display: flex; align-items: center; gap: 10px;">
<h:outputText value=" #{(dataViewDataSet.pageIndex+1)} / #{dataViewDataSet.totalPages}" />
<h:commandLink value="" action="#{dataViewDataSet.back()}">
<f:ajax render="dataview_result_id" />
<i class="fa-solid fa-backward" style=" #{(dataViewDataSet.pageIndex == 0)?'opacity:0.5':''}"></i>
</h:commandLink>
<h:commandLink value="" action="#{dataViewDataSet.forward()}">
<f:ajax render="dataview_result_id" />
<i class="fa-solid fa-forward" style=" #{(dataViewDataSet.endOfList)?'opacity:0.5':''}"></i>
</h:commandLink>
</span>
</div>
</h:panelGroup>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:string'}">
<h:outputText value="#{record.item[columnDef.item['item.name']]}" />
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:date'}"
styleClass="align-center">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.datePatternShort}" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:double'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:float'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:dateTime'}">
<f:facet name="header">#{columnDef.item['item.label']}</f:facet>
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePatternShort}" />
</h:outputText>
</ui:fragment>
</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
<!-- navigation -->
<div
style="background-color: #f9f9f9; font-size:0.85rem; border-bottom: 1px solid var(--input-border);border-left: 1px solid var(--input-border);border-right: 1px solid var(--input-border); height: 30px; display: flex; justify-content: space-between; align-items: center;padding: 5px 10px;">
<span style="display: flex; align-items: center;gap: 10px;">
<h:commandLink title="Excel Export" rendered="false"
actionListener="#{dataGroupController.export()}" onclick="handleSubmit(this)">
<i class="fa-solid fa-file-csv"></i>
</h:commandLink>
<h:commandLink title="Excel Export" rendered="#{dataViewDataSet.hasPoiExport()}"
actionListener="#{dataViewDataSet.export()}" onclick="handleSubmit(this)">
<i class="fa-solid fa-file-excel">Excel</i>
</h:commandLink>
</span>
<span style="display: flex; align-items: center; gap: 10px;">
<h:outputText value=" #{(dataViewDataSet.pageIndex+1)} / #{dataViewDataSet.totalPages}" />
<h:commandLink value="" action="#{dataViewDataSet.back()}">
<f:ajax render="#{dataViewDataSet.viewId}" />
<i class="fa-solid fa-backward"
style="font-size:1.2rem; #{(dataViewDataSet.pageIndex == 0)?'opacity:0.5':''}">«</i>
</h:commandLink>
<h:commandLink value="" action="#{dataViewDataSet.forward()}">
<f:ajax render="#{dataViewDataSet.viewId}" />
<i class="fa-solid fa-forward"
style="font-size:1.2rem; #{(dataViewDataSet.endOfList)?'opacity:0.5':''}">»</i>
</h:commandLink>
</span>
</div>
</h:panelGroup>
</f:view>
<!-- Missing Data View --> <!-- Missing Data View -->
<h:panelGroup styleClass="ui-widget" rendered="#{!dataViewSectionController.hasDataSet(options)}"> <h:panelGroup styleClass="ui-widget" rendered="#{!dataViewSectionController.hasDataSet(options)}">
<div class="" style="padding: .7em; margin-bottom: .7em; border: solid 1px #ccc;"> <div class="" style="padding: .7em; margin-bottom: .7em; border: solid 1px #ccc;">

View file

@ -0,0 +1,118 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:i="http://java.sun.com/jsf/composite/imixs"
xmlns:marty="http://java.sun.com/jsf/composite/marty">
<!-- preload view options -->
<h:panelGroup styleClass="imixs-view imixs-search" layout="block" id="dataview_result_id"
rendered="#{dataViewSectionController.hasDataSet(options)}">
<ui:param name="dataViewDataSet" value="#{dataViewSectionController.loadDataSet(options)}" />
<ui:param name="searchPage"
value="#{(dataViewDataSet.getPageIndex()+1)}/#{(dataViewDataSet.getTotalPages())}" />
<table class="imixsdatatable imixs-orderitems">
<tr>
<ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef">
<th>#{columnDef.item['item.label']}</th>
</ui:repeat>
</tr>
<ui:repeat value="#{dataViewDataSet.data}" var="record">
<tr>
<ui:repeat value="#{dataViewDataSet.getViewItemDefinitions()}" var="columnDef">
<td>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:anyURI'}">
<h:link outcome="/pages/workitems/workitem.xhtml?faces-redirect=true"
styleClass="imixs-viewentry-main-link">
<h:outputText value="#{record.item[columnDef.item['item.name']]}" />
<f:param name="id" value="#{record.item['$uniqueid']}" />
</h:link>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:string'}">
<h:outputText value="#{record.item[columnDef.item['item.name']]}" />
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:date'}"
styleClass="align-center">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.datePatternShort}" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:double'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:float'}"
styleClass="align-right">
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertNumber minFractionDigits="2" locale="de" />
</h:outputText>
</ui:fragment>
<ui:fragment rendered="#{columnDef.item['item.type'] eq 'xs:dateTime'}">
<f:facet name="header">#{columnDef.item['item.label']}</f:facet>
<h:outputText value="#{record.item[columnDef.item['item.name']]}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePatternShort}" />
</h:outputText>
</ui:fragment>
</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
<!-- navigation -->
<div
style="background-color: #f9f9f9; font-size:0.85rem; border-bottom: 1px solid var(--input-border);border-left: 1px solid var(--input-border);border-right: 1px solid var(--input-border); height: 30px; display: flex; justify-content: space-between; align-items: center;padding: 5px 10px;">
<span style="display: flex; align-items: center;gap: 10px;">
<h:commandLink title="Excel Export" rendered="false" actionListener="#{dataGroupController.export()}"
onclick="handleSubmit(this)">
<i class="fa-solid fa-file-csv"></i>
</h:commandLink>
<h:commandLink title="Excel Export" rendered="#{dataViewDataSet.hasPoiExport()}"
actionListener="#{dataViewDataSet.export()}" onclick="handleSubmit(this)">
<span class="typcn typcn-vendor-microsoft"></span>
</h:commandLink>
</span>
<span style="display: flex; align-items: center; gap: 10px;">
<h:outputText value=" #{(dataViewDataSet.pageIndex+1)} / #{dataViewDataSet.totalPages}" />
<h:commandLink value="" action="#{dataViewDataSet.back()}">
<f:ajax render="dataview_result_id" />
<i class="fa-solid fa-backward" style=" #{(dataViewDataSet.pageIndex == 0)?'opacity:0.5':''}"></i>
</h:commandLink>
<h:commandLink value="" action="#{dataViewDataSet.forward()}">
<f:ajax render="dataview_result_id" />
<i class="fa-solid fa-forward" style=" #{(dataViewDataSet.endOfList)?'opacity:0.5':''}"></i>
</h:commandLink>
</span>
</div>
</h:panelGroup>
<!-- Missing Data View -->
<h:panelGroup styleClass="ui-widget" rendered="#{!dataViewSectionController.hasDataSet(options)}">
<div class="" style="padding: .7em; margin-bottom: .7em; border: solid 1px #ccc;">
<p style="font-size: 1.1em; font-weight: bold"> <span class="typcn typcn-cog-outline"
style="margin-right:5px;"></span>Model
error in #{workitem.modelVersion}:</p>
Data View not defined: #{options}
</div>
</h:panelGroup>
<script type="text/javascript">
/*<![CDATA[*/
function handleSubmit(event) {
// remove ajax loader 1sec after trigger excel export
setTimeout(function () {
document.body.classList.remove('loading');
}, 2000);
}
/*]]>*/
</script>
</ui:composition>