001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.wicket;
018:
019: import info.jtrac.domain.AbstractItem;
020: import info.jtrac.domain.ColumnHeading;
021: import info.jtrac.domain.History;
022: import info.jtrac.domain.ItemSearch;
023: import info.jtrac.util.DateUtils;
024: import info.jtrac.util.ExcelUtils;
025: import java.io.IOException;
026: import java.util.ArrayList;
027: import java.util.List;
028: import org.apache.wicket.IRequestTarget;
029: import org.apache.wicket.PageParameters;
030: import org.apache.wicket.RequestCycle;
031: import org.apache.wicket.behavior.SimpleAttributeModifier;
032: import org.apache.wicket.markup.html.WebMarkupContainer;
033: import org.apache.wicket.markup.html.basic.Label;
034: import org.apache.wicket.markup.html.link.BookmarkablePageLink;
035: import org.apache.wicket.markup.html.link.Link;
036: import org.apache.wicket.markup.html.list.ListItem;
037: import org.apache.wicket.markup.html.list.ListView;
038: import org.apache.wicket.markup.html.panel.Fragment;
039: import org.apache.wicket.model.IModel;
040: import org.apache.wicket.model.LoadableDetachableModel;
041: import org.apache.wicket.model.Model;
042: import org.apache.wicket.model.PropertyModel;
043: import org.apache.wicket.protocol.http.WebResponse;
044:
045: /**
046: * item list panel
047: */
048: public class ItemListPanel extends BasePanel {
049:
050: private ItemSearch itemSearch;
051:
052: private void doSort(String sortFieldName) {
053: itemSearch.setCurrentPage(0);
054: if (itemSearch.getSortFieldName().equals(sortFieldName)) {
055: itemSearch.toggleSortDirection();
056: } else {
057: itemSearch.setSortFieldName(sortFieldName);
058: itemSearch.setSortDescending(false);
059: }
060: }
061:
062: public ItemListPanel(final String id) {
063: super (id);
064: this .itemSearch = getCurrentItemSearch();
065: LoadableDetachableModel itemListModel = new LoadableDetachableModel() {
066: protected Object load() {
067: logger.debug("loading item list from database");
068: return getJtrac().findItems(itemSearch);
069: }
070: };
071:
072: // hack - ensure that wicket model "attach" happens NOW before pagination logic sp that
073: // itemSearch is properly initialized in the LoadableDetachableModel#load() above
074: itemListModel.getObject();
075:
076: //======================== PAGINATION ==================================
077:
078: int pageCount = 1;
079: final int pageSize = itemSearch.getPageSize();
080: long resultCount = itemSearch.getResultCount();
081: if (pageSize != -1) {
082: pageCount = (int) Math
083: .ceil((double) resultCount / pageSize);
084: }
085: final int currentPage = itemSearch.getCurrentPage();
086:
087: Link link = new Link("count") {
088: public void onClick() {
089: // return to item search form
090: itemSearch.setCurrentPage(0);
091: setResponsePage(new ItemSearchFormPage(itemSearch));
092: }
093: };
094: link.add(new Label("count", resultCount + ""));
095: String resultCountMessage = resultCount == 1 ? "item_list.recordFound"
096: : "item_list.recordsFound";
097: link
098: .add(new Label("recordsFound",
099: localize(resultCountMessage)));
100: add(link);
101:
102: WebMarkupContainer pagination = new WebMarkupContainer(
103: "pagination");
104:
105: if (pageCount > 1) {
106: Link prevOn = new Link("prevOn") {
107: public void onClick() {
108: itemSearch.setCurrentPage(currentPage - 1);
109: setCurrentItemSearch(itemSearch);
110: // TODO avoid next line, refresh pagination only
111: setResponsePage(ItemListPage.class);
112: }
113: };
114: prevOn.add(new Label("prevOn", "<<"));
115: Label prevOff = new Label("prevOff", "<<");
116: if (currentPage == 0) {
117: prevOn.setVisible(false);
118: } else {
119: prevOff.setVisible(false);
120: }
121: pagination.add(prevOn);
122: pagination.add(prevOff);
123:
124: List<Integer> pageNumbers = new ArrayList<Integer>(
125: pageCount);
126: for (int i = 0; i < pageCount; i++) {
127: pageNumbers.add(new Integer(i));
128: }
129:
130: ListView pages = new ListView("pages", pageNumbers) {
131: protected void populateItem(ListItem listItem) {
132: final Integer i = (Integer) listItem
133: .getModelObject();
134: String pageNumber = i + 1 + "";
135: Link pageOn = new Link("pageOn") {
136: public void onClick() {
137: itemSearch.setCurrentPage(i);
138: setCurrentItemSearch(itemSearch);
139: // TODO avoid next line, refresh pagination only
140: setResponsePage(ItemListPage.class);
141: }
142: };
143: pageOn.add(new Label("pageOn", pageNumber));
144: Label pageOff = new Label("pageOff", pageNumber);
145: if (i == currentPage) {
146: pageOn.setVisible(false);
147: } else {
148: pageOff.setVisible(false);
149: }
150: listItem.add(pageOn);
151: listItem.add(pageOff);
152: }
153: };
154: pagination.add(pages);
155:
156: Link nextOn = new Link("nextOn") {
157: public void onClick() {
158: itemSearch.setCurrentPage(currentPage + 1);
159: setCurrentItemSearch(itemSearch);
160: // TODO avoid next line, refresh pagination only
161: setResponsePage(ItemListPage.class);
162: }
163: };
164: nextOn.add(new Label("nextOn", ">>"));
165: Label nextOff = new Label("nextOff", ">>");
166: if (currentPage == pageCount - 1) {
167: nextOn.setVisible(false);
168: } else {
169: nextOff.setVisible(false);
170: }
171: pagination.add(nextOn);
172: pagination.add(nextOff);
173: } else { // if pageCount == 1
174: pagination.setVisible(false);
175: }
176:
177: add(pagination);
178:
179: //========================== EXCEL EXPORT ==============================
180:
181: add(new Link("export") {
182: public void onClick() {
183: // temporarily switch off paging of results
184: itemSearch.setPageSize(-1);
185: final ExcelUtils eu = new ExcelUtils(getJtrac()
186: .findItems(itemSearch), itemSearch);
187: // restore page size
188: itemSearch.setPageSize(pageSize);
189: getRequestCycle().setRequestTarget(
190: new IRequestTarget() {
191: public void detach(RequestCycle requestCycle) {
192: }
193:
194: public void respond(
195: RequestCycle requestCycle) {
196: WebResponse r = (WebResponse) requestCycle
197: .getResponse();
198: r
199: .setAttachmentHeader("jtrac-export.xls");
200: try {
201: eu.exportToExcel().write(
202: r.getOutputStream());
203: } catch (IOException e) {
204: throw new RuntimeException(e);
205: }
206: }
207: });
208: }
209: });
210:
211: //====================== HEADER ========================================
212:
213: final List<ColumnHeading> columnHeadings = itemSearch
214: .getColumnHeadingsToRender();
215:
216: ListView headings = new ListView("headings", columnHeadings) {
217: protected void populateItem(ListItem listItem) {
218: final ColumnHeading ch = (ColumnHeading) listItem
219: .getModelObject();
220: Link headingLink = new Link("heading") {
221: public void onClick() {
222: doSort(ch.getName());
223: }
224: };
225: listItem.add(headingLink);
226: String label = ch.isField() ? ch.getLabel()
227: : localize("item_list." + ch.getName());
228: headingLink.add(new Label("heading", label));
229: if (ch.getName().equals(itemSearch.getSortFieldName())) {
230: String order = itemSearch.isSortDescending() ? "order-down"
231: : "order-up";
232: listItem.add(new SimpleAttributeModifier("class",
233: order));
234: }
235: }
236: };
237:
238: add(headings);
239:
240: //======================== ITEMS =======================================
241:
242: final long selectedItemId = itemSearch.getSelectedItemId();
243:
244: final SimpleAttributeModifier sam = new SimpleAttributeModifier(
245: "class", "alt");
246:
247: ListView itemList = new ListView("itemList", itemListModel) {
248: protected void populateItem(ListItem listItem) {
249: // cast to AbstactItem - show history may be == true
250: final AbstractItem item = (AbstractItem) listItem
251: .getModelObject();
252:
253: if (selectedItemId == item.getId()) {
254: listItem.add(new SimpleAttributeModifier("class",
255: "selected"));
256: } else if (listItem.getIndex() % 2 == 1) {
257: listItem.add(sam);
258: }
259:
260: final boolean showHistory = itemSearch.isShowHistory();
261:
262: ListView fieldValues = new ListView("columns",
263: columnHeadings) {
264: protected void populateItem(ListItem listItem) {
265: ColumnHeading ch = (ColumnHeading) listItem
266: .getModelObject();
267: IModel value = null;
268: if (ch.isField()) {
269: value = new Model(item.getCustomValue(ch
270: .getField().getName()));
271: } else {
272: // TODO optimize if-then for performance
273: String name = ch.getName();
274: if (name.equals(ColumnHeading.ID)) {
275: String refId = item.getRefId();
276: Fragment refIdFrag = new Fragment(
277: "column", "refId");
278: listItem.add(refIdFrag);
279: Link refIdLink = new BookmarkablePageLink(
280: "refId",
281: ItemViewPage.class,
282: new PageParameters("0=" + refId));
283: refIdFrag.add(refIdLink);
284: refIdLink
285: .add(new Label("refId", refId));
286: if (showHistory) {
287: int index = ((History) item)
288: .getIndex();
289: if (index > 0) {
290: refIdFrag.add(new Label(
291: "index", " (" + index
292: + ")"));
293: } else {
294: refIdFrag
295: .add(new WebMarkupContainer(
296: "index")
297: .setVisible(false));
298: }
299: } else {
300: refIdFrag
301: .add(new WebMarkupContainer(
302: "index")
303: .setVisible(false));
304: }
305: return;
306: } else if (name
307: .equals(ColumnHeading.SUMMARY)) {
308: value = new PropertyModel(item,
309: "summary");
310: } else if (name
311: .equals(ColumnHeading.DETAIL)) {
312: if (showHistory) {
313: Fragment detailFrag = new Fragment(
314: "column", "detail");
315: final History history = (History) item;
316: detailFrag
317: .add(new AttachmentLinkPanel(
318: "attachment",
319: history
320: .getAttachment()));
321: if (history.getIndex() > 0) {
322: detailFrag.add(new Label(
323: "detail",
324: new PropertyModel(
325: history,
326: "comment")));
327: } else {
328: detailFrag.add(new Label(
329: "detail",
330: new PropertyModel(
331: history,
332: "detail")));
333: }
334: listItem.add(detailFrag);
335: return;
336: } else {
337: value = new PropertyModel(item,
338: "detail");
339: }
340: } else if (name
341: .equals(ColumnHeading.LOGGED_BY)) {
342: value = new PropertyModel(item,
343: "loggedBy.name");
344: } else if (name
345: .equals(ColumnHeading.STATUS)) {
346: value = new PropertyModel(item,
347: "statusValue");
348: } else if (name
349: .equals(ColumnHeading.ASSIGNED_TO)) {
350: value = new PropertyModel(item,
351: "assignedTo.name");
352: } else if (name
353: .equals(ColumnHeading.TIME_STAMP)) {
354: value = new Model(DateUtils
355: .formatTimeStamp(item
356: .getTimeStamp()));
357: } else if (name.equals(ColumnHeading.SPACE)) {
358: if (showHistory) {
359: value = new PropertyModel(item,
360: "parent.space.name");
361: } else {
362: value = new PropertyModel(item,
363: "space.name");
364: }
365: } else {
366: throw new RuntimeException(
367: "Unexpected name: '" + name
368: + "'");
369: }
370: }
371: listItem.add(new Label("column", value));
372: }
373: };
374:
375: listItem.add(fieldValues);
376:
377: }
378: };
379:
380: add(itemList);
381:
382: }
383:
384: }
|