/* * Copyright 2014 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.List; import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Instance; import javax.inject.Inject; import org.jboss.errai.ui.nav.client.local.Page; import org.jboss.errai.ui.nav.client.local.TransitionAnchor; 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.commons.gwt.client.local.widgets.Pager; import org.overlord.commons.gwt.client.local.widgets.SortableTemplatedWidgetTable.SortColumn; import org.overlord.dtgov.ui.client.local.ClientMessages; import org.overlord.dtgov.ui.client.local.events.DialogOkCancelEvent; import org.overlord.dtgov.ui.client.local.events.StopProcessEvent; import org.overlord.dtgov.ui.client.local.pages.processes.AbortProcessDialog; import org.overlord.dtgov.ui.client.local.pages.processes.ProcessesFilter; import org.overlord.dtgov.ui.client.local.pages.processes.ProcessesTable; import org.overlord.dtgov.ui.client.local.pages.processes.WorkflowsTable; import org.overlord.dtgov.ui.client.local.services.ApplicationStateService; import org.overlord.dtgov.ui.client.local.services.NotificationService; import org.overlord.dtgov.ui.client.local.services.ProcessesRpcService; import org.overlord.dtgov.ui.client.local.services.WorkflowQueriesRpcService; import org.overlord.dtgov.ui.client.local.services.rpc.IRpcServiceInvocationHandler; import org.overlord.dtgov.ui.client.shared.beans.NotificationBean; import org.overlord.dtgov.ui.client.shared.beans.ProcessBean; import org.overlord.dtgov.ui.client.shared.beans.ProcessesFilterBean; import org.overlord.dtgov.ui.client.shared.beans.ProcessesResultSetBean; import org.overlord.dtgov.ui.client.shared.beans.Workflow; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.user.client.ui.Button; /** * Manage Processes initial page. Used to list all the workflow processes. It * shows the RUNNING, STOPPED and COMPLETED processes * * @author David Virgil Naranjo */ @Templated("/org/overlord/dtgov/ui/client/local/site/processes.html#page") @Page(path = "processes") @Dependent public class ProcessesPage extends AbstractPage { public static final String PROCESSES_FILTER = "processes.filter-bean"; //$NON-NLS-1$ public static final String PROCESSES_PAGE = "processes.page"; //$NON-NLS-1$ public static final String PROCESSES_SORT_COLUMN = "processes.sort-column"; //$NON-NLS-1$ /** The _event bus. */ public static EventBus _eventBus = GWT.create(SimpleEventBus.class); @Inject @DataField("back-to-dashboard") private TransitionAnchor<DashboardPage> _backToDashboard; /** The delete workflow query dialog. */ @Inject private Instance<AbortProcessDialog> _stopProcessDialog; @Inject private ApplicationStateService _stateService; /** The i18n. */ @Inject private ClientMessages _i18n; /** The no data message. */ @Inject @DataField("processes-none") private HtmlSnippet _noDataMessage; /** The no data message. */ @Inject @DataField("workflows-none") private HtmlSnippet workflowsNoDataMessage; /** The notification service. */ @Inject private NotificationService _notificationService; /** The refresh button. */ @Inject @DataField("btn-refresh") private Button _refreshButton; /** The search in progress message. */ @Inject @DataField("processes-searching") private HtmlSnippet _searchInProgressMessage; /** The search in progress message. */ @Inject @DataField("workflows-searching") private HtmlSnippet workflowsSearchInProgressMessage; /** The workflow query service. */ @Inject private ProcessesRpcService _processesService; /** The _workflow query table. */ @Inject @DataField("processes-table") private ProcessesTable _processesTable; /** The _workflow query table. */ @Inject @DataField("workflows-table") private WorkflowsTable workflowsTable; @Inject @DataField("processes-filter-sidebar") private ProcessesFilter _filtersPanel; /** The _pager. */ @Inject @DataField("processes-pager") private Pager _pager; /** The _range span. */ @DataField("processes-range") private final SpanElement _processesRangeSpan = Document.get().createSpanElement(); /** The _total span. */ @DataField("processes-total") private final SpanElement _processesTotalSpan = Document.get().createSpanElement(); /** The _range span. */ @DataField("workflows-range") private final SpanElement workflowsRangeSpan = Document.get().createSpanElement(); /** The _total span. */ @DataField("workflows-total") private final SpanElement workflowsTotalSpan = Document.get().createSpanElement(); /** The _current page. */ private int _currentPage = 1; /** The _workflow query service. */ @Inject private WorkflowQueriesRpcService _workflowQueryService; /** * Instantiates a new targets page. */ public ProcessesPage() { } /** * On refresh click. * * @param event * the event */ @EventHandler("btn-refresh") public void onRefreshClick(ClickEvent event) { doSearch(_currentPage); } /* * (non-Javadoc) * * @see * org.overlord.dtgov.ui.client.local.pages.AbstractPage#onPageShowing() */ @Override protected void onPageShowing() { _filtersPanel.refresh(); ProcessesFilterBean filterBean = (ProcessesFilterBean) _stateService.get(PROCESSES_FILTER, new ProcessesFilterBean()); Integer page = (Integer) _stateService.get(PROCESSES_PAGE, 1); SortColumn sortColumn = (SortColumn) _stateService.get(PROCESSES_SORT_COLUMN, this._processesTable.getDefaultSortColumn()); this._filtersPanel.setValue(filterBean); this._processesTable.sortBy(sortColumn.columnId, sortColumn.ascending); doSearch(page); doWorkflowSearch(); } /** * Do search. */ protected void doSearch() { doSearch(1); } /** * Initializes the page on the post construct event. */ @PostConstruct protected void postConstruct() { _filtersPanel.addValueChangeHandler(new ValueChangeHandler<ProcessesFilterBean>() { @Override public void onValueChange(ValueChangeEvent<ProcessesFilterBean> event) { doSearch(); } }); _pager.addValueChangeHandler(new ValueChangeHandler<Integer>() { @Override public void onValueChange(ValueChangeEvent<Integer> event) { doSearch(event.getValue()); } }); _processesTable.addStopProcessHandler(new StopProcessEvent.Handler() { @Override public void onProcessStopped(StopProcessEvent event) { AbortProcessDialog dialog = _stopProcessDialog.get(); final ProcessBean process = (ProcessBean) event.getItem(); dialog.setProcess(process); dialog.addDialogOkCancelHandler(new DialogOkCancelEvent.Handler() { @Override public void onDialogOkCancel(DialogOkCancelEvent event) { stopProcess(process); } }); dialog.show(); } }); this._processesRangeSpan.setInnerText("?"); //$NON-NLS-1$ this._processesTotalSpan.setInnerText("?"); //$NON-NLS-1$ this.workflowsRangeSpan.setInnerText("?"); //$NON-NLS-1$ this.workflowsTotalSpan.setInnerText("?"); //$NON-NLS-1$ } /** * Do search method. Used on refresh, stop event and init method. * * @param page * the page */ protected void doWorkflowSearch() { onWorkflowSearchStarting(); _workflowQueryService.getWorkflowTypes(new IRpcServiceInvocationHandler<List<Workflow>>() { @Override public void onReturn(List<Workflow> workflowTypes) { updateWorkflowsTable(workflowTypes); String rangeText = "1-" + workflowTypes.size(); //$NON-NLS-1$ workflowsRangeSpan.setInnerText(rangeText); workflowsTotalSpan.setInnerText(workflowTypes.size() + ""); //$NON-NLS-1$ } @Override public void onError(Throwable error) { _notificationService.sendErrorNotification(_i18n.format("processes.error-loading"), error); //$NON-NLS-1$ workflowsNoDataMessage.setVisible(true); workflowsSearchInProgressMessage.setVisible(false); } }); } /** * Do search method. Used on refresh, stop event and init method. * * @param page * the page */ protected void doSearch(int page) { onSearchStarting(); _currentPage = page; final ProcessesFilterBean filterBean = _filtersPanel.getValue(); final SortColumn currentSortColumn = this._processesTable.getCurrentSortColumn(); _stateService.put(PROCESSES_FILTER, filterBean); _stateService.put(PROCESSES_PAGE, _currentPage); _stateService.put(PROCESSES_SORT_COLUMN, currentSortColumn); _processesService.search(filterBean, page, currentSortColumn.columnId, currentSortColumn.ascending, new IRpcServiceInvocationHandler<ProcessesResultSetBean>() { @Override public void onError(Throwable error) { _notificationService.sendErrorNotification(_i18n.format("processes.error-loading"), error); //$NON-NLS-1$ _noDataMessage.setVisible(true); _searchInProgressMessage.setVisible(false); updatePager(null); } @Override public void onReturn(ProcessesResultSetBean data) { updateTable(data); updatePager(data); } }); } /** * Updates the table of processes with the given data. Called when the * doSearch asynchronous call is successful. * * @param data * the data */ protected void updateTable(ProcessesResultSetBean data) { this._processesTable.clear(); this._searchInProgressMessage.setVisible(false); if (data.getProcesses() != null && data.getProcesses().size() > 0) { for (ProcessBean processBean : data.getProcesses()) { this._processesTable.addRow(processBean); } this._processesTable.setVisible(true); } else { this._noDataMessage.setVisible(true); } } /** * Updates the table of processes with the given data. Called when the * doSearch asynchronous call is successful. * * @param data * the data */ protected void updateWorkflowsTable(List<Workflow> data) { this.workflowsTable.clear(); this.workflowsSearchInProgressMessage.setVisible(false); if (data != null && data.size() > 0) { this.workflowsTable.setValue(data); this.workflowsTable.setVisible(true); } else { this.workflowsNoDataMessage.setVisible(true); } } /** * Called when a new search is kicked off. */ protected void onSearchStarting() { this._pager.setVisible(false); this._searchInProgressMessage.setVisible(true); this._processesTable.setVisible(false); this._noDataMessage.setVisible(false); this._processesRangeSpan.setInnerText("?"); //$NON-NLS-1$ this._processesTotalSpan.setInnerText("?"); //$NON-NLS-1$ } /** * Called when a new search is kicked off. */ protected void onWorkflowSearchStarting() { this.workflowsSearchInProgressMessage.setVisible(true); this.workflowsTable.setVisible(false); this.workflowsNoDataMessage.setVisible(false); this.workflowsRangeSpan.setInnerText("?"); //$NON-NLS-1$ this.workflowsTotalSpan.setInnerText("?"); //$NON-NLS-1$ } /** * Update pager. * * @param data * the data */ protected void updatePager(ProcessesResultSetBean data) { if (data != null && data.getProcesses() != null && data.getProcesses().size() > 0) { int numPages = ((int) (data.get_totalResults() / data.getItemsPerPage())) + (data.get_totalResults() % data.getItemsPerPage() == 0 ? 0 : 1); int thisPage = (data.getStartIndex() / data.getItemsPerPage()) + 1; this._pager.setNumPages(numPages); this._pager.setPage(thisPage); if (numPages > 1) this._pager.setVisible(true); int startIndex = data.getStartIndex() + 1; int endIndex = startIndex + data.getProcesses().size() - 1; String rangeText = "" + startIndex + "-" + endIndex; //$NON-NLS-1$ //$NON-NLS-2$ String totalText = String.valueOf(data.get_totalResults()); this._processesRangeSpan.setInnerText(rangeText); this._processesTotalSpan.setInnerText(totalText); } else { this._pager.setVisible(false); this._noDataMessage.setVisible(true); this._processesRangeSpan.setInnerText("0"); //$NON-NLS-1$ this._processesTotalSpan.setInnerText("0"); //$NON-NLS-1$ } } /** * Stop a process workflow. * * @param process * the process */ private void stopProcess(final ProcessBean process) { final NotificationBean notification = _notificationService.startProgressNotification(_i18n.format("abort-process-submit.aborting"), //$NON-NLS-1$ _i18n.format("abort-process-submit.aborting-msg")); //$NON-NLS-1$ _processesService.abort(process.getUuid(), new IRpcServiceInvocationHandler<Boolean>() { @Override public void onReturn(Boolean data) { _notificationService.completeProgressNotification(notification.getUuid(), _i18n.format("abort-process-submit.successfully-aborted"), //$NON-NLS-1$ _i18n.format("abort-process-submit.successfully-aborted-msg")); //$NON-NLS-1$ doSearch(); } @Override public void onError(Throwable error) { _notificationService.sendErrorNotification( _i18n.format("abort-process-submit.error", process.getArtifactName(), process.getWorkflow()), error); //$NON-NLS-1$ } }); } /** * Gets the back to dashboard. * * @return the back to dashboard */ public TransitionAnchor<DashboardPage> getBackToDashboard() { return _backToDashboard; } /** * Sets the back to dashboard. * * @param backToDashboard * the new back to dashboard */ public void setBackToDashboard(TransitionAnchor<DashboardPage> backToDashboard) { this._backToDashboard = backToDashboard; } /** * Gets the i18n. * * @return the i18n */ public ClientMessages getI18n() { return _i18n; } /** * Sets the i18n. * * @param i18n * the new i18n */ public void setI18n(ClientMessages i18n) { this._i18n = i18n; } /** * Gets the no data message. * * @return the no data message */ public HtmlSnippet getNoDataMessage() { return _noDataMessage; } /** * Sets the no data message. * * @param noDataMessage * the new no data message */ public void setNoDataMessage(HtmlSnippet noDataMessage) { this._noDataMessage = noDataMessage; } /** * Gets the notification service. * * @return the notification service */ public NotificationService getNotificationService() { return _notificationService; } /** * Sets the notification service. * * @param notificationService * the new notification service */ public void setNotificationService(NotificationService notificationService) { this._notificationService = notificationService; } /** * Gets the refresh button. * * @return the refresh button */ public Button getRefreshButton() { return _refreshButton; } /** * Sets the refresh button. * * @param refreshButton * the new refresh button */ public void setRefreshButton(Button refreshButton) { this._refreshButton = refreshButton; } /** * Gets the search in progress message. * * @return the search in progress message */ public HtmlSnippet getSearchInProgressMessage() { return _searchInProgressMessage; } /** * Sets the search in progress message. * * @param searchInProgressMessage * the new search in progress message */ public void setSearchInProgressMessage(HtmlSnippet searchInProgressMessage) { this._searchInProgressMessage = searchInProgressMessage; } /** * Gets the stop process dialog. * * @return the stop process dialog */ public Instance<AbortProcessDialog> getStopProcessDialog() { return _stopProcessDialog; } /** * Sets the stop process dialog. * * @param stopProcessDialog * the new stop process dialog */ public void setStopProcessDialog(Instance<AbortProcessDialog> stopProcessDialog) { this._stopProcessDialog = stopProcessDialog; } /** * Gets the state service. * * @return the state service */ public ApplicationStateService getStateService() { return _stateService; } /** * Sets the state service. * * @param stateService * the new state service */ public void setStateService(ApplicationStateService stateService) { this._stateService = stateService; } /** * Gets the processes service. * * @return the processes service */ public ProcessesRpcService getProcessesService() { return _processesService; } /** * Sets the processes service. * * @param processesService * the new processes service */ public void setProcessesService(ProcessesRpcService processesService) { this._processesService = processesService; } /** * Gets the processes table. * * @return the processes table */ public ProcessesTable getProcessesTable() { return _processesTable; } /** * Sets the processes table. * * @param processesTable * the new processes table */ public void setProcessesTable(ProcessesTable processesTable) { this._processesTable = processesTable; } /** * Gets the filters panel. * * @return the filters panel */ public ProcessesFilter getFiltersPanel() { return _filtersPanel; } /** * Sets the filters panel. * * @param filtersPanel * the new filters panel */ public void setFiltersPanel(ProcessesFilter filtersPanel) { this._filtersPanel = filtersPanel; } /** * Gets the pager. * * @return the pager */ public Pager getPager() { return _pager; } /** * Sets the pager. * * @param pager * the new pager */ public void setPager(Pager pager) { this._pager = pager; } /** * Gets the current page. * * @return the current page */ public int getCurrentPage() { return _currentPage; } /** * Sets the current page. * * @param currentPage * the new current page */ public void setCurrentPage(int currentPage) { this._currentPage = currentPage; } /** * Gets the range span. * * @return the range span */ public SpanElement getRangeSpan() { return _processesRangeSpan; } /** * Gets the total span. * * @return the total span */ public SpanElement getTotalSpan() { return _processesTotalSpan; } /** * Gets the event bus. * * @return the event bus */ public static EventBus getEventBus() { return _eventBus; } /** * Sets the event bus. * * @param eventBus * the new event bus */ public static void setEventBus(EventBus eventBus) { ProcessesPage._eventBus = eventBus; } }