package org.joget.workflow.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.joget.commons.util.FileStore;
import org.joget.commons.util.LogUtil;
import org.joget.form.model.Form;
import org.joget.form.model.FormMetaData;
import org.joget.form.model.dao.DynamicFormDao;
import org.joget.form.model.service.FormManager;
import org.joget.workflow.model.ActivityForm;
import org.joget.workflow.model.UserviewProcess;
import org.joget.workflow.model.UserviewSetup;
import org.joget.workflow.model.WorkflowActivity;
import org.joget.workflow.model.WorkflowFacade;
import org.joget.workflow.model.WorkflowPackage;
import org.joget.workflow.model.WorkflowProcess;
import org.joget.workflow.model.dao.ActivityFormDao;
import org.joget.workflow.model.dao.UserviewProcessDao;
import org.joget.workflow.model.service.ImportExportManager;
import org.joget.workflow.model.service.UserviewProcessManager;
import org.joget.workflow.model.service.UserviewSetupManager;
import org.joget.workflow.model.service.WorkflowUserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;
@Controller
public class UserviewWebController {
public static final String USERVIEW_ZIP_PREFIX = "userview-";
@Autowired
private WorkflowFacade workflowFacade;
@Autowired
private UserviewProcessManager userviewProcessManager;
@Autowired
private UserviewSetupManager userviewSetupManager;
@Autowired
private WorkflowUserManager workflowUserManager;
@Autowired
private FormManager formManager;
@Autowired
private ActivityFormDao activityFormDao;
@Autowired
private ImportExportManager importExportManager;
@RequestMapping(value = "/admin/userview/list")
public String userviewList(ModelMap map, @RequestParam(value = "sort", required = false) String sort, @RequestParam(value = "desc", required = false) Boolean desc, @RequestParam(value = "start", required = false) Integer start, @RequestParam(value = "rows", required = false) Integer rows) throws IOException {
Collection<WorkflowProcess> processList = workflowFacade.getProcessList("name", false, 0, -1, null, true, false);
map.addAttribute("processList", processList);
return "userview/userviewList";
}
@RequestMapping(value = "/admin/userview/create")
public String userviewCreate(ModelMap map) throws IOException {
Collection<WorkflowProcess> processList = workflowFacade.getProcessList("name", false, 0, -1, null, true, false);
map.addAttribute("processList", processList);
return "userview/userviewCreate";
}
@RequestMapping(value = "/admin/userview/submit", method = RequestMethod.POST)
public String userviewSaveSubmit(ModelMap map, HttpServletRequest request) throws IOException {
Collection<String> errors = new ArrayList<String>();
String name = request.getParameter("name");
String userviewSetupId = request.getParameter("userviewSetupId");
String id = request.getParameter("id");
String inboxLabel = request.getParameter("inboxLabel");
String startProcessLabel = request.getParameter("startProcessLabel");
String startProcessDefId = request.getParameter("startProcessDefId");
int runProcessDirectly = (request.getParameter("runProcessDirectly")!= null && "1".equals(request.getParameter("runProcessDirectly")))?1:0;
String customHeader = request.getParameter("userviewHeader");
String customFooter = request.getParameter("userviewFooter");
String customMenu = request.getParameter("userviewMenu");
String customCss = request.getParameter("userviewCss");
String customCssLink = request.getParameter("userviewCssLink");
String[] categoryId = request.getParameterValues("categoryId");
String[] categoryLabel = request.getParameterValues("categoryLabel");
String[] permission = request.getParameterValues("permission");
String[] processList = request.getParameterValues("process");
String[] activityList = request.getParameterValues("activity");
String[] activityLabel = request.getParameterValues("activityLabel");
String[] buttonSaveLabel = request.getParameterValues("buttonSaveLabel");
String[] buttonWithdrawLabel = request.getParameterValues("buttonWithdrawLabel");
String[] buttonCancelLabel = request.getParameterValues("buttonCancelLabel");
String[] buttonCompleteLabel = request.getParameterValues("buttonCompleteLabel");
String[] buttonSaveShow = request.getParameterValues("buttonSaveShow");
String[] buttonWithdrawShow = request.getParameterValues("buttonWithdrawShow");
String[] category = request.getParameterValues("category");
String[] activityFormType = request.getParameterValues("activityFormType");
String[] activityForm = request.getParameterValues("activityForm");
String[] columnList = request.getParameterValues("columns");
String[] filter = request.getParameterValues("filter");
String[] sort = request.getParameterValues("sort");
String[] tableHeader = request.getParameterValues("tableHeader");
String[] tableFooter = request.getParameterValues("tableFooter");
String[] tableNameList = request.getParameterValues("tableName");
String[] viewType = request.getParameterValues("viewType");
String[] permType = request.getParameterValues("permType");
UserviewSetup userviewSetup = new UserviewSetup();
if(userviewSetupId != null && userviewSetupId.trim().length() > 0){
userviewSetup.setId(userviewSetupId);
userviewProcessManager.removeUserviewProcessBySetupId(userviewSetupId);
}else{
userviewSetup.setId(id);
}
userviewSetup.setActive(1);
userviewSetup.setSetupName(name);
userviewSetup.setInboxLabel(inboxLabel);
userviewSetup.setStartProcessDefId(startProcessDefId);
userviewSetup.setStartProcessLabel(startProcessLabel);
userviewSetup.setRunProcessDirectly(runProcessDirectly);
userviewSetup.setHeader(customHeader);
userviewSetup.setFooter(customFooter);
userviewSetup.setMenu(customMenu);
userviewSetup.setCss(customCss);
userviewSetup.setCssLink(customCssLink);
userviewSetup.setCreatedBy(workflowUserManager.getCurrentUsername());
userviewSetup.setCreatedOn(new Date());
String categories = "";
if(categoryId != null){
for(int i=0; i<categoryId.length; i++){
if(categoryId[i].trim().length() > 0){
categories += categoryId[i] + ":" + categoryLabel[i].replaceAll(":", ":").replaceAll(",", ",") + ",";
}
}
}
userviewSetup.setCategories(categories);
userviewSetupManager.saveUserviewSetup(userviewSetup);
if(processList != null){
for(int i=0; i<processList.length; i++){
if(processList[i]!=null && !processList[i].equals("")){
UserviewProcess userviewProcess = new UserviewProcess();
userviewProcess.setCreatedBy(workflowUserManager.getCurrentUsername());
userviewProcess.setCreatedOn(new Date());
userviewProcess.setActivityDefId(activityList[i]);
userviewProcess.setActivityLabel(activityLabel[i]);
userviewProcess.setButtonCancelLabel(buttonCancelLabel[i]);
userviewProcess.setButtonCompleteLabel(buttonCompleteLabel[i]);
userviewProcess.setButtonSaveLabel(buttonSaveLabel[i]);
userviewProcess.setButtonWithdrawLabel(buttonWithdrawLabel[i]);
userviewProcess.setButtonSaveShow(Integer.parseInt(buttonSaveShow[i]));
userviewProcess.setButtonWithdrawShow(Integer.parseInt(buttonWithdrawShow[i]));
userviewProcess.setCategoryId(category[i]);
userviewProcess.setSequence(i);
userviewProcess.setProcessDefId(URLDecoder.decode(processList[i], "UTF-8"));
userviewProcess.setTableColumn(columnList[i].trim());
userviewProcess.setFilter(filter[i].trim());
userviewProcess.setSort(sort[i].trim());
userviewProcess.setTableName(tableNameList[i]);
userviewProcess.setHeader(tableHeader[i]);
userviewProcess.setFooter(tableFooter[i]);
userviewProcess.setViewType(Integer.parseInt(viewType[i]));
userviewProcess.setPermType(Integer.parseInt(permType[i]));
userviewProcess.setDvSetup(userviewSetup);
userviewProcess.setMappingType(UserviewProcessDao.MAPPING_TYPE_GROUP);
userviewProcess.setMappingValue(permission[i]);
if(activityFormType[i].equals("normal")){
userviewProcess.setActivityFormId(activityForm[i]);
}else if(activityFormType[i].equals("external")){
userviewProcess.setActivityFormUrl(activityForm[i]);
}
userviewProcessManager.saveUserviewProcess(userviewProcess);
}
}
}
if(userviewSetupId != null && userviewSetupId.trim().length() > 0){
map.addAttribute("save", "true");
return userviewEditView(map, userviewSetupId);
}else{
return "redirect:/web/admin/userview/list";
}
}
@RequestMapping(value = "/admin/userview/create/permission")
public String userviewCreatePermission(ModelMap map) throws IOException {
return "userview/userviewCreatePermission";
}
@RequestMapping(value = "/admin/userview/create/updateProcessVersion")
public String userviewCreateUpdateProcessVersion(ModelMap map, @RequestParam("processes") String processes) throws IOException {
String[] processList = processes.split(",");
Map<String, String> processVersionMap = new HashMap<String, String>();
Map<String, String> processNameMap = new HashMap<String, String>();
Map<String, Boolean> processVersionIsLatestMap = new HashMap<String, Boolean>();
if(processList.length > 0){
for(String processDefId : processList){
String packageId = processDefId.split("#")[0];
String version = processDefId.split("#")[1];
String latestVersion = workflowFacade.getCurrentPackageVersion(packageId);
WorkflowProcess process = workflowFacade.getProcess(processDefId);
processNameMap.put(processDefId, process.getPackageName() + " : " + process.getName());
if(version.equals(latestVersion)){
processVersionIsLatestMap.put(processDefId, true);
}
processVersionMap.put(processDefId, latestVersion);
}
}
map.addAttribute("processVersionMap", processVersionMap);
map.addAttribute("processNameMap", processNameMap);
map.addAttribute("processVersionIsLatestMap", processVersionIsLatestMap);
return "userview/userviewCreateUpdateProcessVersion";
}
@RequestMapping(value = "/admin/userview/create/updateFormVersion")
public String userviewCreateUpdateFormVersion(ModelMap map, @RequestParam("formids") String formIds) throws IOException {
String[] formIdList = formIds.split(",");
Map<String, Map> formMap = new HashMap<String, Map>();
Map<String, String> formNameMap = new HashMap<String, String>();
Map<String, Boolean> formVersionIsLatestMap = new HashMap<String, Boolean>();
if(formIdList.length > 0){
for(String formId : formIdList){
Map<String, String> versionMap = new LinkedHashMap<String, String>();
Collection<Form> forms = workflowFacade.getAllFormVersion(formId, "id", true);
String latestVersion = "";
for(Form form : forms){
String id = form.getId();
String version = "1";
String name = form.getName();
if("".equals(latestVersion)){
latestVersion = id;
}
if(id.contains("_ver_")){
version = id.substring(id.indexOf("_ver_") + 5, id.length());
}
versionMap.put(id+","+name, version);
if(formId.equals(id)){
formNameMap.put(id, name);
}
}
formMap.put(formId, versionMap);
if(latestVersion.equals(formId)){
formVersionIsLatestMap.put(formId, Boolean.TRUE);
}
}
}
map.addAttribute("formMap", formMap);
map.addAttribute("formNameMap", formNameMap);
map.addAttribute("formVersionIsLatestMap", formVersionIsLatestMap);
return "userview/userviewCreateUpdateFormVersion";
}
@RequestMapping(value = "/admin/userview/create/selectActivity")
public String userviewCreateSelectActivity(ModelMap map) throws IOException {
map.addAttribute("categoryList", formManager.getCategories("name", Boolean.FALSE, null, null));
Collection<WorkflowPackage> packageList = workflowFacade.getPackageList();
map.addAttribute("packageList", packageList);
return "userview/userviewCreateSelectActivity";
}
@RequestMapping("/admin/userview/edit/view/(*:userviewSetupId)")
public String userviewEditView(ModelMap map, @RequestParam("userviewSetupId") String userviewSetupId) throws IOException {
Collection<WorkflowProcess> processList = workflowFacade.getProcessList("name", false, 0, -1, null, true, false);
map.addAttribute("processList", processList);
map.addAttribute("userviewSetupId", userviewSetupId);
return "userview/userviewCreate";
}
@RequestMapping("/admin/userview/removeMultiple")
public String removeMultipleRunningProcessInstance(ModelMap model, @RequestParam("userviewIds") String userviewIds) {
StringTokenizer strToken = new StringTokenizer(userviewIds, ",");
while (strToken.hasMoreTokens()) {
String userviewId = (String) strToken.nextElement();
userviewSetupManager.removeUserview(userviewId);
}
return "workflow/runningProcessList";
}
@RequestMapping(value = "/userview/form/view/(*:userviewProcessId)/(*:formMetaDataId)")
public String userviewEmbeddedFormView(ModelMap map, @RequestParam("userviewProcessId") String userviewProcessId, @RequestParam("formMetaDataId") String formMetaDataId) throws IOException {
UserviewProcess userviewProcess = userviewProcessManager.getUserviewProcess(userviewProcessId);
String activityId = "";
String processId = "";
FormMetaData formMetaData = formManager.loadDynamicFormMetaData(userviewProcess.getTableName(), formMetaDataId);
if(formMetaData != null){
activityId = formMetaData.getActivityId();
WorkflowActivity activity = workflowFacade.getActivityById(activityId);
if(activity != null){
processId = activity.getProcessId();
}
}
map.addAttribute("buttonCancelLabel", userviewProcess.getButtonCancelLabel());
map.addAttribute("buttonCompleteLabel", userviewProcess.getButtonCompleteLabel());
map.addAttribute("buttonSaveLabel", userviewProcess.getButtonSaveLabel());
map.addAttribute("buttonWithdrawLabel", userviewProcess.getButtonWithdrawLabel());
map.addAttribute("buttonSaveShow", (userviewProcess.getButtonSaveShow() != null && userviewProcess.getButtonSaveShow() == 0) ? "false" : "true");
map.addAttribute("buttonWithdrawShow", (userviewProcess.getButtonSaveShow() != null && userviewProcess.getButtonWithdrawShow() == 0) ? "false" : "true");
map.addAttribute("formId", userviewProcess.getActivityFormId());
map.addAttribute("formUrl", userviewProcess.getActivityFormUrl());
map.addAttribute("processId", processId);
map.addAttribute("username", workflowUserManager.getCurrentUsername());
map.addAttribute("activityId", activityId);
if(workflowFacade.isAssignmentExist(activityId)){
map.addAttribute("hasAssignment", "true");
}else{
map.addAttribute("hasAssignment", "false");
}
WorkflowActivity act = workflowFacade.getActivityById(activityId);
if(act != null && act.getState().contains("closed")){
map.addAttribute("completed", "true");
Collection<ActivityForm> actFormList = workflowFacade.getFormByActivity(userviewProcess.getProcessDefId(), Integer.parseInt(userviewProcess.getProcessDefId().split("#")[1]), userviewProcess.getActivityDefId());
if(actFormList.size() > 0){
ActivityForm actForm = actFormList.iterator().next();
if(actForm != null && actForm.getFormId().trim().length() > 0){
map.addAttribute("historyFormId", actForm.getFormId());
}
}
}else{
map.addAttribute("completed", "false");
}
return "userview/userviewEmbeddedFormView";
}
@RequestMapping(value = "/userview/(*:id)")
public String userviewEmbedded(ModelMap map, @RequestParam("id") String id, @RequestParam(value="detail", required=false) String detail) throws IOException {
Map<String, String> categories = new HashMap<String, String>();
Map<String, Collection<HashMap>> categoryActivityMap = new LinkedHashMap<String, Collection<HashMap>>();
UserviewSetup uvs = userviewSetupManager.getUserviewSetup(id);
if(workflowFacade.isUserInWhiteList(uvs.getStartProcessDefId().replaceAll("%23", "#"))){
map.addAttribute("showStartProcess", "true");
}else{
map.addAttribute("showStartProcess", "false");
}
// check that userview exists
if (uvs == null) {
return "error404.jsp";
}
if(uvs.getCategories() != null && uvs.getCategories().trim().length() != 0){
String category[] = uvs.getCategories().split(",");
for(String c: category){
String temp[] = c.split(":");
categories.put(temp[0], temp[1]);
}
}
String currentUsername = workflowUserManager.getCurrentUsername();
Collection<UserviewProcess> userviewProcessList = userviewProcessManager.getUserviewProcessBySetupId(uvs.getId());
for(UserviewProcess userviewProcess : userviewProcessList){
if(userviewProcessManager.isUserAllowToView(userviewProcess, currentUsername)){
WorkflowActivity wfActObj = workflowFacade.getActivityById(userviewProcess.getProcessDefId(), userviewProcess.getActivityDefId());
if(wfActObj == null && userviewProcess.getActivityDefId().equals("runProcess")){
wfActObj = new WorkflowActivity();
wfActObj.setId("runProcess");
wfActObj.setName("Run Process");
}else if(wfActObj == null){
return "error404.jsp";
}
wfActObj.setLatestActivityCount(formManager.countActivityFromMetaData(userviewProcess.getTableName(), userviewProcess.getActivityDefId(), DynamicFormDao.STATUS_RUNNING, DynamicFormDao.VIEW_PERMISSION_PERSONAL, currentUsername));
if (userviewProcess.getActivityLabel() != null && !userviewProcess.getActivityLabel().equals("")) {
wfActObj.setName(userviewProcess.getActivityLabel());
}
Collection<HashMap> activityList = new ArrayList<HashMap>();
if(categoryActivityMap.containsKey(categories.get(userviewProcess.getCategoryId()))){
activityList = categoryActivityMap.get(categories.get(userviewProcess.getCategoryId()));
}
HashMap activity = new HashMap();
activity.put("wfActivityObj", wfActObj);
activity.put("userviewActivityObj", userviewProcess);
activityList.add(activity);
categoryActivityMap.put(categories.get(userviewProcess.getCategoryId()), activityList);
}
}
map.addAttribute("categoryActivityMap", categoryActivityMap);
map.addAttribute("userviewId", id);
map.addAttribute("userviewSetup", uvs);
if(detail != null && detail.trim().length() > 0 && !"inbox".equals(detail)){
Collection<String> columns = new ArrayList();
UserviewProcess userviewProcess = userviewProcessManager.getUserviewProcess(detail);
if(userviewProcess != null){
StringTokenizer tempStringTokenizer = new StringTokenizer(userviewProcess.getTableColumn(), ",");
Map<String, String> columnLabels = new HashMap<String, String>();
Collection<String> sort = null;
if(userviewProcess.getSort() != null && userviewProcess.getSort().trim().length() > 0){
sort = Arrays.asList(userviewProcess.getSort().replace(", ",",").split(","));
}
while (tempStringTokenizer.hasMoreTokens()) {
String columnNameLabel = (String) tempStringTokenizer.nextElement();
String [] colNameLbl = columnNameLabel.split(":");
String columnName = colNameLbl[0].trim();
String columnLabel = colNameLbl[0].trim();
if(colNameLbl.length > 1){
columnLabel = colNameLbl[1]!=null && !colNameLbl[1].trim().equals("")?colNameLbl[1].trim():colNameLbl[0].trim();
columnLabel = columnLabel.replaceAll("'", "\\\\'");
}
columnLabels.put(columnName, columnLabel);
String stringSort = "";
if(sort != null && sort.contains(columnName)){
stringSort = " | sortable: true";
}
if(columnName.endsWith("(System)")){
columns.add("{key: 'dynamicForm.customProperties." + columnName.replace("(System)", "") + "' | label: '" + columnLabel + "'" + stringSort + "}");
}else{
columns.add("{key: 'dynamicForm.customProperties.c_" + columnName + "' | label: '" + columnLabel + "'" + stringSort + "}");
}
}
Map<String, String> filterTypes = new LinkedHashMap<String, String>();
if(userviewProcess.getFilter() != null && userviewProcess.getFilter().trim().length() > 0){
StringTokenizer tempFilterTokenizer = new StringTokenizer(userviewProcess.getFilter(), ",");
while (tempFilterTokenizer.hasMoreTokens()) {
String key = ((String) tempFilterTokenizer.nextElement()).trim();
filterTypes.put(key, columnLabels.get(key));
}
}
map.addAttribute("detail", detail);
map.addAttribute("columns", columns);
map.addAttribute("filterTypes", filterTypes);
map.addAttribute("tableHeader", userviewProcess.getHeader());
map.addAttribute("tableFooter", userviewProcess.getFooter());
}
}
return "userview/userviewEmbedded";
}
@RequestMapping("/admin/userview/import")
public String userviewImport(ModelMap map) {
return "userview/userviewImport";
}
@RequestMapping(value = "/admin/userview/import/submit", method = RequestMethod.POST)
public String userviewImportSubmit(ModelMap map) throws IOException {
MultipartFile packageZip = FileStore.getFile("packageZip");
String tempDir = System.getProperty("java.io.tmpdir");
String tempFileName = "userview-packageZip-" + System.currentTimeMillis() + ".zip";
FileOutputStream out = new FileOutputStream(new File(tempDir, tempFileName));
out.write(packageZip.getBytes());
out.close();
byte[] packageData = null;
try {
packageData = importExportManager.getPackageDataXmlFromZip(packageZip.getBytes());
} catch (Exception e) {
map.addAttribute("errorMessage", e.getMessage());
return "userview/userviewImport";
}
List<String> errorList = importExportManager.validateImportPackageData(packageData);
if (!errorList.isEmpty()) {
map.addAttribute("errorList", errorList);
map.addAttribute("tempFileName", tempFileName);
return "userview/userviewImportError";
}
return "redirect:/web/admin/userview/import/confirm?tempFileName=" + tempFileName;
}
@RequestMapping("/admin/userview/import/confirm")
public String userviewImportConfirm(ModelMap map, @RequestParam("tempFileName") String tempFileName) throws IOException {
String tempDir = System.getProperty("java.io.tmpdir");
File tempFile = new File(tempDir, tempFileName);
FileInputStream in = new FileInputStream(tempFile);
byte[] bytes = new byte[(int) tempFile.length()];
in.read(bytes);
in.close();
byte[] packageData = null;
Collection<byte[]> packageXpdlList = null;
Map<String, byte[]> mobileFormList = null;
try {
packageData = importExportManager.getPackageDataXmlFromZip(bytes);
packageXpdlList = importExportManager.getAllPackageXpdlFromZip(bytes);
mobileFormList = importExportManager.getAllMobileFormFromZip(bytes);
} catch (Exception e) {
map.addAttribute("errorMessage", e.getMessage());
return "userview/userviewImport";
}
importExportManager.importUserview(packageData, packageXpdlList, mobileFormList);
return "redirect:/web/admin/userview/list";
}
@RequestMapping("/admin/userview/export/(*:userviewId)")
public void userviewExport(HttpServletResponse response, @RequestParam("userviewId") String userviewId) throws IOException {
try {
//byte[] userviewData = importExportManager.exportUserview(userviewId);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String timestamp = sdf.format(new Date());
response.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment; filename=" + USERVIEW_ZIP_PREFIX + userviewId + "-" + timestamp + ".zip");
ServletOutputStream stream = response.getOutputStream();
importExportManager.exportUserview(userviewId, stream);
stream.close();
} catch (Exception ex) {
LogUtil.error(getClass().getName(), ex, "");
}
}
}