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

View file

@ -42,7 +42,7 @@
<h1><span class="typcn typcn-edit"></span> Query Definition
<span style="font-size: 1rem;margin-left:20px;">
<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"
style="font-size: 1.2rem;"></span> Test View
</h:outputLink>
@ -182,7 +182,7 @@
<h1><span class="typcn typcn-th-list-outline"></span> Form Definition<span
style="font-size: 1rem;margin-left:20px;">
<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"
style="font-size: 1.2rem;"></span> Test View
</h:outputLink>
@ -213,7 +213,7 @@
<h1><span class="typcn typcn-news"></span> Template<span
style="font-size: 1rem;margin-left:20px;">
<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"
style="font-size: 1.2rem;"></span> Test View
</h:outputLink>

View file

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