001 /** 002 * Copyright 2010 The Kuali Foundation Licensed under the 003 * Educational Community License, Version 2.0 (the "License"); you may 004 * not use this file except in compliance with the License. You may 005 * obtain a copy of the License at 006 * 007 * http://www.osedu.org/licenses/ECL-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, 010 * software distributed under the License is distributed on an "AS IS" 011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 012 * or implied. See the License for the specific language governing 013 * permissions and limitations under the License. 014 */ 015 016 package org.kuali.student.common.ui.client.widgets.search; 017 018 import java.util.ArrayList; 019 import java.util.HashMap; 020 import java.util.LinkedHashMap; 021 import java.util.List; 022 import java.util.Map; 023 024 import org.kuali.student.common.assembly.data.LookupMetadata; 025 import org.kuali.student.common.assembly.data.LookupParamMetadata; 026 import org.kuali.student.common.assembly.data.Metadata; 027 import org.kuali.student.common.assembly.data.LookupMetadata.Usage; 028 import org.kuali.student.common.assembly.data.Metadata.WriteAccess; 029 import org.kuali.student.common.search.dto.SearchParam; 030 import org.kuali.student.common.search.dto.SearchRequest; 031 import org.kuali.student.common.ui.client.application.Application; 032 import org.kuali.student.common.ui.client.configurable.mvc.DefaultWidgetFactory; 033 import org.kuali.student.common.ui.client.mvc.Callback; 034 import org.kuali.student.common.ui.client.util.UtilConstants; 035 import org.kuali.student.common.ui.client.widgets.KSButton; 036 import org.kuali.student.common.ui.client.widgets.KSDropDown; 037 import org.kuali.student.common.ui.client.widgets.KSLabel; 038 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle; 039 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations; 040 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations.ButtonEnum; 041 import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup; 042 import org.kuali.student.common.ui.client.widgets.field.layout.button.ButtonGroup; 043 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement; 044 import org.kuali.student.common.ui.client.widgets.layout.HorizontalBlockFlowPanel; 045 import org.kuali.student.common.ui.client.widgets.layout.VerticalFlowPanel; 046 import org.kuali.student.common.ui.client.widgets.list.KSSelectItemWidgetAbstract; 047 import org.kuali.student.common.ui.client.widgets.list.ListItems; 048 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent; 049 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler; 050 import org.kuali.student.common.ui.client.widgets.searchtable.ResultRow; 051 052 import com.google.gwt.core.client.GWT; 053 import com.google.gwt.event.dom.client.ClickEvent; 054 import com.google.gwt.event.dom.client.ClickHandler; 055 import com.google.gwt.user.client.Window; 056 import com.google.gwt.user.client.ui.Composite; 057 import com.google.gwt.user.client.ui.HTMLPanel; 058 import com.google.gwt.user.client.ui.HasText; 059 import com.google.gwt.user.client.ui.HasValue; 060 import com.google.gwt.user.client.ui.SimplePanel; 061 import com.google.gwt.user.client.ui.SuggestBox; 062 import com.google.gwt.user.client.ui.VerticalPanel; 063 import com.google.gwt.user.client.ui.Widget; 064 065 public class SearchPanel extends Composite{ 066 067 //Layout configuration 068 private VerticalFlowPanel layout = new VerticalFlowPanel(); 069 private SimplePanel searchSelectorPanel = new SimplePanel(); 070 private VerticalFlowPanel resultsTablePanel = new VerticalFlowPanel(); 071 private HorizontalBlockFlowPanel enteredCriteriaString = new HorizontalBlockFlowPanel(); 072 private CollapsablePanel modifySearchPanel; 073 private String criteriaInstructions = getMessage("searchPanelEnterFields"); 074 private KSLabel enteredCriteriaHeading = new KSLabel(getMessage("searchPanelCriteria")); 075 private SearchResultsTable table; 076 private boolean isMultiSelect = true; 077 078 public static enum SearchStyle{ADVANCED, CUSTOM}; 079 private ActionCancelGroup actionCancelButtons; 080 081 private String actionLabel = getMessage("search"); //set default action label 082 private boolean resultsSelected = false; 083 084 //Search data 085 private List<LookupMetadata> lookups = new ArrayList<LookupMetadata>(); 086 private boolean multiSelect = false; 087 private boolean resultsShown = false; 088 private SearchParametersWidget activeSearchParametersWidget = null; 089 // uses "name" of the lookup metadata to lookup the widget that layouts the search UI 090 private Map<String, SearchParametersWidget> searchParameterWidgetMap = new HashMap<String, SearchParametersWidget>(); 091 private List<SearchField> searchFields = new ArrayList<SearchField>(); 092 private List<Callback<LookupMetadata>> lookupChangedCallbacks = new ArrayList<Callback<LookupMetadata>>(); 093 private String selectedLookupName; 094 private List<Callback<List<SelectedResults>>> selectedCompleteCallbacks = new ArrayList<Callback<List<SelectedResults>>>(); 095 private List<Callback<Boolean>> actionCompletedCallbacks = new ArrayList<Callback<Boolean>>(); 096 097 098 interface SearchParametersWidget { 099 public SearchRequest getSearchRequest(); 100 public LookupMetadata getLookupMetadata(); 101 public List<HasSearchParam> getSearchParams(); 102 } 103 104 public SearchPanel(LookupMetadata meta){ 105 lookups.add(meta); 106 // setupSearch(); 107 this.initWidget(layout); 108 } 109 110 public SearchPanel(List<LookupMetadata> metas){ 111 lookups = metas; 112 // setupSearch(); 113 this.initWidget(layout); 114 } 115 116 @SuppressWarnings("unchecked") 117 public ButtonGroup getButtons(){ 118 return actionCancelButtons; 119 } 120 121 public void setMutipleSelect(boolean isMultiSelect){ 122 this.isMultiSelect = isMultiSelect; 123 } 124 125 public void setupButtons() { 126 if (actionCancelButtons != null) { 127 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 128 actionCancelButtons.addCallback(new Callback<ButtonEnumerations.ButtonEnum>(){ 129 @Override 130 public void exec(ButtonEnum result) { 131 if (result == ButtonEnumerations.SearchCancelEnum.SEARCH) { 132 table.getContentTable().removeContent(); 133 getActionCompleteCallback().exec(true); 134 } 135 } 136 }); 137 } 138 } 139 140 public void setupSearch() { 141 142 resultsTablePanel.clear(); 143 layout.clear(); 144 resultsShown = false; 145 146 //create search panel 147 Widget searchParamPanel; 148 if (lookups.size() == 1) { 149 searchParamPanel = createSearchParamPanel(lookups.get(0)); 150 selectedLookupName = lookups.get(0).getName(); 151 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookupName); 152 } else { 153 LinkedHashMap<String, Widget> searches = new LinkedHashMap<String, Widget>(); 154 LinkedHashMap<String, LookupMetadata> searchLookups = new LinkedHashMap<String, LookupMetadata>(); 155 for(LookupMetadata lookup: lookups){ 156 searches.put(lookup.getName(), createSearchParamPanel(lookup)); 157 searchLookups.put(lookup.getName(), lookup); 158 } 159 selectedLookupName = lookups.get(0).getName(); 160 // Sets the activeSearchParametersWidget to be the first search 161 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookupName); 162 String actionLabel = (lookups.get(0) == null)? null : lookups.get(0) 163 .getWidgetOptionValue(LookupMetadata.WidgetOption.ADVANCED_LIGHTBOX_ACTION_LABEL); 164 setActionLabel(actionLabel); 165 searchParamPanel = new SwappablePanel(searches); 166 ((SwappablePanel)searchParamPanel).setSearchLookups(searchLookups); 167 ((SwappablePanel)searchParamPanel).addLookupChangedCallback(new Callback<LookupMetadata>() { 168 @Override 169 public void exec(LookupMetadata selectedLookup) { 170 activeSearchParametersWidget = searchParameterWidgetMap.get(selectedLookup.getName()); 171 selectedLookupName = selectedLookup.getName(); 172 if (lookupChangedCallbacks != null) { 173 for (Callback<LookupMetadata> callback : lookupChangedCallbacks) { 174 callback.exec(selectedLookup); 175 } 176 } 177 } 178 }); 179 } 180 searchSelectorPanel.setWidget(searchParamPanel); 181 layout.add(searchSelectorPanel); 182 183 //create layout for results screen 184 enteredCriteriaHeading.addStyleName("ks-form-module-single-line-margin"); 185 enteredCriteriaHeading.addStyleName("KS-Advanced-Search-Search-Criteria-Label"); 186 resultsTablePanel.add(enteredCriteriaHeading); 187 resultsTablePanel.add(enteredCriteriaString); 188 resultsTablePanel.setVisible(false); 189 table = new SearchResultsTable(); 190 table.setMutipleSelect(isMultiSelect); 191 table.addStyleName("KS-Advanced-Search-Results-Table"); 192 resultsTablePanel.add(table); 193 layout.add(resultsTablePanel); 194 195 table.getMslabel().addClickHandler(new ClickHandler(){ 196 197 @Override 198 public void onClick(ClickEvent event) { 199 if(modifySearchPanel.isOpen()){ 200 modifySearchPanel.close(); 201 } 202 else{ 203 modifySearchPanel.open(); 204 } 205 206 resultsTablePanel.setVisible(false); 207 resultsSelected = false; 208 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 209 } 210 }); 211 212 resultsSelected = false; 213 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 214 } 215 216 private Widget createSearchParamPanel(LookupMetadata meta){ 217 ParamListItems listItems = new ParamListItems(meta); 218 final AdvancedSearch advancedSearch = new AdvancedSearch(meta); 219 LinkPanel panel = new LinkPanel(SearchStyle.ADVANCED, advancedSearch); 220 searchParameterWidgetMap.put(meta.getName(), advancedSearch); 221 222 //check whether we need custom tab i.e. whether we have at least one parameter that should appear on custom tab 223 for(LookupParamMetadata metaParam: meta.getParams()){ 224 if ((metaParam.getUsage() == Usage.CUSTOM) || (metaParam.getUsage() == Usage.ADVANCED_CUSTOM)) { 225 final CustomizedSearch customizedSearch = new CustomizedSearch(meta, listItems); 226 KSButton button = panel.addLinkToPanel(SearchStyle.ADVANCED, getMessage("searchPanelCustomizeSearch"), SearchStyle.CUSTOM); 227 button.addClickHandler(new ClickHandler(){ 228 229 @Override 230 public void onClick(ClickEvent event) { 231 resultsTablePanel.setVisible(false); 232 activeSearchParametersWidget = customizedSearch; 233 }}); 234 button.addStyleName("KS-Advanced-Search-Link"); 235 button.getParent().addStyleName("clearfix"); 236 panel.addPanel(SearchStyle.CUSTOM, customizedSearch); 237 button = panel.addLinkToPanel(SearchStyle.CUSTOM, getMessage("searchPanelReturnToAdvancedSearch"), SearchStyle.ADVANCED); 238 button.addClickHandler(new ClickHandler(){ 239 240 @Override 241 public void onClick(ClickEvent event) { 242 resultsTablePanel.setVisible(false); 243 activeSearchParametersWidget = advancedSearch; 244 }}); 245 button.addStyleName("KS-Advanced-Search-Link"); 246 button.getParent().addStyleName("clearfix"); 247 break; 248 } 249 } 250 251 return panel; 252 } 253 254 private class CustomizedSearch extends Composite implements SearchParametersWidget { 255 256 private List<CustomLine> lines = new ArrayList<CustomLine>(); 257 private List<HasSearchParam> searchParams = new ArrayList<HasSearchParam>(); 258 private VerticalPanel layout = new VerticalPanel(); 259 private VerticalPanel linePanel = new VerticalPanel(); 260 private LookupMetadata meta; 261 262 public CustomizedSearch(final LookupMetadata meta, final ParamListItems listItems){ 263 264 KSLabel instrLabel = new KSLabel(criteriaInstructions); 265 layout.add(instrLabel); 266 267 layout.add(linePanel); 268 CustomLine line = new CustomLine(meta, listItems); 269 line.addStyleName("ks-form-module-single-line-margin"); 270 linePanel.add(line); 271 lines.add(line); 272 searchParams.add(line); 273 this.meta = meta; 274 275 KSButton addCriteria = new KSButton(getMessage("searchPanelAddCriteria"), ButtonStyle.SECONDARY); 276 addCriteria.addClickHandler(new ClickHandler(){ 277 278 @Override 279 public void onClick(ClickEvent event) { 280 CustomLine line = new CustomLine(meta, listItems); 281 line.addStyleName("ks-form-module-single-line-margin"); 282 linePanel.add(line); 283 lines.add(line); 284 searchParams.add(line); 285 } 286 }); 287 288 addCriteria.addStyleName("ks-form-module-single-line-margin"); 289 layout.add(addCriteria); 290 291 this.initWidget(layout); 292 } 293 294 public LookupMetadata getLookupMetadata() { 295 return meta; 296 } 297 298 @Override 299 public SearchRequest getSearchRequest() { 300 //Create search request and then pass it to the table 301 //TODO pass search to the table 302 SearchRequest sr = new SearchRequest(); 303 List<SearchParam> params = new ArrayList<SearchParam>(); 304 for(CustomLine field: lines){ 305 SearchParam param = field.getSearchParam(); 306 //TODO is this check needed here? probably. assuming string here 307 if((param.getValue() != null)){ 308 params.add(param); 309 } 310 } 311 312 //add search criteria widgets to the custom tab 313 for(LookupParamMetadata metaParam: meta.getParams()){ 314 315 //select only parameters shown on custom search tab 316 if ((metaParam.getUsage() != Usage.CUSTOM) && (metaParam.getUsage() != Usage.ADVANCED_CUSTOM)) { 317 continue; 318 } 319 320 if(metaParam.getWriteAccess() == WriteAccess.NEVER){ 321 SearchParam param = new SearchParam(); 322 param.setKey(metaParam.getKey()); 323 if(metaParam.getDefaultValueList()==null){ 324 param.setValue(metaParam.getDefaultValueString()); 325 }else{ 326 param.setValue(metaParam.getDefaultValueList()); 327 } 328 params.add(param); 329 } 330 else if(metaParam.getWriteAccess() == WriteAccess.WHEN_NULL){ 331 if((metaParam.getDefaultValueString() != null && !metaParam.getDefaultValueString().isEmpty())|| 332 (metaParam.getDefaultValueList() != null && !metaParam.getDefaultValueList().isEmpty())){ 333 SearchParam param = new SearchParam(); 334 param.setKey(metaParam.getKey()); 335 if(metaParam.getDefaultValueList()==null){ 336 param.setValue(metaParam.getDefaultValueString()); 337 }else{ 338 param.setValue(metaParam.getDefaultValueList()); 339 } 340 params.add(param); 341 } 342 } 343 } 344 345 sr.setParams(params); 346 sr.setSearchKey(meta.getSearchTypeId()); 347 return sr; 348 } 349 350 @Override 351 public List<HasSearchParam> getSearchParams() { 352 return searchParams; 353 } 354 355 } 356 357 private interface HasSearchParam{ 358 public SearchParam getSearchParam(); 359 public String getFieldName(); 360 } 361 362 private static class CustomLine extends Composite implements HasSearchParam{ 363 private KSDropDown paramSelector = new KSDropDown(); 364 private SimplePanel widgetPanel = new SimplePanel(); 365 private Widget widget = null; 366 private String key; 367 private HorizontalBlockFlowPanel layout = new HorizontalBlockFlowPanel(); 368 private ParamListItems listItems; 369 370 public CustomLine(LookupMetadata meta, final ParamListItems listItems){ 371 372 List<LookupParamMetadata> customParams = new ArrayList<LookupParamMetadata>(); 373 374 for (LookupParamMetadata lookupParamMetadata : listItems.getParams()) { 375 if (lookupParamMetadata.getWriteAccess() != WriteAccess.NEVER){ 376 if (lookupParamMetadata.getUsage() == Usage.CUSTOM || lookupParamMetadata.getUsage() == Usage.ADVANCED_CUSTOM ) { 377 customParams.add(lookupParamMetadata); 378 } 379 } 380 } 381 382 ParamListItems customParamList = new ParamListItems(customParams); 383 384 this.listItems = customParamList; 385 paramSelector.setBlankFirstItem(false); 386 paramSelector.setListItems(customParamList); 387 388 String id = meta.getParams().get(0).getKey(); 389 paramSelector.selectItem(id); 390 widget = listItems.getWidget(id); 391 key = id; 392 widgetPanel.setWidget(widget); 393 paramSelector.addSelectionChangeHandler(new SelectionChangeHandler(){ 394 395 @Override 396 public void onSelectionChange(SelectionChangeEvent event) { 397 String id = ((KSSelectItemWidgetAbstract)event.getWidget()).getSelectedItem(); 398 widget = listItems.getWidget(id); 399 widgetPanel.setWidget(widget); 400 key = id; 401 402 } 403 }); 404 layout.add(paramSelector); 405 layout.add(widgetPanel); 406 this.initWidget(layout); 407 } 408 409 public SearchParam getSearchParam(){ 410 return SearchPanel.getSearchParam(widget, key); 411 } 412 413 public String getKey(){ 414 return key; 415 } 416 417 public String getFieldName(){ 418 String id = paramSelector.getSelectedItem(); 419 return listItems.getItemText(id); 420 } 421 } 422 423 private class AdvancedSearch extends Composite implements SearchParametersWidget { 424 private LookupMetadata meta; 425 private List<HasSearchParam> searchParams = new ArrayList<HasSearchParam>(); 426 427 public AdvancedSearch(final LookupMetadata meta){ 428 VerticalPanel panel = new VerticalPanel(); 429 430 KSLabel instrLabel = new KSLabel(); 431 panel.add(instrLabel); 432 this.meta = meta; 433 434 //add widget for each search criteria to the advanced tab 435 boolean allFieldsRequired = true; 436 for(LookupParamMetadata param: meta.getParams()){ 437 438 //select only parameters shown on advanced search tab 439 if ((param.getUsage() != Usage.ADVANCED) && (param.getUsage() != Usage.ADVANCED_CUSTOM)) { 440 continue; 441 } 442 443 if ((param.getWriteAccess() == WriteAccess.ALWAYS) || (param.getWriteAccess() == WriteAccess.REQUIRED)){ 444 SearchField paramField = new SearchField(param); 445 searchFields.add(paramField); 446 panel.add(paramField); 447 searchParams.add(paramField); 448 } 449 else if (param.getWriteAccess() == WriteAccess.WHEN_NULL){ 450 if(param.getDefaultValueString() == null && param.getDefaultValueList() == null){ 451 SearchField paramField = new SearchField(param); 452 searchFields.add(paramField); 453 panel.add(paramField); 454 searchParams.add(paramField); 455 } 456 } 457 458 if (param.getWriteAccess() != Metadata.WriteAccess.REQUIRED) { 459 allFieldsRequired = false; 460 } 461 } 462 463 //do not show criteria instructions if we have only one criteria field or in case all fields are required 464 if ((searchFields.size() > 1) || (allFieldsRequired == false)) { 465 instrLabel.setText(criteriaInstructions); 466 } 467 468 this.initWidget(panel); 469 } 470 471 public LookupMetadata getLookupMetadata() { 472 return meta; 473 } 474 475 @Override 476 public SearchRequest getSearchRequest() { 477 SearchRequest sr = new SearchRequest(); 478 List<SearchParam> params = new ArrayList<SearchParam>(); 479 List<HasSearchParam> searchParams = getSearchParams(); 480 481 //initialize search parameters if user entered values into search criteria fields in UI 482 483 for(HasSearchParam field: searchParams){ 484 SearchParam param = field.getSearchParam(); 485 //TODO is this null check needed here? probably. assuming string here 486 //TODO make check more robust here/inserting params more robust 487 //do not pass to the search parameters that are empty 488 //FIXME hack - comparison to 'optional' - replace with check against 'optional' field and update related lookup metadata 489 if ((param.getValue() != null) && ((param.getValue().toString().trim().isEmpty() == false) || (param.getKey().toLowerCase().indexOf("optional") == -1))) { 490 params.add(param); 491 } 492 } 493 494 //initialize search parameters that are hidden from the UI because they are set to default context specific values 495 for(LookupParamMetadata metaParam: meta.getParams()){ 496 if(metaParam.getWriteAccess() == WriteAccess.NEVER){ 497 if ((metaParam.getDefaultValueString() == null || metaParam.getDefaultValueString().isEmpty())&& 498 (metaParam.getDefaultValueList() == null || metaParam.getDefaultValueList().isEmpty())) { 499 //FIXME throw an exception? 500 GWT.log("Key = " + metaParam.getKey() + " has write access NEVER but has no default value!", null); 501 continue; 502 } 503 SearchParam param = new SearchParam(); 504 param.setKey(metaParam.getKey()); 505 if(metaParam.getDefaultValueList()==null){ 506 param.setValue(metaParam.getDefaultValueString()); 507 }else{ 508 param.setValue(metaParam.getDefaultValueList()); 509 } 510 params.add(param); 511 } 512 else if(metaParam.getWriteAccess() == WriteAccess.WHEN_NULL){ 513 if((metaParam.getDefaultValueString() != null && !metaParam.getDefaultValueString().isEmpty())|| 514 (metaParam.getDefaultValueList() != null && !metaParam.getDefaultValueList().isEmpty())){ 515 SearchParam param = new SearchParam(); 516 param.setKey(metaParam.getKey()); 517 if(metaParam.getDefaultValueList()==null){ 518 param.setValue(metaParam.getDefaultValueString()); 519 }else{ 520 param.setValue(metaParam.getDefaultValueList()); 521 } 522 params.add(param); 523 } 524 } 525 } 526 sr.setParams(params); 527 if (meta.getResultSortKey() != null) { 528 sr.setSortColumn(meta.getResultSortKey()); 529 } 530 sr.setSearchKey(meta.getSearchTypeId()); 531 return sr; 532 } 533 534 @Override 535 public List<HasSearchParam> getSearchParams() { 536 return searchParams; 537 } 538 } 539 540 private static class SearchField extends Composite implements HasSearchParam{ 541 542 private Widget widget = null; 543 private LookupParamMetadata meta = null; 544 private VerticalFlowPanel panel = new VerticalFlowPanel(); 545 private String fieldName; 546 547 public SearchParam getSearchParam(){ 548 return SearchPanel.getSearchParam(widget, meta.getKey()); 549 } 550 551 public SearchField(LookupParamMetadata param){ 552 meta = param; 553 //TODO use message call here 554 fieldName = param.getName(); 555 widget = DefaultWidgetFactory.getInstance().getWidget(param); 556 if(param.getDefaultValueString() != null){ 557 //TODO Add handling of default value lists here 558 if(widget instanceof HasText){ 559 ((HasText) widget).setText(param.getDefaultValueString().toString()); 560 } 561 else if(widget instanceof HasValue){ 562 ((HasValue) widget).setValue(param.getDefaultValueString()); 563 } 564 } 565 566 //FIXME: remove because required field '*' indication will be part of FieldElement class 567 if (param.getWriteAccess() == Metadata.WriteAccess.REQUIRED) { 568 fieldName += " *"; 569 } 570 571 FieldElement fieldElement = new FieldElement(fieldName, widget); 572 fieldElement.getTitleWidget().addStyleName("KS-Picker-Criteria-Text"); 573 panel.add(fieldElement); 574 panel.addStyleName("clear"); 575 576 this.initWidget(panel); 577 } 578 579 public Widget getFieldPanel(){ 580 return panel; 581 } 582 583 public String getFieldName() { 584 return fieldName; 585 } 586 } 587 588 private static SearchParam getSearchParam(final Widget widget, String key){ 589 SearchParam param = new SearchParam(); 590 param.setKey(key); 591 if(widget instanceof HasText){ 592 param.setValue(((HasText) widget).getText()); 593 } 594 else if(widget instanceof HasValue){ 595 Object value = ((HasValue) widget).getValue(); 596 if(value != null){ 597 //TODO need to handle date and other types here, how they are converted for search, etc 598 if(value instanceof String){ 599 param.setValue((String)value); 600 } 601 else{ 602 param.setValue(value.toString()); 603 GWT.log("Fields in search probably(?) shouldnt have values other than string", null); 604 } 605 } 606 } 607 else if (widget instanceof KSPicker){ 608 KSPicker pickerWidget = (KSPicker)widget; 609 String pickerValue = pickerWidget.getValue().toString(); 610 if (UtilConstants.IMPOSSIBLE_CHARACTERS.equals(pickerValue)){ 611 SuggestBox suggestBox = (SuggestBox)pickerWidget.getInputWidget(); 612 pickerValue = suggestBox.getText(); 613 } 614 615 param.setValue(pickerValue); 616 } 617 else { 618 param.setValue(""); 619 } 620 621 return param; 622 } 623 624 private void showCriteriaChosen(List<HasSearchParam> fields){ 625 enteredCriteriaString.clear(); 626 boolean first = true;; 627 for(HasSearchParam field: fields){ 628 String name = field.getFieldName(); 629 //TODO Should be string only, needs type safety 630 String value = field.getSearchParam().getValue().toString(); 631 if(!value.isEmpty()){ 632 HTMLPanel label = new HTMLPanel(name + ": <b>" + value + "</b> "); 633 if (!first) { 634 label.addStyleName("KS-Advanced-Search-Search-Criteria-Text"); 635 } 636 enteredCriteriaString.add(label); 637 first = false; 638 } 639 } 640 } 641 642 public List<String> getSelectedIds(){ 643 List<String> ids = new ArrayList<String>(); 644 if(table != null){ 645 ids = table.getSelectedIds(); 646 } 647 return ids; 648 } 649 650 public List<SelectedResults> getSelectedValues() { 651 652 List<SelectedResults> selectedValues = new ArrayList<SelectedResults>(); 653 if (table != null) { 654 List<ResultRow> selectedRows = table.getSelectedRows(); 655 for (ResultRow row : selectedRows) { 656 String displayKey = row.getValue(activeSearchParametersWidget.getLookupMetadata().getResultDisplayKey()); 657 String returnKey = row.getValue(activeSearchParametersWidget.getLookupMetadata().getResultReturnKey()); 658 selectedValues.add(new SelectedResults(displayKey, returnKey, row)); 659 if (multiSelect == false) { 660 break; 661 } 662 } 663 } 664 665 return selectedValues; 666 } 667 668 public boolean isMultiSelect() { 669 return multiSelect; 670 } 671 672 public void setMultiSelect(boolean multiSelect) { 673 this.multiSelect = multiSelect; 674 } 675 676 private static class ParamListItems implements ListItems{ 677 678 private List<LookupParamMetadata> params = new ArrayList<LookupParamMetadata>(); 679 680 public ParamListItems(LookupMetadata meta){ 681 params = meta.getParams(); 682 } 683 684 public ParamListItems(List<LookupParamMetadata> params){ 685 this.params = params; 686 } 687 688 @Override 689 public List<String> getAttrKeys() { 690 return new ArrayList<String>(); 691 } 692 693 @Override 694 public String getItemAttribute(String id, String attrkey) { 695 return ""; 696 } 697 698 @Override 699 public int getItemCount() { 700 return params.size(); 701 } 702 703 @Override 704 public List<String> getItemIds() { 705 List<String> ids = new ArrayList<String>(); 706 for(LookupParamMetadata param: params){ 707 ids.add(param.getKey()); 708 } 709 return ids; 710 } 711 712 @Override 713 public String getItemText(String id) { 714 String itemText = id; 715 for(LookupParamMetadata param: params){ 716 if(param.getKey().equals(id)){ 717 //TODO this should be a message key 718 itemText = param.getName(); 719 break; 720 } 721 } 722 return itemText; 723 } 724 725 public Widget getWidget(String id){ 726 Widget w = null; 727 for(LookupParamMetadata param: params){ 728 if(param.getKey().equals(id)){ 729 w = DefaultWidgetFactory.getInstance().getWidget(param); 730 break; 731 } 732 } 733 return w; 734 } 735 736 public List<LookupParamMetadata> getParams() { 737 return params; 738 } 739 } 740 741 private String getMessage(final String msgKey) { 742 return Application.getApplicationContext().getMessage(msgKey); 743 } 744 745 public void addLookupChangedCallback(Callback<LookupMetadata> callback) { 746 lookupChangedCallbacks.add(callback); 747 } 748 749 public Callback<Boolean> getActionCompleteCallback() { 750 return new Callback<Boolean>() { 751 752 @Override 753 public void exec(Boolean result) { 754 755 if (resultsSelected == true) { 756 List<SelectedResults> selectedItems = getSelectedValues(); 757 if (selectedItems.isEmpty()) 758 Window.alert("Please, select a value"); 759 else 760 { 761 for(Callback<List<SelectedResults>> callback: selectedCompleteCallbacks){ 762 callback.exec(selectedItems); 763 } 764 return; 765 } 766 } 767 768 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getMessage("select")); 769 resultsSelected = true; 770 771 SearchRequest sr = getSearchRequest(); 772 table.performSearch(sr, activeSearchParametersWidget.getLookupMetadata().getResults(), activeSearchParametersWidget.getLookupMetadata().getResultReturnKey()); 773 resultsTablePanel.setVisible(true); 774 List<HasSearchParam> userCriteria = new ArrayList<HasSearchParam>(); 775 List<HasSearchParam> searchParams = activeSearchParametersWidget.getSearchParams(); 776 777 //initialize search parameters if user entered values into search criteria fields in UI 778 for(HasSearchParam field: searchParams){ 779 SearchParam param = field.getSearchParam(); 780 //TODO is this null check needed here? probably. assuming string here 781 //TODO make check more robust here/inserting params more robust 782 //do not pass to the search parameters that are empty 783 //FIXME hack - comparison to 'optional' - replace with check against 'optional' field and update related lookup metadata 784 if ((param.getValue() != null) && ((param.getValue().toString().trim().isEmpty() == false) || (param.getKey().toLowerCase().indexOf("optional") == -1))) { 785 userCriteria.add(field); 786 } 787 } 788 showCriteriaChosen(userCriteria); 789 790 if(!resultsShown){ 791 searchSelectorPanel.removeFromParent(); 792 modifySearchPanel = new CollapsablePanel(getMessage("searchPanelModifySearch"), searchSelectorPanel, false); 793 modifySearchPanel.getLabel().addClickHandler(new ClickHandler(){ 794 @Override 795 public void onClick(ClickEvent event) { 796 resultsTablePanel.setVisible(false); 797 actionCancelButtons.setButtonText(ButtonEnumerations.SearchCancelEnum.SEARCH, getActionLabel()); 798 resultsSelected = false; 799 }}); 800 SearchPanel.this.layout.insert(modifySearchPanel, 0); 801 802 } 803 else{ 804 modifySearchPanel.close(); 805 } 806 resultsShown = true; 807 808 for(Callback<Boolean> callback: actionCompletedCallbacks){ 809 callback.exec( Boolean.valueOf(true)); 810 } 811 } 812 }; 813 } 814 815 public SearchRequest getSearchRequest() { 816 if (activeSearchParametersWidget != null) { 817 return activeSearchParametersWidget.getSearchRequest(); 818 } 819 return null; 820 } 821 822 public void setActionCancelButtonGroup(ActionCancelGroup actionCancelButtons) { 823 this.actionCancelButtons = actionCancelButtons; 824 } 825 826 public String getSelectedLookupName() { 827 return selectedLookupName; 828 } 829 830 public void setSelectedLookupName(String selectedLookupName) { 831 this.selectedLookupName = selectedLookupName; 832 } 833 834 public void addSelectionCompleteCallback(Callback<List<SelectedResults>> callback){ 835 selectedCompleteCallbacks.add(callback); 836 } 837 838 public void addActionCompleteCallback(Callback<Boolean> callback){ 839 actionCompletedCallbacks.add(callback); 840 } 841 842 public String getActionLabel() { 843 return actionLabel; 844 } 845 846 public void setActionLabel(String actionLabel) { 847 if ((actionLabel != null) && (actionLabel.trim().length() > 0)) { 848 this.actionLabel = actionLabel; 849 } 850 } 851 852 853 }