/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.mantle.client.workspace; import static org.pentaho.mantle.client.workspace.SchedulesPerspectivePanel.PAGE_SIZE; import org.pentaho.gwt.widgets.client.dialogs.IDialogCallback; import org.pentaho.gwt.widgets.client.dialogs.MessageDialogBox; import org.pentaho.gwt.widgets.client.dialogs.PromptDialogBox; import org.pentaho.gwt.widgets.client.toolbar.Toolbar; import org.pentaho.gwt.widgets.client.toolbar.ToolbarButton; import org.pentaho.gwt.widgets.client.utils.string.StringUtils; import org.pentaho.mantle.client.commands.RefreshSchedulesCommand; import org.pentaho.mantle.client.dialogs.scheduling.NewScheduleDialog; import org.pentaho.mantle.client.dialogs.scheduling.OutputLocationUtils; import org.pentaho.mantle.client.events.EventBusUtil; import org.pentaho.mantle.client.events.GenericEvent; import org.pentaho.mantle.client.images.ImageUtil; import org.pentaho.mantle.client.messages.Messages; import org.pentaho.mantle.client.solutionbrowser.SolutionBrowserPanel; import org.pentaho.mantle.client.ui.PerspectiveManager; import org.pentaho.mantle.client.ui.column.HtmlColumn; import org.pentaho.mantle.client.workspace.SchedulesPerspectivePanel.CellTableResources; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsonUtils; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.TableCellElement; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestBuilder.Method; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.http.client.URL; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.cellview.client.AbstractHeaderOrFooterBuilder; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.SimplePager; import com.google.gwt.user.cellview.client.SimplePager.TextLocation; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.CellPreviewEvent; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.MultiSelectionModel; import com.google.gwt.view.client.ProvidesKey; import com.google.gwt.view.client.Range; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; public class SchedulesPanel extends SimplePanel { private static final int READ_PERMISSION = 0; private ToolbarButton controlScheduleButton = new ToolbarButton( ImageUtil.getThemeableImage( "icon-small", "icon-run" ) ); private ToolbarButton editButton = new ToolbarButton( ImageUtil.getThemeableImage( "pentaho-editbutton" ) ); private ToolbarButton triggerNowButton = new ToolbarButton( ImageUtil .getThemeableImage( "icon-small", "icon-execute" ) ); private ToolbarButton scheduleRemoveButton = new ToolbarButton( ImageUtil.getThemeableImage( "pentaho-deletebutton" ) ); private ToolbarButton filterButton = new ToolbarButton( ImageUtil.getThemeableImage( "icon-small", "icon-filter-add" ) ); private ToolbarButton filterRemoveButton = new ToolbarButton( ImageUtil.getThemeableImage( "icon-small", "icon-filter-remove" ) ); private JsArray<JsJob> allJobs; private ArrayList<IJobFilter> filters = new ArrayList<IJobFilter>(); private CellTable<JsJob> table = new CellTable<JsJob>( PAGE_SIZE, (CellTableResources) GWT .create( CellTableResources.class ) ); private ListDataProvider<JsJob> dataProvider = new ListDataProvider<JsJob>(); private SimplePager pager; private FilterDialog filterDialog; private IDialogCallback filterDialogCallback = new IDialogCallback() { public void okPressed() { filters.clear(); // create filters if ( filterDialog.getAfterDate() != null ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getNextRun().after( filterDialog.getAfterDate() ); } } ); } if ( filterDialog.getBeforeDate() != null ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getNextRun().before( filterDialog.getBeforeDate() ); } } ); } if ( !StringUtils.isEmpty( filterDialog.getResourceName() ) ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getShortResourceName().toLowerCase().contains( filterDialog.getResourceName().toLowerCase() ); } } ); } final String showAll = Messages.getString( "showAll" ); if ( !StringUtils.isEmpty( filterDialog.getUserFilter() ) && !filterDialog.getUserFilter().equals( showAll ) ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getUserName().equalsIgnoreCase( filterDialog.getUserFilter() ); } } ); } if ( !StringUtils.isEmpty( filterDialog.getStateFilter() ) && !filterDialog.getStateFilter().equals( showAll ) ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getState().toLowerCase().equalsIgnoreCase( filterDialog.getStateFilter() ); } } ); } if ( !StringUtils.isEmpty( filterDialog.getTypeFilter() ) && !filterDialog.getTypeFilter().equals( showAll ) ) { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return job.getJobTrigger().getScheduleType().equalsIgnoreCase( filterDialog.getTypeFilter() ); } } ); } filterRemoveButton.setEnabled( filters.size() > 0 ); filterAndShowData(); } public void cancelPressed() { } }; @SuppressWarnings ( "unchecked" ) private Set<JsJob> getSelectedJobs() { Set<JsJob> selectedJobs = ( (MultiSelectionModel<JsJob>) table.getSelectionModel() ).getSelectedSet(); return selectedJobs; } private IDialogCallback scheduleDialogCallback = new IDialogCallback() { public void okPressed() { refresh(); MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "scheduleUpdatedTitle" ), Messages.getString( "scheduleUpdatedMessage" ), false, false, true ); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ dialogBox.center(); } public void cancelPressed() { } }; public SchedulesPanel( final boolean isAdmin, final boolean isScheduler ) { createUI( isAdmin, isScheduler ); refresh(); } public void refresh() { String moduleBaseURL = GWT.getModuleBaseURL(); String moduleName = GWT.getModuleName(); String contextURL = moduleBaseURL.substring( 0, moduleBaseURL.lastIndexOf( moduleName ) ); final String url = contextURL + "api/scheduler/jobs"; //$NON-NLS-1$ RequestBuilder executableTypesRequestBuilder = new RequestBuilder( RequestBuilder.GET, url ); executableTypesRequestBuilder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); executableTypesRequestBuilder.setHeader( "accept", "application/json" ); try { executableTypesRequestBuilder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == Response.SC_OK ) { allJobs = parseJson( JsonUtils.escapeJsonForEval( response.getText() ) ); filterAndShowData(); } } } ); } catch ( RequestException e ) { // showError(e); } } private void filterAndShowData() { filters.add( new IJobFilter() { public boolean accept( JsJob job ) { return !job.getFullResourceName().equals( "GeneratedContentCleaner" ); } } ); ArrayList<JsJob> filteredList = new ArrayList<JsJob>(); for ( int i = 0; i < allJobs.length(); i++ ) { filteredList.add( allJobs.get( i ) ); // filter if needed for ( IJobFilter filter : filters ) { if ( !filter.accept( allJobs.get( i ) ) ) { filteredList.remove( allJobs.get( i ) ); } } } List<JsJob> list = dataProvider.getList(); list.clear(); list.addAll( filteredList ); pager.setVisible( filteredList.size() > PAGE_SIZE ); for ( JsJob job : filteredList ) { table.getSelectionModel().setSelected( job, false ); } editButton.setEnabled( false ); controlScheduleButton.setEnabled( false ); scheduleRemoveButton.setEnabled( false ); triggerNowButton.setEnabled( false ); table.setPageStart( 0 ); table.redraw(); } private void updateControlSchedulerButtonState( final ToolbarButton controlSchedulerButton, final boolean isScheduler ) { final String url = GWT.getHostPageBaseURL() + "api/scheduler/state"; //$NON-NLS-1$ RequestBuilder builder = new RequestBuilder( RequestBuilder.GET, url ); builder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); try { builder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { boolean isRunning = "RUNNING".equalsIgnoreCase( response.getText() ); if ( isRunning ) { controlSchedulerButton.setToolTip( Messages.getString( "stopScheduler" ) ); controlSchedulerButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-stop-scheduler" ) ); } else { controlSchedulerButton.setToolTip( Messages.getString( "startScheduler" ) ); controlSchedulerButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-start-scheduler" ) ); } if ( !isScheduler ) { controlSchedulerButton.setEnabled( false ); } else { controlSchedulerButton.setEnabled( true ); } } } ); } catch ( RequestException e ) { // showError(e); } } private void toggleSchedulerOnOff( final ToolbarButton controlSchedulerButton, final boolean isScheduler ) { final String url = GWT.getHostPageBaseURL() + "api/scheduler/state"; //$NON-NLS-1$ RequestBuilder builder = new RequestBuilder( RequestBuilder.GET, url ); builder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); try { builder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { boolean isRunning = "RUNNING".equalsIgnoreCase( response.getText() ); if ( isRunning ) { controlScheduler( controlSchedulerButton, "pause", isScheduler ); } else { controlScheduler( controlSchedulerButton, "start", isScheduler ); } } } ); } catch ( RequestException e ) { // showError(e); } } private void createUI( boolean isAdmin, final boolean isScheduler ) { table.getElement().setId( "schedule-table" ); table.setStylePrimaryName( "pentaho-table" ); table.setWidth( "100%", true ); // BISERVER-9331 Column sort indicators should be to the right of header text in the Manage Schedules table. if ( table.getHeaderBuilder() instanceof AbstractHeaderOrFooterBuilder ) { ( (AbstractHeaderOrFooterBuilder<JsJob>) table.getHeaderBuilder() ).setSortIconStartOfLine( false ); } final MultiSelectionModel<JsJob> selectionModel = new MultiSelectionModel<JsJob>( new ProvidesKey<JsJob>() { public Object getKey( JsJob item ) { return item.getJobId(); } } ); table.setSelectionModel( selectionModel ); Label noDataLabel = new Label( Messages.getString( "noSchedules" ) ); noDataLabel.setStyleName( "noDataForScheduleTable" ); table.setEmptyTableWidget( noDataLabel ); TextColumn<JsJob> idColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { return job.getJobId(); } }; idColumn.setSortable( true ); TextColumn<JsJob> nameColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { return job.getJobName(); } }; nameColumn.setSortable( true ); HtmlColumn<JsJob> resourceColumn = new HtmlColumn<JsJob>() { @Override public String getStringValue( JsJob job ) { String name = job.getFullResourceName().split( "\\." )[0]; return name.replaceAll( "/", "/<wbr/>" ); } }; resourceColumn.setSortable( true ); HtmlColumn<JsJob> outputPathColumn = new HtmlColumn<JsJob>( new ClickableSafeHtmlCell() ) { @Override public String getStringValue( JsJob jsJob ) { try { String outputPath = jsJob.getOutputPath(); if ( StringUtils.isEmpty( outputPath ) ) { return "-"; } else { outputPath = new SafeHtmlBuilder().appendEscaped( outputPath ).toSafeHtml().asString(); return MessageFormat.format( "<span class=''workspace-resource-link'' title=''{0}''>{0}</span>", outputPath ); } } catch ( Throwable t ) { return "-"; } } }; outputPathColumn.setFieldUpdater( new FieldUpdater<JsJob, SafeHtml>() { @Override public void update( final int index, final JsJob jsJob, final SafeHtml value ) { if ( !value.equals( "-" ) ) { final Command errorCallback = new Command() { @Override public void execute() { showValidateOutputLocationError(); } }; final Command successCallback = new Command() { @Override public void execute() { openOutputLocation( jsJob.getOutputPath() ); } }; OutputLocationUtils.validateOutputLocation( jsJob.getOutputPath(), successCallback, errorCallback ); } } } ); outputPathColumn.setSortable( true ); TextColumn<JsJob> scheduleColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { try { return job.getJobTrigger().getDescription(); } catch ( Throwable t ) { return "-"; } } }; scheduleColumn.setSortable( true ); TextColumn<JsJob> userNameColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { try { return job.getUserName(); } catch ( Throwable t ) { return "-"; } } }; userNameColumn.setSortable( true ); TextColumn<JsJob> stateColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { try { // BISERVER-9965 final String jobState = "COMPLETE".equalsIgnoreCase( job.getState() ) ? "FINISHED" : job.getState(); // not css text-transform because tooltip will use pure text from the cell return jobState.substring( 0, 1 ).toUpperCase() + jobState.substring( 1 ).toLowerCase(); } catch ( Throwable t ) { return "-"; } } }; stateColumn.setSortable( true ); TextColumn<JsJob> nextFireColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { try { Date date = job.getNextRun(); if ( date == null ) { return "-"; } DateTimeFormat format = DateTimeFormat.getFormat( PredefinedFormat.DATE_TIME_MEDIUM ); return format.format( date ); } catch ( Throwable t ) { return "-"; } } }; nextFireColumn.setSortable( true ); TextColumn<JsJob> lastFireColumn = new TextColumn<JsJob>() { public String getValue( JsJob job ) { try { Date date = job.getLastRun(); if ( date == null ) { return "-"; } DateTimeFormat format = DateTimeFormat.getFormat( PredefinedFormat.DATE_TIME_MEDIUM ); return format.format( date ); } catch ( Throwable t ) { return "-"; } } }; lastFireColumn.setSortable( true ); // table.addColumn(idColumn, "ID"); table.addColumn( nameColumn, Messages.getString( "scheduleName" ) ); table.addColumn( scheduleColumn, Messages.getString( "recurrence" ) ); table.addColumn( resourceColumn, Messages.getString( "sourceFile" ) ); table.addColumn( outputPathColumn, Messages.getString( "outputPath" ) ); table.addColumn( lastFireColumn, Messages.getString( "lastFire" ) ); table.addColumn( nextFireColumn, Messages.getString( "nextFire" ) ); if ( isAdmin ) { table.addColumn( userNameColumn, Messages.getString( "user" ) ); } table.addColumn( stateColumn, Messages.getString( "state" ) ); table.addColumnStyleName( 0, "backgroundContentHeaderTableCell" ); table.addColumnStyleName( 1, "backgroundContentHeaderTableCell" ); table.addColumnStyleName( 2, "backgroundContentHeaderTableCell" ); table.addColumnStyleName( 3, "backgroundContentHeaderTableCell" ); table.addColumnStyleName( 4, "backgroundContentHeaderTableCell" ); table.addColumnStyleName( 5, "backgroundContentHeaderTableCell" ); if ( isAdmin ) { table.addColumnStyleName( 6, "backgroundContentHeaderTableCell" ); } table.addColumnStyleName( isAdmin ? 7 : 6, "backgroundContentHeaderTableCell" ); table.setColumnWidth( nameColumn, 160, Unit.PX ); table.setColumnWidth( resourceColumn, 200, Unit.PX ); table.setColumnWidth( outputPathColumn, 180, Unit.PX ); table.setColumnWidth( scheduleColumn, 170, Unit.PX ); table.setColumnWidth( lastFireColumn, 120, Unit.PX ); table.setColumnWidth( nextFireColumn, 120, Unit.PX ); if ( isAdmin ) { table.setColumnWidth( userNameColumn, 100, Unit.PX ); } table.setColumnWidth( stateColumn, 90, Unit.PX ); dataProvider.addDataDisplay( table ); List<JsJob> list = dataProvider.getList(); ListHandler<JsJob> columnSortHandler = new ListHandler<JsJob>( list ); columnSortHandler.setComparator( idColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { return ( o2 != null ) ? o1.getJobId().compareTo( o2.getJobId() ) : 1; } return -1; } } ); columnSortHandler.setComparator( nameColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { return ( o2 != null ) ? o1.getJobName().compareTo( o2.getJobName() ) : 1; } return -1; } } ); columnSortHandler.setComparator( resourceColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { String r1 = o1.getShortResourceName(); String r2 = null; if ( o2 != null ) { r2 = o2.getShortResourceName(); } return ( o2 != null ) ? r1.compareTo( r2 ) : 1; } return -1; } } ); columnSortHandler.setComparator( outputPathColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { String r1 = o1.getOutputPath(); String r2 = null; if ( o2 != null ) { r2 = o2.getOutputPath(); } return ( o2 != null ) ? r1.compareTo( r2 ) : 1; } return -1; } } ); columnSortHandler.setComparator( scheduleColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { String s1 = o1.getJobTrigger().getDescription(); String s2 = o2.getJobTrigger().getDescription(); return s1.compareTo( s2 ); } } ); columnSortHandler.setComparator( userNameColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { return ( o2 != null ) ? o1.getUserName().compareTo( o2.getUserName() ) : 1; } return -1; } } ); columnSortHandler.setComparator( stateColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 != null ) { return ( o2 != null ) ? o1.getState().compareTo( o2.getState() ) : 1; } return -1; } } ); columnSortHandler.setComparator( nextFireColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 == null || o1.getNextRun() == null ) { return -1; } if ( o2 == null || o2.getNextRun() == null ) { return 1; } if ( o1.getNextRun() == o2.getNextRun() ) { return 0; } return o1.getNextRun().compareTo( o2.getNextRun() ); } } ); columnSortHandler.setComparator( lastFireColumn, new Comparator<JsJob>() { public int compare( JsJob o1, JsJob o2 ) { if ( o1 == o2 ) { return 0; } if ( o1 == null || o1.getLastRun() == null ) { return -1; } if ( o2 == null || o2.getLastRun() == null ) { return 1; } if ( o1.getLastRun() == o2.getLastRun() ) { return 0; } return o1.getLastRun().compareTo( o2.getLastRun() ); } } ); table.addColumnSortHandler( columnSortHandler ); table.getColumnSortList().push( idColumn ); table.getColumnSortList().push( resourceColumn ); table.getColumnSortList().push( outputPathColumn ); table.getColumnSortList().push( nameColumn ); table.getSelectionModel().addSelectionChangeHandler( new Handler() { public void onSelectionChange( SelectionChangeEvent event ) { Set<JsJob> selectedJobs = getSelectedJobs(); if ( selectedJobs != null && selectedJobs.size() > 0 ) { JsJob[] jobs = selectedJobs.toArray( new JsJob[selectedJobs.size()] ); editButton.setEnabled( isScheduler ); if ( "NORMAL".equalsIgnoreCase( jobs[0].getState() ) ) { controlScheduleButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-stop" ) ); } else { controlScheduleButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-run" ) ); } controlScheduleButton.setEnabled( isScheduler ); boolean isRunning = "NORMAL".equalsIgnoreCase( jobs[0].getState() ); controlScheduleButton.setToolTip( isRunning ? Messages.getString( "stop" ) : Messages.getString( "start" ) ); scheduleRemoveButton.setEnabled( isScheduler ); triggerNowButton.setEnabled( isScheduler ); } else { editButton.setEnabled( false ); controlScheduleButton.setEnabled( false ); scheduleRemoveButton.setEnabled( false ); triggerNowButton.setEnabled( false ); } } } ); // BISERVER-9965 table.addCellPreviewHandler( new CellPreviewEvent.Handler<JsJob>() { @Override public void onCellPreview( CellPreviewEvent<JsJob> event ) { if ( "mouseover".equals( event.getNativeEvent().getType() ) ) { final TableCellElement cell = table.getRowElement( event.getIndex() ).getCells().getItem( event.getColumn() ); cell.setTitle( cell.getInnerText() ); } } } ); SimplePager.Resources pagerResources = GWT.create( SimplePager.Resources.class ); pager = new SimplePager( TextLocation.CENTER, pagerResources, false, 0, true ) { @Override public void setPageStart( int index ) { if ( getDisplay() != null ) { Range range = getDisplay().getVisibleRange(); int pageSize = range.getLength(); // Removed the min to show fixed ranges // if (isRangeLimited && display.isRowCountExact()) { // index = Math.min(index, display.getRowCount() - pageSize); // } index = Math.max( 0, index ); if ( index != range.getStart() ) { getDisplay().setVisibleRange( index, pageSize ); } } } }; pager.setDisplay( table ); // pager.setRangeLimited(false); VerticalPanel tableAndPager = new VerticalPanel(); tableAndPager.setHorizontalAlignment( HasHorizontalAlignment.ALIGN_CENTER ); Toolbar bar = new Toolbar(); bar.addSpacer( 10 ); bar.add( Toolbar.GLUE ); // Add control scheduler button if ( isAdmin ) { final ToolbarButton controlSchedulerButton = new ToolbarButton( ImageUtil.getThemeableImage( "icon-small", "icon-start-scheduler" ) ); controlSchedulerButton.setCommand( new Command() { public void execute() { toggleSchedulerOnOff( controlSchedulerButton, isScheduler ); } } ); updateControlSchedulerButtonState( controlSchedulerButton, isScheduler ); bar.add( controlSchedulerButton ); bar.addSpacer( 20 ); } // Add filter button filterButton.setCommand( new Command() { public void execute() { if ( filterDialog == null ) { filterDialog = new FilterDialog( allJobs, filterDialogCallback ); } else { filterDialog.initUI( allJobs ); } filterDialog.center(); } } ); filterButton.setToolTip( Messages.getString( "filterSchedules" ) ); if ( isAdmin ) { bar.add( filterButton ); } // Add remove filters button filterRemoveButton.setCommand( new Command() { public void execute() { filterDialog = null; filters.clear(); filterAndShowData(); filterRemoveButton.setEnabled( false ); filterButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-filter-add" ) ); } } ); filterRemoveButton.setToolTip( Messages.getString( "removeFilters" ) ); filterRemoveButton.setEnabled( filters.size() > 0 ); if ( isAdmin ) { bar.add( filterRemoveButton ); } // Add refresh button ToolbarButton refresh = new ToolbarButton( ImageUtil.getThemeableImage( "icon-small", "icon-refresh" ) ); refresh.setToolTip( Messages.getString( "refreshTooltip" ) ); refresh.setCommand( new Command() { public void execute() { RefreshSchedulesCommand cmd = new RefreshSchedulesCommand(); cmd.execute(); } } ); bar.add( refresh ); bar.addSpacer( 20 ); // Add execute now button triggerNowButton.setToolTip( Messages.getString( "executeNow" ) ); triggerNowButton.setCommand( new Command() { public void execute() { Set<JsJob> selectedJobs = getSelectedJobs(); if ( selectedJobs != null && selectedJobs.size() > 0 ) { MessageDialogBox messageDialog = new MessageDialogBox( Messages.getString( "executeNow" ), Messages.getString( "executeNowStarted" ), false, true, true ); messageDialog.setCallback( new IDialogCallback() { public void okPressed() { // wait a little to refresh to give schedule time to update the last run Timer t = new Timer() { public void run() { refresh(); } }; t.schedule( 2000 ); } public void cancelPressed() { } } ); messageDialog.center(); controlJobs( selectedJobs, "triggerNow", RequestBuilder.POST, false ); } } } ); triggerNowButton.setEnabled( false ); bar.add( triggerNowButton ); // Add control schedule button controlScheduleButton.setCommand( new Command() { public void execute() { Set<JsJob> selectedJobs = getSelectedJobs(); if ( selectedJobs != null && selectedJobs.size() > 0 ) { JsJob[] jobs = selectedJobs.toArray( new JsJob[selectedJobs.size()] ); if ( "NORMAL".equals( jobs[0].getState() ) ) { controlJobs( selectedJobs, "pauseJob", RequestBuilder.POST, false ); } else { controlJobs( selectedJobs, "resumeJob", RequestBuilder.POST, false ); } } } } ); controlScheduleButton.setEnabled( false ); bar.add( controlScheduleButton ); bar.addSpacer( 20 ); // Add edit button editButton.setCommand( new Command() { public void execute() { Set<JsJob> selectedJobs = getSelectedJobs(); if ( selectedJobs != null && selectedJobs.size() > 0 ) { JsJob[] jobs = selectedJobs.toArray( new JsJob[selectedJobs.size()] ); final JsJob editJob = jobs[0]; final String url = GWT.getHostPageBaseURL() + "api/repo/files/" + SolutionBrowserPanel.pathToId( editJob.getFullResourceName() ) + "/canAccess?cb=" + System.currentTimeMillis() + "&permissions=" + READ_PERMISSION; RequestBuilder executableTypesRequestBuilder = new RequestBuilder( RequestBuilder.GET, url ); try { executableTypesRequestBuilder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); executableTypesRequestBuilder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { promptForScheduleResourceError( editJob ); } public void onResponseReceived( Request request, Response response ) { if ( "true".equalsIgnoreCase( response.getText() ) ) { editJob( editJob ); } else { promptForScheduleResourceError( editJob ); } } } ); } catch ( RequestException e ) { // showError(e); } } } } ); editButton.setEnabled( false ); editButton.setToolTip( Messages.getString( "editTooltip" ) ); bar.add( editButton ); // Add remove button scheduleRemoveButton.setCommand( new Command() { public void execute() { Set<JsJob> selectedJobs = getSelectedJobs(); if ( selectedJobs != null && selectedJobs.size() > 0 ) { final PromptDialogBox prompt = new PromptDialogBox( Messages.getString( "warning" ), Messages.getString( "yes" ), Messages .getString( "no" ), false, true ); prompt.setContent( new Label( Messages.getString( "deleteConfirmSchedles", "" + selectedJobs.size() ) ) ); prompt.setCallback( new IDialogCallback() { public void okPressed() { controlJobs( getSelectedJobs(), "removeJob", RequestBuilder.DELETE, true ); prompt.hide(); } public void cancelPressed() { prompt.hide(); } } ); prompt.center(); } } } ); scheduleRemoveButton.setToolTip( Messages.getString( "remove" ) ); scheduleRemoveButton.setEnabled( false ); bar.add( scheduleRemoveButton ); tableAndPager.add( bar ); tableAndPager.add( table ); tableAndPager.add( pager ); // Add it to the root panel. setWidget( tableAndPager ); } private void editJob( JsJob editJob ) { final String url = GWT.getHostPageBaseURL() + "api/scheduler/jobinfo?jobId=" + URL.encodeQueryString( editJob.getJobId() ); RequestBuilder executableTypesRequestBuilder = new RequestBuilder( RequestBuilder.GET, url ); executableTypesRequestBuilder.setHeader( "accept", "application/json" ); executableTypesRequestBuilder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); try { executableTypesRequestBuilder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == Response.SC_OK ) { final JsJob jsJob = parseJsonJob( JsonUtils.escapeJsonForEval( response.getText() ) ); // check email is setup RequestBuilder emailValidRequest = new RequestBuilder( RequestBuilder.GET, GWT.getHostPageBaseURL() + "api/emailconfig/isValid" ); emailValidRequest.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); emailValidRequest.setHeader( "accept", "text/plain" ); try { emailValidRequest.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), exception.toString(), false, false, true ); //$NON-NLS-1$ dialogBox.center(); } public void onResponseReceived( Request request, Response response ) { if ( response.getStatusCode() == Response.SC_OK ) { final boolean isEmailConfValid = Boolean.parseBoolean( response.getText() ); final NewScheduleDialog schedDialog = new NewScheduleDialog( jsJob, scheduleDialogCallback, isEmailConfValid ); schedDialog.center(); } } } ); } catch ( RequestException e ) { // showError(e); } } else { MessageDialogBox dialogBox = new MessageDialogBox( Messages.getString( "error" ), Messages.getString( "serverErrorColon" ) + " " + response.getStatusCode(), false, false, true ); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ dialogBox.center(); } } } ); } catch ( RequestException e ) { // showError(e); } } private void promptForScheduleResourceError( final JsJob job ) { final PromptDialogBox prompt = new PromptDialogBox( Messages.getString( "fileUnavailable" ), Messages.getString( "yesDelete" ), Messages .getString( "no" ), false, true ); prompt.setContent( new HTML( Messages.getString( "editScheduleResourceDoesNotExist", job.getFullResourceName() ) ) ); prompt.setCallback( new IDialogCallback() { public void okPressed() { HashSet<JsJob> jobSet = new HashSet<JsJob>(); jobSet.add( job ); controlJobs( jobSet, "removeJob", RequestBuilder.DELETE, true ); prompt.hide(); } public void cancelPressed() { prompt.hide(); } } ); prompt.setWidth( "530px" ); prompt.center(); } private void controlJobs( final Set<JsJob> jobs, String function, final Method method, final boolean refreshData ) { for ( final JsJob job : jobs ) { final String url = GWT.getHostPageBaseURL() + "api/scheduler/" + function; //$NON-NLS-1$ RequestBuilder builder = new RequestBuilder( method, url ); builder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); builder.setHeader( "Content-Type", "application/json" ); //$NON-NLS-1$//$NON-NLS-2$ JSONObject startJobRequest = new JSONObject(); startJobRequest.put( "jobId", new JSONString( job.getJobId() ) ); //$NON-NLS-1$ try { builder.sendRequest( startJobRequest.toString(), new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { job.setState( response.getText() ); table.redraw(); boolean isRunning = "NORMAL".equalsIgnoreCase( response.getText() ); if ( isRunning ) { controlScheduleButton.setToolTip( Messages.getString( "stop" ) ); controlScheduleButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-stop" ) ); } else { controlScheduleButton.setToolTip( Messages.getString( "start" ) ); controlScheduleButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-run" ) ); } if ( refreshData ) { refresh(); } } } ); } catch ( RequestException e ) { // showError(e); } } } private void controlScheduler( final ToolbarButton controlSchedulerButton, final String function, final boolean isScheduler ) { final String url = GWT.getHostPageBaseURL() + "api/scheduler/" + function; //$NON-NLS-1$ RequestBuilder builder = new RequestBuilder( RequestBuilder.POST, url ); builder.setHeader( "If-Modified-Since", "01 Jan 1970 00:00:00 GMT" ); try { builder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { // showError(exception); } public void onResponseReceived( Request request, Response response ) { boolean isRunning = "RUNNING".equalsIgnoreCase( response.getText() ); if ( isRunning ) { controlSchedulerButton.setToolTip( Messages.getString( "stopScheduler" ) ); controlSchedulerButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-stop-scheduler" ) ); } else { controlSchedulerButton.setToolTip( Messages.getString( "startScheduler" ) ); controlSchedulerButton.setImage( ImageUtil.getThemeableImage( "icon-small", "icon-start-scheduler" ) ); } if ( !isScheduler ) { controlSchedulerButton.setEnabled( false ); } else { controlSchedulerButton.setEnabled( true ); } } } ); } catch ( RequestException e ) { // showError(e); } } private void openOutputLocation( final String outputLocation ) { final String url = GWT.getHostPageBaseURL() + "api/mantle/session-variable?key=scheduler_folder&value=" + outputLocation; PerspectiveManager.getInstance().setPerspective( PerspectiveManager.BROWSER_PERSPECTIVE ); RequestBuilder executableTypesRequestBuilder = new RequestBuilder( RequestBuilder.POST, url ); try { executableTypesRequestBuilder.sendRequest( null, new RequestCallback() { public void onError( Request request, Throwable exception ) { } public void onResponseReceived( Request request, Response response ) { } } ); } catch ( RequestException e ) { //IGNORE } GenericEvent event = new GenericEvent(); event.setEventSubType( "RefreshFolderEvent" ); event.setStringParam( outputLocation ); EventBusUtil.EVENT_BUS.fireEvent( event ); } private void showValidateOutputLocationError() { String title = Messages.getString( "outputLocationErrorTitle" ); String message = Messages.getString( "outputLocationErrorMessage" ); MessageDialogBox dialogBox = new MessageDialogBox( title, message, false, false, true, Messages.getString( "close" ), null, null ); //$NON-NLS-1$ dialogBox.addStyleName( "pentaho-dialog-small" ); dialogBox.center(); } private native JsArray<JsJob> parseJson( String json ) /*-{ var obj = JSON.parse(json); if (obj != null && obj.hasOwnProperty("job")) { return obj.job; } return []; }-*/; private native JsJob parseJsonJob( String json ) /*-{ var obj = JSON.parse(json); return obj; }-*/; }