/*
* Copyright (C) 2015 Jan Pokorsky
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.webapp.client.widget.workflow;
import com.smartgwt.client.data.AdvancedCriteria;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.RecordList;
import com.smartgwt.client.data.ResultSet;
import com.smartgwt.client.types.CriteriaPolicy;
import com.smartgwt.client.types.FetchMode;
import com.smartgwt.client.types.OperatorId;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionUpdatedEvent;
import com.smartgwt.client.widgets.grid.events.SelectionUpdatedHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.toolbar.ToolStrip;
import cz.cas.lib.proarc.webapp.client.ClientMessages;
import cz.cas.lib.proarc.webapp.client.ClientUtils;
import cz.cas.lib.proarc.webapp.client.Editor;
import cz.cas.lib.proarc.webapp.client.action.AbstractAction;
import cz.cas.lib.proarc.webapp.client.action.ActionEvent;
import cz.cas.lib.proarc.webapp.client.action.Actions;
import cz.cas.lib.proarc.webapp.client.action.Actions.ActionSource;
import cz.cas.lib.proarc.webapp.client.action.RefreshAction;
import cz.cas.lib.proarc.webapp.client.action.RefreshAction.Refreshable;
import cz.cas.lib.proarc.webapp.client.ds.UserDataSource;
import cz.cas.lib.proarc.webapp.client.ds.WorkflowJobDataSource;
import cz.cas.lib.proarc.webapp.client.ds.WorkflowProfileDataSource;
import cz.cas.lib.proarc.webapp.client.presenter.WorkflowJobsEditor;
import cz.cas.lib.proarc.webapp.client.widget.ListGridPersistance;
/**
*
* @author Jan Pokorsky
*/
public class WorkflowJobView implements Refreshable {
private final ClientMessages i18n;
private final Canvas widget;
private ListGrid jobGrid;
private ListGridPersistance jobsPersistance;
private WorkflowJobFormView jobFormView;
private WorkflowJobsEditor handler;
private final ActionSource actionSource = new ActionSource(this);
private boolean isUpdateOperation;
private boolean isDataInitialized;
private ListGridRecord lastSelection;
public WorkflowJobView(ClientMessages i18n) {
this.i18n = i18n;
this.widget = createMainLayout();
}
public Canvas getWidget() {
return widget;
}
private void init() {
if (!isDataInitialized) {
isDataInitialized = true;
jobGrid.fetchData(jobsPersistance.getFilterCriteria());
}
}
public void edit(String jobId) {
if (jobId == null) {
init();
return ;
}
int jobRec = jobGrid.findIndex(
new AdvancedCriteria(WorkflowJobDataSource.FIELD_ID, OperatorId.EQUALS, jobId));
if (jobRec >= 0) {
jobGrid.selectSingleRecord(jobRec);
jobGrid.scrollToRow(jobRec);
} else {
lastSelection = null;
jobGrid.deselectAllRecords();
Record r = new Record();
r.setAttribute(WorkflowJobDataSource.FIELD_ID, jobId);
jobFormView.setJob(r);
}
}
public void setHandler(WorkflowJobsEditor handler) {
this.handler = handler;
jobFormView.setHandler(handler);
}
@Override
public void refresh() {
if (isDataInitialized) {
jobGrid.invalidateCache();
} else {
init();
}
}
public void editSelection() {
jobFormView.setJob(jobGrid.getSelectedRecord());
refreshState();
}
public void refreshState() {
actionSource.fireEvent();
jobFormView.refreshState();
}
/**
* Set to {@code true} before saving a job. It is a hack not to select
* the job again inside {@code onDataArrived}.
*/
public void setExpectUpdateOperation(boolean isUpdateOperation) {
this.isUpdateOperation = isUpdateOperation;
}
private Canvas createMainLayout() {
VLayout main = new VLayout();
main.addMember(createPanelLabel());
// filter
main.addMember(createFilter());
// list + item
main.addMember(createJobLayout());
return main;
}
private Canvas createJobLayout() {
VLayout left = new VLayout();
left.addMember(createJobsToolbar());
left.addMember(createJobList());
HLayout l = new HLayout();
l.addMember(left);
l.addMember(createJobFormLayout());
return l;
}
private Label createPanelLabel() {
Label lblHeader = new Label();
String title = ClientUtils.format("<b>%s</b>", i18n.WorkflowJob_View_Title());
lblHeader.setContents(title);
lblHeader.setAutoHeight();
lblHeader.setPadding(4);
lblHeader.setStyleName(Editor.CSS_PANEL_DESCRIPTION_TITLE);
return lblHeader;
}
private DynamicForm createFilter() {
DynamicForm form = new DynamicForm();
form.setBrowserSpellCheck(false);
form.setValidateOnExit(true);
form.setSaveOnEnter(true);
form.setAutoHeight();
form.setWidth100();
form.setNumCols(3);
// ????
return form;
}
private ToolStrip createJobsToolbar() {
ToolStrip toolbar = Actions.createToolStrip();
RefreshAction refreshAction = new RefreshAction(i18n);
AbstractAction addAction = new AbstractAction(i18n.WorkflowJob_View_NewAction_Title(),
"[SKIN]/actions/add.png", i18n.WorkflowJob_View_NewAction_Hint()) {
@Override
public void performAction(ActionEvent event) {
if (handler != null) {
handler.onCreateNew();
}
}
};
toolbar.addMember(Actions.asIconButton(refreshAction, this));
toolbar.addMember(Actions.asIconButton(addAction, this));
return toolbar;
}
private ListGrid createJobList() {
jobGrid = new ListGrid();
jobsPersistance = new ListGridPersistance("WorkflowJobView.jobList", jobGrid);
jobGrid.setSelectionType(SelectionStyle.SINGLE);
jobGrid.setShowFilterEditor(true);
jobGrid.setAllowFilterOperators(false);
jobGrid.setFilterOnKeypress(true);
jobGrid.setFilterLocalData(false);
jobGrid.setCanSort(true);
jobGrid.setCanGroupBy(false);
jobGrid.setDataFetchMode(FetchMode.PAGED);
ResultSet rs = new ResultSet();
rs.setCriteriaPolicy(CriteriaPolicy.DROPONCHANGE);
rs.setUseClientFiltering(false);
rs.setUseClientSorting(false);
jobGrid.setDataProperties(rs);
jobGrid.setDataSource(WorkflowJobDataSource.getInstance(),
new ListGridField(WorkflowJobDataSource.FIELD_LABEL),
new ListGridField(WorkflowJobDataSource.FIELD_ID, 30),
new ListGridField(WorkflowJobDataSource.FIELD_STATE, 50),
new ListGridField(WorkflowJobDataSource.FIELD_PROFILE_ID, 80),
new ListGridField(WorkflowJobDataSource.FIELD_OWNER, 50),
new ListGridField(WorkflowJobDataSource.FIELD_PRIORITY, 60),
new ListGridField(WorkflowJobDataSource.FIELD_CREATED, 100),
new ListGridField(WorkflowJobDataSource.FIELD_MODIFIED, 100),
new ListGridField(WorkflowJobDataSource.FIELD_FINANCED, 100),
new ListGridField(WorkflowJobDataSource.FIELD_NOTE)
);
jobGrid.getField(WorkflowJobDataSource.FIELD_LABEL).setWidth("80%");
jobGrid.getField(WorkflowJobDataSource.FIELD_LABEL).setFilterOnKeypress(false);
jobGrid.getField(WorkflowJobDataSource.FIELD_STATE).setCanSort(false);
jobGrid.getField(WorkflowJobDataSource.FIELD_PROFILE_ID).setCanSort(false);
SelectItem profileFilter = new SelectItem();
profileFilter.setOptionDataSource(WorkflowProfileDataSource.getInstance());
profileFilter.setValueField(WorkflowProfileDataSource.FIELD_ID);
profileFilter.setDisplayField(WorkflowProfileDataSource.FIELD_LABEL);
jobGrid.getField(WorkflowJobDataSource.FIELD_PROFILE_ID).setFilterEditorProperties(profileFilter);
jobGrid.getField(WorkflowJobDataSource.FIELD_OWNER).setCanSort(false);
SelectItem owner = new SelectItem();
owner.setOptionDataSource(UserDataSource.getInstance());
owner.setValueField(UserDataSource.FIELD_ID);
owner.setDisplayField(UserDataSource.FIELD_USERNAME);
jobGrid.getField(WorkflowJobDataSource.FIELD_OWNER).setFilterEditorProperties(owner);
jobGrid.getField(WorkflowJobDataSource.FIELD_FINANCED).setCanFilter(false);
jobGrid.getField(WorkflowJobDataSource.FIELD_FINANCED).setCanSort(false);
jobGrid.getField(WorkflowJobDataSource.FIELD_NOTE).setCanFilter(false);
jobGrid.getField(WorkflowJobDataSource.FIELD_NOTE).setCanSort(false);
jobGrid.addDataArrivedHandler(new DataArrivedHandler() {
@Override
public void onDataArrived(DataArrivedEvent event) {
if (isUpdateOperation) {
isUpdateOperation = false;
return ;
}
int startRow = event.getStartRow();
int endRow = event.getEndRow();
if (startRow == 0 && endRow >= 0) {
jobGrid.focus();
updateSelection();
} else if (endRow < 0) {
jobGrid.deselectAllRecords();
}
}
});
jobGrid.addSelectionUpdatedHandler(new SelectionUpdatedHandler() {
@Override
public void onSelectionUpdated(SelectionUpdatedEvent event) {
lastSelection = jobGrid.getSelectedRecord();
editSelection();
}
});
jobGrid.setViewState(jobsPersistance.getViewState());
return jobGrid;
}
private void updateSelection() {
RecordList rl = jobGrid.getRecordList();
if (rl.isEmpty()) {
return ;
}
if (lastSelection == null) {
jobGrid.selectSingleRecord(0);
return ;
}
Record newRec = rl.find(WorkflowJobDataSource.FIELD_ID,
lastSelection.getAttribute(WorkflowJobDataSource.FIELD_ID));
if (newRec != null) {
jobGrid.selectSingleRecord(newRec);
int rowNum = jobGrid.getRecordIndex(newRec);
if (rowNum >= 0) {
jobGrid.scrollToRow(rowNum);
}
}
}
private Canvas createJobFormLayout() {
jobFormView = new WorkflowJobFormView(i18n);
return jobFormView.getWidget();
}
}