package com.constellio.app.modules.tasks.ui.pages.workflow;
import static com.constellio.app.ui.i18n.i18n.$;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ObjectUtils;
import org.vaadin.dialogs.ConfirmDialog;
import org.vaadin.dialogs.DefaultConfirmDialogFactory;
import org.vaadin.peter.contextmenu.ContextMenu;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuItem;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuItemClickEvent;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuItemClickListener;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableFooterEvent;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableHeaderEvent;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableRowEvent;
import com.constellio.app.modules.tasks.model.wrappers.types.TaskType;
import com.constellio.app.modules.tasks.ui.entities.WorkflowTaskVO;
import com.constellio.app.modules.tasks.ui.entities.WorkflowVO;
import com.constellio.app.ui.framework.buttons.AddButton;
import com.constellio.app.ui.framework.buttons.BaseButton;
import com.constellio.app.ui.framework.buttons.DeleteButton;
import com.constellio.app.ui.framework.buttons.EditButton;
import com.constellio.app.ui.framework.components.BaseForm;
import com.constellio.app.ui.framework.components.BaseWindow;
import com.constellio.app.ui.framework.components.RecordDisplay;
import com.constellio.app.ui.framework.components.contextmenu.BaseContextMenuTableListener;
import com.constellio.app.ui.framework.components.fields.BaseComboBox;
import com.constellio.app.ui.framework.components.fields.BaseTextField;
import com.constellio.app.ui.framework.components.fields.list.ListAddRemoveTextField;
import com.constellio.app.ui.framework.components.fields.record.RecordComboBox;
import com.constellio.app.ui.framework.data.RecordVODataProvider;
import com.constellio.app.ui.pages.base.BaseViewImpl;
import com.constellio.app.ui.pages.base.NoDragAndDrop;
import com.constellio.data.utils.dev.Toggle;
import com.constellio.model.frameworks.validation.ValidationException;
import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Table.TableDragMode;
import com.vaadin.ui.Table.TableTransferable;
import com.vaadin.ui.TextField;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
public class DisplayWorkflowViewImpl extends BaseViewImpl implements DisplayWorkflowView, NoDragAndDrop {
private WorkflowVO workflowVO;
private List<WorkflowTaskVO> workflowTaskVOs = new ArrayList<>();
private RecordVODataProvider taskTypeDataProvider;
private WorkflowTaskVO selectedWorkflowTaskVO;
private VerticalLayout mainLayout;
private RecordDisplay workflowDisplay;
private Button addTaskButton;
private TreeTable workflowTaskVOTable;
private Button editButton;
private Button deleteButton;
private Window addTaskWindow;
private DisplayWorkflowPresenter presenter;
private static ConfirmDialog.Factory factory = new DefaultConfirmDialogFactory();
static {
ConfirmDialog.setFactory(new ConfirmDialog.Factory() {
@Override
public ConfirmDialog create(String windowCaption, String message, String okTitle, String cancelTitle,
String notOKCaption) {
ConfirmDialog confirmDialog = factory.create(windowCaption, message, okTitle, cancelTitle, notOKCaption);
confirmDialog.addAttachListener(new AttachListener() {
@Override
public void attach(AttachEvent event) {
BaseWindow.executeZIndexAdjustJavascript(BaseWindow.OVER_ADVANCED_SEARCH_FORM_Z_INDEX + 1);
}
});
return confirmDialog;
}
});
}
public DisplayWorkflowViewImpl() {
presenter = new DisplayWorkflowPresenter(this);
}
@Override
protected void initBeforeCreateComponents(ViewChangeEvent event) {
presenter.forParams(event.getParameters());
}
@Override
public void setTaskTypeDataProvider(RecordVODataProvider taskTypeDataProvider) {
this.taskTypeDataProvider = taskTypeDataProvider;
}
@Override
public void setWorkflowVO(WorkflowVO workflowVO) {
this.workflowVO = workflowVO;
}
@Override
public void setWorkflowTaskVOs(List<WorkflowTaskVO> workflowTaskVOs) {
this.workflowTaskVOs = workflowTaskVOs;
}
@Override
public void remove(WorkflowTaskVO workflowTaskVO) {
List<WorkflowTaskVO> children = presenter.getChildren(workflowTaskVO);
for (WorkflowTaskVO child : children) {
// Recursive call
remove(child);
}
workflowTaskVOTable.removeItem(workflowTaskVO);
}
@Override
protected String getTitle() {
return $("DisplayWorkflowView.viewTitle");
}
@Override
protected ClickListener getBackButtonClickListener() {
return new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
presenter.backButtonClicked();
}
};
}
@Override
protected Component buildMainComponent(ViewChangeEvent event) {
mainLayout = new VerticalLayout();
mainLayout.setSizeFull();
mainLayout.setSpacing(true);
buildWorkflowDisplay();
buildAddTaskButton();
workflowTaskVOTable = buildTasksTable();
buildContextMenu(workflowTaskVOTable);
buildAddTaskWindow();
mainLayout.addComponents(workflowDisplay, addTaskButton, workflowTaskVOTable);
mainLayout.setExpandRatio(workflowTaskVOTable, 1);
mainLayout.setComponentAlignment(addTaskButton, Alignment.TOP_RIGHT);
return mainLayout;
}
private void buildWorkflowDisplay() {
workflowDisplay = new RecordDisplay(workflowVO);
}
private void buildAddTaskButton() {
addTaskButton = new AddButton() {
@Override
protected void buttonClick(ClickEvent event) {
presenter.addTaskButtonClicked();
}
};
}
private TreeTable buildTasksTable() {
TreeTable newWorkflowTaskVOTable = new TreeTable($("DisplayWorkflowView.tableTitle"));
newWorkflowTaskVOTable.setDragMode(TableDragMode.ROW);
newWorkflowTaskVOTable.setWidth("100%");
final HierarchicalContainer container = new HierarchicalContainer();
container.addContainerProperty("title", String.class, "");
newWorkflowTaskVOTable.setDropHandler(new DropHandler() {
@Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
@Override
public void drop(DragAndDropEvent event) {
TableTransferable transferable = (TableTransferable) event.getTransferable();
AbstractSelectTargetDetails targetDetails = (AbstractSelectTargetDetails) event.getTargetDetails();
WorkflowTaskVO droppedItemId = (WorkflowTaskVO) transferable.getItemId();
WorkflowTaskVO targetItemId = (WorkflowTaskVO) targetDetails.getItemIdOver();
Object droppedItemParent = container.getParent(droppedItemId);
Object targetItemParent = container.getParent(targetItemId);
boolean accept;
if (droppedItemParent == null && targetItemParent == null) {
accept = true;
} else if (ObjectUtils.equals(droppedItemParent, targetItemParent)) {
accept = true;
} else {
accept = false;
}
if (accept && presenter.moveAfter(droppedItemId, targetItemId)) {
container.moveAfterSibling(droppedItemId, targetItemId);
}
}
});
for (WorkflowTaskVO workflowTaskVO : workflowTaskVOs) {
addToTable(workflowTaskVO, container, null);
}
newWorkflowTaskVOTable.setColumnHeader("title", $("DisplayWorkflowView.table.title"));
newWorkflowTaskVOTable.setColumnExpandRatio("title", 1);
newWorkflowTaskVOTable.setContainerDataSource(container);
return newWorkflowTaskVOTable;
}
@SuppressWarnings("unchecked")
private void addToTable(WorkflowTaskVO workflowTaskVO, HierarchicalContainer container, WorkflowTaskVO parentWorkflowTaskVO) {
if (container.getItem(workflowTaskVO) != null) {
WorkflowTaskVO newWorkflowTaskVO = new WorkflowTaskVO();
String title = $("DisplayWorkflowView.redirect", workflowTaskVO.getTitle());
newWorkflowTaskVO.setTitle(title);
Item item = container.addItem(newWorkflowTaskVO);
item.getItemProperty("title").setValue(title);
if (parentWorkflowTaskVO != null) {
container.setParent(newWorkflowTaskVO, parentWorkflowTaskVO);
}
} else {
Item item = container.addItem(workflowTaskVO);
String title = workflowTaskVO.getTitle();
item.getItemProperty("title").setValue(title);
List<WorkflowTaskVO> children = presenter.getChildren(workflowTaskVO);
for (WorkflowTaskVO child : children) {
boolean setParent = true;
if (container.getItem(child) != null) {
setParent = false;
}
// Recursive call
addToTable(child, container, workflowTaskVO);
if (setParent) {
container.setParent(child, workflowTaskVO);
} else {
break;
}
}
}
}
private void buildContextMenu(TreeTable workflowTaskVOTable) {
ContextMenu contextMenu = new ContextMenu();
ContextMenuItem createTaskAfterItem = contextMenu.addItem($("DisplayWorkflowView.menu.createTaskAfter"));
createTaskAfterItem.addItemClickListener(new ContextMenuItemClickListener() {
@Override
public void contextMenuItemClicked(ContextMenuItemClickEvent event) {
presenter.createTaskSelected(selectedWorkflowTaskVO);
}
});
ContextMenuItem editTaskItem = contextMenu.addItem($("DisplayWorkflowView.menu.editTask"));
editTaskItem.addItemClickListener(new ContextMenuItemClickListener() {
@Override
public void contextMenuItemClicked(ContextMenuItemClickEvent event) {
presenter.editTaskSelected(selectedWorkflowTaskVO);
}
});
ContextMenuItem deleteTaskItem = contextMenu.addItem($("DisplayWorkflowView.menu.deleteTask"));
deleteTaskItem.addItemClickListener(new ContextMenuItemClickListener() {
@Override
public void contextMenuItemClicked(ContextMenuItemClickEvent event) {
ConfirmDialog.show(
UI.getCurrent(),
$("ConfirmDialog.title"),
$("ConfirmDialog.confirmDelete"),
$("ConfirmDialog.yes"),
$("ConfirmDialog.no"),
new ConfirmDialog.Listener() {
public void onClose(ConfirmDialog dialog) {
if (dialog.isConfirmed()) {
presenter.deleteTaskSelected(selectedWorkflowTaskVO);
}
}
});
}
});
if (Toggle.ADD_EXISTING_TASK.isEnabled()) {
ContextMenuItem createExistingTaskAfterItem = contextMenu
.addItem($("DisplayWorkflowView.menu.createExistingTaskAfter"));
createExistingTaskAfterItem.addItemClickListener(new ContextMenuItemClickListener() {
@Override
public void contextMenuItemClicked(ContextMenuItemClickEvent event) {
if (selectedWorkflowTaskVO.getTaskVO() != null) {
presenter.createExistingTaskSelected(selectedWorkflowTaskVO);
}
}
});
}
contextMenu.setAsTableContextMenu(workflowTaskVOTable);
BaseContextMenuTableListener contextMenuTableListener = new BaseContextMenuTableListener() {
@Override
public void onContextMenuOpenFromFooter(ContextMenuOpenedOnTableFooterEvent event) {
}
@Override
public void onContextMenuOpenFromHeader(ContextMenuOpenedOnTableHeaderEvent event) {
}
@Override
public void onContextMenuOpenFromRow(ContextMenuOpenedOnTableRowEvent event) {
selectedWorkflowTaskVO = (WorkflowTaskVO) event.getItemId();
}
};
contextMenu.addContextMenuTableListener(contextMenuTableListener);
}
private void buildAddTaskWindow() {
addTaskWindow = new BaseWindow($("DisplayWorkflowView.addTaskWindow.windowTitle"));
addTaskWindow.center();
addTaskWindow.setModal(true);
addTaskWindow.setWidth("80%");
}
@Override
protected List<Button> buildActionMenuButtons(ViewChangeEvent event) {
editButton = new EditButton(false) {
@Override
protected void buttonClick(ClickEvent event) {
presenter.editButtonClicked();
}
};
deleteButton = new DeleteButton(false) {
@Override
protected void confirmButtonClick(ConfirmDialog dialog) {
presenter.deleteButtonClicked();
}
};
return Arrays.asList(editButton, deleteButton);
}
@Override
public void openAddTaskWindow(WorkflowTaskVO workflowTaskVO, List<WorkflowTaskVO> availableTaskVOs) {
addTaskWindow.setContent(new AddTaskWindowContent(workflowTaskVO, availableTaskVOs));
UI.getCurrent().addWindow(addTaskWindow);
}
@Override
public void openExistingTasksWindow(WorkflowTaskVO workflowTaskVO, List<WorkflowTaskVO> availableTaskVOs) {
addTaskWindow.setContent(buildExistingTasksContent(workflowTaskVO, availableTaskVOs));
UI.getCurrent().addWindow(addTaskWindow);
}
@Override
public void closeAddTaskWindow() {
addTaskWindow.close();
}
public class AddTaskWindowContent extends Panel {
private WorkflowTaskVO workflowTaskVO;
private String taskType;
private String taskTitle;
private List<String> decisions = new ArrayList<>();
private BaseForm<AddTaskWindowContent> baseForm;
@PropertyId("taskType")
private RecordComboBox typeField;
@PropertyId("taskTitle")
private TextField taskTitleField;
@PropertyId("workflowTaskVO")
private ComboBox workflowTaskVOField;
@PropertyId("decisions")
private ListAddRemoveTextField decisionsField;
public AddTaskWindowContent(WorkflowTaskVO workflowTaskVO, List<WorkflowTaskVO> availableTaskVOs) {
this.workflowTaskVO = workflowTaskVO;
typeField = new RecordComboBox(TaskType.DEFAULT_SCHEMA);
typeField.setCaption($("DisplayWorkflowView.addTaskWindow.taskType"));
typeField.setDataProvider(taskTypeDataProvider);
taskTitleField = new BaseTextField($("DisplayWorkflowView.addTaskWindow.taskTitle"));
workflowTaskVOField = new BaseComboBox();
workflowTaskVOField.setCaption($("DisplayWorkflowView.addTaskWindow.workflowTaskVO"));
for (WorkflowTaskVO availableTaskVO : availableTaskVOs) {
workflowTaskVOField.addItem(availableTaskVO);
workflowTaskVOField.setItemCaption(availableTaskVO, availableTaskVO.getTitle());
}
workflowTaskVOField.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
boolean decisionsFieldVisible;
WorkflowTaskVO newValue = (WorkflowTaskVO) event.getProperty().getValue();
if (newValue != null) {
decisionsFieldVisible = presenter.isDecisionField(newValue);
} else {
decisionsFieldVisible = false;
}
decisionsField.setVisible(decisionsFieldVisible);
}
});
decisionsField = new ListAddRemoveTextField();
decisionsField.setCaption($("DisplayWorkflowView.addTaskWindow.decisions"));
if (workflowTaskVO != null && !presenter.isDecisionField(workflowTaskVO)) {
decisionsField.setVisible(false);
}
baseForm = new BaseForm<AddTaskWindowContent>(this, this, typeField, taskTitleField, workflowTaskVOField,
decisionsField) {
@Override
protected void saveButtonClick(AddTaskWindowContent viewObject)
throws ValidationException {
presenter.saveNewTaskButtonClicked(taskType, taskTitle, decisions, AddTaskWindowContent.this.workflowTaskVO);
}
@Override
protected void cancelButtonClick(AddTaskWindowContent viewObject) {
presenter.cancelNewTaskButtonClicked();
}
};
setContent(baseForm);
}
public WorkflowTaskVO getWorkflowTaskVO() {
return workflowTaskVO;
}
public void setWorkflowTaskVO(WorkflowTaskVO workflowTaskVO) {
this.workflowTaskVO = workflowTaskVO;
}
public String getTaskType() {
return taskType;
}
public void setTaskType(String taskType) {
this.taskType = taskType;
}
public String getTaskTitle() {
return taskTitle;
}
public void setTaskTitle(String taskTitle) {
this.taskTitle = taskTitle;
}
public List<String> getDecisions() {
return decisions;
}
public void setDecisions(List<String> decisions) {
this.decisions = decisions;
}
}
protected Component buildExistingTasksContent(final WorkflowTaskVO workflowTaskVO, List<WorkflowTaskVO> availableTaskVOs) {
final ComboBox workflowTaskVOField = new BaseComboBox();
workflowTaskVOField.setCaption($("DisplayWorkflowView.addTaskWindow.availableTasks"));
for (WorkflowTaskVO availableTaskVO : availableTaskVOs) {
workflowTaskVOField.addItem(availableTaskVO);
workflowTaskVOField.setItemCaption(availableTaskVO, availableTaskVO.getTitle());
}
BaseButton saveButton = new BaseButton($("save")) {
@Override
protected void buttonClick(ClickEvent event) {
WorkflowTaskVO selectedWorkflowTaskVO = (WorkflowTaskVO) workflowTaskVOField.getValue();
if (selectedWorkflowTaskVO != null) {
presenter.addExistingTaskAfter(selectedWorkflowTaskVO, workflowTaskVO);
}
}
};
saveButton.addStyleName(BaseForm.SAVE_BUTTON);
saveButton.addStyleName(ValoTheme.BUTTON_PRIMARY);
BaseButton cancelButton = new BaseButton($("cancel")) {
@Override
protected void buttonClick(ClickEvent event) {
addTaskWindow.close();
}
};
saveButton.addStyleName(BaseForm.CANCEL_BUTTON);
cancelButton.addStyleName(ValoTheme.BUTTON_PRIMARY);
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.setSpacing(true);
horizontalLayout.addComponents(saveButton, cancelButton);
VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout
.addComponents(workflowTaskVOField, horizontalLayout);
verticalLayout.setSpacing(true);
return verticalLayout;
}
}