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.Item;
020: import info.jtrac.domain.ItemUser;
021: import info.jtrac.domain.Space;
022: import info.jtrac.domain.State;
023: import info.jtrac.domain.User;
024: import info.jtrac.domain.UserSpaceRole;
025: import info.jtrac.util.UserUtils;
026: import java.util.List;
027: import org.apache.wicket.PageParameters;
028: import org.apache.wicket.behavior.HeaderContributor;
029: import org.apache.wicket.markup.html.IHeaderContributor;
030: import org.apache.wicket.markup.html.IHeaderResponse;
031: import org.apache.wicket.markup.html.WebMarkupContainer;
032: import org.apache.wicket.markup.html.form.Button;
033: import org.apache.wicket.markup.html.form.CheckBox;
034: import org.apache.wicket.markup.html.form.DropDownChoice;
035: import org.apache.wicket.markup.html.form.Form;
036: import org.apache.wicket.markup.html.form.IChoiceRenderer;
037: import org.apache.wicket.markup.html.form.ListMultipleChoice;
038: import org.apache.wicket.markup.html.form.TextArea;
039: import org.apache.wicket.markup.html.form.TextField;
040: import org.apache.wicket.markup.html.form.upload.FileUpload;
041: import org.apache.wicket.markup.html.form.upload.FileUploadField;
042: import org.apache.wicket.markup.html.link.Link;
043: import org.apache.wicket.markup.html.panel.FeedbackPanel;
044: import org.apache.wicket.model.BoundCompoundPropertyModel;
045: import org.apache.wicket.model.LoadableDetachableModel;
046: import org.apache.wicket.util.lang.Bytes;
047:
048: /**
049: * Create / Edit item form page
050: */
051: public class ItemFormPage extends BasePage {
052:
053: public ItemFormPage() {
054: Item item = new Item();
055: item.setSpace(getCurrentSpace());
056: item.setStatus(State.NEW);
057: add(new ItemForm("form", item));
058: }
059:
060: public ItemFormPage(long itemId) {
061: Item item = getJtrac().loadItem(itemId);
062: add(new ItemForm("form", item));
063: }
064:
065: /**
066: * wicket form
067: */
068: private class ItemForm extends Form {
069:
070: private JtracFeedbackMessageFilter filter;
071: private FileUploadField fileUploadField = new FileUploadField(
072: "file");
073: private boolean editMode;
074: private int version;
075:
076: public ItemForm(String id, final Item item) {
077: super (id);
078: setMultiPart(true);
079: FeedbackPanel feedback = new FeedbackPanel("feedback");
080: filter = new JtracFeedbackMessageFilter();
081: feedback.setFilter(filter);
082: add(feedback);
083: version = item.getVersion();
084: if (item.getId() > 0) {
085: editMode = true;
086: }
087: BoundCompoundPropertyModel model = null;
088: if (editMode) {
089: // this ensures that the model object is re-loaded as part of the
090: // form submission workflow before form binding and avoids
091: // hibernate lazy loading issues during the whole update transaction
092: LoadableDetachableModel itemModel = new LoadableDetachableModel() {
093: protected Object load() {
094: logger.debug("attaching existing item "
095: + item.getId());
096: return getJtrac().loadItem(item.getId());
097: }
098: };
099: model = new BoundCompoundPropertyModel(itemModel);
100: } else {
101: model = new BoundCompoundPropertyModel(item);
102: }
103: setModel(model);
104: // summary =========================================================
105: final TextField summaryField = new TextField("summary");
106: summaryField.setRequired(true);
107: summaryField.add(new ErrorHighlighter());
108: summaryField.setOutputMarkupId(true);
109: add(summaryField);
110: add(new HeaderContributor(new IHeaderContributor() {
111: public void renderHead(IHeaderResponse response) {
112: response
113: .renderOnLoadJavascript("document.getElementById('"
114: + summaryField.getMarkupId()
115: + "').focus()");
116: }
117: }));
118: // delete button ===================================================
119: Button delete = new Button("delete") {
120: @Override
121: public void onSubmit() {
122: String heading = localize("item_delete.confirm");
123: String warning = localize("item_delete.line2");
124: String line1 = localize("item_delete.line1");
125: ConfirmPage confirm = new ConfirmPage(
126: ItemFormPage.this , heading, warning,
127: new String[] { line1 }) {
128: public void onConfirm() {
129: // avoid lazy init problem
130: getJtrac().removeItem(
131: getJtrac().loadItem(item.getId()));
132: if (getCurrentItemSearch() != null) {
133: setResponsePage(ItemListPage.class);
134: } else {
135: setResponsePage(DashboardPage.class);
136: }
137: }
138: };
139: setResponsePage(confirm);
140: }
141: };
142: delete.setDefaultFormProcessing(false);
143: add(delete);
144: if (!editMode) {
145: delete.setVisible(false);
146: }
147: // detail ==========================================================
148: add(new TextArea("detail").setRequired(true).add(
149: new ErrorHighlighter()));
150: // custom fields ===================================================
151: if (editMode) {
152: add(new CustomFieldsFormPanel("fields", model, item
153: .getSpace()).setRenderBodyOnly(true));
154: } else {
155: add(new CustomFieldsFormPanel("fields", model, item,
156: getPrincipal()).setRenderBodyOnly(true));
157: }
158: // hide some components if editing item
159: WebMarkupContainer hideAssignedTo = new WebMarkupContainer(
160: "hideAssignedTo");
161: WebMarkupContainer hideNotifyList = new WebMarkupContainer(
162: "hideNotifyList");
163: WebMarkupContainer hideEditReason = new WebMarkupContainer(
164: "hideEditReason");
165: add(hideAssignedTo);
166: add(hideNotifyList);
167: add(hideEditReason);
168: if (editMode) {
169: hideAssignedTo.setVisible(false);
170: hideNotifyList.setVisible(false);
171: hideEditReason.add(new TextArea("editReason")
172: .setRequired(true).add(new ErrorHighlighter()));
173: } else {
174: hideEditReason.setVisible(false);
175: // assigned to =================================================
176: Space space = item.getSpace();
177: List<UserSpaceRole> userSpaceRoles = getJtrac()
178: .findUserRolesForSpace(space.getId());
179: List<User> assignable = UserUtils
180: .filterUsersAbleToTransitionFrom(
181: userSpaceRoles, space, State.OPEN);
182: DropDownChoice choice = new DropDownChoice(
183: "assignedTo", assignable,
184: new IChoiceRenderer() {
185: public Object getDisplayValue(Object o) {
186: return ((User) o).getName();
187: }
188:
189: public String getIdValue(Object o, int i) {
190: return ((User) o).getId() + "";
191: }
192: });
193: choice.setNullValid(true);
194: choice.setRequired(true);
195: WebMarkupContainer border = new WebMarkupContainer(
196: "border");
197: border.add(choice);
198: border.add(new ErrorHighlighter(choice));
199: hideAssignedTo.add(border);
200: // notify list =================================================
201: List<ItemUser> choices = UserUtils
202: .convertToItemUserList(userSpaceRoles);
203: ListMultipleChoice itemUsers = new JtracCheckBoxMultipleChoice(
204: "itemUsers", choices, new IChoiceRenderer() {
205: public Object getDisplayValue(Object o) {
206: return ((ItemUser) o).getUser()
207: .getName();
208: }
209:
210: public String getIdValue(Object o, int i) {
211: return ((ItemUser) o).getUser().getId()
212: + "";
213: }
214: }, true);
215: hideNotifyList.add(itemUsers);
216: // attachment ==================================================
217: hideNotifyList.add(fileUploadField);
218: setMaxSize(Bytes.megabytes(getJtrac()
219: .getAttachmentMaxSizeInMb()));
220: }
221: // send notifications ==========================================
222: add(new CheckBox("sendNotifications"));
223: // cancel ==========================================================
224: add(new Link("cancel") {
225: public void onClick() {
226: setResponsePage(ItemViewPage.class,
227: new PageParameters("0=" + item.getRefId()));
228: }
229: }.setVisible(editMode && getCurrentItemSearch() != null));
230: }
231:
232: @Override
233: protected void validate() {
234: filter.reset();
235: Item item = (Item) getModelObject();
236: if (editMode && item.getVersion() != version) {
237: // user must have used back button after edit
238: error(localize("item_form.error.version"));
239: }
240: super .validate();
241: }
242:
243: @Override
244: protected void onSubmit() {
245: final FileUpload fileUpload = fileUploadField
246: .getFileUpload();
247: Item item = (Item) getModelObject();
248: User user = getPrincipal();
249: if (editMode) {
250: getJtrac().updateItem(item, user);
251: } else {
252: item.setLoggedBy(user);
253: item.setStatus(State.OPEN);
254: getJtrac().storeItem(item, fileUpload);
255: }
256: // on creating an item, clear any search filter (especially the related item) from session
257: setCurrentItemSearch(null);
258: setResponsePage(ItemViewPage.class, new PageParameters("0="
259: + item.getRefId()));
260: }
261:
262: }
263:
264: }
|