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.Field;
020: import info.jtrac.domain.Space;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.LinkedHashMap;
025: import java.util.List;
026: import java.util.Map;
027: import org.apache.wicket.behavior.HeaderContributor;
028: import org.apache.wicket.markup.html.IHeaderContributor;
029: import org.apache.wicket.markup.html.IHeaderResponse;
030: import org.apache.wicket.markup.html.WebMarkupContainer;
031: import org.apache.wicket.markup.html.WebPage;
032: import org.apache.wicket.markup.html.basic.Label;
033: import org.apache.wicket.markup.html.form.Button;
034: import org.apache.wicket.markup.html.form.Form;
035: import org.apache.wicket.markup.html.form.TextField;
036: import org.apache.wicket.markup.html.link.Link;
037: import org.apache.wicket.markup.html.list.ListItem;
038: import org.apache.wicket.markup.html.list.ListView;
039: import org.apache.wicket.markup.html.panel.FeedbackPanel;
040: import org.apache.wicket.model.BoundCompoundPropertyModel;
041: import org.apache.wicket.model.PropertyModel;
042: import org.apache.wicket.validation.IValidatable;
043: import org.apache.wicket.validation.validator.AbstractValidator;
044:
045: /**
046: * space field edit form
047: */
048: public class SpaceFieldFormPage extends BasePage {
049:
050: private WebPage previous;
051: private Space space;
052:
053: private void addComponents(Field field) {
054: add(new SpaceFieldForm("form", field));
055: }
056:
057: public SpaceFieldFormPage(Space space, Field field, WebPage previous) {
058: this .space = space;
059: this .previous = previous;
060: addComponents(field);
061: }
062:
063: /**
064: * wicket form
065: */
066: private class SpaceFieldForm extends Form {
067:
068: private JtracFeedbackMessageFilter filter;
069: private TextField optionField;
070:
071: private Field field;
072: private String option;
073:
074: public Field getField() {
075: return field;
076: }
077:
078: public void setField(Field field) {
079: this .field = field;
080: }
081:
082: public String getOption() {
083: return option;
084: }
085:
086: public void setOption(String option) {
087: this .option = option;
088: }
089:
090: public SpaceFieldForm(String id, final Field field) {
091:
092: super (id);
093: this .field = field;
094:
095: FeedbackPanel feedback = new FeedbackPanel("feedback");
096: filter = new JtracFeedbackMessageFilter();
097: feedback.setFilter(filter);
098: add(feedback);
099:
100: final BoundCompoundPropertyModel model = new BoundCompoundPropertyModel(
101: this );
102: setModel(model);
103:
104: // delete button only if edit ======================================
105: Button delete = new Button("delete") {
106: @Override
107: public void onSubmit() {
108: int affectedCount = getJtrac()
109: .loadCountOfRecordsHavingFieldNotNull(
110: space, field);
111: if (affectedCount > 0) {
112: String heading = localize("space_field_delete.confirm")
113: + " : "
114: + field.getLabel()
115: + " ["
116: + field.getName().getDescription()
117: + " - "
118: + field.getName().getText()
119: + "]";
120: String warning = localize("space_field_delete.line3");
121: String line1 = localize("space_field_delete.line1");
122: String line2 = localize(
123: "space_field_delete.line2",
124: affectedCount + "");
125: ConfirmPage confirm = new ConfirmPage(
126: SpaceFieldFormPage.this , heading,
127: warning, new String[] { line1, line2 }) {
128: public void onConfirm() {
129: // database will be updated, if we don't do this
130: // user may leave without committing metadata change
131: getJtrac().bulkUpdateFieldToNull(space,
132: field);
133: space.getMetadata().removeField(
134: field.getName().getText());
135: getJtrac().storeSpace(space);
136: // synchronize metadata version or else if we save again we get Stale Object Exception
137: space.setMetadata(getJtrac()
138: .loadMetadata(
139: space.getMetadata()
140: .getId()));
141: setResponsePage(new SpaceFieldListPage(
142: space, null, previous));
143: }
144: };
145: setResponsePage(confirm);
146: } else {
147: // this is an unsaved space or there are no impacted items
148: space.getMetadata().removeField(
149: field.getName().getText());
150: setResponsePage(new SpaceFieldListPage(space,
151: null, previous));
152: }
153: }
154: };
155: delete.setDefaultFormProcessing(false);
156: if (!space.getMetadata().getFields().containsKey(
157: field.getName())) {
158: delete.setVisible(false);
159: }
160: add(delete);
161: // internal name ===================================================
162: add(new Label("name", new PropertyModel(field, "name.text")));
163: // label ===========================================================
164: final TextField label = new TextField("field.label");
165: label.setRequired(true);
166: label.setOutputMarkupId(true);
167: label.add(new ErrorHighlighter());
168: add(label);
169: // intelligently set focus on right input field
170: add(new HeaderContributor(new IHeaderContributor() {
171: public void renderHead(IHeaderResponse response) {
172: if (field.getLabel() == null) {
173: response
174: .renderOnLoadJavascript("document.getElementById('"
175: + label.getMarkupId()
176: + "').focus()");
177: } else if (optionField != null) {
178: response
179: .renderOnLoadJavascript("document.getElementById('"
180: + optionField.getMarkupId()
181: + "').focus()");
182: }
183: }
184: }));
185: // options =========================================================
186: WebMarkupContainer hide = new WebMarkupContainer("hide");
187: if (field.getName().getType() < 4) { // drop down type
188: final Map<String, String> optionsMap;
189: if (field.getOptions() == null) {
190: optionsMap = new HashMap<String, String>();
191: } else {
192: optionsMap = field.getOptions();
193: }
194: final List<String> options = new ArrayList(optionsMap
195: .keySet());
196: ListView listView = new ListView("options", options) {
197: protected void populateItem(ListItem listItem) {
198: final String key = (String) listItem
199: .getModelObject();
200: listItem.add(new Label("key", key));
201: listItem.add(new Label("value", optionsMap
202: .get(key)));
203: listItem.add(new Link("up") {
204: @Override
205: public void onClick() {
206: int index = options.indexOf(key);
207: int swapIndex = index - 1;
208: if (swapIndex < 0) {
209: if (options.size() > 1) {
210: swapIndex = options.size() - 1;
211: } else {
212: swapIndex = 0;
213: }
214: }
215: if (index != swapIndex) {
216: Collections.swap(options, index,
217: swapIndex);
218: }
219: Map<String, String> updated = new LinkedHashMap<String, String>(
220: options.size());
221: for (String s : options) {
222: updated.put(s, optionsMap.get(s));
223: }
224: field.setOptions(updated);
225: setResponsePage(new SpaceFieldFormPage(
226: space, field, previous));
227: }
228: });
229: listItem.add(new Link("down") {
230: @Override
231: public void onClick() {
232: int index = options.indexOf(key);
233: int swapIndex = index + 1;
234: if (swapIndex == options.size()) {
235: swapIndex = 0;
236: }
237: if (index != swapIndex) {
238: Collections.swap(options, index,
239: swapIndex);
240: }
241: Map<String, String> updated = new LinkedHashMap<String, String>(
242: options.size());
243: for (String s : options) {
244: updated.put(s, optionsMap.get(s));
245: }
246: field.setOptions(updated);
247: setResponsePage(new SpaceFieldFormPage(
248: space, field, previous));
249: }
250: });
251: listItem.add(new Link("edit") {
252: @Override
253: public void onClick() {
254: setResponsePage(new SpaceFieldOptionPage(
255: space, field, key, previous));
256: }
257: });
258: }
259: };
260: hide.add(listView);
261: optionField = new TextField("option");
262: // validation, does option already exist?
263: optionField.add(new AbstractValidator() {
264: protected void onValidate(IValidatable v) {
265: String s = (String) v.getValue();
266: if (field.hasOption(s)) {
267: error(v);
268: }
269: }
270:
271: @Override
272: protected String resourceKey() {
273: return "space_field_form.error.optionExists";
274: }
275: });
276: optionField.add(new ErrorHighlighter());
277: optionField.setOutputMarkupId(true);
278: hide.add(optionField);
279: hide.add(new Button("add") {
280: @Override
281: public void onSubmit() {
282: if (option != null) {
283: field.addOption(option);
284: }
285: setResponsePage(new SpaceFieldFormPage(space,
286: field, previous));
287: }
288: });
289: } else {
290: hide.setVisible(false);
291: }
292: add(hide);
293: // done ============================================================
294: add(new Button("done") {
295: @Override
296: public void onSubmit() {
297: if (option != null) {
298: field.addOption(option);
299: }
300: // may be clone, overwrite anyway
301: space.getMetadata().add(field);
302: setResponsePage(new SpaceFieldListPage(space, field
303: .getName().getText(), previous));
304: }
305: });
306: // cancel ==========================================================
307: add(new Link("cancel") {
308: public void onClick() {
309: setResponsePage(new SpaceFieldListPage(space, field
310: .getName().getText(), previous));
311: }
312: });
313: }
314:
315: @Override
316: protected void validate() {
317: filter.reset();
318: super.validate();
319: }
320:
321: }
322:
323: }
|