/******************************************************************************* * Copyright (c) 2012 Dmitry Tikhomirov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Dmitry Tikhomirov - initial API and implementation ******************************************************************************/ package org.opensheet.client.widges; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import org.opensheet.client.dto.UserDTO; import org.opensheet.client.dto.grid.HourFolder; import org.opensheet.client.l10n.OpensheetConstants; import org.opensheet.client.l10n.OpensheetMessages; import org.opensheet.client.mvc.events.EventBus; import org.opensheet.client.mvc.events.SheetPanelEvent; import org.opensheet.client.services.AssignmentService; import org.opensheet.client.services.AssignmentServiceAsync; import org.opensheet.client.services.HourService; import org.opensheet.client.services.HourServiceAsync; import org.opensheet.client.services.SystemService; import org.opensheet.client.services.SystemServiceAsync; import org.opensheet.client.utils.MyTreeGridView; import org.opensheet.client.utils.Resources; import com.extjs.gxt.ui.client.Registry; import com.extjs.gxt.ui.client.Style.HorizontalAlignment; import com.extjs.gxt.ui.client.Style.SortDir; import com.extjs.gxt.ui.client.data.BaseModel; import com.extjs.gxt.ui.client.data.BaseTreeModel; import com.extjs.gxt.ui.client.data.BeanModel; import com.extjs.gxt.ui.client.data.ListLoader; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.GridEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.store.TreeStore; import com.extjs.gxt.ui.client.util.IconHelper; import com.extjs.gxt.ui.client.widget.ContentPanel; import com.extjs.gxt.ui.client.widget.Info; import com.extjs.gxt.ui.client.widget.MessageBox; import com.extjs.gxt.ui.client.widget.Text; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.ComboBox; import com.extjs.gxt.ui.client.widget.form.NumberField; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.grid.CellEditor; import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; import com.extjs.gxt.ui.client.widget.grid.ColumnData; import com.extjs.gxt.ui.client.widget.grid.ColumnModel; import com.extjs.gxt.ui.client.widget.grid.EditorGrid.ClicksToEdit; import com.extjs.gxt.ui.client.widget.grid.Grid; import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem; import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; import com.extjs.gxt.ui.client.widget.treegrid.EditorTreeGrid; import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid; import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer; import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.Joint; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AbstractImagePrototype; public class SheetPanel extends ContentPanel { private UserSwitchMenu userSwitchMenu; private FootBarSheetPanel footBarSheetPanel; TreeStore<ModelData> store; ListStore<BeanModel> userStore = new ListStore<BeanModel>(); ListLoader<?> userloader; List<Integer> disabledAssignments; EditorTreeGrid<ModelData> tree; HashMap<Integer, Boolean> holidays; private MonthHelper monthHelper = new MonthHelper(); private UserDTO userDTO; private UserDTO currentUserDTO; private List<ColumnConfig> columns; private Boolean timesheetInputMode; private Date timesheetInputBorderDate; Text textDaysInMonth; Button thisMonthButton; ComboBox<BeanModel> usersComboBox; Date date = new Date(); final private HourServiceAsync hourService = GWT.create(HourService.class); final private AssignmentServiceAsync assignmentService = GWT .create(AssignmentService.class); private SystemServiceAsync systemService = GWT.create(SystemService.class); private OpensheetConstants myConstants = (OpensheetConstants) GWT .create(OpensheetConstants.class); private OpensheetMessages myMessages = (OpensheetMessages) GWT .create(OpensheetMessages.class); @SuppressWarnings({ "rawtypes", "deprecation", "unchecked" }) public SheetPanel() { addListener(Events.Attach, new Listener() { @Override public void handleEvent(BaseEvent be) { getHolidays(date); } }); // hmmm ? userDTO = (UserDTO) Registry.get("userCurrent"); currentUserDTO = (UserDTO) Registry.get("userCurrent"); getTimesheetEditMode(); store = new TreeStore<ModelData>(); columns = new ArrayList<ColumnConfig>(); ColumnConfig type = new ColumnConfig("type", myConstants.type(), 51); type.setFixed(true); type.setSortable(false); type.setMenuDisabled(true); type.setAlignment(HorizontalAlignment.LEFT); type.setRenderer(new GridCellRenderer<ModelData>() { @Override public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid) { String itype = ""; if (Integer.parseInt((String) model.get(property).toString()) == 0) { itype = "cache"; } else if (Integer.parseInt((String) model.get(property) .toString()) == 1) { itype = "filetypes"; } else if (Integer.parseInt((String) model.get(property) .toString()) == 2) { itype = "kteatime"; } else if (Integer.parseInt((String) model.get(property) .toString()) == 3) { itype = "kuickshow"; } else if (Integer.parseInt((String) model.get(property) .toString()) == 4) { itype = "alarm_bell"; } else if (Integer.parseInt((String) model.get(property) .toString()) == 5) { itype = "sum"; } return "<img src=\"resources/images/nuvola/16x16/apps/" + itype + ".png\" />"; } }); columns.add(type); ColumnConfig name = new ColumnConfig("name", myConstants.assignment(), 320); name.setFixed(true); name.setMenuDisabled(true); name.setStyle("padding-left:0px;"); name.setFixed(true); name.setSortable(false); name.setAlignment(HorizontalAlignment.LEFT); name.setRenderer(new TreeGridCellRenderer<ModelData>() { public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid) { config.css = "x-treegrid-column"; assert grid instanceof TreeGrid : "TreeGridCellRenderer can only be used in a TreeGrid"; TreeGrid tree = (TreeGrid) grid; TreeStore ts = tree.getTreeStore(); int level = ts.getDepth(model); String id = getId(tree, model, property, rowIndex, colIndex); String text = getText(tree, model, property, rowIndex, colIndex); AbstractImagePrototype icon = calculateIconStyle(tree, model, property, rowIndex, colIndex); Joint j = calcualteJoint(tree, model, property, rowIndex, colIndex); return tree.getTreeView().getTemplate(model, id, text, icon, false, j, level - 1); } }); columns.add(name); ColumnConfig sum = new ColumnConfig("summ", "∑", 39); sum.setAlignment(HorizontalAlignment.CENTER); sum.setFixed(true); columns.add(sum); NumberField nf = new NumberField(); nf.setAllowDecimals(false); nf.setPropertyEditorType(Integer.class); CellEditor ce = new CellEditor(nf); Integer i = 32; for (Integer day = 1; day < i; day++) { final Integer thisDay = day; ColumnConfig dayColumnConfig = new ColumnConfig(day.toString(), day.toString(), 22); dayColumnConfig.setEditor(ce); dayColumnConfig.setMenuDisabled(true); dayColumnConfig.setSortable(false); dayColumnConfig.setFixed(true); dayColumnConfig.setRenderer(new GridCellRenderer<ModelData>() { @Override public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid) { if (holidays.size() >= thisDay) { if (holidays.get(thisDay) == true) { config.css = "x-treegrid-column-holiday"; }else{ config.css = "x-treegrid-column-noholiday"; } } else if (holidays.size() < thisDay) { config.css = "x-treegrid-column-outoforder"; } if (model.get(property) == null) { return ""; } else { if (Integer.parseInt((String) model.get(property) .toString()) > 8) { return "<span style='color: red'>" + model.get(property) + "</span>"; } else { return "<span style='color: black'>" + model.get(property) + "</span>"; } } } }); columns.add(dayColumnConfig); } ColumnModel cm = new ColumnModel(columns); TextField<String> text = new TextField<String>(); text.setAllowBlank(false); thisMonthButton = new Button(); thisMonthButton.setWidth(100); thisMonthButton.setText(monthHelper.get(date.getMonth()) + " " + (date.getYear() + 1900)); Button privMonthButton = new Button(); privMonthButton.setIconStyle("privMonthButton"); privMonthButton.addListener(Events.Select, new Listener<BaseEvent>() { @Override public void handleEvent(BaseEvent be) { date.setMonth(date.getMonth() - 1); thisMonthButton.setText(monthHelper.get(date.getMonth()) + " " + (date.getYear() + 1900)); getHolidays(date); } }); Button nextMonthButton = new Button(); nextMonthButton.setIconStyle("nextMonthButton"); nextMonthButton.addListener(Events.Select, new Listener<BaseEvent>() { @Override public void handleEvent(BaseEvent be) { date.setMonth(date.getMonth() + 1); thisMonthButton.setText(monthHelper.get(date.getMonth()) + " " + (date.getYear() + 1900)); getHolidays(date); } }); Button xlsExportButton = new Button(); xlsExportButton.setText("Excel Export"); xlsExportButton.setIcon(Resources.ICONS.table()); xlsExportButton.addListener(Events.Select, new Listener<BaseEvent>() { @Override public void handleEvent(BaseEvent be) { Integer getYear = date.getYear() + 1900; Window.Location.assign(GWT.getHostPageBaseURL().toString() + "timesheettoxls.htm?user_id=" + userDTO.getId() + "&month=" + date.getMonth() + "&year=" + getYear); } }); Button printButton = new Button(); printButton.setText("Print Me"); printButton.setIconStyle("icon-printer"); printButton.addListener(Events.Select, new Listener<BaseEvent>() { @Override public void handleEvent(BaseEvent be) { Integer getYear = date.getYear() + 1900; String winUrl = GWT.getHostPageBaseURL() + "timesheettoprinter.htm?user_id=" + userDTO.getId() + "&month=" + date.getMonth() + "&year=" + getYear; String winName = "Print Page"; openNewWindow(winName, winUrl); } }); Text textUserName = new Text(); textUserName.setText(currentUserDTO.getfullName()); textUserName.setStateId("icon-user"); textUserName.setWidth(200); Text textBR = new Text(); textBR.setText("BR : 100%"); textBR.setWidth(60); Text textFTEE = new Text(); textFTEE.setText("FTEE : 100%"); textFTEE.setWidth(80); textDaysInMonth = new Text(); textDaysInMonth.setWidth(140); ContentPanel cp = new ContentPanel(); cp.setBodyBorder(false); cp.setButtonAlign(HorizontalAlignment.CENTER); cp.setLayout(new FitLayout()); cp.setFrame(true); cp.setSize(1200, 350); tree = new EditorTreeGrid<ModelData>(store, cm); tree.setClicksToEdit(ClicksToEdit.ONE); tree.setBorders(true); tree.setAutoWidth(false); tree.setLoadMask(true); tree.setColumnLines(true); tree.getStyle().setLeafIcon(IconHelper.createStyle("icon-music")); tree.setSize(1200, 400); tree.setAutoExpandColumn("name"); tree.setTrackMouseOver(false); tree.addListener(Events.BeforeEdit, new Listener<GridEvent<BaseModel>>() { public void handleEvent(GridEvent<BaseModel> be) { Integer assignmentId = Integer.parseInt((String) be .getRecord().get("index").toString()); if (holidays.size() < Integer.parseInt((String) be .getProperty())) { be.setCancelled(true); } else if (tree.getTreeStore() .getModelState(be.getModel()).getChildCount() > 0) { be.setCancelled(true); } else if (be.getRecord().get("type").toString() .equals("4")) { be.setCancelled(true); } else if (be.getRecord().get("type").toString() .equals("5")) { be.setCancelled(true); } else if (currentUserDTO.equals(userDTO) && timesheetInputMode == true && currentUserDTO.getPermission().getAdmin() != true && (new Date().getMonth() - date.getMonth()) == 1 && disabledAssignments.contains(assignmentId) != true) { /** * ADD new year fix * */ int results = timesheetInputBorderDate .compareTo(date); if (results < 0) { be.setCancelled(true); } } else if (currentUserDTO.getPermission().getAdmin() != true && date.getMonth() != new Date().getMonth()) { be.setCancelled(true); } else if (disabledAssignments.contains(assignmentId)) { be.setCancelled(true); } /** * Check, what hour is in assignments * */ Integer thisHour = null; if (be.getValue() != null) { thisHour = Integer.parseInt(be.getValue() .toString()); } Boolean leaf = Boolean.parseBoolean(be.getRecord() .get("leaf").toString()); Integer type = Integer.parseInt(be.getRecord() .get("type").toString()); Integer day = Integer.parseInt((String) be .getProperty().toString()); String sum = be.getRecord().get("summ").toString(); Date actionDate = new Date(); actionDate.setYear(date.getYear()); actionDate.setMonth(date.getMonth()); actionDate.setDate(day); footBarSheetPanel.updateData(userDTO, actionDate, assignmentId, thisHour, sum, leaf, type); } }); tree.addListener(Events.AfterEdit, new Listener<GridEvent<BaseModel>>() { public void handleEvent(GridEvent<BaseModel> be) { if (be.getStartValue() != be.getValue()) { Integer newValue = 0; Integer oldValue = 0; if (be.getValue() != null) { newValue = Integer.parseInt((String) be .getValue().toString()); } if (be.getStartValue() != null) { oldValue = Integer.parseInt((String) be .getStartValue().toString()); } Integer assignmentId = Integer.parseInt((String) be .getRecord().get("index").toString()); Integer day = Integer.parseInt((String) be .getProperty().toString()); Date actionDate = new Date(); actionDate.setYear(date.getYear()); actionDate.setMonth(date.getMonth()); actionDate.setDate(day); hourService.setOrUpdateHour(userDTO, actionDate, oldValue, newValue, assignmentId, new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { MessageBox.alert("Cannot add Hour", caught.getMessage(), null); } @Override public void onSuccess(Void result) { Info.display( "Hours Has Been Added", "Succesfull"); } }); } } }); /* * Event for UserSwitch */ EventBus.get().addListener(SheetPanelEvent.UserChanged, new Listener<BaseEvent>() { public void handleEvent(BaseEvent e) { userDTO.setId(Integer.parseInt((String) userSwitchMenu .getSelectedUser().getId().toString())); populateTimesheet(); } }); cp.add(tree); cp.setStyleName("border-collapse"); cp.setHeaderVisible(false); cp.addButton(new Button(myConstants.save(), new SelectionListener<ButtonEvent>() { @Override public void componentSelected(ButtonEvent ce) { populateTimesheet(); } })); ToolBar tb = new ToolBar(); userSwitchMenu = new UserSwitchMenu(currentUserDTO); userSwitchMenu.disable(); if (currentUserDTO.getPermission().getAdmin() == true || currentUserDTO.getPermission().getDm() == true) { userSwitchMenu.enable(); } tb.add(userSwitchMenu); tb.add(new SeparatorToolItem()); tb.add(privMonthButton); tb.add(thisMonthButton); tb.add(nextMonthButton); tb.add(new SeparatorToolItem()); tb.add(xlsExportButton); tb.add(new SeparatorToolItem()); tb.add(printButton); tb.add(new SeparatorToolItem()); tb.add(textUserName); tb.add(new SeparatorToolItem()); tb.add(textBR); tb.add(new SeparatorToolItem()); tb.add(textFTEE); tb.add(new SeparatorToolItem()); tb.add(textDaysInMonth); tb.add(new SeparatorToolItem()); add(tb); add(cp); setHeaderVisible(false); footBarSheetPanel = new FootBarSheetPanel(); add(footBarSheetPanel); } private void populateTimesheet() { tree.mask("Loading Data"); final HourServiceAsync hourService = GWT.create(HourService.class); hourService.getHours(userDTO, date, new AsyncCallback<BaseTreeModel>() { public void onFailure(Throwable caught) { MessageBox.alert("Cannot get Hours", caught.getMessage(), null); } public void onSuccess(BaseTreeModel model) { if (model == null) { MessageBox.alert("Cannot get Hours", "server answer is null", null); } else { store.removeAll(); store.add(model.getChildren(), true); store.sort(myConstants.type(), SortDir.ASC); tree.unmask(); } } }); } private void getHolidays(Date date) { final HourServiceAsync hourService = GWT.create(HourService.class); hourService.getHolidays(date, new AsyncCallback<HashMap<Integer, Boolean>>() { @Override public void onFailure(Throwable caught) { MessageBox.alert("Cannot get holidays", caught.getMessage(), null); } @Override public void onSuccess(HashMap<Integer, Boolean> holidaysHM) { holidays = holidaysHM; Integer count = 0; for (Integer i = 1; i <= holidays.size(); i++) { if (holidays.get(i) == false) { count++; } } textDaysInMonth.setText(myMessages .this_month_we_have_param_work_days_and_param_work_hours( count.toString(), new Integer(count * 8).toString())); getDisabledAssignments(userDTO); } }); } private void getDisabledAssignments(UserDTO userDTO) { assignmentService.getDisabledAssignment(userDTO, date, new AsyncCallback<List<Integer>>() { @Override public void onFailure(Throwable caught) { MessageBox.alert("Cannot get Disabled Assignments", caught.getMessage(), null); } @Override public void onSuccess(List<Integer> result) { disabledAssignments = result; populateTimesheet(); } }); } public static void openNewWindow(String name, String url) { com.google.gwt.user.client.Window.open(url, name.replace(" ", "_"), "menubar=no," + "location=false," + "resizable=yes," + "scrollbars=yes," + "status=no," + "dependent=true"); } private void getTimesheetEditMode() { systemService .getTimeSheetInputMode(new AsyncCallback<HashMap<Boolean, Date>>() { @Override public void onFailure(Throwable caught) { MessageBox.info("Error", caught.getMessage(), null); } @Override public void onSuccess(HashMap<Boolean, Date> result) { if (result.containsKey(true)) { timesheetInputMode = true; timesheetInputBorderDate = result.get(true); } else { timesheetInputMode = false; } } }); } } class MonthHelper { private OpensheetConstants myConstants = (OpensheetConstants) GWT .create(OpensheetConstants.class); public String get(Integer number) { String answer = ""; switch (number) { case 0: { answer = myConstants.January(); break; } case 1: { answer = myConstants.February(); break; } case 2: { answer = myConstants.March(); break; } case 3: { answer = myConstants.April(); break; } case 4: { answer = myConstants.May(); break; } case 5: { answer = myConstants.June(); break; } case 6: { answer = myConstants.July(); break; } case 7: { answer = myConstants.August(); break; } case 8: { answer = myConstants.September(); break; } case 9: { answer = myConstants.October(); break; } case 10: { answer = myConstants.November(); break; } case 11: { answer = myConstants.December(); break; } case 12: { answer = myConstants.January(); break; } } return answer; } }