CCM NG/ccm-cms: Workflow tab
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4626 8810af33-2d31-482b-a856-94f89814c4df
parent
45f9e5bda0
commit
96b150582c
|
|
@ -293,10 +293,9 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Fix this.
|
private static final String[] COLUMNS = new String[]{
|
||||||
private static final String[] s_columns = new String[]{
|
lz("cms.ui.workflow.task.name"),
|
||||||
lz("cms.ui.name"),
|
lz("cms.ui.workflow.task.description"),
|
||||||
lz("cms.ui.description"),
|
|
||||||
lz("cms.ui.workflow.task.dependencies"),
|
lz("cms.ui.workflow.task.dependencies"),
|
||||||
lz("cms.ui.workflow.task.state")
|
lz("cms.ui.workflow.task.state")
|
||||||
};
|
};
|
||||||
|
|
@ -304,7 +303,7 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
|
||||||
private class TaskTable extends Table {
|
private class TaskTable extends Table {
|
||||||
|
|
||||||
public TaskTable() {
|
public TaskTable() {
|
||||||
super(new TaskTableModelBuilder(workflowRequestLocal), s_columns);
|
super(new TaskTableModelBuilder(workflowRequestLocal), COLUMNS);
|
||||||
|
|
||||||
setEmptyView(new Label(gz("cms.ui.workflow.task.none")));
|
setEmptyView(new Label(gz("cms.ui.workflow.task.none")));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -440,9 +440,11 @@ final class TaskItemPane extends BaseItemPane {
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
|
||||||
private Model(final CmsTask task) {
|
private Model(final CmsTask task) {
|
||||||
roles = task.getAssignments().stream()
|
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||||
.map(assignment -> assignment.getRole())
|
final WorkflowAdminPaneController controller = cdiUtil.findBean(
|
||||||
.collect(Collectors.toList());
|
WorkflowAdminPaneController.class);
|
||||||
|
|
||||||
|
roles = controller.findAssignees(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -22,32 +22,29 @@ import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.Table;
|
import com.arsdigita.bebop.Table;
|
||||||
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
|
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
import com.arsdigita.util.GraphSet;
|
|
||||||
import com.arsdigita.util.Graphs;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.libreccm.workflow.Task;
|
import org.libreccm.workflow.Task;
|
||||||
import org.libreccm.workflow.Workflow;
|
import org.libreccm.workflow.Workflow;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
TaskTableModelBuilder.class);
|
TaskTableModelBuilder.class);
|
||||||
|
|
||||||
private final WorkflowRequestLocal m_workflow;
|
private final WorkflowRequestLocal workflow;
|
||||||
|
|
||||||
TaskTableModelBuilder(final WorkflowRequestLocal workflow) {
|
TaskTableModelBuilder(final WorkflowRequestLocal workflow) {
|
||||||
m_workflow = workflow;
|
this.workflow = workflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -55,14 +52,14 @@ class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
||||||
final PageState state) {
|
final PageState state) {
|
||||||
LOGGER.debug("Creating a new table model for the current request");
|
LOGGER.debug("Creating a new table model for the current request");
|
||||||
|
|
||||||
return new Model(m_workflow.getWorkflow(state));
|
return new Model(workflow.getWorkflow(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Model implements TableModel {
|
private static class Model implements TableModel {
|
||||||
|
|
||||||
private Task m_task;
|
private Task currentTask;
|
||||||
private Iterator m_tasks;
|
private Iterator<Task> tasksIterator;
|
||||||
private Map m_dependencies = new HashMap();
|
private Map<Task, String> dependencies;
|
||||||
|
|
||||||
private Model(final Workflow workflow) {
|
private Model(final Workflow workflow) {
|
||||||
|
|
||||||
|
|
@ -70,46 +67,54 @@ class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
||||||
final WorkflowAdminPaneController controller = cdiUtil.findBean(
|
final WorkflowAdminPaneController controller = cdiUtil.findBean(
|
||||||
WorkflowAdminPaneController.class);
|
WorkflowAdminPaneController.class);
|
||||||
|
|
||||||
final Iterator<Task> tasksIter = controller
|
final TaskTableModelData data = controller
|
||||||
.getTasksForWorkflow(workflow)
|
.getTaskTableModelData(workflow);
|
||||||
.iterator();
|
tasksIterator = data.getTasks();
|
||||||
GraphSet g = new GraphSet();
|
dependencies = data.getDependencies();
|
||||||
|
|
||||||
while (tasksIter.hasNext()) {
|
|
||||||
Task t = tasksIter.next();
|
|
||||||
final Iterator<Task> deps = t.getDependsOn().iterator();
|
|
||||||
final StringBuffer buffer = new StringBuffer();
|
|
||||||
while (deps.hasNext()) {
|
|
||||||
Task dep = deps.next();
|
|
||||||
g.addEdge(t, dep, null);
|
|
||||||
buffer.append(dep.getLabel() + ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int len = buffer.length();
|
// final Iterator<Task> tasksIter = controller
|
||||||
if (len >= 2) {
|
// .getTasksForWorkflow(workflow)
|
||||||
buffer.setLength(len - 2);
|
// .iterator();
|
||||||
} else {
|
// GraphSet graphSet = new GraphSet();
|
||||||
g.addNode(t);
|
//
|
||||||
}
|
// while (tasksIter.hasNext()) {
|
||||||
m_dependencies.put(t, buffer.toString());
|
// Task task = tasksIter.next();
|
||||||
}
|
// final Iterator<Task> deps = task.getDependsOn().iterator();
|
||||||
|
// final StringBuffer buffer = new StringBuffer();
|
||||||
List tasks = new ArrayList();
|
// while (deps.hasNext()) {
|
||||||
outer:
|
// Task dep = deps.next();
|
||||||
while (g.nodeCount() > 0) {
|
// graphSet.addEdge(task, dep, null);
|
||||||
List l = Graphs.getSinkNodes(g);
|
// buffer
|
||||||
for (Iterator it = l.iterator(); it.hasNext();) {
|
// .append(dep.getLabel())
|
||||||
Task t = (Task) it.next();
|
// .append(", ");
|
||||||
tasks.add(t);
|
// }
|
||||||
g.removeNode(t);
|
//
|
||||||
continue outer;
|
// final int len = buffer.length();
|
||||||
}
|
// if (len >= 2) {
|
||||||
// break loop if no nodes removed
|
// buffer.setLength(len - 2);
|
||||||
LOGGER.error("found possible loop in tasks for " + workflow);
|
// } else {
|
||||||
break;
|
// graphSet.addNode(task);
|
||||||
}
|
// }
|
||||||
|
// m_dependencies.put(task, buffer.toString());
|
||||||
m_tasks = tasks.iterator();
|
// }
|
||||||
|
//
|
||||||
|
// List tasks = new ArrayList();
|
||||||
|
// outer:
|
||||||
|
// while (graphSet.nodeCount() > 0) {
|
||||||
|
// List list = Graphs.getSinkNodes(graphSet);
|
||||||
|
// for (Iterator it = list.iterator(); it.hasNext();) {
|
||||||
|
// Task t = (Task) it.next();
|
||||||
|
// tasks.add(t);
|
||||||
|
// graphSet.removeNode(t);
|
||||||
|
// continue outer;
|
||||||
|
// }
|
||||||
|
// // break loop if no nodes removed
|
||||||
|
// LOGGER.error("found possible loop in tasks for " + workflow);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// m_tasks = tasks.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -119,8 +124,8 @@ class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean nextRow() {
|
public final boolean nextRow() {
|
||||||
if (m_tasks.hasNext()) {
|
if (tasksIterator.hasNext()) {
|
||||||
m_task = (Task) m_tasks.next();
|
currentTask = tasksIterator.next();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -129,18 +134,20 @@ class TaskTableModelBuilder extends AbstractTableModelBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Object getKeyAt(final int column) {
|
public final Object getKeyAt(final int column) {
|
||||||
return m_task.getTaskId();
|
return currentTask.getTaskId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Object getElementAt(final int column) {
|
public final Object getElementAt(final int column) {
|
||||||
|
final Locale defaultLocale = KernelConfig.getConfig().getDefaultLocale();
|
||||||
|
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case 0:
|
case 0:
|
||||||
return m_task.getLabel();
|
return currentTask.getLabel().getValue(defaultLocale);
|
||||||
case 1:
|
case 1:
|
||||||
return m_task.getDescription();
|
return currentTask.getDescription().getValue(defaultLocale);
|
||||||
case 2:
|
case 2:
|
||||||
return m_dependencies.get(m_task);
|
return dependencies.get(currentTask);
|
||||||
case 3:
|
case 3:
|
||||||
return "";
|
return "";
|
||||||
// return m_task.getStateString();
|
// return m_task.getStateString();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package com.arsdigita.cms.ui.workflow;
|
||||||
|
|
||||||
|
import org.libreccm.workflow.Task;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
class TaskTableModelData {
|
||||||
|
|
||||||
|
private final Iterator<Task> tasks;
|
||||||
|
private final Map<Task, String> dependencies;
|
||||||
|
|
||||||
|
protected TaskTableModelData(final Iterator<Task> tasks,
|
||||||
|
final Map<Task, String> dependencies) {
|
||||||
|
this.tasks = tasks;
|
||||||
|
this.dependencies = dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<Task> getTasks() {
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Task, String> getDependencies() {
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,10 +19,15 @@
|
||||||
package com.arsdigita.cms.ui.workflow;
|
package com.arsdigita.cms.ui.workflow;
|
||||||
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
|
import com.arsdigita.util.GraphSet;
|
||||||
|
import com.arsdigita.util.Graphs;
|
||||||
import com.arsdigita.util.UncheckedWrapperException;
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
|
import org.libreccm.security.Role;
|
||||||
import org.libreccm.workflow.CircularTaskDependencyException;
|
import org.libreccm.workflow.CircularTaskDependencyException;
|
||||||
import org.libreccm.workflow.Task;
|
import org.libreccm.workflow.Task;
|
||||||
import org.libreccm.workflow.TaskManager;
|
import org.libreccm.workflow.TaskManager;
|
||||||
|
|
@ -40,6 +45,7 @@ import org.librecms.workflow.CmsTaskType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -56,6 +62,9 @@ import javax.transaction.Transactional;
|
||||||
@RequestScoped
|
@RequestScoped
|
||||||
public class WorkflowAdminPaneController {
|
public class WorkflowAdminPaneController {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager
|
||||||
|
.getLogger(WorkflowAdminPaneController.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ConfigurationManager confManager;
|
private ConfigurationManager confManager;
|
||||||
|
|
||||||
|
|
@ -132,10 +141,10 @@ public class WorkflowAdminPaneController {
|
||||||
|
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public CmsTask addTask(final Workflow workflow,
|
public CmsTask addTask(final Workflow workflow,
|
||||||
final String name,
|
final String name,
|
||||||
final String desc,
|
final String desc,
|
||||||
final CmsTaskType type,
|
final CmsTaskType type,
|
||||||
final String[] deps) {
|
final String[] deps) {
|
||||||
final KernelConfig kernelConfig = confManager
|
final KernelConfig kernelConfig = confManager
|
||||||
.findConfiguration(KernelConfig.class);
|
.findConfiguration(KernelConfig.class);
|
||||||
final Locale defaultLocale = kernelConfig.getDefaultLocale();
|
final Locale defaultLocale = kernelConfig.getDefaultLocale();
|
||||||
|
|
@ -208,11 +217,76 @@ public class WorkflowAdminPaneController {
|
||||||
|
|
||||||
final Task theTask = taskRepo
|
final Task theTask = taskRepo
|
||||||
.findById(task.getTaskId())
|
.findById(task.getTaskId())
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
||||||
"No Task with ID %d in the database. Where did that ID come from?",
|
"No Task with ID %d in the database. Where did that ID come from?",
|
||||||
task.getTaskId())));
|
task.getTaskId())));
|
||||||
|
|
||||||
return new ArrayList<>(theTask.getDependsOn());
|
return new ArrayList<>(theTask.getDependsOn());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
TaskTableModelData getTaskTableModelData(final Workflow workflow) {
|
||||||
|
final Map<Task, String> dependencies = new HashMap<>();
|
||||||
|
|
||||||
|
final Iterator<Task> tasksIter = getTasksForWorkflow(workflow)
|
||||||
|
.iterator();
|
||||||
|
final GraphSet graphSet = new GraphSet();
|
||||||
|
|
||||||
|
while (tasksIter.hasNext()) {
|
||||||
|
Task task = tasksIter.next();
|
||||||
|
final Iterator<Task> deps = task.getDependsOn().iterator();
|
||||||
|
final StringBuffer buffer = new StringBuffer();
|
||||||
|
while (deps.hasNext()) {
|
||||||
|
Task dep = deps.next();
|
||||||
|
graphSet.addEdge(task, dep, null);
|
||||||
|
buffer
|
||||||
|
.append(dep.getLabel())
|
||||||
|
.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int len = buffer.length();
|
||||||
|
if (len >= 2) {
|
||||||
|
buffer.setLength(len - 2);
|
||||||
|
} else {
|
||||||
|
graphSet.addNode(task);
|
||||||
|
}
|
||||||
|
dependencies.put(task, buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Task> tasks = new ArrayList<>();
|
||||||
|
outer:
|
||||||
|
while (graphSet.nodeCount() > 0) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final List<Task> list = Graphs.getSinkNodes(graphSet);
|
||||||
|
for (final Iterator<Task> it = list.iterator(); it.hasNext();) {
|
||||||
|
final Task currentTask = it.next();
|
||||||
|
tasks.add(currentTask);
|
||||||
|
graphSet.removeNode(currentTask);
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
// break loop if no nodes removed
|
||||||
|
LOGGER.error("found possible loop in tasks for " + workflow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Iterator<Task> taskIterator = tasks.iterator();
|
||||||
|
|
||||||
|
return new TaskTableModelData(taskIterator, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public List<Role> findAssignees(final CmsTask task) {
|
||||||
|
final CmsTask theTask = (CmsTask) taskRepo
|
||||||
|
.findById(task.getTaskId())
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
||||||
|
"No Task with ID %d in the database. Where did that ID come from?",
|
||||||
|
task.getTaskId())));
|
||||||
|
|
||||||
|
return theTask
|
||||||
|
.getAssignments()
|
||||||
|
.stream()
|
||||||
|
.map(assignment -> assignment.getRole())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,3 +165,4 @@ cms.ui.workflow.task.dependencies=Dependencies
|
||||||
cms.workflow.task_type.AUTHOR=Author
|
cms.workflow.task_type.AUTHOR=Author
|
||||||
cms.workflow.task_type.EDIT=Edit
|
cms.workflow.task_type.EDIT=Edit
|
||||||
cms.workflow.task_type.DEPLOY=Deploy
|
cms.workflow.task_type.DEPLOY=Deploy
|
||||||
|
cms.ui.workflow.task.state=Status
|
||||||
|
|
|
||||||
|
|
@ -164,3 +164,4 @@ cms.ui.workflow.task.dependencies=Abh\u00e4ngigkeiten
|
||||||
cms.workflow.task_type.AUTHOR=Verfassen
|
cms.workflow.task_type.AUTHOR=Verfassen
|
||||||
cms.workflow.task_type.EDIT=Bearbeiten
|
cms.workflow.task_type.EDIT=Bearbeiten
|
||||||
cms.workflow.task_type.DEPLOY=Ver\u00f6ffentlichen
|
cms.workflow.task_type.DEPLOY=Ver\u00f6ffentlichen
|
||||||
|
cms.ui.workflow.task.state=Status
|
||||||
|
|
|
||||||
|
|
@ -133,3 +133,4 @@ cms.ui.workflow.task.dependencies=Dependencies
|
||||||
cms.workflow.task_type.AUTHOR=Author
|
cms.workflow.task_type.AUTHOR=Author
|
||||||
cms.workflow.task_type.EDIT=Edit
|
cms.workflow.task_type.EDIT=Edit
|
||||||
cms.workflow.task_type.DEPLOY=Deploy
|
cms.workflow.task_type.DEPLOY=Deploy
|
||||||
|
cms.ui.workflow.task.state=Status
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ public class AssignableTaskManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
final TypedQuery<AssignableTask> query = entityManager.createNamedQuery(
|
final TypedQuery<AssignableTask> query = entityManager.createNamedQuery(
|
||||||
"UserTask.findLockedBy", AssignableTask.class);
|
"AssignableTask.findLockedBy", AssignableTask.class);
|
||||||
query.setParameter("user", user);
|
query.setParameter("user", user);
|
||||||
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue