dataViews first working draft!

This commit is contained in:
Ralph Soika 2025-05-11 15:47:01 +02:00
parent 174b230509
commit d948742963
5 changed files with 143 additions and 29 deletions

View file

@ -0,0 +1,64 @@
/*******************************************************************************
* Imixs Workflow Technology
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika
*
*******************************************************************************/
package org.imixs.workflow.office.dataview;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.imixs.workflow.ItemCollection;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
/**
* The DataViewCache implements a sessionScoped cache for the dataView filter.
* The cache uses the cacheId provided in the URL - see DataViewController
* onLoad
*
* @author rsoika
* @version 1.0
*/
@Named
@SessionScoped
public class DataViewCache implements Serializable {
private static final long serialVersionUID = 1L;
private Map<String, ItemCollection> dataViewStates = new ConcurrentHashMap<>();
public void put(String key, ItemCollection data) {
dataViewStates.put(key, data);
}
public ItemCollection get(String key) {
ItemCollection result = dataViewStates.get(key);
if (result == null) {
// init new empty cache object!
result = new ItemCollection();
dataViewStates.put(key, result);
}
return result;
}
}

View file

@ -24,7 +24,6 @@
package org.imixs.workflow.office.dataview; package org.imixs.workflow.office.dataview;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
@ -42,7 +41,7 @@ import org.imixs.workflow.office.forms.CustomFormSection;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.Conversation; import jakarta.enterprise.context.Conversation;
import jakarta.enterprise.context.SessionScoped; import jakarta.enterprise.context.ConversationScoped;
import jakarta.faces.context.FacesContext; import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Named; import jakarta.inject.Named;
@ -55,13 +54,17 @@ import jakarta.servlet.http.HttpServletRequest;
* @version 1.0 * @version 1.0
*/ */
@Named @Named
@SessionScoped // @SessionScoped
@ConversationScoped
public class DataViewController extends ViewController { public class DataViewController extends ViewController {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private List<CustomFormSection> sections; private List<CustomFormSection> sections;
private String errorMessage; private String errorMessage;
@Inject
DataViewCache dataViewCache;
@Inject @Inject
private Conversation conversation; private Conversation conversation;
@ -91,22 +94,16 @@ public class DataViewController extends ViewController {
this.setLoadStubs(false); this.setLoadStubs(false);
} }
public ItemCollection getDefinition() {
return data;
}
public List<CustomFormSection> getSections() {
return sections;
}
/** /**
* This method loads the custom form sections * This method loads the custom form sections
*/ */
public void onLoad() { public void onLoad() {
if (filter == null) {
filter = new ItemCollection(); String cacheid = null;
} logger.info("> onload...");
// super.onLoad();
// Important: start a new conversation beause of the usage of the
// CustomFormController!
startConversation(); startConversation();
FacesContext facesContext = FacesContext.getCurrentInstance(); FacesContext facesContext = FacesContext.getCurrentInstance();
@ -115,6 +112,7 @@ public class DataViewController extends ViewController {
FacesContext fc = FacesContext.getCurrentInstance(); FacesContext fc = FacesContext.getCurrentInstance();
Map<String, String> paramMap = fc.getExternalContext().getRequestParameterMap(); Map<String, String> paramMap = fc.getExternalContext().getRequestParameterMap();
// try to extract the uniqueid form the query string... // try to extract the uniqueid form the query string...
cacheid = paramMap.get("cacheid");
String uniqueid = paramMap.get("id"); String uniqueid = paramMap.get("id");
if (uniqueid == null || uniqueid.isEmpty()) { if (uniqueid == null || uniqueid.isEmpty()) {
// alternative 'workitem=...' // alternative 'workitem=...'
@ -123,20 +121,43 @@ public class DataViewController extends ViewController {
data = documentService.load(uniqueid); data = documentService.load(uniqueid);
} }
logger.info("> cacheid=" + cacheid);
if (cacheid != null && !cacheid.isEmpty()) {
filter = dataViewCache.get(cacheid);
} else {
filter = new ItemCollection();
}
try { try {
// Init new Filter.... // Init new Filter....
if (data != null) { if (data != null) {
filter.setItemValue("txtWorkflowEditorCustomForm", data.getItemValue("form")); filter.setItemValue("txtWorkflowEditorCustomForm", data.getItemValue("form"));
// filter.setItemValue("date.from", new Date());
customFormController.computeFieldDefinition(filter); customFormController.computeFieldDefinition(filter);
sections = customFormController.getSections(); sections = customFormController.getSections();
logger.info(" < cached page index=" + filter.getItemValueInteger("pageIndex"));
this.setPageIndex(filter.getItemValueInteger("pageIndex"));
if (!filter.getItemValueString("query").isEmpty()) {
query = filter.getItemValueString("query");
// Prefetch data to update total count and page count
viewHandler.getData(this);
}
} }
} catch (ModelException e) { } catch (ModelException | QueryException e) {
logger.warning("Failed to load dataview definition: " + e.getMessage()); logger.warning("Failed to load dataview definition: " + e.getMessage());
} }
} }
public ItemCollection getDefinition() {
return data;
}
public List<CustomFormSection> getSections() {
return sections;
}
public ItemCollection getFilter() { public ItemCollection getFilter() {
return filter; return filter;
} }
@ -165,9 +186,8 @@ public class DataViewController extends ViewController {
*/ */
public void run() throws QueryException { public void run() throws QueryException {
reset(); reset();
Date date = filter.getItemValueDate("date.from");
logger.info("x date=" + date);
// build new query from template
query = data.getItemValueString("query"); query = data.getItemValueString("query");
List<String> filterItems = filter.getItemNames(); List<String> filterItems = filter.getItemNames();
@ -191,6 +211,7 @@ public class DataViewController extends ViewController {
query = query.replaceAll("(?i)\\{" + Pattern.quote(itemName) + "\\}", itemValue); query = query.replaceAll("(?i)\\{" + Pattern.quote(itemName) + "\\}", itemValue);
} }
logger.info("query=" + query); logger.info("query=" + query);
filter.setItemValue("query", query);
// Prefetch data to update total count and page count // Prefetch data to update total count and page count
viewHandler.getData(this); viewHandler.getData(this);
@ -221,13 +242,31 @@ public class DataViewController extends ViewController {
} }
/** /**
* Set the current worktItem * Set the current workItem
* *
* @param workitem - new reference or null to clear the current workItem. * @param workitem - new reference or null to clear the current workItem.
*/ */
public void setData(ItemCollection document) { public void setData(ItemCollection document) {
this.data = document; this.data = document;
}
/**
* This method navigates back in the page index and caches the current page
* index
*/
public void back() {
viewHandler.back(this);
filter.setItemValue("pageIndex", this.getPageIndex());
}
/**
* This method navigates forward in the page index and caches the current page
* index
*/
public void forward() {
viewHandler.forward(this);
filter.setItemValue("pageIndex", this.getPageIndex());
logger.info("-> forward to page " + this.getPageIndex());
} }
/** /**
@ -239,7 +278,8 @@ public class DataViewController extends ViewController {
((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()) ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest())
.getSession().getMaxInactiveInterval() * 1000); .getSession().getMaxInactiveInterval() * 1000);
conversation.begin(); conversation.begin();
logger.log(Level.FINEST, "......start new conversation, id={0}", conversation.getId()); logger.log(Level.INFO, "......start new conversation, id={0}",
conversation.getId());
} }
} }

View file

@ -90,6 +90,18 @@ public class DataViewDefinitionController extends AbstractDataController {
return data; return data;
} }
/**
* This method returns a unique view URI to be used zu display the View Data.
* The uri contains a unique random ID to support caching over different browser
* tabs
*
* @return
*/
public String getViewURI() {
return "/pages/dataviews/data.xhtml?id=" + data.getUniqueID() + "&cacheid=" + System.currentTimeMillis()
+ "&faces-redirect=true";
}
/** /**
* Set the current worktItem * Set the current worktItem
* *

View file

@ -42,7 +42,7 @@
<h1><span class="typcn typcn-edit"></span> Query Definition <h1><span class="typcn typcn-edit"></span> Query Definition
<span style="font-size: 1rem;margin-left:20px;"> <span style="font-size: 1rem;margin-left:20px;">
<h:outputLink <h:outputLink
value="#{facesContext.externalContext.requestContextPath}/pages/dataviews/data.xhtml?id=#{dataViewDefinitionController.data.uniqueID}&amp;faces-redirect=true" value="#{facesContext.externalContext.requestContextPath}#{dataViewDefinitionController.viewURI}"
target="dataview"><span class="typcn typcn-camera-outline" target="dataview"><span class="typcn typcn-camera-outline"
style="font-size: 1.2rem;"></span> Test View style="font-size: 1.2rem;"></span> Test View
</h:outputLink> </h:outputLink>
@ -182,7 +182,7 @@
<h1><span class="typcn typcn-th-list-outline"></span> Form Definition<span <h1><span class="typcn typcn-th-list-outline"></span> Form Definition<span
style="font-size: 1rem;margin-left:20px;"> style="font-size: 1rem;margin-left:20px;">
<h:outputLink <h:outputLink
value="#{facesContext.externalContext.requestContextPath}/pages/dataviews/data.xhtml?id=#{dataViewDefinitionController.data.uniqueID}&amp;faces-redirect=true" value="#{facesContext.externalContext.requestContextPath}#{dataViewDefinitionController.viewURI}"
target="dataview"><span class="typcn typcn-camera-outline" target="dataview"><span class="typcn typcn-camera-outline"
style="font-size: 1.2rem;"></span> Test View style="font-size: 1.2rem;"></span> Test View
</h:outputLink> </h:outputLink>
@ -213,7 +213,7 @@
<h1><span class="typcn typcn-news"></span> Template<span <h1><span class="typcn typcn-news"></span> Template<span
style="font-size: 1rem;margin-left:20px;"> style="font-size: 1rem;margin-left:20px;">
<h:outputLink <h:outputLink
value="#{facesContext.externalContext.requestContextPath}/pages/dataviews/data.xhtml?id=#{dataViewDefinitionController.data.uniqueID}&amp;faces-redirect=true" value="#{facesContext.externalContext.requestContextPath}#{dataViewDefinitionController.viewURI}"
target="dataview"><span class="typcn typcn-camera-outline" target="dataview"><span class="typcn typcn-camera-outline"
style="font-size: 1.2rem;"></span> Test View style="font-size: 1.2rem;"></span> Test View
</h:outputLink> </h:outputLink>

View file

@ -89,13 +89,11 @@
</span> </span>
</div> </div>
<h:commandButton actionListener="#{viewHandler.back(dataViewController)}" <h:commandButton actionListener="#{dataViewController.back()}" style="height: 31px;"
style="height: 31px;" disabled="#{dataViewController.pageIndex==0}" disabled="#{dataViewController.pageIndex==0}" value="◀◀ #{message.prev}">
value="◀◀ #{message.prev}">
<f:ajax render="dataview_result_id" onevent="updateDataView" /> <f:ajax render="dataview_result_id" onevent="updateDataView" />
</h:commandButton> </h:commandButton>
<h:commandButton actionListener="#{viewHandler.forward(dataViewController)}" <h:commandButton actionListener="#{dataViewController.forward()}" style="height: 31px;"
style="height: 31px;"
disabled="#{dataViewController.endOfList or dataViewController.getTotalPages() le 1}" disabled="#{dataViewController.endOfList or dataViewController.getTotalPages() le 1}"
value="#{message.next} ▶▶"> value="#{message.next} ▶▶">
<f:ajax render="dataview_result_id" onevent="updateDataView" /> <f:ajax render="dataview_result_id" onevent="updateDataView" />