/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.activiti.explorer.ui.task; import java.util.List; import org.activiti.engine.HistoryService; import org.activiti.engine.ProcessEngines; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.task.Attachment; import org.activiti.explorer.ExplorerApp; import org.activiti.explorer.I18nManager; import org.activiti.explorer.Messages; import org.activiti.explorer.NotificationManager; import org.activiti.explorer.ViewManager; import org.activiti.explorer.ui.Images; import org.activiti.explorer.ui.content.AttachmentDetailPopupWindow; import org.activiti.explorer.ui.content.AttachmentRenderer; import org.activiti.explorer.ui.content.AttachmentRendererManager; import org.activiti.explorer.ui.content.RelatedContentComponent; import org.activiti.explorer.ui.custom.DetailPanel; import org.activiti.explorer.ui.custom.PrettyTimeLabel; import org.activiti.explorer.ui.mainlayout.ExplorerLayout; import com.vaadin.data.Item; 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.Component; import com.vaadin.ui.CssLayout; import com.vaadin.ui.Embedded; import com.vaadin.ui.GridLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.Reindeer; /** * A simplified version of the {@Link TaskDetailPanel}, displaying * read-only historic task details. * * @author Joram Barrez */ public class HistoricTaskDetailPanel extends DetailPanel { private static final long serialVersionUID = 1L; protected HistoricTaskInstance historicTask; // Services protected HistoryService historyService; protected TaskService taskService; protected ViewManager viewManager; protected I18nManager i18nManager; protected NotificationManager notificationManager; protected AttachmentRendererManager attachmentRendererManager; // UI protected TaskPage taskPage; protected VerticalLayout centralLayout; protected VerticalLayout peopleLayout; protected GridLayout peopleGrid; protected VerticalLayout subTasksLayout; protected GridLayout subTaskGrid; protected VerticalLayout relatedContentLayout; public HistoricTaskDetailPanel(HistoricTaskInstance historicTask, TaskPage taskPage) { this.historicTask = historicTask; this.taskPage = taskPage; this.historyService = ProcessEngines.getDefaultProcessEngine().getHistoryService(); this.taskService = ProcessEngines.getDefaultProcessEngine().getTaskService(); this.viewManager = ExplorerApp.get().getViewManager(); this.i18nManager = ExplorerApp.get().getI18nManager(); this.notificationManager = ExplorerApp.get().getNotificationManager(); this.attachmentRendererManager = ExplorerApp.get().getAttachmentRendererManager(); } @Override public void attach() { super.attach(); init(); } protected void init() { setSizeFull(); addStyleName(Reindeer.LAYOUT_WHITE); this.centralLayout = new VerticalLayout(); centralLayout.setMargin(true); setDetailContainer(centralLayout); initHeader(); initDescription(); initParentTaskLink(); initPeopleDetails(); initSubTasks(); initRelatedContent(); } protected void initHeader() { GridLayout taskDetails = new GridLayout(5, 2); taskDetails.setWidth(100, UNITS_PERCENTAGE); taskDetails.addStyleName(ExplorerLayout.STYLE_TITLE_BLOCK); taskDetails.setSpacing(true); taskDetails.setMargin(false, false, true, false); // Add image Embedded image = new Embedded(null, Images.TASK_50); taskDetails.addComponent(image, 0, 0, 0, 1); // Add task name Label nameLabel = new Label(historicTask.getName()); nameLabel.addStyleName(Reindeer.LABEL_H2); taskDetails.addComponent(nameLabel, 1, 0, 4,0); // Add due date PrettyTimeLabel dueDateLabel = new PrettyTimeLabel(i18nManager.getMessage(Messages.TASK_DUEDATE_SHORT), historicTask.getDueDate(), i18nManager.getMessage(Messages.TASK_DUEDATE_UNKNOWN), false); dueDateLabel.addStyleName(ExplorerLayout.STYLE_TASK_HEADER_DUEDATE); taskDetails.addComponent(dueDateLabel, 1, 1); // Add priority Integer lowMedHighPriority = convertPriority(historicTask.getPriority()); Label priorityLabel = new Label(); switch(lowMedHighPriority) { case 1: priorityLabel.setValue(i18nManager.getMessage(Messages.TASK_PRIORITY_LOW)); priorityLabel.addStyleName(ExplorerLayout.STYLE_TASK_HEADER_PRIORITY_LOW); break; case 2: priorityLabel.setValue(i18nManager.getMessage(Messages.TASK_PRIORITY_MEDIUM)); priorityLabel.addStyleName(ExplorerLayout.STYLE_TASK_HEADER_PRIORITY_MEDIUM); break; case 3: default: priorityLabel.setValue(i18nManager.getMessage(Messages.TASK_PRIORITY_HIGH)); priorityLabel.addStyleName(ExplorerLayout.STYLE_TASK_HEADER_PRIORITY_HIGH); } taskDetails.addComponent(priorityLabel, 2, 1); // Add create date PrettyTimeLabel createLabel = new PrettyTimeLabel(i18nManager.getMessage(Messages.TASK_CREATED_SHORT), historicTask.getStartTime(), "", true); createLabel.addStyleName(ExplorerLayout.STYLE_TASK_HEADER_CREATE_TIME); taskDetails.addComponent(createLabel, 3, 1); // Add label to fill excess space Label spacer = new Label(); spacer.setContentMode(Label.CONTENT_XHTML); spacer.setValue(" "); spacer.setSizeUndefined(); taskDetails.addComponent(spacer); taskDetails.setColumnExpandRatio(1, 1.0f); taskDetails.setColumnExpandRatio(2, 1.0f); taskDetails.setColumnExpandRatio(3, 1.0f); taskDetails.setColumnExpandRatio(4, 1.0f); centralLayout.addComponent(taskDetails); } protected void initDescription() { CssLayout descriptionLayout = new CssLayout(); descriptionLayout.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK); descriptionLayout.setWidth(100, UNITS_PERCENTAGE); if (historicTask.getDescription() != null) { Label descriptionLabel = new Label(historicTask.getDescription()); descriptionLayout.addComponent(descriptionLabel); } centralLayout.addComponent(descriptionLayout); } protected void initParentTaskLink() { if (historicTask.getParentTaskId() != null) { final HistoricTaskInstance parentTask = historyService.createHistoricTaskInstanceQuery() .taskId(historicTask.getParentTaskId()) .singleResult(); Button showParentTaskButton = new Button(i18nManager.getMessage( Messages.TASK_SUBTASK_OF_PARENT_TASK, parentTask.getName())); showParentTaskButton.addStyleName(Reindeer.BUTTON_LINK); showParentTaskButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { viewManager.showTaskPage(parentTask.getId()); } }); centralLayout.addComponent(showParentTaskButton); } } protected void initPeopleDetails() { peopleLayout = new VerticalLayout(); peopleLayout.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK); addComponent(peopleLayout); initPeopleTitle(); initPeopleGrid(); initOwner(); initAssignee(); } protected void initPeopleTitle() { Label title = new Label(i18nManager.getMessage(Messages.TASK_PEOPLE)); title.addStyleName(ExplorerLayout.STYLE_H3); title.setWidth(100, UNITS_PERCENTAGE); peopleLayout.addComponent(title); } protected void initPeopleGrid() { peopleGrid = new GridLayout(); peopleGrid.setColumns(2); peopleGrid.setSpacing(true); peopleGrid.setMargin(true, false, false, false); peopleGrid.setWidth(100, UNITS_PERCENTAGE); peopleLayout.addComponent(peopleGrid); } protected void initOwner() { String ownerRole = historicTask.getOwner() != null ? Messages.TASK_OWNER : Messages.TASK_NO_OWNER; UserDetailsComponent owner = new UserDetailsComponent(historicTask.getOwner(), i18nManager.getMessage(ownerRole)); peopleGrid.addComponent(owner); } protected void initAssignee() { String assigneeRole = historicTask.getAssignee() != null ? Messages.TASK_ASSIGNEE : Messages.TASK_NO_ASSIGNEE; UserDetailsComponent assignee = new UserDetailsComponent(historicTask.getAssignee(), i18nManager.getMessage(assigneeRole)); peopleGrid.addComponent(assignee); } protected void initSubTasks() { subTasksLayout = new VerticalLayout(); subTasksLayout.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK); addComponent(subTasksLayout); initSubTaskTitle(); List<HistoricTaskInstance> subTasks = historyService.createHistoricTaskInstanceQuery() .taskParentTaskId(historicTask.getId()) .list(); if (subTasks.size() > 0) { initSubTaskGrid(); populateSubTasks(subTasks); } else { initNoSubTasksLabel(); } } protected void initSubTaskTitle() { Label title = new Label(i18nManager.getMessage(Messages.TASK_SUBTASKS)); title.addStyleName(ExplorerLayout.STYLE_H3); title.setWidth(100, UNITS_PERCENTAGE); subTasksLayout.addComponent(title); } protected void initSubTaskGrid() { subTaskGrid = new GridLayout(); subTaskGrid.setColumns(2); subTasksLayout.addComponent(subTaskGrid); } protected void populateSubTasks(List<HistoricTaskInstance> subTasks) { for (final HistoricTaskInstance subTask : subTasks) { // icon Embedded icon = new Embedded(null, Images.TASK_22); icon.setWidth(22, UNITS_PIXELS); icon.setWidth(22, UNITS_PIXELS); subTaskGrid.addComponent(icon); // Link to subtask Button subTaskLink = new Button(subTask.getName()); subTaskLink.addStyleName(Reindeer.BUTTON_LINK); subTaskLink.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { ExplorerApp.get().getViewManager().showTaskPage(subTask.getId()); } }); subTaskGrid.addComponent(subTaskLink); subTaskGrid.setComponentAlignment(subTaskLink, Alignment.MIDDLE_LEFT); } } protected void initNoSubTasksLabel() { Label noSubTasksLabel = new Label(i18nManager.getMessage(Messages.TASK_NO_SUBTASKS)); noSubTasksLabel.addStyleName(Reindeer.LABEL_SMALL); subTasksLayout.addComponent(noSubTasksLabel); } protected void initRelatedContent() { relatedContentLayout = new VerticalLayout(); relatedContentLayout.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK); addComponent(relatedContentLayout); initRelatedContentTitle(); List<Attachment> attachments = taskService.getTaskAttachments(historicTask.getId()); if (attachments.size() > 0) { Table table = initRelatedContentTable(); populateRelatedContent(table, attachments); } else { initNoRelatedContentLabel(); } } protected void initRelatedContentTitle() { Label title = new Label(ExplorerApp.get().getI18nManager().getMessage(Messages.TASK_RELATED_CONTENT)); title.addStyleName(ExplorerLayout.STYLE_H3); title.setSizeFull(); relatedContentLayout.addComponent(title); } protected Table initRelatedContentTable() { Table table = new Table(); table.setWidth(100, UNITS_PERCENTAGE); table.addStyleName(ExplorerLayout.STYLE_RELATED_CONTENT_LIST); // Invisible by default, only shown when attachments are present table.setVisible(false); table.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_HIDDEN); table.addContainerProperty("type", Embedded.class, null); table.setColumnWidth("type", 16); table.addContainerProperty("name", Component.class, null); relatedContentLayout.addComponent(table); return table; } protected void populateRelatedContent(Table table, List<Attachment> attachments) { for (Attachment attachment : attachments) { AttachmentRenderer renderer = attachmentRendererManager.getRenderer(attachment); Item attachmentItem = table.addItem(attachment.getId()); // Simple renderer that just shows a popup window with the attachment RelatedContentComponent relatedContentComponent = new RelatedContentComponent() { public void showAttachmentDetail(Attachment attachment) { AttachmentDetailPopupWindow popup = new AttachmentDetailPopupWindow(attachment); ExplorerApp.get().getViewManager().showPopupWindow(popup); } }; attachmentItem.getItemProperty("name").setValue(renderer.getOverviewComponent(attachment, relatedContentComponent)); attachmentItem.getItemProperty("type").setValue(new Embedded(null, renderer.getImage(attachment))); } table.setPageLength(table.size()); } protected void initNoRelatedContentLabel() { Label noContentLabel = new Label(i18nManager.getMessage(Messages.TASK_NO_RELATED_CONTENT)); noContentLabel.addStyleName(Reindeer.LABEL_SMALL); relatedContentLayout.addComponent(noContentLabel); } /** * Returns a numeric priority - low (1), medium (2) or high (3) - * based on the given numeric priority value. */ protected Integer convertPriority(int priority) { // TODO: define thresholds return 1; } }