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