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