/* * Copyright 2012 JBoss Inc * * 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.overlord.dtgov.ui.client.local.pages; import java.util.HashMap; import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; import javax.inject.Inject; import org.jboss.errai.databinding.client.api.DataBinder; import org.jboss.errai.databinding.client.api.InitialState; import org.jboss.errai.databinding.client.api.PropertyChangeEvent; import org.jboss.errai.databinding.client.api.PropertyChangeHandler; import org.jboss.errai.ui.nav.client.local.Page; import org.jboss.errai.ui.nav.client.local.PageState; import org.jboss.errai.ui.nav.client.local.TransitionAnchor; import org.jboss.errai.ui.shared.api.annotations.AutoBound; import org.jboss.errai.ui.shared.api.annotations.Bound; import org.jboss.errai.ui.shared.api.annotations.DataField; import org.jboss.errai.ui.shared.api.annotations.EventHandler; import org.jboss.errai.ui.shared.api.annotations.Templated; import org.overlord.commons.gwt.client.local.widgets.HtmlSnippet; import org.overlord.dtgov.ui.client.local.ClientMessages; import org.overlord.dtgov.ui.client.local.pages.taskInbox.TaskFormPanel; import org.overlord.dtgov.ui.client.local.services.NotificationService; import org.overlord.dtgov.ui.client.local.services.TaskInboxRpcService; import org.overlord.dtgov.ui.client.local.services.rpc.IRpcServiceInvocationHandler; import org.overlord.dtgov.ui.client.local.util.DOMUtil; import org.overlord.dtgov.ui.client.local.util.DataBindingDateConverter; import org.overlord.dtgov.ui.client.local.util.DataBindingIntegerConverter; import org.overlord.dtgov.ui.client.local.widgets.common.DescriptionInlineLabel; import org.overlord.dtgov.ui.client.shared.beans.NotificationBean; import org.overlord.dtgov.ui.client.shared.beans.TaskActionEnum; import org.overlord.dtgov.ui.client.shared.beans.TaskBean; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.InlineLabel; /** * The Task Details page. * * @author eric.wittmann@redhat.com */ @Templated("/org/overlord/dtgov/ui/client/local/site/taskDetails.html#page") @Page(path="taskDetails") @Dependent public class TaskDetailsPage extends AbstractPage { @Inject protected ClientMessages i18n; @Inject protected TaskInboxRpcService taskInboxService; @Inject protected NotificationService notificationService; protected TaskBean currentTask; @PageState private String id; @Inject @AutoBound protected DataBinder<TaskBean> task; // Breadcrumbs @Inject @DataField("back-to-dashboard") TransitionAnchor<DashboardPage> backToDashboard; @Inject @DataField("back-to-tasks") TransitionAnchor<TaskInboxPage> backToTaskInbox; // Properties @Inject @DataField("task-name") @Bound(property="name") InlineLabel name; @Inject @DataField("task-id") @Bound(property="id") InlineLabel taskId; @Inject @DataField("task-status") @Bound(property="status") InlineLabel status; @Inject @DataField("task-owner") @Bound(property="owner") InlineLabel owner; @Inject @DataField("task-priority") @Bound(property="priority", converter=DataBindingIntegerConverter.class) InlineLabel priority; @Inject @DataField("task-dueDate") @Bound(property="dueDate", converter=DataBindingDateConverter.class) InlineLabel dueOn; @Inject @DataField("task-description") @Bound(property="description") DescriptionInlineLabel description; // Actions @Inject @DataField("action-claim") Button claimButton; @Inject @DataField("action-release") Button releaseButton; @Inject @DataField("action-start") Button startButton; @Inject @DataField("action-stop") Button stopButton; @Inject @DataField("task-form") TaskFormPanel taskFormWrapper; @Inject @DataField("action-complete") Button completeButton; @Inject @DataField("action-fail") Button failButton; @Inject @DataField("task-details-loading-spinner") protected HtmlSnippet taskLoading; protected Element pageContent; /** * Constructor. */ public TaskDetailsPage() { } /** * Called after the widget is constructed. */ @PostConstruct protected void onPostConstruct() { pageContent = DOMUtil.findElementById(getElement(), "task-details-content-wrapper"); //$NON-NLS-1$ task.addPropertyChangeHandler(new PropertyChangeHandler<Object>() { @Override public void onPropertyChange(PropertyChangeEvent<Object> event) { if ("description".equals(event.getPropertyName())) { //$NON-NLS-1$ pushModelToServer(); } } }); } /** * Sends the model back up to the server (saves local changes). */ protected void pushModelToServer() { final NotificationBean notificationBean = notificationService.startProgressNotification( i18n.format("task-details.updating-task"), //$NON-NLS-1$ i18n.format("task-details.updating-task-msg", task.getModel().getName())); //$NON-NLS-1$ taskInboxService.update(task.getModel(), new IRpcServiceInvocationHandler<Void>() { @Override public void onReturn(Void data) { notificationService.completeProgressNotification(notificationBean.getUuid(), i18n.format("task-details.update-complete"), //$NON-NLS-1$ i18n.format("task-details.update-complete-msg", task.getModel().getName())); //$NON-NLS-1$ } @Override public void onError(Throwable error) { notificationService.completeProgressNotification(notificationBean.getUuid(), i18n.format("task-details.error-updating-task"), //$NON-NLS-1$ error); } }); } /** * @see org.overlord.sramp.ui.client.local.pages.AbstractPage#onPageShowing() */ @Override protected void onPageShowing() { currentTask = null; pageContent.addClassName("hide"); //$NON-NLS-1$ taskLoading.getElement().removeClassName("hide"); //$NON-NLS-1$ taskInboxService.get(id, new IRpcServiceInvocationHandler<TaskBean>() { @Override public void onReturn(TaskBean data) { currentTask = data; updateTaskMetaData(data); updateActionStates(data); } @Override public void onError(Throwable error) { notificationService.sendErrorNotification(i18n.format("task-details.error-getting-details"), error); //$NON-NLS-1$ } }); } /** * Called when the task is loaded. * @param task */ protected void updateTaskMetaData(TaskBean task) { this.task.setModel(task, InitialState.FROM_MODEL); taskLoading.getElement().addClassName("hide"); //$NON-NLS-1$ pageContent.removeClassName("hide"); //$NON-NLS-1$ if (task.getTaskForm() != null) { taskFormWrapper.setHTML(task.getTaskForm()); taskFormWrapper.setData(task.getTaskData()); } else { taskFormWrapper.setHTML(""); //$NON-NLS-1$ taskFormWrapper.setData(new HashMap<String, String>()); } } /** * Updates the states of the action buttons to reflect the available actions * found on the task. * @param data */ protected void updateActionStates(TaskBean task) { claimButton.setEnabled(task.isActionAllowed(TaskActionEnum.claim)); releaseButton.setEnabled(task.isActionAllowed(TaskActionEnum.release)); startButton.setEnabled(task.isActionAllowed(TaskActionEnum.start)); stopButton.setEnabled(task.isActionAllowed(TaskActionEnum.stop)); completeButton.setEnabled(task.isActionAllowed(TaskActionEnum.complete)); //only show the failbutton is specified in the data ("FailButtonIsVisible"="true") if (task.getTaskData()!=null && task.getTaskData().containsKey("FailButtonIsVisible") && //$NON-NLS-1$ task.getTaskData().get("FailButtonIsVisible").equals("true")) { //$NON-NLS-1$ //$NON-NLS-2$ failButton.setEnabled(task.isActionAllowed(TaskActionEnum.fail)); } else { failButton.setEnabled(false); failButton.setVisible(false); } } /** * Called when the user clicks the Claim button. * @param event */ @EventHandler("action-claim") public void onClaimClick(ClickEvent event) { doTaskAction(TaskActionEnum.claim, i18n.format("task-details.claiming-task"), //$NON-NLS-1$ i18n.format("task-details.claiming-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-claimed"), //$NON-NLS-1$ i18n.format("task-details.task-claimed-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Called when the user clicks the Release button. * @param event */ @EventHandler("action-release") public void onReleaseClick(ClickEvent event) { doTaskAction(TaskActionEnum.release, i18n.format("task-details.releasing-task"), //$NON-NLS-1$ i18n.format("task-details.releasing-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-released"), //$NON-NLS-1$ i18n.format("task-details.task-released-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Called when the user clicks the Start button. * @param event */ @EventHandler("action-start") public void onStartClick(ClickEvent event) { doTaskAction(TaskActionEnum.start, i18n.format("task-details.starting-task"), //$NON-NLS-1$ i18n.format("task-details.starting-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-started"), //$NON-NLS-1$ i18n.format("task-details.task-started-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Called when the user clicks the Stop button. * @param event */ @EventHandler("action-stop") public void onStopClick(ClickEvent event) { doTaskAction(TaskActionEnum.stop, i18n.format("task-details.stopping-task"), //$NON-NLS-1$ i18n.format("task-details.stopping-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-stopped"), //$NON-NLS-1$ i18n.format("task-details.task-stopped-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Called when the user clicks the Complete button. * @param event */ @EventHandler("action-complete") public void onCompleteClick(ClickEvent event) { doTaskAction(TaskActionEnum.complete, i18n.format("task-details.completing-task"), //$NON-NLS-1$ i18n.format("task-details.completing-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-comleted"), //$NON-NLS-1$ i18n.format("task-details.task-comleted-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Called when the user clicks the Fail button. * @param event */ @EventHandler("action-fail") public void onFailClick(ClickEvent event) { doTaskAction(TaskActionEnum.fail, i18n.format("task-details.failing-task"), //$NON-NLS-1$ i18n.format("task-details.failing-task-msg", task.getModel().getName()), //$NON-NLS-1$ i18n.format("task-details.task-failed"), //$NON-NLS-1$ i18n.format("task-details.task-failed-msg", task.getModel().getName())); //$NON-NLS-1$ } /** * Executes the action by making an RPC call to the server. * @param action * @param inProgressTitle * @param inProgressDescription * @param successTitle * @param successDescription */ private void doTaskAction(TaskActionEnum action, final String inProgressTitle, final String inProgressDescription, final String successTitle, final String successDescription) { final NotificationBean notificationBean = notificationService.startProgressNotification( inProgressTitle, inProgressDescription); final TaskBean model = task.getModel(); model.setTaskData(taskFormWrapper.getData()); taskInboxService.executeAction(model, action, new IRpcServiceInvocationHandler<TaskBean>() { @Override public void onReturn(TaskBean data) { notificationService.completeProgressNotification(notificationBean.getUuid(), successTitle, successDescription); data.setTaskForm(model.getTaskForm()); data.getTaskData().putAll(taskFormWrapper.getData()); updateTaskMetaData(data); updateActionStates(data); } @Override public void onError(Throwable error) { notificationService.completeProgressNotification(notificationBean.getUuid(), i18n.format("task-details.error", inProgressTitle), error); //$NON-NLS-1$ } }); } }