Several bugfixes for workflow and task handling
parent
b140923d86
commit
2be640f8d4
|
|
@ -22,8 +22,13 @@ import org.libreccm.api.Identifier;
|
||||||
import org.libreccm.api.IdentifierParser;
|
import org.libreccm.api.IdentifierParser;
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
import org.libreccm.security.AuthorizationRequired;
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
|
import org.libreccm.security.Role;
|
||||||
|
import org.libreccm.workflow.AssignableTask;
|
||||||
|
import org.libreccm.workflow.AssignableTaskManager;
|
||||||
|
import org.libreccm.workflow.AssignableTaskRepository;
|
||||||
import org.libreccm.workflow.CircularTaskDependencyException;
|
import org.libreccm.workflow.CircularTaskDependencyException;
|
||||||
import org.libreccm.workflow.Task;
|
import org.libreccm.workflow.Task;
|
||||||
|
import org.libreccm.workflow.TaskAssignment;
|
||||||
import org.libreccm.workflow.TaskManager;
|
import org.libreccm.workflow.TaskManager;
|
||||||
import org.libreccm.workflow.TaskRepository;
|
import org.libreccm.workflow.TaskRepository;
|
||||||
import org.libreccm.workflow.Workflow;
|
import org.libreccm.workflow.Workflow;
|
||||||
|
|
@ -32,6 +37,7 @@ import org.libreccm.workflow.WorkflowRepository;
|
||||||
import org.librecms.contentsection.ContentSection;
|
import org.librecms.contentsection.ContentSection;
|
||||||
import org.librecms.contentsection.ContentSectionManager;
|
import org.librecms.contentsection.ContentSectionManager;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
@ -66,6 +72,12 @@ public class ConfigurationWorkflowController {
|
||||||
@Inject
|
@Inject
|
||||||
private AdminPermissionsChecker adminPermissionsChecker;
|
private AdminPermissionsChecker adminPermissionsChecker;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssignableTaskManager assignableTaskManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssignableTaskRepository assignableTaskRepo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for actions involving content sections.
|
* Used for actions involving content sections.
|
||||||
*/
|
*/
|
||||||
|
|
@ -834,19 +846,60 @@ public class ConfigurationWorkflowController {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (task instanceof AssignableTask) {
|
||||||
|
final AssignableTask assignableTask = (AssignableTask) task;
|
||||||
|
final List<Role> assignedRoles = assignableTask
|
||||||
|
.getAssignments()
|
||||||
|
.stream()
|
||||||
|
.map(TaskAssignment::getRole)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
selectedWorkflowTaskTemplateModel.setAssignedRoles(
|
||||||
|
assignedRoles
|
||||||
|
.stream()
|
||||||
|
.map(Role::getName)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
|
||||||
|
selectedWorkflowTaskTemplateModel.setAvailableRoles(
|
||||||
|
section
|
||||||
|
.getRoles()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(Role::getUuid, Role::getName))
|
||||||
|
);
|
||||||
|
|
||||||
|
selectedWorkflowTaskTemplateModel.setAssignedRoleKeys(
|
||||||
|
assignedRoles
|
||||||
|
.stream()
|
||||||
|
.map(Role::getUuid)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
selectedWorkflowTaskTemplateModel.setAssignedRoles(
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
|
selectedWorkflowTaskTemplateModel.setAvailableRoles(
|
||||||
|
Collections.emptyMap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return "org/librecms/ui/contentsection/configuration/workflow-task.xhtml";
|
return "org/librecms/ui/contentsection/configuration/workflow-task.xhtml";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a task to a workflow template.
|
* Adds a assignable task to a workflow template.
|
||||||
*
|
*
|
||||||
* @param sectionIdentifierParam The identifier of the current content
|
* @param sectionIdentifierParam The identifier of the current content
|
||||||
* section.
|
* section.
|
||||||
* @param workflowIdentiferParam The identifier of the current workflow
|
* @param workflowIdentiferParam The identifier of the current workflow
|
||||||
* template.
|
* template.
|
||||||
* @param label The label of the new task.
|
* @param label The label of the new task.
|
||||||
|
* @param assignments UUIDs of the roles to which the task is
|
||||||
|
* assigned.
|
||||||
*
|
*
|
||||||
* @return A redirect to the details view of the workflow.
|
* @return A redirect to the details view of the workflow.
|
||||||
|
*
|
||||||
|
* @see AssignableTask
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/{workflowIdentifier}/tasks/@add")
|
@Path("/{workflowIdentifier}/tasks/@add")
|
||||||
|
|
@ -855,7 +908,8 @@ public class ConfigurationWorkflowController {
|
||||||
public String addTask(
|
public String addTask(
|
||||||
@PathParam("sectionIdentifier") final String sectionIdentifierParam,
|
@PathParam("sectionIdentifier") final String sectionIdentifierParam,
|
||||||
@PathParam("workflowIdentifier") final String workflowIdentiferParam,
|
@PathParam("workflowIdentifier") final String workflowIdentiferParam,
|
||||||
@FormParam("label") final String label
|
@FormParam("label") final String label,
|
||||||
|
@FormParam("assignments") final List<String> assignments
|
||||||
) {
|
) {
|
||||||
final Optional<ContentSection> sectionResult = sectionsUi
|
final Optional<ContentSection> sectionResult = sectionsUi
|
||||||
.findContentSection(sectionIdentifierParam);
|
.findContentSection(sectionIdentifierParam);
|
||||||
|
|
@ -877,12 +931,23 @@ public class ConfigurationWorkflowController {
|
||||||
return showWorkflowTemplateNotFound(section, workflowIdentiferParam);
|
return showWorkflowTemplateNotFound(section, workflowIdentiferParam);
|
||||||
}
|
}
|
||||||
final Workflow workflow = workflowResult.get();
|
final Workflow workflow = workflowResult.get();
|
||||||
final Task task = new Task();
|
final AssignableTask task = new AssignableTask();
|
||||||
task.getLabel().addValue(
|
task.getLabel().addValue(
|
||||||
globalizationHelper.getNegotiatedLocale(), label
|
globalizationHelper.getNegotiatedLocale(), label
|
||||||
);
|
);
|
||||||
|
|
||||||
taskRepo.save(task);
|
final List<Role> roles = section
|
||||||
|
.getRoles()
|
||||||
|
.stream()
|
||||||
|
.filter(role -> assignments.contains(role.getUuid()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assignableTaskRepo.save(task);
|
||||||
|
|
||||||
|
for (final Role role : roles) {
|
||||||
|
assignableTaskManager.assignTask(task, role);
|
||||||
|
}
|
||||||
|
|
||||||
taskManager.addTask(workflow, task);
|
taskManager.addTask(workflow, task);
|
||||||
|
|
||||||
return String.format(
|
return String.format(
|
||||||
|
|
@ -1479,6 +1544,84 @@ public class ConfigurationWorkflowController {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{workflowIdentifier}/tasks/{taskIdentifier}/@assignments")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String updateAssignments(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifierParam,
|
||||||
|
@PathParam("workflowIdentifier") final String workflowIdentiferParam,
|
||||||
|
@PathParam("taskIdentifier") final String taskIdentifierParam,
|
||||||
|
@FormParam("assignments") final List<String> assignments
|
||||||
|
) {
|
||||||
|
final Optional<ContentSection> sectionResult = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifierParam);
|
||||||
|
if (!sectionResult.isPresent()) {
|
||||||
|
sectionsUi.showContentSectionNotFound(sectionIdentifierParam);
|
||||||
|
}
|
||||||
|
final ContentSection section = sectionResult.get();
|
||||||
|
sectionModel.setSection(section);
|
||||||
|
if (!adminPermissionsChecker.canAdministerWorkflows(section)) {
|
||||||
|
return sectionsUi.showAccessDenied(
|
||||||
|
"sectionIdentifier", sectionIdentifierParam
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<Workflow> workflowResult = findWorkflowTemplate(
|
||||||
|
section, workflowIdentiferParam
|
||||||
|
);
|
||||||
|
if (!workflowResult.isPresent()) {
|
||||||
|
return showWorkflowTemplateNotFound(section, workflowIdentiferParam);
|
||||||
|
}
|
||||||
|
final Workflow workflow = workflowResult.get();
|
||||||
|
final Optional<Task> taskResult = findTaskTemplate(
|
||||||
|
workflow, taskIdentifierParam
|
||||||
|
);
|
||||||
|
if (!taskResult.isPresent()) {
|
||||||
|
return showWorkflowTaskTemplateNotFound(
|
||||||
|
section, workflowIdentiferParam, taskIdentifierParam
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Task task = taskResult.get();
|
||||||
|
if (task instanceof AssignableTask) {
|
||||||
|
final AssignableTask assignableTask = (AssignableTask) task;
|
||||||
|
|
||||||
|
final List<Role> assignedRoles = assignableTask
|
||||||
|
.getAssignments()
|
||||||
|
.stream()
|
||||||
|
.map(TaskAssignment::getRole)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<Role> newAssignements = section
|
||||||
|
.getRoles()
|
||||||
|
.stream()
|
||||||
|
.filter(role -> assignments.contains(role.getUuid()))
|
||||||
|
.filter(role -> !assignedRoles.contains(role))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<Role> removedAssignments = assignedRoles
|
||||||
|
.stream()
|
||||||
|
.filter(role -> !assignments.contains(role.getUuid()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (final Role role : newAssignements) {
|
||||||
|
assignableTaskManager.assignTask(assignableTask, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Role role : removedAssignments) {
|
||||||
|
assignableTaskManager.retractTask(assignableTask, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format(
|
||||||
|
"redirect:/%s/configuration/workflows/%s/tasks/%s",
|
||||||
|
sectionIdentifierParam,
|
||||||
|
workflowIdentiferParam,
|
||||||
|
taskIdentifierParam
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for retrieving a workflow template.
|
* Helper method for retrieving a workflow template.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,13 @@ import org.librecms.ui.contentsections.documents.DocumentWorkflowController;
|
||||||
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
|
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.enterprise.inject.Any;
|
import javax.enterprise.inject.Any;
|
||||||
import javax.enterprise.inject.Instance;
|
import javax.enterprise.inject.Instance;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.mvc.Controller;
|
|
||||||
import javax.ws.rs.ApplicationPath;
|
import javax.ws.rs.ApplicationPath;
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,11 +70,11 @@ public class ContentSectionApplication extends Application {
|
||||||
classes.add(ContentSectionController.class);
|
classes.add(ContentSectionController.class);
|
||||||
classes.add(DocumentFolderController.class);
|
classes.add(DocumentFolderController.class);
|
||||||
classes.add(DocumentController.class);
|
classes.add(DocumentController.class);
|
||||||
|
classes.add(DocumentLifecyclesController.class);
|
||||||
|
classes.add(DocumentWorkflowController.class);
|
||||||
|
|
||||||
classes.addAll(getAuthoringSteps());
|
classes.addAll(getAuthoringSteps());
|
||||||
|
|
||||||
classes.add(DocumentLifecyclesController.class);
|
|
||||||
classes.add(DocumentWorkflowController.class);
|
|
||||||
classes.add(IsAuthenticatedFilter.class);
|
classes.add(IsAuthenticatedFilter.class);
|
||||||
|
|
||||||
return classes;
|
return classes;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,14 @@ public class SelectedWorkflowTaskTemplateModel {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> noneBlockingTasks;
|
private Map<String, String> noneBlockingTasks;
|
||||||
|
|
||||||
|
private List<String> assignedRoles;
|
||||||
|
|
||||||
|
private List<String> assignedRoleKeys;
|
||||||
|
|
||||||
|
private Map<String, String> availableRoles;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public long getTaskId() {
|
public long getTaskId() {
|
||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|
@ -196,4 +204,33 @@ public class SelectedWorkflowTaskTemplateModel {
|
||||||
this.noneBlockingTasks = new HashMap<>(noneBlockingTasks);
|
this.noneBlockingTasks = new HashMap<>(noneBlockingTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getAvailableRoles() {
|
||||||
|
return Collections.unmodifiableMap(availableRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvailableRoles(
|
||||||
|
final Map<String, String> availableRoles
|
||||||
|
) {
|
||||||
|
this.availableRoles = new HashMap<>(availableRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAssignedRoles() {
|
||||||
|
return Collections.unmodifiableList(assignedRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignedRoles(final List<String> assignedRoles) {
|
||||||
|
this.assignedRoles = new ArrayList<>(assignedRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAssignedRoleKeys() {
|
||||||
|
return Collections.unmodifiableList(assignedRoleKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignedRoleKeys(final List<String> assignedRoleKeys) {
|
||||||
|
this.assignedRoleKeys = new ArrayList<>(assignedRoleKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ import org.librecms.contentsection.ContentItemRepository;
|
||||||
import org.librecms.contentsection.ContentSection;
|
import org.librecms.contentsection.ContentSection;
|
||||||
import org.librecms.ui.contentsections.ContentSectionModel;
|
import org.librecms.ui.contentsections.ContentSectionModel;
|
||||||
import org.librecms.ui.contentsections.ContentSectionsUi;
|
import org.librecms.ui.contentsections.ContentSectionsUi;
|
||||||
|
import org.librecms.ui.contentsections.ItemPermissionChecker;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.mvc.Models;
|
import javax.mvc.Models;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
@ -52,6 +52,9 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
|
||||||
@Inject
|
@Inject
|
||||||
private ContentItemManager itemManager;
|
private ContentItemManager itemManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ItemPermissionChecker itemPermissionChecker;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ContentItemRepository itemRepo;
|
private ContentItemRepository itemRepo;
|
||||||
|
|
||||||
|
|
@ -177,6 +180,20 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCanEdit() {
|
||||||
|
if (!itemPermissionChecker.canEditItem(document)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (documentModel.getCurrentTask() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return documentModel.getCurrentTask().isAssignedToCurrentUser()
|
||||||
|
|| itemPermissionChecker.canAdministerItems(document);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return Optional
|
return Optional
|
||||||
|
|
@ -210,6 +227,55 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
|
||||||
documentPath = itemManager.getItemPath(document).substring(1); // Without leading slash
|
documentPath = itemManager.getItemPath(document).substring(1); // Without leading slash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStepPath() {
|
||||||
|
final ContentSection section = Optional
|
||||||
|
.ofNullable(contentSection)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new WebApplicationException(
|
||||||
|
String.format(
|
||||||
|
"Authoring Step %s was not initalized properly. "
|
||||||
|
+ "Did you forget to call %s#init()?",
|
||||||
|
getStepClass().getName(),
|
||||||
|
AbstractMvcAuthoringStep.class.getName()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
final String docPath = Optional
|
||||||
|
.ofNullable(documentPath)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new WebApplicationException(
|
||||||
|
String.format(
|
||||||
|
"Authoring Step %s was not initalized properly. "
|
||||||
|
+ "Did you forget to call %s#init()?",
|
||||||
|
getStepClass().getName(),
|
||||||
|
AbstractMvcAuthoringStep.class.getName()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
final Map<String, String> values = new HashMap<>();
|
||||||
|
values.put(
|
||||||
|
MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM,
|
||||||
|
section.getLabel()
|
||||||
|
);
|
||||||
|
values.put(
|
||||||
|
MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME,
|
||||||
|
docPath
|
||||||
|
);
|
||||||
|
|
||||||
|
return Optional
|
||||||
|
.ofNullable(getStepClass().getAnnotation(Path.class))
|
||||||
|
.map(Path::value)
|
||||||
|
.map(
|
||||||
|
path -> UriBuilder
|
||||||
|
.fromPath(path)
|
||||||
|
.buildFromMap(values)
|
||||||
|
.toString()
|
||||||
|
)
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildRedirectPathForStep() {
|
public String buildRedirectPathForStep() {
|
||||||
final ContentSection section = Optional
|
final ContentSection section = Optional
|
||||||
|
|
@ -254,6 +320,7 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
|
||||||
path -> UriBuilder
|
path -> UriBuilder
|
||||||
.fromPath(path)
|
.fromPath(path)
|
||||||
.buildFromMap(values)
|
.buildFromMap(values)
|
||||||
|
.toString()
|
||||||
)
|
)
|
||||||
.map(path -> String.format("redirect:%s", path))
|
.map(path -> String.format("redirect:%s", path))
|
||||||
.orElse("");
|
.orElse("");
|
||||||
|
|
@ -304,6 +371,7 @@ public abstract class AbstractMvcAuthoringStep implements MvcAuthoringStep {
|
||||||
.fromPath(path)
|
.fromPath(path)
|
||||||
.path(subPath)
|
.path(subPath)
|
||||||
.buildFromMap(values)
|
.buildFromMap(values)
|
||||||
|
.toString()
|
||||||
)
|
)
|
||||||
.map(path -> String.format("redirect:%s", path))
|
.map(path -> String.format("redirect:%s", path))
|
||||||
.orElse("");
|
.orElse("");
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ public class DocumentWorkflowController {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String lockTask(
|
public String lockTask(
|
||||||
@PathParam("sectionIdentifider") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
@PathParam("documentPath") final String documentPath,
|
@PathParam("documentPath") final String documentPath,
|
||||||
@PathParam("taskIdentifier") final String taskIdentifier,
|
@PathParam("taskIdentifier") final String taskIdentifier,
|
||||||
@FormParam("returnUrl") final String returnUrl
|
@FormParam("returnUrl") final String returnUrl
|
||||||
|
|
@ -189,7 +189,7 @@ public class DocumentWorkflowController {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String unlockTask(
|
public String unlockTask(
|
||||||
@PathParam("sectionIdentifider") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
@PathParam("documentPath") final String documentPath,
|
@PathParam("documentPath") final String documentPath,
|
||||||
@PathParam("taskIdentifier") final String taskIdentifier,
|
@PathParam("taskIdentifier") final String taskIdentifier,
|
||||||
@FormParam("returnUrl") final String returnUrl
|
@FormParam("returnUrl") final String returnUrl
|
||||||
|
|
@ -247,7 +247,7 @@ public class DocumentWorkflowController {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String finishTask(
|
public String finishTask(
|
||||||
@PathParam("sectionIdentifider") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
@PathParam("documentPath") final String documentPath,
|
@PathParam("documentPath") final String documentPath,
|
||||||
@PathParam("taskIdentifier") final String taskIdentifier,
|
@PathParam("taskIdentifier") final String taskIdentifier,
|
||||||
@FormParam("comment") @DefaultValue("") final String comment,
|
@FormParam("comment") @DefaultValue("") final String comment,
|
||||||
|
|
@ -310,7 +310,7 @@ public class DocumentWorkflowController {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String applyAlternateWorkflow(
|
public String applyAlternateWorkflow(
|
||||||
@PathParam("sectionIdentifider") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
@PathParam("documentPath") final String documentPath,
|
@PathParam("documentPath") final String documentPath,
|
||||||
@FormParam("newWorkflowUuid") final String newWorkflowUuid,
|
@FormParam("newWorkflowUuid") final String newWorkflowUuid,
|
||||||
@FormParam("returnUrl") final String returnUrl
|
@FormParam("returnUrl") final String returnUrl
|
||||||
|
|
@ -362,6 +362,27 @@ public class DocumentWorkflowController {
|
||||||
return String.format("redirect:%s", returnUrl);
|
return String.format("redirect:%s", returnUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the workflow assigned to an content item.
|
||||||
|
*
|
||||||
|
* @param sectionIdentifier The identifier of the current content section.
|
||||||
|
* @param documentPath The path of the current document.
|
||||||
|
* @param returnUrl The URL to return to.
|
||||||
|
*
|
||||||
|
* @return A redirect to the {@code returnUrl}.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/@start")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String startWorkflow(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("documentPath") final String documentPath,
|
||||||
|
@FormParam("returnUrl") final String returnUrl
|
||||||
|
) {
|
||||||
|
return restartWorkflow(sectionIdentifier, documentPath, returnUrl);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restarts the workflow assigned to an content item.
|
* Restarts the workflow assigned to an content item.
|
||||||
*
|
*
|
||||||
|
|
@ -376,7 +397,7 @@ public class DocumentWorkflowController {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String restartWorkflow(
|
public String restartWorkflow(
|
||||||
@PathParam("sectionIdentifider") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
@PathParam("documentPath") final String documentPath,
|
@PathParam("documentPath") final String documentPath,
|
||||||
@FormParam("returnUrl") final String returnUrl
|
@FormParam("returnUrl") final String returnUrl
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,20 @@ public interface MvcAuthoringStep {
|
||||||
String getDocumentPath() throws ContentSectionNotFoundException,
|
String getDocumentPath() throws ContentSectionNotFoundException,
|
||||||
DocumentNotFoundException;
|
DocumentNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current user edit the document. This method MUST only return
|
||||||
|
* {@code true} if
|
||||||
|
* <ul>
|
||||||
|
* <li>The current user has the permission to edit the item.</li>
|
||||||
|
* <li>The item has an active task.</li>
|
||||||
|
* <li>The task is assigned to the current user or the current user has
|
||||||
|
* admin priviliges for the content section of the item.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return {@code true} if the current user can edit the document/item, {@false} otherwise.
|
||||||
|
*/
|
||||||
|
boolean getCanEdit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the label for an authoring step.
|
* Gets the label for an authoring step.
|
||||||
*
|
*
|
||||||
|
|
@ -73,6 +87,8 @@ public interface MvcAuthoringStep {
|
||||||
void updateDocumentPath() throws ContentSectionNotFoundException,
|
void updateDocumentPath() throws ContentSectionNotFoundException,
|
||||||
DocumentNotFoundException;
|
DocumentNotFoundException;
|
||||||
|
|
||||||
|
String getStepPath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the redirect path of the authoring step.This path is most often
|
* Builds the redirect path of the authoring step.This path is most often
|
||||||
* used to implement the redirect after post pattern.
|
* used to implement the redirect after post pattern.
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ public class MvcArticleCreateStep
|
||||||
itemRepo.save(article);
|
itemRepo.save(article);
|
||||||
|
|
||||||
return String.format(
|
return String.format(
|
||||||
"redirect:/%s/documents/%s/%s/@articleproperties",
|
"redirect:/%s/documents/%s/%s/@article-basicproperties",
|
||||||
getContentSectionLabel(),
|
getContentSectionLabel(),
|
||||||
getFolderPath(),
|
getFolderPath(),
|
||||||
name
|
name
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,79 @@
|
||||||
values="#{SelectedWorkflowTaskTemplateModel.description}"
|
values="#{SelectedWorkflowTaskTemplateModel.description}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<h2>#{CmsAdminMessages['contentsection.configuration.workflows.task_details.assigned_to.title']}</h2>
|
||||||
|
<div class="mb-2">
|
||||||
|
<div class="text-right">
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#update-assignments-dialog"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="person-plus" />
|
||||||
|
<span>#{CmsAdminMessages['contentsection.configuration.workflows.task_details.assigned_to.edit']}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{SelectedWorkflowTaskTemplateModel.assignedRoles.isEmpty()}">
|
||||||
|
<p>
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.workflows.task_details.not_assigned']}
|
||||||
|
</p>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<ul>
|
||||||
|
<c:forEach items="#{SelectedWorkflowTaskTemplateModel.assignedRoles}"
|
||||||
|
var="role">
|
||||||
|
<li>#{role}</li>
|
||||||
|
</c:forEach>
|
||||||
|
</ul>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</div>
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="update-assignments-dialog-title"
|
||||||
|
class="modal fade"
|
||||||
|
id="update-assignments-dialog"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/configuration/workflows/UUID-#{SelectedWorkflowTemplateModel.uuid}/tasks/UUID-#{SelectedWorkflowTaskTemplateModel.uuid}/@assignments"
|
||||||
|
class="modal-content"
|
||||||
|
method="post">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="update-assignments-modal-title">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.workflows.task_details.assigned_to.dialog.title']}
|
||||||
|
<button aria-label="#{CmsAdminMessages['contentsection.configuration.workflow.task_details.assignments.dialog.close']}"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="x" />
|
||||||
|
</button>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<bootstrap:formGroupChecks
|
||||||
|
help="#{CmsAdminMessages['contentsection.configuration.workflow.task_details.assignments.dialog.roles.help']}"
|
||||||
|
inputId="assigments"
|
||||||
|
label="#{CmsAdminMessages['contentsection.configuration.workflow.task_details.assignments.dialog.roles.label']}"
|
||||||
|
name="assignments"
|
||||||
|
options="#{SelectedWorkflowTaskTemplateModel.availableRoles}"
|
||||||
|
selectedOptions="#{SelectedWorkflowTaskTemplateModel.assignedRoleKeys}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.workflow.task_details.assignments.dialog.close']}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
type="submit" >
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.workflow.task_details.assignemnts.dialog.submit']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>#{CmsAdminMessages['contentsection.configuration.workflows.task_details.blocking_tasks.title']}</h2>
|
<h2>#{CmsAdminMessages['contentsection.configuration.workflows.task_details.blocking_tasks.title']}</h2>
|
||||||
|
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link #{activeDocumentTab == 'editTab' ? 'active' : ''}"
|
<a class="nav-link #{activeDocumentTab == 'editTab' ? 'active' : ''}"
|
||||||
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}">
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}">
|
||||||
#{CmsAdminMessages['contentsection.document.tabs.edit.title']}
|
#{CmsAdminMessages['contentsection.document.tabs.edit.title']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link #{activeDocumentTab == 'history' ? 'active' : ''}"
|
<a class="nav-link #{activeDocumentTab == 'history' ? 'active' : ''}"
|
||||||
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@history">
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@history">
|
||||||
#{CmsAdminMessages['contentsection.document.tabs.history.title']}
|
#{CmsAdminMessages['contentsection.document.tabs.history.title']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -35,33 +35,44 @@
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task']}
|
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="#{CmsSelectedDocumentModel.currentTask != null}">
|
<c:when test="#{CmsSelectedDocumentModel.currentTask != null}">
|
||||||
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task']}
|
||||||
#{CmsSelectedDocumentModel.currentTask.label}
|
#{CmsSelectedDocumentModel.currentTask.label}
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.none']}
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.none']}
|
||||||
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/@start"
|
||||||
|
method="post">
|
||||||
|
<input name="returnUrl"
|
||||||
|
type="hidden"
|
||||||
|
value="#{CmsArticlePropertiesStep.stepPath}" />
|
||||||
|
|
||||||
|
<button class="btn btn-primary"
|
||||||
|
type="submit">
|
||||||
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.start']}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<c:if test="#{CmsSelectedDocumentModel.currentTask != null}">
|
<c:if test="#{CmsSelectedDocumentModel.currentTask != null}">
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="#{CmsSelectedDocumentModel.currentTask.assignedToCurrentUser and CmsSelectedDocumentModel.currentTask.locked}">
|
<c:when test="#{CmsSelectedDocumentModel.currentTask.assignedToCurrentUser and CmsSelectedDocumentModel.currentTask.locked}">
|
||||||
<form action="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@unlock"
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@unlock"
|
||||||
method="post">
|
method="post">
|
||||||
<input name="returnUrl"
|
<input name="returnUrl"
|
||||||
type="hidden"
|
type="hidden"
|
||||||
value="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
||||||
<button class="btn btn-secondary btn-sm"
|
<button class="btn btn-secondary btn-sm"
|
||||||
type="submit">
|
type="submit">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.release']}
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.release']}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<form action="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@finish"
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@finish"
|
||||||
method="post">
|
method="post">
|
||||||
<input name="returnUrl"
|
<input name="returnUrl"
|
||||||
type="hidden"
|
type="hidden"
|
||||||
value="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
||||||
<button class="btn btn-secondary btn-sm"
|
<button class="btn btn-secondary btn-sm"
|
||||||
type="submit">
|
type="submit">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.finish']}
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.finish']}
|
||||||
|
|
@ -69,11 +80,11 @@
|
||||||
</form>
|
</form>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{CmsSelectedDocumentModel.currentTask.locked and CmsSelectedDocumentModel.canChangeWorkflow}">
|
<c:when test="#{CmsSelectedDocumentModel.currentTask.locked and CmsSelectedDocumentModel.canChangeWorkflow}">
|
||||||
<form action="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@lock"
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@lock"
|
||||||
method="post">
|
method="post">
|
||||||
<input name="returnUrl"
|
<input name="returnUrl"
|
||||||
type="hidden"
|
type="hidden"
|
||||||
value="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
||||||
<button class="btn btn-secondary btn-sm"
|
<button class="btn btn-secondary btn-sm"
|
||||||
type="submit">
|
type="submit">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.takeover']}
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.takeover']}
|
||||||
|
|
@ -81,10 +92,10 @@
|
||||||
</form>
|
</form>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:when test="#{CmsSelectedDocumentModel.currentTask.assignedToCurrentUser or CmsSelectedDocumentModel.canChangeWorkflow}">
|
<c:when test="#{CmsSelectedDocumentModel.currentTask.assignedToCurrentUser or CmsSelectedDocumentModel.canChangeWorkflow}">
|
||||||
<form action="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@lock">
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@workflow/tasks/UUID-#{CmsSelectedDocumentModel.currentTask.taskUuid}/@lock">
|
||||||
<input name="returnUrl"
|
<input name="returnUrl"
|
||||||
type="hidden"
|
type="hidden"
|
||||||
value="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
value="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@authoringsteps/#{authoringStep}" />
|
||||||
<button class="btn btn-secondary btn-sm"
|
<button class="btn btn-secondary btn-sm"
|
||||||
type="button">
|
type="button">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.lock']}
|
#{CmsAdminMessages['contentsection.document.authoring.workflow.active_task.lock']}
|
||||||
|
|
@ -113,14 +124,14 @@
|
||||||
<li aria-current="#{'categorize' == authoringStep ? 'true' : ''}"
|
<li aria-current="#{'categorize' == authoringStep ? 'true' : ''}"
|
||||||
class="list-group-item #{'categorize' == authoringStep ? 'active' : ''}">
|
class="list-group-item #{'categorize' == authoringStep ? 'active' : ''}">
|
||||||
<a class="list-group-item-action"
|
<a class="list-group-item-action"
|
||||||
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@categorization">
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@categorization">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.steps.categorize.label']}
|
#{CmsAdminMessages['contentsection.document.authoring.steps.categorize.label']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li aria-current="#{'relatedInfo' == authoringStep ? 'true' : ''}"
|
<li aria-current="#{'relatedInfo' == authoringStep ? 'true' : ''}"
|
||||||
class="list-group-item #{'relatedInfo' == authoringStep ? 'active' : ''}">
|
class="list-group-item #{'relatedInfo' == authoringStep ? 'active' : ''}">
|
||||||
<a class="list-group-item-action"
|
<a class="list-group-item-action"
|
||||||
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@relatedinfo">
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@relatedinfo">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.steps.relatedInfo.label']}
|
#{CmsAdminMessages['contentsection.document.authoring.steps.relatedInfo.label']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -129,7 +140,7 @@
|
||||||
<li aria-current="#{'publish' == authoringStep ? 'true' : ''}"
|
<li aria-current="#{'publish' == authoringStep ? 'true' : ''}"
|
||||||
class="list-group-item #{'publish' == authoringStep ? 'active' : ''}">
|
class="list-group-item #{'publish' == authoringStep ? 'active' : ''}">
|
||||||
<a class="list-group-item-action"
|
<a class="list-group-item-action"
|
||||||
href="#{mvc.basePath}/documents/#{CmsSelectedDocumentModel.itemPath}/@publish">
|
href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@publish">
|
||||||
#{CmsAdminMessages['contentsection.document.authoring.steps.publish.label']}
|
#{CmsAdminMessages['contentsection.document.authoring.steps.publish.label']}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<h3>#{CmsArticleMessageBundle.getMessage('basicproperties.name.header')}</h3>
|
<h3>#{CmsArticleMessageBundle.getMessage('basicproperties.name.header')}</h3>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<pre class="mr-2">#{CmsArticlePropertiesStep.name}</pre>
|
<pre class="mr-2">#{CmsArticlePropertiesStep.name}</pre>
|
||||||
|
<c:if test="#{CmsArticlePropertiesStep.canEdit}">
|
||||||
<button class="btn btn-primary btn-sm"
|
<button class="btn btn-primary btn-sm"
|
||||||
data-toggle="modal"
|
data-toggle="modal"
|
||||||
data-target="#name-edit-dialog"
|
data-target="#name-edit-dialog"
|
||||||
|
|
@ -21,7 +22,10 @@
|
||||||
#{CmsArticleMessageBundle['basicproperties.name.edit']}
|
#{CmsArticleMessageBundle['basicproperties.name.edit']}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
</c:if>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<c:if test="#{CmsArticlePropertiesStep.canEdit}">
|
||||||
<div aria-hidden="true"
|
<div aria-hidden="true"
|
||||||
aria-labelledby="name-edit-dialog-title"
|
aria-labelledby="name-edit-dialog-title"
|
||||||
class="modal fade"
|
class="modal fade"
|
||||||
|
|
@ -67,6 +71,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</c:if>
|
||||||
|
|
||||||
|
|
||||||
<libreccm:localizedStringEditor
|
<libreccm:localizedStringEditor
|
||||||
|
|
@ -90,6 +95,7 @@
|
||||||
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedTitleLocales.isEmpty()}"
|
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedTitleLocales.isEmpty()}"
|
||||||
headingLevel="3"
|
headingLevel="3"
|
||||||
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
|
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
|
||||||
|
readOnly="#{!CmsArticlePropertiesStep.canEdit}"
|
||||||
removeButtonLabel="#{CmsArticleMessageBundle['basicproperties.title.remove']}"
|
removeButtonLabel="#{CmsArticleMessageBundle['basicproperties.title.remove']}"
|
||||||
removeDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.cancel']}"
|
removeDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.cancel']}"
|
||||||
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.submit']}"
|
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.title.remove.submit']}"
|
||||||
|
|
@ -123,6 +129,7 @@
|
||||||
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedDescriptionLocales.isEmpty()}"
|
hasUnusedLocales="#{!CmsArticlePropertiesStep.unusedDescriptionLocales.isEmpty()}"
|
||||||
headingLevel="3"
|
headingLevel="3"
|
||||||
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
|
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
|
||||||
|
readOnly="#{!CmsArticlePropertiesStep.canEdit}"
|
||||||
removeButtonLabel="#{CmsArticleMessageBundle['basicproperties.description.remove']}"
|
removeButtonLabel="#{CmsArticleMessageBundle['basicproperties.description.remove']}"
|
||||||
removeDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.cancel']}"
|
removeDialogCancelLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.cancel']}"
|
||||||
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.submit']}"
|
removeDialogSubmitLabel="#{CmsArticleMessageBundle['basicproperties.description.remove.submit']}"
|
||||||
|
|
|
||||||
|
|
@ -756,3 +756,13 @@ contentsection.documentfolder.new_document_dialog.close=Cancel
|
||||||
contentsection.documentfolder.new_document_dialog.documenttype.help=The type of the new document
|
contentsection.documentfolder.new_document_dialog.documenttype.help=The type of the new document
|
||||||
contentsection.documentfolder.new_document_dialog.documenttype.label=Document Type
|
contentsection.documentfolder.new_document_dialog.documenttype.label=Document Type
|
||||||
contentsection.documentfolder.new_document_dialog.submit=Create document
|
contentsection.documentfolder.new_document_dialog.submit=Create document
|
||||||
|
contentsection.document.authoring.workflow.start=Start workflow
|
||||||
|
ontentsection.configuration.workflows.task_details.assigned_to.title=Assigned to
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.edit=Edit assignments
|
||||||
|
contentsection.configuration.workflows.task_details.not_assigned=This task is not assigned to any roles.
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.close=Cancel
|
||||||
|
contentsection.configuration.workflow.task_details.assignemnts.dialog.submit=Update assigned roles
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.title=Assigned roles
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.roles.label=Roles
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.roles.help=Select the roles to which task is assigned.
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.dialog.title=Edit assigned roles
|
||||||
|
|
|
||||||
|
|
@ -757,3 +757,13 @@ contentsection.documentfolder.new_document_dialog.close=Abbrechen
|
||||||
contentsection.documentfolder.new_document_dialog.documenttype.help=Der Typ des neuen Dokumentes
|
contentsection.documentfolder.new_document_dialog.documenttype.help=Der Typ des neuen Dokumentes
|
||||||
contentsection.documentfolder.new_document_dialog.documenttype.label=Dokument Typ
|
contentsection.documentfolder.new_document_dialog.documenttype.label=Dokument Typ
|
||||||
contentsection.documentfolder.new_document_dialog.submit=Dokument anlegen
|
contentsection.documentfolder.new_document_dialog.submit=Dokument anlegen
|
||||||
|
contentsection.document.authoring.workflow.start=Arbeitsablauf starten
|
||||||
|
ontentsection.configuration.workflows.task_details.assigned_to.title=Zugewiesen an
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.edit=Zuweisungen bearbeiten
|
||||||
|
contentsection.configuration.workflows.task_details.not_assigned=Diese Aufgabe ist keiner Rolle zugewiesen
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.close=Abbrechen
|
||||||
|
contentsection.configuration.workflow.task_details.assignemnts.dialog.submit=Zugewiesene Rollen aktualisieren
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.title=Zugewiesen Rollen
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.roles.label=Rollen
|
||||||
|
contentsection.configuration.workflow.task_details.assignments.dialog.roles.help=W\u00e4hlen Sie die Rollen, denen die Aufgabe zugewiesen ist.
|
||||||
|
contentsection.configuration.workflows.task_details.assigned_to.dialog.title=Zugewiesene Rollen bearbeiten
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,10 @@ import org.libreccm.security.User;
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,6 +63,13 @@ public class AssignableTaskRepository
|
||||||
return task.getTaskId() == 0;
|
return task.getTaskId() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initNewEntity(final AssignableTask entity) {
|
||||||
|
if (isNew(entity)) {
|
||||||
|
entity.setUuid(UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a {@link AssignableTask} by its uuid.
|
* Finds a {@link AssignableTask} by its uuid.
|
||||||
*
|
*
|
||||||
|
|
@ -110,4 +119,6 @@ public class AssignableTaskRepository
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,10 @@ public class WorkflowManager implements Serializable {
|
||||||
tasks);
|
tasks);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for(final Map.Entry<Long, Task> task : tasks.entrySet()) {
|
||||||
|
task.getValue().setTaskState(TaskState.DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
workflow.setObject(object);
|
workflow.setObject(object);
|
||||||
workflow.setState(WorkflowState.INIT);
|
workflow.setState(WorkflowState.INIT);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,11 @@
|
||||||
required="true"
|
required="true"
|
||||||
shortDescription="Identifier of the object to which the localized string belongs"
|
shortDescription="Identifier of the object to which the localized string belongs"
|
||||||
type="String" />
|
type="String" />
|
||||||
|
<cc:attribute name="readOnly"
|
||||||
|
default="false"
|
||||||
|
required="false"
|
||||||
|
shortDescription="Don't show edit buttons."
|
||||||
|
type="boolean" />
|
||||||
<cc:attribute name="removeButtonLabel"
|
<cc:attribute name="removeButtonLabel"
|
||||||
default="Remove"
|
default="Remove"
|
||||||
required="false"
|
required="false"
|
||||||
|
|
@ -190,7 +195,7 @@
|
||||||
<div>#{cc.attrs.title}</div>
|
<div>#{cc.attrs.title}</div>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<c:if test="#{cc.attrs.hasUnusedLocales}">
|
<c:if test="#{cc.attrs.hasUnusedLocales and !cc.attrs.readOnly}">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<button class="btn btn-secondary"
|
<button class="btn btn-secondary"
|
||||||
|
|
@ -331,6 +336,7 @@
|
||||||
<td>#{entry.key}</td>
|
<td>#{entry.key}</td>
|
||||||
<td>#{entry.value}</td>
|
<td>#{entry.value}</td>
|
||||||
<td>
|
<td>
|
||||||
|
<c:if test="#{!cc.attrs.readOnly}">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<button class="btn btn-info"
|
<button class="btn btn-info"
|
||||||
data-target="##{cc.attrs.editorId}-#{entry.key}-edit-dialog"
|
data-target="##{cc.attrs.editorId}-#{entry.key}-edit-dialog"
|
||||||
|
|
@ -428,8 +434,10 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</c:if>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<c:if test="#{!cc.attrs.readOnly}">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<button class="btn btn-danger"
|
<button class="btn btn-danger"
|
||||||
data-target="##{cc.attrs.editorId}-#{entry.key}-remove-dialog"
|
data-target="##{cc.attrs.editorId}-#{entry.key}-remove-dialog"
|
||||||
|
|
@ -499,6 +507,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</c:if>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</c:forEach>
|
</c:forEach>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue