new DataView feature

This commit is contained in:
Ralph Soika 2025-05-09 17:56:46 +02:00
parent 6cd3d5d258
commit c2e4df0379
5 changed files with 147 additions and 99 deletions

View file

@ -25,6 +25,7 @@ package org.imixs.workflow.office.reporting;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -32,6 +33,9 @@ import java.util.logging.Logger;
import org.imixs.workflow.ItemCollection; import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentEvent; import org.imixs.workflow.engine.DocumentEvent;
import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.office.forms.ChildItemController;
import com.oracle.svm.core.annotate.Inject;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.ejb.EJB; import jakarta.ejb.EJB;
@ -48,7 +52,7 @@ import jakarta.inject.Named;
@Named @Named
@SessionScoped @SessionScoped
public class ReportingController implements Serializable { public class DataViewController implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -57,7 +61,10 @@ public class ReportingController implements Serializable {
@EJB @EJB
DocumentService documentService; DocumentService documentService;
private static Logger logger = Logger.getLogger(ReportingController.class.getName()); @Inject
ChildItemController childItemController;
private static Logger logger = Logger.getLogger(DataViewController.class.getName());
/** /**
* *
@ -68,9 +75,9 @@ public class ReportingController implements Serializable {
} }
public void setAttributeList(List<ItemCollection> attributeList) { // public void setAttributeList(List<ItemCollection> attributeList) {
this.attributeList = attributeList; // this.attributeList = attributeList;
} // }
public List<ItemCollection> getAttributeList() { public List<ItemCollection> getAttributeList() {
return attributeList; return attributeList;
@ -88,22 +95,25 @@ public class ReportingController implements Serializable {
} }
// update attribute list // update attribute list
if (event.getEventType() == DocumentEvent.ON_DOCUMENT_SAVE) { if (event.getEventType() == DocumentEvent.ON_DOCUMENT_SAVE) {
// convert the option ItemCollection elements into a List of Map // convert the option ItemCollection elements into a List of Map
if (attributeList != null) { if (attributeList != null) {
List<Map> mapItemList = new ArrayList<Map>(); List<Map> mapItemList = new ArrayList<Map>();
logger.fine("Convert option items into Map..."); logger.fine("Convert option items into Map...");
// iterate over all items.. // iterate over all items..
for (ItemCollection attrItem : attributeList) { for (ItemCollection attrItem : attributeList) {
mapItemList.add(attrItem.getAllItems()); ItemCollection ding = (ItemCollection) attrItem.clone();
mapItemList.add(ding.getAllItems());
} }
event.getDocument().replaceItemValue("attributes", mapItemList); event.getDocument().replaceItemValue("report.items", mapItemList);
} }
} }
// update attribute list // update attribute list
if (event.getEventType() == DocumentEvent.ON_DOCUMENT_LOAD) { if (event.getEventType() == DocumentEvent.ON_DOCUMENT_LOAD) {
attributeList = new ArrayList<ItemCollection>(); attributeList = new ArrayList<ItemCollection>();
List<Object> mapItems = event.getDocument().getItemValue("attributes"); List<Object> mapItems = event.getDocument().getItemValue("report.items");
for (Object mapOderItem : mapItems) { for (Object mapOderItem : mapItems) {
if (mapOderItem instanceof Map) { if (mapOderItem instanceof Map) {
ItemCollection itemCol = new ItemCollection((Map) mapOderItem); ItemCollection itemCol = new ItemCollection((Map) mapOderItem);
@ -132,13 +142,61 @@ public class ReportingController implements Serializable {
*/ */
public void removeAttribute(String name) { public void removeAttribute(String name) {
if (name != null && attributeList != null) { if (name != null && attributeList != null) {
for (ItemCollection dbtr : attributeList) { for (ItemCollection item : attributeList) {
if (name.equals(dbtr.getItemValueString("name"))) { if (name.equals(item.getItemValueString("item.name"))) {
attributeList.remove(dbtr); attributeList.remove(item);
break; break;
} }
} }
} }
} }
/**
* Moves an attribute item up in the list
*
* List<ItemCollection> attributeList
*
* @param name - name of attribute
*/
public void moveAttributeUp(String name) {
if (name != null && attributeList != null) {
logger.info("move up: " + name);
for (int i = 0; i < attributeList.size(); i++) {
ItemCollection item = attributeList.get(i);
if (name.equals(item.getItemValueString("item.name"))) {
// Check if it's not already at the top
if (i > 0) {
// Swap with previous element
Collections.swap(attributeList, i, i - 1);
}
break; // Exit loop once found and processed
}
}
}
}
/**
* Moves an attribute item up down the list
*
* List<ItemCollection> attributeList
*
* @param name - name of attribute
*/
public void moveAttributeDown(String name) {
if (name != null && attributeList != null) {
logger.info("move down: " + name);
for (int i = 0; i < attributeList.size(); i++) {
ItemCollection item = attributeList.get(i);
if (name.equals(item.getItemValueString("item.name"))) {
// Check if it's not already at the bottom
if (i < attributeList.size() - 1) {
// Swap with next element
Collections.swap(attributeList, i, i + 1);
}
break; // Exit loop once found and processed
}
}
}
}
} }

View file

@ -11,7 +11,7 @@ import jakarta.inject.Named;
@Named @Named
@ViewScoped @ViewScoped
public class ReportingViewController extends ViewController { public class DataViewDefinitionsController extends ViewController {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -26,7 +26,7 @@ public class ReportingViewController extends ViewController {
@PostConstruct @PostConstruct
public void init() { public void init() {
super.init(); super.init();
this.setQuery("(type:\"reporting\")"); this.setQuery("(type:\"dataview\")");
this.setSortBy("txtname"); this.setSortBy("txtname");
this.setSortReverse(false); this.setSortReverse(false);
this.setPageSize(adminViewPageSize); this.setPageSize(adminViewPageSize);

View file

@ -15,7 +15,7 @@
<h:link outcome="/pages/admin/analyse_invoicing">Analyse Rechnungseingang</h:link> <h:link outcome="/pages/admin/analyse_invoicing">Analyse Rechnungseingang</h:link>
</li> </li>
<li> <li>
<h:link outcome="/pages/admin/reportingDefinitions">Reportings</h:link> <h:link outcome="/pages/admin/dataViewDefinitions">Data Views</h:link>
</li> </li>
<li> <li>

View file

@ -18,7 +18,7 @@
<div class="imixs-form"> <div class="imixs-form">
<div class="imixs-header"> <div class="imixs-header">
<h1> <h1>
<h:outputText value="View Definition: " /> <h:outputText value="Data View Definition: " />
<h:outputText value="#{documentController.document.item['name']} " /> <h:outputText value="#{documentController.document.item['name']} " />
</h1> </h1>
</div> </div>
@ -39,7 +39,7 @@
<div class="imixs-form-panel"> <div class="imixs-form-panel">
<div class="imixs-form-section-2"> <div class="imixs-form-section-2">
<h1>Query Definition</h1> <h1><span class="typcn typcn-edit"></span> Query Definition</h1>
<p> <p>
A Query Defintion defines a custom data list based on the A Query Defintion defines a custom data list based on the
<a href="https://www.imixs.org/doc/engine/queries.html" <a href="https://www.imixs.org/doc/engine/queries.html"
@ -77,7 +77,7 @@
<dd> <dd>
<h:inputTextarea value="#{documentController.document.item['query']}" <h:inputTextarea value="#{documentController.document.item['query']}"
style="height: 14em;" /> style="height: 14em; font-family: 'Courier New', Courier, monospace; autocomplete: off;" />
</dd> </dd>
</dl> </dl>
</div> </div>
@ -97,58 +97,54 @@
aggregator. aggregator.
</p> </p>
<f:ajax render="attributelist" onevent="updateSepaList"> <f:ajax render="attributelist" onevent="updateAttributeList">
<table class="imixsdatatable imixs-orderitems"> <table class="imixsdatatable imixs-orderitems">
<tr> <tr>
<th style="width: 140px">ID</th> <th style="width: 250px">Item</th>
<th style="">Bank<span class="imixs-required"> <th style="width: 250px;">Label</th>
*</span></th> <th style="width: 200px;">Convert</th>
<th style="width: 250px;">IBAN</th> <th style="">Format</th>
<th style="width: 150px;">BIC</th> <th style="width: 100px">
<th style="width: 150px;">Report (optional)</th> <!-- actions -->
<th style="width: 50px">
<!-- delete -->
</th> </th>
</tr> </tr>
<ui:repeat var="attribute" value="#{reportingController.attributeList}"> <ui:repeat var="attribute" value="#{dataViewController.attributeList}">
<tr> <tr>
<!-- ID -->
<td> <td>
<h:inputText value="#{attribute.item['name']}" <h:inputText value="#{attribute.item['item.name']}"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<!-- attribute.name -->
<td> <td>
<h:inputText value="#{attribute.item['attribute.name']}" <h:inputText value="#{attribute.item['item.label']}"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<!-- attribute.iban -->
<td> <td>
<h:inputText value="#{attribute.item['attribute.iban']}" <h:inputText value="#{attribute.item['item.convert']}"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<!-- attribute.bic -->
<td> <td>
<h:inputText value="#{attribute.item['attribute.bic']}" <h:inputText value="#{attribute.item['item.format']}"
style="width:100%;" /> style="width:100%;" />
</td> </td>
<!-- attribute.bic --> <td style="font-size: 1.25em;">
<td>
<h:inputText value="#{attribute.item['report']}"
style="width:100%;" />
</td>
<td>
<h:commandLink <h:commandLink
actionListener="#{reportingController.removeattribute(attribute.item['name'])}"> actionListener="#{dataViewController.moveAttributeDown(attribute.item['item.name'])}">
<span class="typcn typcn-trash imixs-state-info"></span> <span class="typcn typcn-arrow-sorted-down"></span>
<f:ajax render="#{attributelistContainer.clientId}" <f:ajax render="#{attributelistContainer.clientId}"
onevent="updateSepaList" /> onevent="updateAttributeList" />
</h:commandLink>
<h:commandLink
actionListener="#{dataViewController.moveAttributeUp(attribute.item['item.name'])}">
<span class="typcn typcn-arrow-sorted-up"></span>
<f:ajax render="#{attributelistContainer.clientId}"
onevent="updateAttributeList" />
</h:commandLink>
<h:commandLink
actionListener="#{dataViewController.removeAttribute(attribute.item['item.name'])}">
<span class="typcn typcn-times imixs-state-info"></span>
<f:ajax render="#{attributelistContainer.clientId}"
onevent="updateAttributeList" />
</h:commandLink> </h:commandLink>
</td> </td>
</tr> </tr>
@ -159,7 +155,7 @@
<!-- add button --> <!-- add button -->
<h:commandButton value="#{message.add}" pt:data-id="addposbutton_id" <h:commandButton value="#{message.add}" pt:data-id="addposbutton_id"
actionListener="#{reportingController.addAttribute}"> actionListener="#{dataViewController.addAttribute}">
</h:commandButton> </h:commandButton>
</f:ajax> </f:ajax>
</h:panelGroup> </h:panelGroup>
@ -174,22 +170,20 @@
<div id="tab-2"> <div id="tab-2">
<div class="imixs-form-panel"> <div class="imixs-form-panel">
<h1>Form Definition</h1> <div class="imixs-form-section-1">
<h1><span class="typcn typcn-th-list-outline"></span> Form Definition</h1>
<p> <p>
The Form Definition defines query and filter parameters. The Form Definition defines query and filter parameters.
</p> </p>
<div class="imixs-form-section-1">
<dl> <dl>
<dt> <dt>
Form:<span class="imixs-required"> * Form:
<h:message for="_subject" />
</span>
</dt> </dt>
<dd> <dd>
<h:inputTextarea value="#{documentController.document.item['form']}" <h:inputTextarea value="#{documentController.document.item['form']}"
style="height: 27em;" /> style="height: 27em; font-family: 'Courier New', Courier, monospace; autocomplete: off;" />
</dd> </dd>
</dl> </dl>
</div> </div>
@ -198,29 +192,20 @@
<div id="tab-3"> <div id="tab-3">
<div class="imixs-form-panel"> <div class="imixs-form-panel">
<div class="imixs-form-section-1"> <div class="imixs-form-section-1">
<h1><span class="typcn typcn-news"></span> Template</h1>
<h1>Template</h1>
<dl> <dl>
<dt>#{message['form.minutes.description']}:</dt> <dl>
<dt>
POI Update:
</dt>
<dd> <dd>
<h:panelGroup styleClass="textblock-html-input" id="text_input">
<h:inputTextarea class="imixs-editor-basic"
rendered="#{documentController.document.item['txtmode'] eq 'HTML'}"
value="#{documentController.document.item['txtcontent']}" />
</h:panelGroup>
<h:panelGroup styleClass="textblock-text-input" id="html_input">
<h:inputTextarea <h:inputTextarea
rendered="#{documentController.document.item['txtmode'] ne 'HTML'}" value="#{documentController.document.item['poi.update']}"
value="#{documentController.document.item['txtcontent']}" /> style="height: 27em; font-family: 'Courier New', Courier, monospace; autocomplete: off;" />
</h:panelGroup> </dd>
</dl>
<div class="textblock-file-input" style="width: 50%;"> <div class="textblock-file-input" style="width: 50%;">
<i:imixsFileUpload showattachments="true" <i:imixsFileUpload showattachments="true"
@ -230,7 +215,7 @@
</div> </div>
</dd>
</dl> </dl>
</div> </div>
@ -242,15 +227,15 @@
<div class="imixs-footer"> <div class="imixs-footer">
<h:commandButton action="/pages/admin/reportingDefinitions?faces-redirect=true" <h:commandButton action="/pages/admin/dataViewDefinitions?faces-redirect=true"
actionListener="#{documentController.save()}" value="#{message.save}" /> actionListener="#{documentController.save()}" value="#{message.save}" />
<h:commandButton value="Open View" <h:commandButton value="Open View"
action="/pages/admin/reportingDefinitions?faces-redirect=true" action="/pages/admin/dataViewDefinitions?faces-redirect=true"
actionListener="#{documentController.close()}" /> actionListener="#{documentController.close()}" />
<h:commandButton value="#{message.close}" immediate="true" <h:commandButton value="#{message.close}" immediate="true"
action="/pages/admin/reportingDefinitions?faces-redirect=true" action="/pages/admin/dataViewDefinitions?faces-redirect=true"
actionListener="#{documentController.close()}" /> actionListener="#{documentController.close()}" />
@ -270,7 +255,13 @@
$(document).ready(function () { $(document).ready(function () {
}); });
// This method refreshs the layout
function updateAttributeList(data) {
if (data.status === 'success') {
$('[id$=attributelist]').imixsLayout();
}
}
/*]]>*/ /*]]>*/

View file

@ -13,17 +13,17 @@
<!-- *** Header **** --> <!-- *** Header **** -->
<div class="imixs-header"> <div class="imixs-header">
<h1> <h1>
<h:outputText value="#{message['report.view']}" /> <h:outputText value="Data Views" />
</h1> </h1>
</div> </div>
<div class="imixs-body"> <div class="imixs-body">
<h:dataTable id="view_body" styleClass="imixsdatatable" <h:dataTable id="view_body" styleClass="imixsdatatable"
value="#{viewHandler.getData(reportingViewController)}" var="record"> value="#{viewHandler.getData(dataViewDefinitionsController)}" var="record">
<h:column> <h:column>
<f:facet name="header">#{message.name}</f:facet> <f:facet name="header">#{message.name}</f:facet>
<h:link outcome="/pages/admin/reportingDefinition?faces-redirect=true" <h:link outcome="/pages/admin/dataViewDefinition?faces-redirect=true"
styleClass="imixs-viewentry-main-link"> styleClass="imixs-viewentry-main-link">
<h:outputText value="#{record.item['Name']}" /> <h:outputText value="#{record.item['Name']}" />
<h:outputText rendered="#{empty record.item['Name']}" value=" - no name - " /> <h:outputText rendered="#{empty record.item['Name']}" value=" - no name - " />
@ -32,6 +32,10 @@
</h:column> </h:column>
<h:column>
<f:facet name="header">Description</f:facet>
<pre>#{record.item['description']}</pre>
</h:column>
<h:column> <h:column>
<f:facet name="header">#{message.modified}</f:facet> <f:facet name="header">#{message.modified}</f:facet>
@ -44,25 +48,20 @@
<h:column> <h:column>
<f:facet name="header">#{message.action}</f:facet> <f:facet name="header">#{message.action}</f:facet>
<!-- Edit --> <!-- Edit -->
<h:link outcome="/pages/admin/reportingDefinition?faces-redirect=true" <h:link outcome="/pages/admin/dataViewDefinition?faces-redirect=true"
styleClass="imixs-viewentry-main-link"> styleClass="imixs-viewentry-main-link">
<span class="typcn typcn-pencil imixs-state-info"></span>#{message.open} <span class="typcn typcn-pencil imixs-state-info"></span>#{message.open}
<f:param name="id" value="#{record.item['$uniqueid']}" /> <f:param name="id" value="#{record.item['$uniqueid']}" />
</h:link> </h:link>
<!-- Delete --> <!-- Delete -->
<h:commandLink title="#{message.delete}" <h:commandLink title="#{message.delete}"
rendered="#{loginController.isUserInRole('org.imixs.ACCESSLEVEL.MANAGERACCESS')}" rendered="#{loginController.isUserInRole('org.imixs.ACCESSLEVEL.MANAGERACCESS')}"
action="/pages/admin/reportingDefinitions?faces-redirect=true" action="/pages/admin/dataViewDefinitions?faces-redirect=true"
actionListener="#{documentController.delete(record.item['$UniqueID'])}" actionListener="#{documentController.delete(record.item['$UniqueID'])}"
onclick="if (!confirm('#{message.help_delete}')) return false;"> onclick="if (!confirm('#{message.help_delete}')) return false;">
<span class="typcn typcn-trash imixs-state-error"></span>#{message.delete} <span class="typcn typcn-trash imixs-state-error"></span>#{message.delete}
</h:commandLink> </h:commandLink>
</h:column> </h:column>
</h:dataTable> </h:dataTable>
</div> </div>
@ -81,10 +80,10 @@
<div style="clear: left;" /> <div style="clear: left;" />
<h:commandButton value="#{message.add}" action="/pages/admin/reportingDefinition" <h:commandButton value="#{message.add}" action="/pages/admin/dataViewDefinition"
actionListener="#{documentController.create}"> actionListener="#{documentController.create}">
<f:setPropertyActionListener target="#{documentController.document.item['type']}" <f:setPropertyActionListener target="#{documentController.document.item['type']}"
value="reporting" /> value="dataview" />
</h:commandButton> </h:commandButton>