001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.apps.lists; 029 030import org.opencms.acacia.shared.I_CmsSerialDateValue; 031import org.opencms.ade.configuration.CmsADEConfigData; 032import org.opencms.ade.configuration.CmsResourceTypeConfig; 033import org.opencms.ade.containerpage.shared.CmsDialogOptions; 034import org.opencms.file.CmsFile; 035import org.opencms.file.CmsObject; 036import org.opencms.file.CmsPropertyDefinition; 037import org.opencms.file.CmsResource; 038import org.opencms.file.CmsResourceFilter; 039import org.opencms.file.types.CmsResourceTypeXmlContent; 040import org.opencms.file.types.I_CmsResourceType; 041import org.opencms.gwt.shared.CmsResourceStatusTabId; 042import org.opencms.i18n.CmsLocaleManager; 043import org.opencms.jsp.search.config.CmsSearchConfiguration; 044import org.opencms.jsp.search.config.CmsSearchConfigurationPagination; 045import org.opencms.jsp.search.config.I_CmsSearchConfigurationCommon; 046import org.opencms.jsp.search.config.I_CmsSearchConfigurationPagination; 047import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser; 048import org.opencms.jsp.search.config.parser.CmsSimpleSearchConfigurationParser.SortOption; 049import org.opencms.jsp.search.controller.CmsSearchController; 050import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetField; 051import org.opencms.jsp.search.controller.I_CmsSearchControllerFacetRange; 052import org.opencms.jsp.search.result.CmsSearchResultWrapper; 053import org.opencms.jsp.search.state.I_CmsSearchStateFacet; 054import org.opencms.loader.CmsLoaderException; 055import org.opencms.lock.CmsLockActionRecord; 056import org.opencms.lock.CmsLockActionRecord.LockChange; 057import org.opencms.lock.CmsLockUtil; 058import org.opencms.main.CmsException; 059import org.opencms.main.CmsLog; 060import org.opencms.main.OpenCms; 061import org.opencms.relations.CmsCategoryService; 062import org.opencms.relations.CmsLink; 063import org.opencms.search.CmsSearchException; 064import org.opencms.search.CmsSearchResource; 065import org.opencms.search.fields.CmsSearchField; 066import org.opencms.search.solr.CmsSolrIndex; 067import org.opencms.search.solr.CmsSolrQuery; 068import org.opencms.search.solr.CmsSolrResultList; 069import org.opencms.ui.A_CmsUI; 070import org.opencms.ui.CmsVaadinUtils; 071import org.opencms.ui.FontOpenCms; 072import org.opencms.ui.I_CmsDialogContext; 073import org.opencms.ui.I_CmsDialogContext.ContextType; 074import org.opencms.ui.I_CmsUpdateListener; 075import org.opencms.ui.actions.A_CmsWorkplaceAction; 076import org.opencms.ui.actions.CmsContextMenuActionItem; 077import org.opencms.ui.actions.CmsDeleteDialogAction; 078import org.opencms.ui.actions.CmsEditDialogAction; 079import org.opencms.ui.actions.CmsResourceInfoAction; 080import org.opencms.ui.apps.A_CmsWorkplaceApp; 081import org.opencms.ui.apps.CmsAppView; 082import org.opencms.ui.apps.CmsAppView.CacheStatus; 083import org.opencms.ui.apps.CmsAppWorkplaceUi; 084import org.opencms.ui.apps.CmsEditor; 085import org.opencms.ui.apps.CmsEditorConfiguration; 086import org.opencms.ui.apps.CmsFileExplorer; 087import org.opencms.ui.apps.CmsFileExplorerSettings; 088import org.opencms.ui.apps.I_CmsAppUIContext; 089import org.opencms.ui.apps.I_CmsCachableApp; 090import org.opencms.ui.apps.I_CmsContextProvider; 091import org.opencms.ui.apps.Messages; 092import org.opencms.ui.apps.lists.CmsListManager.ListConfigurationBean.ListCategoryFolderRestrictionBean; 093import org.opencms.ui.apps.lists.CmsListManager.ListConfigurationBean.ListGeoFilterBean; 094import org.opencms.ui.apps.lists.CmsOptionDialog.I_OptionHandler; 095import org.opencms.ui.apps.lists.daterestrictions.CmsDateRestrictionParser; 096import org.opencms.ui.apps.lists.daterestrictions.I_CmsListDateRestriction; 097import org.opencms.ui.apps.projects.CmsProjectManagerConfiguration; 098import org.opencms.ui.components.CmsBasicDialog; 099import org.opencms.ui.components.CmsErrorDialog; 100import org.opencms.ui.components.CmsFileTable; 101import org.opencms.ui.components.CmsFileTableDialogContext; 102import org.opencms.ui.components.CmsResourceTable; 103import org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider; 104import org.opencms.ui.components.CmsResourceTableProperty; 105import org.opencms.ui.components.CmsToolBar; 106import org.opencms.ui.components.I_CmsWindowCloseListener; 107import org.opencms.ui.components.OpenCmsTheme; 108import org.opencms.ui.components.extensions.CmsGwtDialogExtension; 109import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode; 110import org.opencms.ui.contextmenu.CmsResourceContextMenuBuilder; 111import org.opencms.ui.contextmenu.I_CmsContextMenuItem; 112import org.opencms.ui.contextmenu.I_CmsContextMenuItemProvider; 113import org.opencms.util.CmsGeoUtil; 114import org.opencms.util.CmsStringUtil; 115import org.opencms.util.CmsUUID; 116import org.opencms.workplace.editors.directedit.CmsDateSeriesEditHandler; 117import org.opencms.workplace.editors.directedit.I_CmsEditHandler; 118import org.opencms.workplace.explorer.CmsResourceUtil; 119import org.opencms.xml.CmsXmlUtils; 120import org.opencms.xml.containerpage.CmsContainerElementBean; 121import org.opencms.xml.content.CmsXmlContent; 122import org.opencms.xml.content.CmsXmlContentFactory; 123import org.opencms.xml.content.CmsXmlContentValueLocation; 124import org.opencms.xml.types.CmsXmlDisplayFormatterValue; 125import org.opencms.xml.types.CmsXmlVfsFileValue; 126import org.opencms.xml.types.I_CmsXmlContentValue; 127 128import java.util.ArrayList; 129import java.util.Arrays; 130import java.util.Collection; 131import java.util.Collections; 132import java.util.Date; 133import java.util.HashMap; 134import java.util.HashSet; 135import java.util.LinkedHashMap; 136import java.util.List; 137import java.util.Locale; 138import java.util.Map; 139import java.util.Set; 140 141import org.apache.commons.logging.Log; 142 143import com.vaadin.navigator.View; 144import com.vaadin.navigator.ViewChangeListener; 145import com.vaadin.server.Sizeable.Unit; 146import com.vaadin.ui.Button; 147import com.vaadin.ui.Button.ClickEvent; 148import com.vaadin.ui.Button.ClickListener; 149import com.vaadin.ui.Component; 150import com.vaadin.ui.HorizontalSplitPanel; 151import com.vaadin.ui.UI; 152import com.vaadin.ui.Window; 153import com.vaadin.ui.themes.ValoTheme; 154import com.vaadin.v7.data.Item; 155import com.vaadin.v7.data.Property.ValueChangeEvent; 156import com.vaadin.v7.data.Property.ValueChangeListener; 157import com.vaadin.v7.event.FieldEvents.TextChangeEvent; 158import com.vaadin.v7.event.FieldEvents.TextChangeListener; 159import com.vaadin.v7.ui.AbstractSelect.ItemDescriptionGenerator; 160import com.vaadin.v7.ui.ComboBox; 161import com.vaadin.v7.ui.Table; 162import com.vaadin.v7.ui.Table.CellStyleGenerator; 163import com.vaadin.v7.ui.TextField; 164 165/** 166 * Manager for list configuration files.<p> 167 */ 168@SuppressWarnings("deprecation") 169public class CmsListManager extends A_CmsWorkplaceApp 170implements I_ResourcePropertyProvider, I_CmsContextProvider, ViewChangeListener, I_CmsWindowCloseListener, 171I_CmsCachableApp { 172 173 /** 174 * Enum representing how selected categories should be combined in a search.<p> 175 */ 176 public static enum CategoryMode { 177 /** Combine categories with AND. */ 178 AND, 179 180 /** Combine categories with OR. */ 181 OR; 182 } 183 184 /** 185 * The list configuration data.<p> 186 */ 187 public static class ListConfigurationBean { 188 189 /** Wrapper for a combined category and folder restriction. */ 190 public static class ListCategoryFolderRestrictionBean { 191 192 /** The categories to restrict the search to. */ 193 private List<String> m_categories; 194 195 /** The folders to restrict the search to. */ 196 private List<String> m_folders; 197 198 /** The category combination mode, i.e., "AND" or "OR". */ 199 private CategoryMode m_categoryMode; 200 201 /** 202 * Constructor for the wrapper. 203 * @param categories the categories to filter 204 * @param folders the folders to filter 205 * @param categoryMode the combination mode for categories 206 */ 207 public ListCategoryFolderRestrictionBean( 208 List<String> categories, 209 List<String> folders, 210 CategoryMode categoryMode) { 211 212 m_categories = categories == null ? Collections.<String> emptyList() : categories; 213 m_folders = folders == null ? Collections.<String> emptyList() : folders; 214 m_categoryMode = categoryMode == null ? CategoryMode.OR : categoryMode; 215 } 216 217 /** 218 * Outputs the restriction as Solr filter query. 219 * 220 * @see java.lang.Object#toString() 221 */ 222 @Override 223 public String toString() { 224 225 if (m_categories.isEmpty() && m_folders.isEmpty()) { 226 return ""; 227 } 228 String result = "("; 229 if (!m_categories.isEmpty()) { 230 result += "category_exact:("; 231 if (m_categories.size() > 1) { 232 result += m_categories.stream().reduce( 233 (cat1, cat2) -> "\"" + cat1 + "\" " + m_categoryMode + " \"" + cat2 + "\"").get(); 234 } else { 235 result += "\"" + m_categories.get(0) + "\""; 236 } 237 result += ")"; 238 } 239 if (!m_folders.isEmpty()) { 240 if (!m_categories.isEmpty()) { 241 result += " AND "; 242 } 243 result += "parent-folders:("; 244 if (m_folders.size() > 1) { 245 result += m_folders.stream().reduce((f1, f2) -> "\"" + f1 + "\" OR \"" + f2 + "\"").get(); 246 } else { 247 result += "\"" + m_folders.get(0) + "\""; 248 } 249 result += ")"; 250 } 251 result += ")"; 252 return result; 253 } 254 } 255 256 /** 257 * Bean representing a Geo filter. 258 */ 259 public static class ListGeoFilterBean { 260 261 /** The center point coordinates. */ 262 private String m_coordinates; 263 264 /** The search radius. */ 265 private String m_radius; 266 267 /** 268 * Creates a new Geo filter bean. 269 * @param coordinates the coordinates 270 * @param radius the radius 271 */ 272 public ListGeoFilterBean(String coordinates, String radius) { 273 274 m_coordinates = coordinates; 275 m_radius = radius; 276 } 277 278 /** 279 * Returns the center point coordinates. 280 * @return the center point coordinates 281 */ 282 public String getCoordinates() { 283 284 return m_coordinates; 285 } 286 287 /** 288 * Returns the search radius. 289 * @return the search radius 290 */ 291 public String getRadius() { 292 293 return m_radius; 294 } 295 } 296 297 /** Special parameter to configure the maximally returned results. */ 298 private static final String ADDITIONAL_PARAM_MAX_RETURNED_RESULTS = "maxresults"; 299 300 /** The additional content parameters. */ 301 private Map<String, String> m_additionalParameters; 302 303 /** The resource blacklist. */ 304 private List<CmsUUID> m_blacklist; 305 306 /** The categories. */ 307 private List<String> m_categories; 308 309 /** The category mode. */ 310 private CategoryMode m_categoryMode; 311 312 /** The date restriction. */ 313 private I_CmsListDateRestriction m_dateRestriction; 314 315 /** The display types. */ 316 private List<String> m_dislayTypes; 317 318 /** The Geo filter */ 319 private ListGeoFilterBean m_geoFilter; 320 321 /** The folders. */ 322 private List<String> m_folders; 323 324 /** Search parameters by configuration node name. */ 325 private Map<String, String> m_parameterFields; 326 327 /** Combined category and folder restrictions. */ 328 private List<ListCategoryFolderRestrictionBean> m_categoryFolderRestrictions = new ArrayList<>(); 329 330 /** 331 * Constructor.<p> 332 */ 333 public ListConfigurationBean() { 334 335 m_parameterFields = new HashMap<String, String>(); 336 } 337 338 /** 339 * Add a combined category-folder restriction. 340 * @param listCategoryFolderRestrictionBean the category-folder restriction to add. 341 */ 342 public void addCategoryFolderFilter(ListCategoryFolderRestrictionBean listCategoryFolderRestrictionBean) { 343 344 m_categoryFolderRestrictions.add(listCategoryFolderRestrictionBean); 345 346 } 347 348 /** 349 * Returns the additional content parameters.<p> 350 * 351 * @return the additional content parameters 352 */ 353 public Map<String, String> getAdditionalParameters() { 354 355 return m_additionalParameters; 356 } 357 358 /** 359 * Returns the black list.<p> 360 * 361 * @return the black list 362 */ 363 public List<CmsUUID> getBlacklist() { 364 365 return m_blacklist; 366 } 367 368 /** 369 * Returns the categories.<p> 370 * 371 * @return the categories 372 */ 373 public List<String> getCategories() { 374 375 return m_categories; 376 } 377 378 /** 379 * Returns the combined category-folder restrictions.<p> 380 * 381 * @return the combined category-folder restrictions 382 */ 383 public List<ListCategoryFolderRestrictionBean> getCategoryFolderRestrictions() { 384 385 return m_categoryFolderRestrictions; 386 } 387 388 /** 389 * Gets the category mode.<p> 390 * 391 * @return the category mode 392 */ 393 public CategoryMode getCategoryMode() { 394 395 return m_categoryMode; 396 } 397 398 /** 399 * Gets the date restriction.<p> 400 * 401 * @return the date restriction 402 */ 403 public I_CmsListDateRestriction getDateRestriction() { 404 405 return m_dateRestriction; 406 } 407 408 /** 409 * Returns the display types.<p> 410 * 411 * @return the display types 412 */ 413 public List<String> getDisplayTypes() { 414 415 return m_dislayTypes; 416 } 417 418 /** 419 * Gets the filter query.<p> 420 * 421 * @return the filter query 422 */ 423 public String getFilterQuery() { 424 425 return m_parameterFields.get(N_FILTER_QUERY); 426 } 427 428 /** 429 * Returns the folders.<p> 430 * 431 * @return the folders 432 */ 433 public List<String> getFolders() { 434 435 return m_folders; 436 } 437 438 /** 439 * Returns the Geo filter.<p> 440 * 441 * @return the Geo filter 442 */ 443 public ListGeoFilterBean getGeoFilter() { 444 445 return m_geoFilter; 446 } 447 448 /** 449 * Returns the number of results to return maximally, or <code>null</code> if not explicitly specified. 450 * @return the number of results to return maximally, or <code>null</code> if not explicitly specified. 451 */ 452 public Integer getMaximallyReturnedResults() { 453 454 String resString = m_parameterFields.get(N_MAX_RESULTS); 455 // Fallback, we first added the restriction as additional parameter. To make it more obvious, we integrated it as extra field. 456 // Only if the extra field is not set, we use the additional parameter to be backward compatible. 457 if (null == resString) { 458 m_additionalParameters.get(ADDITIONAL_PARAM_MAX_RETURNED_RESULTS); 459 } 460 if (null != resString) { 461 try { 462 return Integer.valueOf(resString); 463 } catch (NumberFormatException e) { 464 if (LOG.isErrorEnabled()) { 465 LOG.error("Ignoring invalid maxresults param " + resString + " in list-config."); 466 } 467 } 468 } 469 return null; 470 } 471 472 /** 473 * Returns the parameter map.<p> 474 * 475 * @return the parameters 476 */ 477 public Map<String, String> getParameters() { 478 479 return m_parameterFields; 480 } 481 482 /** 483 * Returns the parameter by name.<p> 484 * 485 * @param key the parameter name 486 * 487 * @return the parameter value 488 */ 489 public String getParameterValue(String key) { 490 491 return m_parameterFields.get(key); 492 } 493 494 /** 495 * Gets the sort order.<p> 496 * 497 * @return the sort order 498 */ 499 public String getSortOrder() { 500 501 return getParameterValue(N_SORT_ORDER); 502 } 503 504 /** 505 * Returns the search types.<p> 506 * 507 * @return the search types 508 */ 509 public List<String> getTypes() { 510 511 List<String> result = new ArrayList<String>(); 512 if (m_dislayTypes != null) { 513 for (String displayType : m_dislayTypes) { 514 String type = displayType; 515 if (type.contains(CmsXmlDisplayFormatterValue.SEPARATOR)) { 516 type = type.substring(0, type.indexOf(CmsXmlDisplayFormatterValue.SEPARATOR)); 517 } 518 if (!result.contains(type)) { 519 result.add(type); 520 } 521 } 522 } 523 return result; 524 } 525 526 /** 527 * Returns the 'show expired' setting.<p> 528 * 529 * @return the 'show expired' setting 530 */ 531 public boolean isShowExpired() { 532 533 return Boolean.parseBoolean(m_parameterFields.get(N_SHOW_EXPIRED)); 534 535 } 536 537 /** 538 * Sets the additional content parameters.<p> 539 * 540 * @param additionalParameters the additional content parameters to set 541 */ 542 public void setAdditionalParameters(Map<String, String> additionalParameters) { 543 544 m_additionalParameters = additionalParameters; 545 } 546 547 /** 548 * Sets the blacklist.<p> 549 * 550 * @param blacklist the blacklist 551 */ 552 public void setBlacklist(List<CmsUUID> blacklist) { 553 554 m_blacklist = blacklist; 555 } 556 557 /** 558 * Sets the categories.<p> 559 * 560 * @param categories the categories 561 */ 562 public void setCategories(List<String> categories) { 563 564 m_categories = categories; 565 } 566 567 /** 568 * Sets the category mode.<p> 569 * 570 * @param categoryMode the category mode to set 571 */ 572 public void setCategoryMode(CategoryMode categoryMode) { 573 574 m_categoryMode = categoryMode; 575 } 576 577 /** 578 * Sets the date restrictions.<p> 579 * 580 * @param restriction the date restrictions 581 */ 582 public void setDateRestriction(I_CmsListDateRestriction restriction) { 583 584 m_dateRestriction = restriction; 585 } 586 587 /** 588 * Sets the display types.<p> 589 * 590 * @param displayTypes the display types 591 */ 592 public void setDisplayTypes(List<String> displayTypes) { 593 594 m_dislayTypes = displayTypes; 595 } 596 597 /** 598 * Sets the folders.<p> 599 * 600 * @param folders the folders 601 */ 602 public void setFolders(List<String> folders) { 603 604 m_folders = folders; 605 } 606 607 /** 608 * Sets the Geo filter.<p> 609 * 610 * @param geoFilter the Geo filter 611 */ 612 public void setGeoFilter(ListGeoFilterBean geoFilter) { 613 614 m_geoFilter = geoFilter; 615 } 616 617 /** 618 * Sets the parameter by name.<p> 619 * 620 * @param name the parameter name 621 * @param value the parameter value 622 */ 623 public void setParameterValue(String name, String value) { 624 625 m_parameterFields.put(name, value); 626 627 } 628 } 629 630 /** 631 * Extended dialog context.<p> 632 */ 633 protected class DialogContext extends CmsFileTableDialogContext { 634 635 /** The selected table items. */ 636 private List<Item> m_selectedItems; 637 638 /** 639 * Constructor.<p> 640 * 641 * @param appId the app id 642 * @param contextType the context type 643 * @param fileTable the file table instance 644 * @param resources the list of selected resources 645 */ 646 public DialogContext( 647 String appId, 648 ContextType contextType, 649 CmsFileTable fileTable, 650 List<CmsResource> resources) { 651 652 super(appId, contextType, fileTable, resources); 653 } 654 655 /** 656 * @see org.opencms.ui.components.CmsFileTableDialogContext#finish(java.util.Collection) 657 */ 658 @Override 659 public void finish(Collection<CmsUUID> ids) { 660 661 if (m_selectedItems == null) { 662 super.finish(ids); 663 } else { 664 refreshResult(); 665 closeWindow(); 666 } 667 } 668 669 /** 670 * Returns the selected table items.<p> 671 * 672 * @return the selected table items 673 */ 674 public List<Item> getSelectedItems() { 675 676 return m_selectedItems; 677 } 678 679 /** 680 * Sets the table items.<p> 681 * 682 * @param items the table items 683 */ 684 public void setSelectedItems(List<Item> items) { 685 686 m_selectedItems = items; 687 } 688 } 689 690 /** 691 * Overrides the standard delete action to enable use of edit handlers.<p> 692 */ 693 class DeleteAction extends CmsDeleteDialogAction { 694 695 /** 696 * @see org.opencms.ui.actions.CmsDeleteDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext) 697 */ 698 @Override 699 public void executeAction(final I_CmsDialogContext context) { 700 701 final CmsResource resource = context.getResources().get(0); 702 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource); 703 if ((resourceType instanceof CmsResourceTypeXmlContent) 704 && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) { 705 final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler( 706 context.getCms()); 707 final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context); 708 CmsDialogOptions options = handler.getDeleteOptions( 709 context.getCms(), 710 elementBean, 711 null, 712 Collections.<String, String[]> emptyMap()); 713 if (options == null) { 714 super.executeAction(context); 715 } else if (options.getOptions().size() == 1) { 716 deleteForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context); 717 } else { 718 Window window = CmsBasicDialog.prepareWindow(); 719 window.setCaption(options.getTitle()); 720 CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() { 721 722 public void handleOption(String option) { 723 724 deleteForOption(resource, elementBean, option, handler, context); 725 } 726 }, null, window); 727 window.setContent(dialog); 728 CmsAppWorkplaceUi.get().addWindow(window); 729 dialog.initActionHandler(window); 730 731 } 732 } else { 733 super.executeAction(context); 734 } 735 } 736 737 /** 738 * Deletes with the given option.<p> 739 * 740 * @param resource the resource to delete 741 * @param elementBean the element bean 742 * @param deleteOption the delete option 743 * @param editHandler edit handler 744 * @param context the dialog context 745 */ 746 void deleteForOption( 747 CmsResource resource, 748 CmsContainerElementBean elementBean, 749 String deleteOption, 750 I_CmsEditHandler editHandler, 751 I_CmsDialogContext context) { 752 753 try { 754 editHandler.handleDelete(context.getCms(), elementBean, deleteOption, null, null); 755 } catch (CmsException e) { 756 CmsErrorDialog.showErrorDialog(e); 757 } 758 } 759 } 760 761 /** 762 * Overrides the standard edit action to enable use of edit handlers.<p> 763 */ 764 class EditAction extends CmsEditDialogAction { 765 766 /** 767 * @see org.opencms.ui.actions.CmsEditDialogAction#executeAction(org.opencms.ui.I_CmsDialogContext) 768 */ 769 @Override 770 public void executeAction(final I_CmsDialogContext context) { 771 772 final CmsResource resource = context.getResources().get(0); 773 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource); 774 if ((resourceType instanceof CmsResourceTypeXmlContent) 775 && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(context.getCms()) != null)) { 776 final I_CmsEditHandler handler = ((CmsResourceTypeXmlContent)resourceType).getEditHandler( 777 context.getCms()); 778 final CmsContainerElementBean elementBean = getElementForEditHandler((DialogContext)context); 779 CmsDialogOptions options = handler.getEditOptions( 780 context.getCms(), 781 elementBean, 782 null, 783 Collections.<String, String[]> emptyMap(), 784 true); 785 if (options == null) { 786 super.executeAction(context); 787 } else if (options.getOptions().size() == 1) { 788 editForOption(resource, elementBean, options.getOptions().get(0).getValue(), handler, context); 789 } else { 790 Window window = CmsBasicDialog.prepareWindow(); 791 window.setCaption(options.getTitle()); 792 CmsOptionDialog dialog = new CmsOptionDialog(resource, options, new I_OptionHandler() { 793 794 public void handleOption(String option) { 795 796 editForOption(resource, elementBean, option, handler, context); 797 } 798 }, null, window); 799 window.setContent(dialog); 800 CmsAppWorkplaceUi.get().addWindow(window); 801 dialog.initActionHandler(window); 802 803 } 804 } else { 805 super.executeAction(context); 806 } 807 } 808 809 /** 810 * Calls the editor with the given option.<p> 811 * 812 * @param resource the resource to delete 813 * @param elementBean the element bean 814 * @param editOption the edit option 815 * @param editHandler edit handler 816 * @param context the dialog context 817 */ 818 void editForOption( 819 CmsResource resource, 820 CmsContainerElementBean elementBean, 821 String editOption, 822 I_CmsEditHandler editHandler, 823 I_CmsDialogContext context) { 824 825 try { 826 CmsUUID id = editHandler.prepareForEdit( 827 context.getCms(), 828 elementBean, 829 editOption, 830 null, 831 Collections.<String, String[]> emptyMap()); 832 if (resource.getStructureId().equals(id)) { 833 super.executeAction(context); 834 } else if (id != null) { 835 CmsFileTableDialogContext changedContext = new CmsFileTableDialogContext( 836 CmsProjectManagerConfiguration.APP_ID, 837 ContextType.fileTable, 838 m_resultTable, 839 Collections.singletonList(context.getCms().readResource(id))); 840 super.executeAction(changedContext); 841 } 842 } catch (CmsException e) { 843 CmsErrorDialog.showErrorDialog(e); 844 } 845 } 846 } 847 848 /** SOLR field name. */ 849 public static final String FIELD_CATEGORIES = "category_exact"; 850 851 /** SOLR field name. */ 852 public static final String FIELD_DATE = "instancedate_%s_dt"; 853 854 /** SOLR field name. */ 855 public static final String FIELD_DATE_RANGE = "instancedaterange_%s_dr"; 856 857 /** SOLR field name. */ 858 public static final String FIELD_DATE_FACET_NAME = "instancedate"; 859 860 /** SOLR field name. */ 861 public static final String FIELD_PARENT_FOLDERS = "parent-folders"; 862 863 /** List configuration node name and field key. */ 864 public static final String N_BLACKLIST = "Blacklist"; 865 866 /** List configuration node name and field key. */ 867 public static final String N_CATEGORY = "Category"; 868 869 /** List configuration node name and field key. */ 870 private static final String N_CATEGORY_FOLDER_RESTRICTION = "CategoryFolderFilter"; 871 872 /** List configuration node name and field key. */ 873 private static final String N_COORDINATES = "Coordinates"; 874 875 /** List configuration node name and field key. */ 876 private static final String N_FOLDER = "Folder"; 877 878 /** List configuration node name for the category mode. */ 879 public static final String N_CATEGORY_MODE = "CategoryMode"; 880 881 /** XML content node name. */ 882 public static final String N_DATE_RESTRICTION = "DateRestriction"; 883 884 /** List configuration node name and field key. */ 885 public static final String N_DISPLAY_TYPE = "TypesToCollect"; 886 887 /** List configuration node name and field key. */ 888 public static final String N_FILTER_MULTI_DAY = "FilterMultiDay"; 889 890 /** List configuration node name and field key. */ 891 public static final String N_FILTER_QUERY = "FilterQuery"; 892 893 /** List configuration node name and field key. */ 894 public static final String N_GEO_FILTER = "GeoFilter"; 895 896 /** List configuration node name and field key. */ 897 public static final String N_KEY = "Key"; 898 899 /** List configuration node name and field key. */ 900 public static final String N_PARAMETER = "Parameter"; 901 902 /** List configuration node name and field key. */ 903 public static final String N_RADIUS = "Radius"; 904 905 /** List configuration node name and field key. */ 906 public static final String N_SEARCH_FOLDER = "SearchFolder"; 907 908 /** List configuration node name and field key. */ 909 public static final String N_SHOW_EXPIRED = "ShowExpired"; 910 911 /** List configuration node name and field key. */ 912 public static final String N_SORT_ORDER = "SortOrder"; 913 914 /** List configuration node name and field key. */ 915 public static final String N_TITLE = "Title"; 916 917 /** List configuration node name and field key. */ 918 public static final String N_VALUE = "Value"; 919 920 /** List configuration node name and field key. */ 921 public static final String PARAM_LOCALE = "locale"; 922 923 /** List configuration node name and field key. */ 924 public static final String N_MAX_RESULTS = "MaxResults"; 925 926 /** The parameter fields. */ 927 public static final String[] PARAMETER_FIELDS = new String[] { 928 N_TITLE, 929 N_CATEGORY, 930 N_FILTER_MULTI_DAY, 931 N_FILTER_QUERY, 932 N_SORT_ORDER, 933 N_SHOW_EXPIRED, 934 N_MAX_RESULTS}; 935 936 /** The view content list path name. */ 937 public static final String PATH_NAME_VIEW = "view"; 938 939 /** The list configuration resource type name. */ 940 public static final String RES_TYPE_LIST_CONFIG = "listconfig"; 941 942 /** The blacklisted table column property id. */ 943 protected static final CmsResourceTableProperty BLACKLISTED_PROPERTY = new CmsResourceTableProperty( 944 "BLACKLISTED", 945 Boolean.class, 946 Boolean.FALSE, 947 Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0, 948 true, 949 0, 950 110); 951 952 /** The date series info table column property id. */ 953 protected static final CmsResourceTableProperty INFO_PROPERTY = new CmsResourceTableProperty( 954 "INFO_PROPERTY", 955 String.class, 956 null, 957 null, 958 true, 959 1, 960 0); 961 962 /** The date series info label table column property id. */ 963 protected static final CmsResourceTableProperty INFO_PROPERTY_LABEL = new CmsResourceTableProperty( 964 "INFO_PROPERTY_LABEL", 965 String.class, 966 null, 967 Messages.GUI_LISTMANAGER_COLUMN_INFO_0, 968 true, 969 0, 970 110); 971 972 /** The blacklisted table column property id. */ 973 protected static final CmsResourceTableProperty INSTANCEDATE_PROPERTY = new CmsResourceTableProperty( 974 "INSTANCEDATE_PROPERTY", 975 Date.class, 976 null, 977 Messages.GUI_LISTMANAGER_COLUMN_INSTANCEDATE_0, 978 true, 979 0, 980 145); 981 982 /** The available sort options. */ 983 protected static final String[][] SORT_OPTIONS = new String[][] { 984 { 985 SortOption.DATE_ASC.toString(), 986 SortOption.DATE_DESC.toString(), 987 SortOption.TITLE_ASC.toString(), 988 SortOption.TITLE_DESC.toString(), 989 SortOption.ORDER_ASC.toString(), 990 SortOption.ORDER_DESC.toString()}, 991 { 992 Messages.GUI_LISTMANAGER_SORT_DATE_ASC_0, 993 Messages.GUI_LISTMANAGER_SORT_DATE_DESC_0, 994 Messages.GUI_LISTMANAGER_SORT_TITLE_ASC_0, 995 Messages.GUI_LISTMANAGER_SORT_TITLE_DESC_0, 996 Messages.GUI_LISTMANAGER_SORT_ORDER_ASC_0, 997 Messages.GUI_LISTMANAGER_SORT_ORDER_DESC_0}}; 998 999 /** The month name abbreviations. */ 1000 static final String[] MONTHS = new String[] { 1001 "JAN", 1002 "FEB", 1003 "MAR", 1004 "APR", 1005 "MAY", 1006 "JUN", 1007 "JUL", 1008 "AUG", 1009 "SEP", 1010 "OCT", 1011 "NOV", 1012 "DEC"}; 1013 1014 /** The logger for this class. */ 1015 static final Log LOG = CmsLog.getLog(CmsListManager.class.getName()); 1016 1017 /** Default backend pagination. */ 1018 private static final I_CmsSearchConfigurationPagination PAGINATION = new CmsSearchConfigurationPagination( 1019 null, 1020 Integer.valueOf(10000), 1021 Integer.valueOf(1)); 1022 1023 /** The serial version id. */ 1024 private static final long serialVersionUID = -25954374225590319L; 1025 1026 /** The current list configuration data. */ 1027 ListConfigurationBean m_currentConfig; 1028 1029 /** The current list configuration resource. */ 1030 CmsResource m_currentResource; 1031 1032 /** The result table. */ 1033 CmsResultTable m_resultTable; 1034 1035 /** The create new button. */ 1036 private Button m_createNewButton; 1037 1038 /** The current search parser. */ 1039 private CmsSimpleSearchConfigurationParser m_currentConfigParser; 1040 1041 /** The current app state. */ 1042 private String m_currentState; 1043 1044 /** The current edit dialog window. */ 1045 private Window m_dialogWindow; 1046 1047 /** The edit current configuration button. */ 1048 private Button m_editCurrentButton; 1049 1050 /** Indicates multiple instances of a series are present in the current search result. */ 1051 private boolean m_hasSeriesInstances; 1052 1053 /** Indicates series types are present in the current search result. */ 1054 private boolean m_hasSeriesType; 1055 1056 /** Flag indicating individual instances of a date series should be hidden. */ 1057 private boolean m_hideSeriesInstances; 1058 1059 /** The info button. */ 1060 private Button m_infoButton; 1061 1062 /** Indicates if the overview list is shown. */ 1063 private boolean m_isOverView; 1064 1065 /** The locale select. */ 1066 private ComboBox m_localeSelect; 1067 1068 /** The current lock action. */ 1069 private CmsLockActionRecord m_lockAction; 1070 1071 /** The list configurations overview table. */ 1072 private CmsFileTable m_overviewTable; 1073 1074 /** The publish button. */ 1075 private Button m_publishButton; 1076 1077 /** The resetting flag. */ 1078 private boolean m_resetting; 1079 1080 /** The facet result display. */ 1081 private CmsResultFacets m_resultFacets; 1082 1083 /** The mail layout. */ 1084 private HorizontalSplitPanel m_resultLayout; 1085 1086 /** The sort select. */ 1087 private ComboBox m_resultSorter; 1088 1089 /** The table filter input. */ 1090 private TextField m_tableFilter; 1091 1092 /** The text search input. */ 1093 private TextField m_textSearch; 1094 1095 /** The toggle date series display. */ 1096 private Button m_toggleSeriesButton; 1097 1098 /** 1099 * Parses the list configuration resource.<p> 1100 * 1101 * @param cms the CMS context to use 1102 * @param res the list configuration resource 1103 * 1104 * @return the configuration data bean 1105 */ 1106 public static ListConfigurationBean parseListConfiguration(CmsObject cms, CmsResource res) { 1107 1108 ListConfigurationBean result = new ListConfigurationBean(); 1109 try { 1110 CmsFile configFile = cms.readFile(res); 1111 CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile); 1112 Locale locale = CmsLocaleManager.MASTER_LOCALE; 1113 1114 if (!content.hasLocale(locale)) { 1115 locale = content.getLocales().get(0); 1116 } 1117 for (String field : PARAMETER_FIELDS) { 1118 String val = content.getStringValue(cms, field, locale); 1119 if (N_CATEGORY.equals(field)) { 1120 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(val)) { 1121 result.setCategories(Arrays.asList(val.split(","))); 1122 } else { 1123 result.setCategories(Collections.<String> emptyList()); 1124 } 1125 } else { 1126 result.setParameterValue(field, val); 1127 } 1128 } 1129 1130 I_CmsXmlContentValue restrictValue = content.getValue(N_DATE_RESTRICTION, locale); 1131 if (restrictValue != null) { 1132 CmsDateRestrictionParser parser = new CmsDateRestrictionParser(cms); 1133 I_CmsListDateRestriction restriction = parser.parse(new CmsXmlContentValueLocation(restrictValue)); 1134 if (restriction == null) { 1135 LOG.warn( 1136 "Improper date restriction configuration in content " 1137 + content.getFile().getRootPath() 1138 + ", online=" 1139 + cms.getRequestContext().getCurrentProject().isOnlineProject()); 1140 } 1141 result.setDateRestriction(restriction); 1142 } 1143 1144 I_CmsXmlContentValue geoFilterValue = content.getValue(N_GEO_FILTER, locale); 1145 if (geoFilterValue != null) { 1146 String coordinatesPath = geoFilterValue.getPath() + "/" + N_COORDINATES; 1147 String radiusPath = geoFilterValue.getPath() + "/" + N_RADIUS; 1148 I_CmsXmlContentValue coordinatesValue = content.getValue(coordinatesPath, locale); 1149 I_CmsXmlContentValue radiusValue = content.getValue(radiusPath, locale); 1150 String coordinates = CmsGeoUtil.parseCoordinates(coordinatesValue.getStringValue(cms)); 1151 String radius = radiusValue.getStringValue(cms); 1152 boolean radiusValid = false; 1153 try { 1154 Float.parseFloat(radius); 1155 radiusValid = true; 1156 } catch (NumberFormatException e) { 1157 radiusValid = false; 1158 } 1159 if ((coordinates != null) && radiusValid) { 1160 ListGeoFilterBean listGeoFilterBean = new ListGeoFilterBean(coordinates, radius); 1161 result.setGeoFilter(listGeoFilterBean); 1162 } else { 1163 LOG.warn( 1164 "Improper Geo filter in content " 1165 + content.getFile().getRootPath() 1166 + ", online=" 1167 + cms.getRequestContext().getCurrentProject().isOnlineProject()); 1168 } 1169 } 1170 1171 I_CmsXmlContentValue categoryModeVal = content.getValue(N_CATEGORY_MODE, locale); 1172 CategoryMode categoryMode = CategoryMode.OR; 1173 if (categoryModeVal != null) { 1174 try { 1175 categoryMode = CategoryMode.valueOf(categoryModeVal.getStringValue(cms)); 1176 } catch (Exception e) { 1177 LOG.error(e.getLocalizedMessage(), e); 1178 } 1179 } 1180 result.setCategoryMode(categoryMode); 1181 1182 LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>(); 1183 for (I_CmsXmlContentValue parameter : content.getValues(N_PARAMETER, locale)) { 1184 I_CmsXmlContentValue keyVal = content.getValue(parameter.getPath() + "/" + N_KEY, locale); 1185 I_CmsXmlContentValue valueVal = content.getValue(parameter.getPath() + "/" + N_VALUE, locale); 1186 if ((keyVal != null) 1187 && CmsStringUtil.isNotEmptyOrWhitespaceOnly(keyVal.getStringValue(cms)) 1188 && (valueVal != null)) { 1189 parameters.put(keyVal.getStringValue(cms), valueVal.getStringValue(cms)); 1190 } 1191 } 1192 result.setAdditionalParameters(parameters); 1193 List<String> displayTypes = new ArrayList<String>(); 1194 List<I_CmsXmlContentValue> typeValues = content.getValues(N_DISPLAY_TYPE, locale); 1195 if (!typeValues.isEmpty()) { 1196 for (I_CmsXmlContentValue value : typeValues) { 1197 displayTypes.add(value.getStringValue(cms)); 1198 } 1199 } 1200 result.setDisplayTypes(displayTypes); 1201 List<String> folders = new ArrayList<String>(); 1202 List<I_CmsXmlContentValue> folderValues = content.getValues(N_SEARCH_FOLDER, locale); 1203 if (!folderValues.isEmpty()) { 1204 for (I_CmsXmlContentValue value : folderValues) { 1205 CmsLink val = ((CmsXmlVfsFileValue)value).getLink(cms); 1206 if (val != null) { 1207 // we are using root paths 1208 folders.add(cms.getRequestContext().addSiteRoot(val.getSitePath(cms))); 1209 } 1210 } 1211 } 1212 result.setFolders(folders); 1213 List<CmsUUID> blackList = new ArrayList<CmsUUID>(); 1214 List<I_CmsXmlContentValue> blacklistValues = content.getValues(N_BLACKLIST, locale); 1215 if (!blacklistValues.isEmpty()) { 1216 for (I_CmsXmlContentValue value : blacklistValues) { 1217 CmsLink link = ((CmsXmlVfsFileValue)value).getLink(cms); 1218 if (link != null) { 1219 blackList.add(link.getStructureId()); 1220 } 1221 } 1222 } 1223 List<I_CmsXmlContentValue> categoryFolderRestrictions = content.getValues( 1224 N_CATEGORY_FOLDER_RESTRICTION, 1225 locale); 1226 if (!categoryFolderRestrictions.isEmpty()) { 1227 for (I_CmsXmlContentValue restriction : categoryFolderRestrictions) { 1228 List<String> restrictionFolders = new ArrayList<>(); 1229 List<I_CmsXmlContentValue> folderVals = content.getValues( 1230 CmsXmlUtils.concatXpath(restriction.getPath(), N_FOLDER), 1231 locale); 1232 for (I_CmsXmlContentValue folderVal : folderVals) { 1233 CmsLink val = ((CmsXmlVfsFileValue)folderVal).getLink(cms); 1234 if (val != null) { 1235 // we are using root paths 1236 restrictionFolders.add(cms.getRequestContext().addSiteRoot(val.getSitePath(cms))); 1237 } 1238 } 1239 List<String> restrictionCategorySitePaths; 1240 I_CmsXmlContentValue categoryVal = content.getValue( 1241 CmsXmlUtils.concatXpath(restriction.getPath(), N_CATEGORY), 1242 locale); 1243 String categoryString = null != categoryVal ? categoryVal.getStringValue(cms) : ""; 1244 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(categoryString)) { 1245 restrictionCategorySitePaths = Arrays.asList(categoryString.split(",")); 1246 } else { 1247 restrictionCategorySitePaths = Collections.<String> emptyList(); 1248 } 1249 List<String> restrictionCategories = new ArrayList<>(restrictionCategorySitePaths.size()); 1250 for (String sitePath : restrictionCategorySitePaths) { 1251 try { 1252 String path = CmsCategoryService.getInstance().getCategory( 1253 cms, 1254 cms.getRequestContext().addSiteRoot(sitePath)).getPath(); 1255 restrictionCategories.add(path); 1256 } catch (CmsException e) { 1257 LOG.warn(e.getLocalizedMessage(), e); 1258 } 1259 } 1260 String restrictionCategoryMode = content.getValue( 1261 CmsXmlUtils.concatXpath(restriction.getPath(), N_CATEGORY_MODE), 1262 locale).getStringValue(cms); 1263 result.addCategoryFolderFilter( 1264 new ListCategoryFolderRestrictionBean( 1265 restrictionCategories, 1266 restrictionFolders, 1267 null == restrictionCategoryMode ? null : CategoryMode.valueOf(restrictionCategoryMode))); 1268 1269 } 1270 } 1271 result.setBlacklist(blackList); 1272 } catch (CmsException e) { 1273 e.printStackTrace(); 1274 } 1275 return result; 1276 } 1277 1278 /** 1279 * @see org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider#addItemProperties(com.vaadin.v7.data.Item, org.opencms.file.CmsObject, org.opencms.file.CmsResource, java.util.Locale) 1280 */ 1281 @Override 1282 public void addItemProperties(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale) { 1283 1284 if ((m_currentConfig != null) && (resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY) != null)) { 1285 resourceItem.getItemProperty(CmsListManager.BLACKLISTED_PROPERTY).setValue( 1286 Boolean.valueOf(m_currentConfig.getBlacklist().contains(resource.getStructureId()))); 1287 } 1288 if ((m_currentConfig != null) 1289 && (resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE) != null)) { 1290 CmsResourceUtil resUtil = new CmsResourceUtil(cms, resource); 1291 String title = resUtil.getGalleryTitle((Locale)m_localeSelect.getValue()); 1292 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(title)) { 1293 resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE).setValue(title); 1294 } 1295 } 1296 if ((resource instanceof CmsSearchResource) 1297 && (resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL) != null)) { 1298 String seriesType = ((CmsSearchResource)resource).getField(CmsSearchField.FIELD_SERIESDATES_TYPE); 1299 resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY_LABEL).setValue( 1300 CmsVaadinUtils.getMessageText( 1301 "GUI_LISTMANAGER_SERIES_TYPE_" + (seriesType == null ? "DEFAULT" : seriesType) + "_0")); 1302 resourceItem.getItemProperty(CmsListManager.INFO_PROPERTY).setValue(seriesType); 1303 1304 } 1305 if ((resource instanceof CmsSearchResource) 1306 && (resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY) != null)) { 1307 Date date = ((CmsSearchResource)resource).getDateField(m_resultTable.getDateFieldKey()); 1308 resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY).setValue(date); 1309 } 1310 } 1311 1312 /** 1313 * @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent) 1314 */ 1315 @Override 1316 public void afterViewChange(ViewChangeEvent event) { 1317 1318 // nothing to do 1319 } 1320 1321 /** 1322 * @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent) 1323 */ 1324 @Override 1325 public boolean beforeViewChange(ViewChangeEvent event) { 1326 1327 unlockCurrent(); 1328 return true; 1329 } 1330 1331 /** 1332 * @see org.opencms.ui.apps.I_CmsContextProvider#getDialogContext() 1333 */ 1334 @Override 1335 public I_CmsDialogContext getDialogContext() { 1336 1337 CmsFileTable table = isOverView() ? m_overviewTable : m_resultTable; 1338 List<CmsResource> resources = table.getSelectedResources(); 1339 DialogContext context = new DialogContext( 1340 CmsProjectManagerConfiguration.APP_ID, 1341 ContextType.fileTable, 1342 table, 1343 resources); 1344 if (!isOverView()) { 1345 context.setSelectedItems(m_resultTable.getSelectedItems()); 1346 } 1347 return context; 1348 } 1349 1350 /** 1351 * @see org.opencms.ui.apps.A_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext) 1352 */ 1353 @Override 1354 public void initUI(I_CmsAppUIContext uiContext) { 1355 1356 super.initUI(uiContext); 1357 m_publishButton = CmsToolBar.createButton( 1358 FontOpenCms.PUBLISH, 1359 CmsVaadinUtils.getMessageText(Messages.GUI_PUBLISH_BUTTON_TITLE_0)); 1360 if (CmsAppWorkplaceUi.isOnlineProject()) { 1361 // disable publishing in online project 1362 m_publishButton.setEnabled(false); 1363 m_publishButton.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_TOOLBAR_NOT_AVAILABLE_ONLINE_0)); 1364 } 1365 1366 m_publishButton.addClickListener(new ClickListener() { 1367 1368 /** Serial version id. */ 1369 private static final long serialVersionUID = 1L; 1370 1371 @Override 1372 public void buttonClick(ClickEvent event) { 1373 1374 publish(); 1375 } 1376 }); 1377 uiContext.addToolbarButton(m_publishButton); 1378 1379 m_editCurrentButton = CmsToolBar.createButton( 1380 FontOpenCms.PEN, 1381 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_EDIT_CONFIG_0)); 1382 m_editCurrentButton.addClickListener(new ClickListener() { 1383 1384 /** Serial version id. */ 1385 private static final long serialVersionUID = 1L; 1386 1387 @Override 1388 public void buttonClick(ClickEvent event) { 1389 1390 editListConfiguration(m_currentResource); 1391 } 1392 }); 1393 uiContext.addToolbarButton(m_editCurrentButton); 1394 1395 m_infoButton = CmsToolBar.createButton( 1396 FontOpenCms.INFO, 1397 CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_RESOURCE_INFO_0)); 1398 m_infoButton.addClickListener(new ClickListener() { 1399 1400 /** Serial version id. */ 1401 private static final long serialVersionUID = 1L; 1402 1403 @Override 1404 public void buttonClick(ClickEvent event) { 1405 1406 DialogContext context = new DialogContext( 1407 CmsProjectManagerConfiguration.APP_ID, 1408 ContextType.fileTable, 1409 m_resultTable, 1410 Collections.singletonList(m_currentResource)); 1411 CmsResourceInfoAction action = new CmsResourceInfoAction(); 1412 action.openDialog(context, CmsResourceStatusTabId.tabRelationsTo.name()); 1413 } 1414 }); 1415 uiContext.addToolbarButton(m_infoButton); 1416 1417 m_toggleSeriesButton = CmsToolBar.createButton( 1418 FontOpenCms.LIST, 1419 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TOGGLE_SERIES_BUTTON_0)); 1420 m_toggleSeriesButton.addClickListener(new ClickListener() { 1421 1422 /** Serial version id. */ 1423 private static final long serialVersionUID = 1L; 1424 1425 @Override 1426 public void buttonClick(ClickEvent event) { 1427 1428 toggleDateSeries(); 1429 } 1430 }); 1431 uiContext.addToolbarButton(m_toggleSeriesButton); 1432 1433 m_createNewButton = CmsToolBar.createButton( 1434 FontOpenCms.WAND, 1435 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0)); 1436 m_createNewButton.addClickListener(new ClickListener() { 1437 1438 /** Serial version id. */ 1439 private static final long serialVersionUID = 1L; 1440 1441 @Override 1442 public void buttonClick(ClickEvent event) { 1443 1444 createNew(); 1445 } 1446 }); 1447 uiContext.addToolbarButton(m_createNewButton); 1448 1449 m_rootLayout.setMainHeightFull(true); 1450 m_resultLayout = new HorizontalSplitPanel(); 1451 m_resultLayout.setSizeFull(); 1452 m_resultFacets = new CmsResultFacets(this); 1453 m_resultFacets.setWidth("100%"); 1454 m_resultLayout.setFirstComponent(m_resultFacets); 1455 LinkedHashMap<CmsResourceTableProperty, Integer> tableColumns = new LinkedHashMap<CmsResourceTableProperty, Integer>(); 1456 // insert columns a specific positions 1457 for (Map.Entry<CmsResourceTableProperty, Integer> columnsEntry : CmsFileTable.DEFAULT_TABLE_PROPERTIES.entrySet()) { 1458 if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME)) { 1459 tableColumns.put(INFO_PROPERTY_LABEL, Integer.valueOf(0)); 1460 } else if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE)) { 1461 tableColumns.put(INSTANCEDATE_PROPERTY, Integer.valueOf(0)); 1462 } 1463 tableColumns.put(columnsEntry.getKey(), columnsEntry.getValue()); 1464 } 1465 tableColumns.put(BLACKLISTED_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE)); 1466 tableColumns.put(INFO_PROPERTY, Integer.valueOf(CmsResourceTable.INVISIBLE)); 1467 m_resultTable = new CmsResultTable(null, tableColumns); 1468 m_resultTable.applyWorkplaceAppSettings(); 1469 CmsResourceContextMenuBuilder menuBuilderOverView = new CmsResourceContextMenuBuilder(); 1470 menuBuilderOverView.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider()); 1471 menuBuilderOverView.addMenuItemProvider(new I_CmsContextMenuItemProvider() { 1472 1473 @Override 1474 public List<I_CmsContextMenuItem> getMenuItems() { 1475 1476 return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new CmsEditDialogAction() { 1477 1478 @Override 1479 public void executeAction(I_CmsDialogContext context) { 1480 1481 editListConfiguration(context.getResources().get(0)); 1482 } 1483 }, null, 10, 1000)); 1484 } 1485 }); 1486 CmsResourceContextMenuBuilder menuBuilder = new CmsResourceContextMenuBuilder(); 1487 menuBuilder.addMenuItemProvider(OpenCms.getWorkplaceAppManager().getMenuItemProvider()); 1488 menuBuilder.addMenuItemProvider(new I_CmsContextMenuItemProvider() { 1489 1490 @Override 1491 public List<I_CmsContextMenuItem> getMenuItems() { 1492 1493 return Arrays.<I_CmsContextMenuItem> asList(new CmsContextMenuActionItem(new A_CmsWorkplaceAction() { 1494 1495 @Override 1496 public void executeAction(I_CmsDialogContext context) { 1497 1498 CmsUUID structureId = context.getResources().get(0).getStructureId(); 1499 m_currentConfig.getBlacklist().add(structureId); 1500 saveBlacklist(m_currentConfig); 1501 context.finish(Collections.singletonList(structureId)); 1502 } 1503 1504 @Override 1505 public String getId() { 1506 1507 return "hideresource"; 1508 } 1509 1510 @Override 1511 public String getTitleKey() { 1512 1513 return Messages.GUI_LISTMANAGER_BLACKLIST_MENU_ENTRY_0; 1514 } 1515 1516 @Override 1517 public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) { 1518 1519 if ((m_currentConfig != null) 1520 && (resources != null) 1521 && (resources.size() == 1) 1522 && !m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) { 1523 return CmsEditDialogAction.VISIBILITY.getVisibility( 1524 cms, 1525 Collections.singletonList(m_currentResource)); 1526 } else { 1527 return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE; 1528 } 1529 } 1530 1531 }, null, 10, 0), new CmsContextMenuActionItem(new A_CmsWorkplaceAction() { 1532 1533 @Override 1534 public void executeAction(I_CmsDialogContext context) { 1535 1536 CmsUUID structureId = context.getResources().get(0).getStructureId(); 1537 m_currentConfig.getBlacklist().remove(structureId); 1538 saveBlacklist(m_currentConfig); 1539 context.finish(Collections.singletonList(structureId)); 1540 } 1541 1542 @Override 1543 public String getId() { 1544 1545 return "showresource"; 1546 } 1547 1548 @Override 1549 public String getTitleKey() { 1550 1551 return Messages.GUI_LISTMANAGER_REMOVE_FROM_BLACKLIST_MENU_ENTRY_0; 1552 } 1553 1554 @Override 1555 public CmsMenuItemVisibilityMode getVisibility(CmsObject cms, List<CmsResource> resources) { 1556 1557 if ((m_currentConfig != null) 1558 && (resources != null) 1559 && (resources.size() == 1) 1560 && m_currentConfig.getBlacklist().contains(resources.get(0).getStructureId())) { 1561 return CmsEditDialogAction.VISIBILITY.getVisibility( 1562 cms, 1563 Collections.singletonList(m_currentResource)); 1564 } else { 1565 return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE; 1566 } 1567 } 1568 1569 }, null, 10, 0), 1570 new CmsContextMenuActionItem(new EditAction(), null, 10, 1000), 1571 new CmsContextMenuActionItem(new DeleteAction(), null, 10, 1000)); 1572 } 1573 }); 1574 m_resultTable.setMenuBuilder(menuBuilder); 1575 m_resultTable.addAdditionalStyleGenerator(new CellStyleGenerator() { 1576 1577 private static final long serialVersionUID = 1L; 1578 1579 @Override 1580 public String getStyle(Table source, Object itemId, Object propertyId) { 1581 1582 String style = ""; 1583 Item item = source.getItem(itemId); 1584 Boolean blacklisted = (Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue(); 1585 if (blacklisted.booleanValue()) { 1586 style += OpenCmsTheme.PROJECT_OTHER + " "; 1587 } else if (CmsResourceTableProperty.PROPERTY_TITLE.equals(propertyId) 1588 && ((item.getItemProperty(CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED) == null) 1589 || ((Boolean)item.getItemProperty( 1590 CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED).getValue()).booleanValue())) { 1591 style += OpenCmsTheme.IN_NAVIGATION + " "; 1592 } 1593 if (INFO_PROPERTY_LABEL.equals(propertyId)) { 1594 if (blacklisted.booleanValue()) { 1595 style += OpenCmsTheme.TABLE_COLUMN_BOX_BLACK; 1596 } else { 1597 Object value = item.getItemProperty(INFO_PROPERTY).getValue(); 1598 if (value == null) { 1599 style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY; 1600 } else { 1601 I_CmsSerialDateValue.DateType type = I_CmsSerialDateValue.DateType.valueOf((String)value); 1602 switch (type) { 1603 case SERIES: 1604 style += OpenCmsTheme.TABLE_COLUMN_BOX_BLUE_LIGHT; 1605 break; 1606 case SINGLE: 1607 style += OpenCmsTheme.TABLE_COLUMN_BOX_GRAY; 1608 break; 1609 case EXTRACTED: 1610 style += OpenCmsTheme.TABLE_COLUMN_BOX_ORANGE; 1611 break; 1612 default: 1613 break; 1614 } 1615 } 1616 } 1617 } 1618 return style; 1619 } 1620 }); 1621 final ItemDescriptionGenerator defaultDescriptionGenerator = new CmsResourceTable.DefaultItemDescriptionGenerator(); 1622 m_resultTable.setsetItemDescriptionGenerator(new ItemDescriptionGenerator() { 1623 1624 private static final long serialVersionUID = 1L; 1625 1626 public String generateDescription(Component source, Object itemId, Object propertyId) { 1627 1628 Item item = ((Table)source).getItem(itemId); 1629 if (INFO_PROPERTY_LABEL.equals(propertyId) 1630 && ((Boolean)item.getItemProperty(BLACKLISTED_PROPERTY).getValue()).booleanValue()) { 1631 return CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_COLUMN_BLACKLISTED_0); 1632 } 1633 return defaultDescriptionGenerator.generateDescription(source, itemId, propertyId); 1634 } 1635 }); 1636 m_resultTable.setContextProvider(this); 1637 m_resultTable.addPropertyProvider(this); 1638 m_resultTable.setSizeFull(); 1639 m_resultLayout.setSecondComponent(m_resultTable); 1640 m_overviewTable = new CmsFileTable(this); 1641 m_overviewTable.applyWorkplaceAppSettings(); 1642 m_overviewTable.setMenuBuilder(menuBuilderOverView); 1643 m_overviewTable.setSizeFull(); 1644 1645 m_tableFilter = new TextField(); 1646 m_tableFilter.setIcon(FontOpenCms.FILTER); 1647 m_tableFilter.setInputPrompt( 1648 Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0)); 1649 m_tableFilter.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON); 1650 m_tableFilter.setWidth("200px"); 1651 m_tableFilter.addTextChangeListener(new TextChangeListener() { 1652 1653 private static final long serialVersionUID = 1L; 1654 1655 @Override 1656 public void textChange(TextChangeEvent event) { 1657 1658 filterTable(event.getText()); 1659 1660 } 1661 }); 1662 m_infoLayout.addComponent(m_tableFilter); 1663 1664 m_localeSelect = new ComboBox(); 1665 m_localeSelect.setNullSelectionAllowed(false); 1666 m_localeSelect.setWidth("100px"); 1667 m_localeSelect.addValueChangeListener(new ValueChangeListener() { 1668 1669 /** Serial version id. */ 1670 private static final long serialVersionUID = 1L; 1671 1672 @Override 1673 public void valueChange(ValueChangeEvent event) { 1674 1675 changeContentLocale((Locale)event.getProperty().getValue()); 1676 } 1677 }); 1678 m_infoLayout.addComponent(m_localeSelect); 1679 1680 m_resultSorter = new ComboBox(); 1681 m_resultSorter.setNullSelectionAllowed(false); 1682 m_resultSorter.setWidth("200px"); 1683 for (int i = 0; i < SORT_OPTIONS[0].length; i++) { 1684 m_resultSorter.addItem(SORT_OPTIONS[0][i]); 1685 m_resultSorter.setItemCaption(SORT_OPTIONS[0][i], CmsVaadinUtils.getMessageText(SORT_OPTIONS[1][i])); 1686 } 1687 m_resultSorter.addValueChangeListener(new ValueChangeListener() { 1688 1689 /** Serial version id. */ 1690 private static final long serialVersionUID = 1L; 1691 1692 @Override 1693 public void valueChange(ValueChangeEvent event) { 1694 1695 sortResult(); 1696 } 1697 }); 1698 m_infoLayout.addComponent(m_resultSorter); 1699 1700 m_textSearch = new TextField(); 1701 m_textSearch.setIcon(FontOpenCms.SEARCH); 1702 m_textSearch.setInputPrompt(CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_SEARCH_0)); 1703 m_textSearch.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON); 1704 m_textSearch.setWidth("200px"); 1705 m_textSearch.addValueChangeListener(new ValueChangeListener() { 1706 1707 /** Serial version id. */ 1708 private static final long serialVersionUID = 1L; 1709 1710 @Override 1711 public void valueChange(ValueChangeEvent event) { 1712 1713 search((String)event.getProperty().getValue()); 1714 } 1715 }); 1716 m_infoLayout.addComponent(m_textSearch); 1717 m_resultLayout.setSecondComponent(m_resultTable); 1718 m_resultLayout.setSplitPosition(CmsFileExplorer.LAYOUT_SPLIT_POSITION, Unit.PIXELS); 1719 } 1720 1721 /** 1722 * @see org.opencms.ui.apps.I_CmsCachableApp#isCachable() 1723 */ 1724 public boolean isCachable() { 1725 1726 return true; 1727 } 1728 1729 /** 1730 * @see org.opencms.ui.apps.I_CmsCachableApp#onRestoreFromCache() 1731 */ 1732 public void onRestoreFromCache() { 1733 1734 if (isOverView()) { 1735 CmsFileExplorerSettings state = m_overviewTable.getTableSettings(); 1736 displayListConfigs(); 1737 m_overviewTable.setTableState(state); 1738 m_overviewTable.updateSorting(); 1739 } else { 1740 refreshResult(); 1741 } 1742 } 1743 1744 /** 1745 * @see org.opencms.ui.apps.A_CmsWorkplaceApp#onStateChange(java.lang.String) 1746 */ 1747 @Override 1748 public void onStateChange(String state) { 1749 1750 if ((m_currentState == null) || !m_currentState.equals(state)) { 1751 m_currentState = state; 1752 super.onStateChange(state); 1753 } 1754 } 1755 1756 /** 1757 * @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose() 1758 */ 1759 @Override 1760 public void onWindowClose() { 1761 1762 unlockCurrent(); 1763 } 1764 1765 /** 1766 * Saves the blacklist from the bean in the current list configuration.<p> 1767 * 1768 * @param configBean the bean whose blacklist should be saved 1769 */ 1770 public void saveBlacklist(ListConfigurationBean configBean) { 1771 1772 if (m_dialogWindow != null) { 1773 m_dialogWindow.close(); 1774 m_dialogWindow = null; 1775 } 1776 CmsObject cms = A_CmsUI.getCmsObject(); 1777 1778 try { 1779 m_lockAction = CmsLockUtil.ensureLock(cms, m_currentResource); 1780 } catch (CmsException e) { 1781 CmsErrorDialog.showErrorDialog(e); 1782 return; 1783 } 1784 1785 try { 1786 CmsFile configFile = cms.readFile(m_currentResource); 1787 CmsXmlContent content = CmsXmlContentFactory.unmarshal(cms, configFile); 1788 // list configurations are single locale contents 1789 Locale locale = CmsLocaleManager.MASTER_LOCALE; 1790 int count = 0; 1791 while (content.hasValue(N_BLACKLIST, locale)) { 1792 content.removeValue(N_BLACKLIST, locale, 0); 1793 } 1794 for (CmsUUID hiddenId : configBean.getBlacklist()) { 1795 CmsXmlVfsFileValue contentVal; 1796 contentVal = (CmsXmlVfsFileValue)content.addValue(cms, N_BLACKLIST, locale, count); 1797 contentVal.setIdValue(cms, hiddenId); 1798 count++; 1799 } 1800 configFile.setContents(content.marshal()); 1801 cms.writeFile(configFile); 1802 if (m_lockAction.getChange().equals(LockChange.locked)) { 1803 CmsLockUtil.tryUnlock(cms, configFile); 1804 } 1805 } catch (CmsException e) { 1806 e.printStackTrace(); 1807 } 1808 m_currentConfig = configBean; 1809 } 1810 1811 /** 1812 * Execute a search with the given search configuration parser.<p> 1813 * 1814 * @param configParser the search configuration parser 1815 * @param resource the current configuration resource 1816 */ 1817 public void search(CmsSimpleSearchConfigurationParser configParser, CmsResource resource) { 1818 1819 m_currentResource = resource; 1820 m_currentConfigParser = configParser; 1821 resetContentLocale(configParser.getSearchLocale()); 1822 m_resetting = true; 1823 m_resultSorter.setValue(m_currentConfig.getParameterValue(N_SORT_ORDER)); 1824 m_resetting = false; 1825 1826 search(null, null, null); 1827 } 1828 1829 /** 1830 * Updates the search result.<p> 1831 * 1832 * @param fieldFacets the field facets 1833 * @param rangeFacets the range facets 1834 */ 1835 public void search(Map<String, List<String>> fieldFacets, Map<String, List<String>> rangeFacets) { 1836 1837 search(fieldFacets, rangeFacets, null); 1838 } 1839 1840 /** 1841 * Updates the search result.<p> 1842 * 1843 * @param fieldFacets the field facets 1844 * @param rangeFacets the range facets 1845 * @param additionalQuery the additional query 1846 */ 1847 public void search( 1848 Map<String, List<String>> fieldFacets, 1849 Map<String, List<String>> rangeFacets, 1850 String additionalQuery) { 1851 1852 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly((String)m_resultSorter.getValue())) { 1853 m_currentConfigParser.setSortOption((String)m_resultSorter.getValue()); 1854 } 1855 1856 CmsSolrQuery query = m_currentConfigParser.getInitialQuery(); 1857 CmsSearchController controller = new CmsSearchController( 1858 new CmsSearchConfiguration(m_currentConfigParser, A_CmsUI.getCmsObject())); 1859 controller.getPagination().getState().setCurrentPage(1); 1860 if (fieldFacets != null) { 1861 Map<String, I_CmsSearchControllerFacetField> fieldFacetControllers = controller.getFieldFacets().getFieldFacetController(); 1862 for (Map.Entry<String, List<String>> facetEntry : fieldFacets.entrySet()) { 1863 I_CmsSearchStateFacet state = fieldFacetControllers.get(facetEntry.getKey()).getState(); 1864 state.clearChecked(); 1865 for (String check : facetEntry.getValue()) { 1866 state.addChecked(check); 1867 } 1868 } 1869 } 1870 if (rangeFacets != null) { 1871 Map<String, I_CmsSearchControllerFacetRange> rangeFacetControllers = controller.getRangeFacets().getRangeFacetController(); 1872 for (Map.Entry<String, List<String>> facetEntry : rangeFacets.entrySet()) { 1873 I_CmsSearchStateFacet state = rangeFacetControllers.get(facetEntry.getKey()).getState(); 1874 state.clearChecked(); 1875 for (String check : facetEntry.getValue()) { 1876 state.addChecked(check); 1877 } 1878 } 1879 } 1880 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(additionalQuery)) { 1881 controller.getCommon().getState().setQuery(additionalQuery); 1882 } else { 1883 resetTextSearch(); 1884 } 1885 1886 controller.addQueryParts(query, A_CmsUI.getCmsObject()); 1887 executeSearch(controller, query); 1888 } 1889 1890 /** 1891 * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String) 1892 */ 1893 @Override 1894 protected LinkedHashMap<String, String> getBreadCrumbForState(String state) { 1895 1896 LinkedHashMap<String, String> crumbs = new LinkedHashMap<String, String>(); 1897 if (CmsStringUtil.isEmptyOrWhitespaceOnly(state)) { 1898 crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0)); 1899 } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly( 1900 A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) { 1901 crumbs.put( 1902 CmsListManagerConfiguration.APP_ID, 1903 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_TITLE_0)); 1904 String title = ""; 1905 try { 1906 title = A_CmsUI.getCmsObject().readPropertyObject( 1907 m_currentResource, 1908 CmsPropertyDefinition.PROPERTY_TITLE, 1909 false).getValue(); 1910 } catch (Exception e) { 1911 // ignore 1912 } 1913 if ((m_currentResource != null) && CmsStringUtil.isEmptyOrWhitespaceOnly(title)) { 1914 title = m_currentResource.getName(); 1915 } 1916 crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_VIEW_1, title)); 1917 } 1918 return crumbs; 1919 } 1920 1921 /** 1922 * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String) 1923 */ 1924 @Override 1925 protected Component getComponentForState(String state) { 1926 1927 CmsObject cms = A_CmsUI.getCmsObject(); 1928 boolean showOverview = true; 1929 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly( 1930 A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX))) { 1931 try { 1932 CmsUUID id = new CmsUUID(A_CmsWorkplaceApp.getParamFromState(state, CmsEditor.RESOURCE_ID_PREFIX)); 1933 CmsResource res = cms.readResource(id, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1934 m_currentConfig = parseListConfiguration(A_CmsUI.getCmsObject(), res); 1935 String localeString = A_CmsWorkplaceApp.getParamFromState(state, PARAM_LOCALE); 1936 Locale locale; 1937 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(localeString)) { 1938 locale = CmsLocaleManager.getLocale(localeString); 1939 } else { 1940 locale = getContentLocale(m_currentConfig); 1941 } 1942 //SearchConfigParser configParser = new SearchConfigParser(m_currentConfig, m_collapseItemSeries, locale); 1943 CmsSimpleSearchConfigurationParser configParser = new CmsSimpleSearchConfigurationParser( 1944 cms, 1945 m_currentConfig, 1946 null); 1947 setBackendSpecificOptions(configParser, locale); 1948 search(configParser, res); 1949 showOverview = false; 1950 1951 } catch (Exception e) { 1952 CmsErrorDialog.showErrorDialog(e); 1953 LOG.error(e.getLocalizedMessage(), e); 1954 } 1955 } 1956 if (showOverview) { 1957 unlockCurrent(); 1958 m_lockAction = null; 1959 displayListConfigs(); 1960 } 1961 enableOverviewMode(showOverview); 1962 1963 return showOverview ? m_overviewTable : m_resultLayout; 1964 } 1965 1966 /** 1967 * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String) 1968 */ 1969 @Override 1970 protected List<NavEntry> getSubNavEntries(String state) { 1971 1972 return null; 1973 } 1974 1975 /** 1976 * Changes the search content locale, reissuing a search.<p> 1977 * 1978 * @param contentLocale the content locale to set 1979 */ 1980 void changeContentLocale(Locale contentLocale) { 1981 1982 if (!m_resetting) { 1983 m_currentConfigParser.setSearchLocale(contentLocale); 1984 } 1985 m_resultTable.setContentLocale(contentLocale); 1986 search(null, null, null); 1987 } 1988 1989 /** 1990 * Closes the edit dialog window.<p> 1991 */ 1992 void closeEditDialog() { 1993 1994 if (m_dialogWindow != null) { 1995 m_dialogWindow.close(); 1996 m_dialogWindow = null; 1997 } 1998 if (m_isOverView) { 1999 unlockCurrent(); 2000 m_currentResource = null; 2001 } 2002 } 2003 2004 /** 2005 * Opens the create new dialog.<p> 2006 */ 2007 void createNew() { 2008 2009 if (m_isOverView) { 2010 editListConfiguration(null); 2011 } 2012 } 2013 2014 /** 2015 * Displays the search result in the result table.<p> 2016 * 2017 * @param resultList the search result 2018 */ 2019 void displayResult(CmsSolrResultList resultList) { 2020 2021 List<CmsResource> resources; 2022 evalSeries(resultList); 2023 if (m_hideSeriesInstances) { 2024 Set<CmsUUID> instanceIds = new HashSet<CmsUUID>(); 2025 resources = new ArrayList<CmsResource>(); 2026 for (CmsSearchResource res : resultList) { 2027 if (!instanceIds.contains(res.getStructureId())) { 2028 instanceIds.add(res.getStructureId()); 2029 resources.add(res); 2030 } 2031 } 2032 } else { 2033 resources = new ArrayList<CmsResource>(resultList); 2034 } 2035 m_resultTable.fillTable(A_CmsUI.getCmsObject(), resources, true, false); 2036 String state = A_CmsWorkplaceApp.addParamToState( 2037 "", 2038 CmsEditor.RESOURCE_ID_PREFIX, 2039 m_currentResource.getStructureId().toString()); 2040 state = A_CmsWorkplaceApp.addParamToState( 2041 state, 2042 PARAM_LOCALE, 2043 m_currentConfigParser.getSearchLocale().toString()); 2044 m_currentState = state; 2045 CmsAppWorkplaceUi.get().changeCurrentAppState(state); 2046 if (m_isOverView) { 2047 enableOverviewMode(false); 2048 updateBreadCrumb(getBreadCrumbForState(state)); 2049 } 2050 } 2051 2052 /** 2053 * Edits the given list configuration resource.<p> 2054 * 2055 * @param resource the configuration resource 2056 */ 2057 void editListConfiguration(CmsResource resource) { 2058 2059 try { 2060 CmsObject cms = A_CmsUI.getCmsObject(); 2061 String editState; 2062 if (resource == null) { 2063 editState = CmsEditor.getEditStateForNew( 2064 cms, 2065 OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG), 2066 "/", 2067 null, 2068 false, 2069 UI.getCurrent().getPage().getLocation().toString()); 2070 } else { 2071 editState = CmsEditor.getEditState( 2072 resource.getStructureId(), 2073 false, 2074 UI.getCurrent().getPage().getLocation().toString()); 2075 } 2076 View view = CmsAppWorkplaceUi.get().getCurrentView(); 2077 if (view instanceof CmsAppView) { 2078 ((CmsAppView)view).setCacheStatus(CacheStatus.cacheOnce); 2079 } 2080 CmsAppWorkplaceUi.get().showApp( 2081 OpenCms.getWorkplaceAppManager().getAppConfiguration(CmsEditorConfiguration.APP_ID), 2082 editState); 2083 2084 } catch (CmsLoaderException e) { 2085 CmsErrorDialog.showErrorDialog(e); 2086 } 2087 } 2088 2089 /** 2090 * Enables the overview mode.<p> 2091 * 2092 * @param enabled <code>true</code> to enable the mode 2093 */ 2094 void enableOverviewMode(boolean enabled) { 2095 2096 boolean isOffline = !A_CmsUI.getCmsObject().getRequestContext().getCurrentProject().isOnlineProject(); 2097 m_publishButton.setVisible(!enabled); 2098 m_publishButton.setEnabled(isOffline); 2099 m_infoButton.setVisible(!enabled); 2100 m_tableFilter.setVisible(enabled); 2101 m_textSearch.setVisible(!enabled); 2102 m_editCurrentButton.setVisible(!enabled); 2103 m_editCurrentButton.setEnabled(isOffline); 2104 2105 m_toggleSeriesButton.setVisible(m_hasSeriesType && !enabled); 2106 m_resultSorter.setVisible(!enabled); 2107 m_localeSelect.setVisible(!enabled); 2108 m_isOverView = enabled; 2109 m_rootLayout.setMainContent(enabled ? m_overviewTable : m_resultLayout); 2110 m_createNewButton.setVisible(enabled); 2111 if (enabled) { 2112 if (!isOffline) { 2113 m_createNewButton.setEnabled(false); 2114 m_createNewButton.setDescription( 2115 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_ONLINE_0)); 2116 } else { 2117 CmsObject cms = A_CmsUI.getCmsObject(); 2118 CmsADEConfigData data = OpenCms.getADEManager().lookupConfiguration( 2119 cms, 2120 cms.getRequestContext().getSiteRoot()); 2121 CmsResourceTypeConfig typeConfig = data.getResourceType(RES_TYPE_LIST_CONFIG); 2122 try { 2123 if ((typeConfig == null) 2124 || !typeConfig.checkCreatable(cms, cms.getRequestContext().getSiteRoot())) { 2125 m_createNewButton.setEnabled(false); 2126 m_createNewButton.setDescription( 2127 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0)); 2128 } else { 2129 m_createNewButton.setEnabled(true); 2130 m_createNewButton.setDescription( 2131 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_CREATE_NEW_0)); 2132 } 2133 } catch (CmsException e) { 2134 m_createNewButton.setEnabled(false); 2135 m_createNewButton.setDescription( 2136 CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_NOT_CREATABLE_TYPE_0)); 2137 } 2138 } 2139 } 2140 } 2141 2142 /** 2143 * Evaluates if date series types are present and if more than one instance of a series is in the search result.<p> 2144 * 2145 * @param resultList the search result list 2146 */ 2147 void evalSeries(CmsSolrResultList resultList) { 2148 2149 m_hasSeriesType = false; 2150 m_hasSeriesInstances = false; 2151 Set<CmsUUID> instanceIds = new HashSet<CmsUUID>(); 2152 for (CmsSearchResource res : resultList) { 2153 String seriesType = res.getField(CmsSearchField.FIELD_SERIESDATES_TYPE); 2154 m_hasSeriesType = m_hasSeriesType || CmsStringUtil.isNotEmptyOrWhitespaceOnly(seriesType); 2155 if (m_hasSeriesType && I_CmsSerialDateValue.DateType.SERIES.name().equals(seriesType)) { 2156 if (instanceIds.contains(res.getStructureId())) { 2157 m_hasSeriesInstances = true; 2158 break; 2159 } else { 2160 instanceIds.add(res.getStructureId()); 2161 } 2162 } 2163 } 2164 if (!m_hasSeriesInstances) { 2165 setsDateSeriesHiddenFlag(false); 2166 } 2167 m_toggleSeriesButton.setEnabled(m_hasSeriesInstances); 2168 m_toggleSeriesButton.setVisible(m_hasSeriesType); 2169 2170 } 2171 2172 /** 2173 * Filters the result table.<p> 2174 * 2175 * @param filter the filter string 2176 */ 2177 void filterTable(String filter) { 2178 2179 if (!m_resetting) { 2180 m_overviewTable.filterTable(filter); 2181 } 2182 } 2183 2184 /** 2185 * Creates an element bean of the selected table item to be used with edit handlers.<p> 2186 * 2187 * @param context the dialog context 2188 * 2189 * @return the element bean 2190 */ 2191 CmsContainerElementBean getElementForEditHandler(DialogContext context) { 2192 2193 List<Item> selected = context.getSelectedItems(); 2194 if (selected.size() == 1) { 2195 Item item = selected.get(0); 2196 Date instanceDate = (Date)item.getItemProperty(INSTANCEDATE_PROPERTY).getValue(); 2197 CmsResource resource = context.getResources().get(0); 2198 return new CmsContainerElementBean( 2199 resource.getStructureId(), 2200 null, 2201 Collections.singletonMap( 2202 CmsDateSeriesEditHandler.PARAM_INSTANCEDATE, 2203 String.valueOf(instanceDate.getTime())), 2204 false); 2205 } 2206 return null; 2207 } 2208 2209 /** 2210 * Returns the resources to publish for the current list.<p> 2211 * 2212 * @return the publish resources 2213 */ 2214 List<CmsResource> getPublishResources() { 2215 2216 List<CmsResource> result = new ArrayList<CmsResource>(); 2217 if (m_currentResource != null) { 2218 result.add(m_currentResource); 2219 CmsObject cms = A_CmsUI.getCmsObject(); 2220 CmsSolrQuery query = m_currentConfigParser.getInitialQuery(); 2221 CmsSearchController controller = new CmsSearchController( 2222 new CmsSearchConfiguration(m_currentConfigParser, A_CmsUI.getCmsObject())); 2223 controller.getPagination().getState().setCurrentPage(1); 2224 controller.addQueryParts(query, A_CmsUI.getCmsObject()); 2225 I_CmsSearchConfigurationCommon commonConfig = controller.getCommon().getConfig(); 2226 CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(commonConfig.getSolrIndex()); 2227 try { 2228 CmsSolrResultList solrResultList = index.search( 2229 cms, 2230 query, 2231 true, 2232 null, 2233 false, 2234 CmsResourceFilter.IGNORE_EXPIRATION, 2235 commonConfig.getMaxReturnedResults()); 2236 result.addAll(solrResultList); 2237 } catch (CmsSearchException e) { 2238 LOG.error("Error reading resources for publish.", e); 2239 } 2240 } 2241 return result; 2242 } 2243 2244 /** 2245 * Returns whether the overview mode is active.<p> 2246 * 2247 * @return <code>true</code> in case the overview mode is active 2248 */ 2249 boolean isOverView() { 2250 2251 return m_isOverView; 2252 } 2253 2254 /** 2255 * Opens the publish dialog to publish all resources related to the current search configuration.<p> 2256 */ 2257 void publish() { 2258 2259 I_CmsUpdateListener<String> updateListener = new I_CmsUpdateListener<String>() { 2260 2261 @Override 2262 public void onUpdate(List<String> updatedItems) { 2263 2264 updateItems(updatedItems); 2265 } 2266 }; 2267 CmsAppWorkplaceUi.get().disableGlobalShortcuts(); 2268 CmsGwtDialogExtension extension = new CmsGwtDialogExtension(A_CmsUI.get(), updateListener); 2269 extension.openPublishDialog(getPublishResources()); 2270 } 2271 2272 /** 2273 * Refreshes the search result maintaining the current scroll position.<p> 2274 */ 2275 void refreshResult() { 2276 2277 String itemId = m_resultTable.getCurrentPageFirstItemId(); 2278 CmsFileExplorerSettings state = m_resultTable.getTableSettings(); 2279 search( 2280 m_resultFacets.getSelectedFieldFacets(), 2281 m_resultFacets.getSelectedRangeFactes(), 2282 m_textSearch.getValue()); 2283 m_resultTable.setTableState(state); 2284 m_resultTable.updateSorting(); 2285 m_resultTable.setCurrentPageFirstItemId(itemId); 2286 } 2287 2288 /** 2289 * Searches within the current list.<p> 2290 * 2291 * @param query the query string 2292 */ 2293 void search(String query) { 2294 2295 if (!m_resetting) { 2296 search(null, null, query); 2297 } 2298 } 2299 2300 /** 2301 * Sets the date series hidden flag.<p> 2302 * 2303 * @param hide the date series hidden flag 2304 */ 2305 void setsDateSeriesHiddenFlag(boolean hide) { 2306 2307 m_hideSeriesInstances = hide; 2308 if (m_hideSeriesInstances) { 2309 m_toggleSeriesButton.addStyleName(OpenCmsTheme.BUTTON_PRESSED); 2310 } else { 2311 m_toggleSeriesButton.removeStyleName(OpenCmsTheme.BUTTON_PRESSED); 2312 } 2313 } 2314 2315 /** 2316 * Sorts the search result.<p> 2317 */ 2318 void sortResult() { 2319 2320 if (!m_resetting) { 2321 search( 2322 m_resultFacets.getSelectedFieldFacets(), 2323 m_resultFacets.getSelectedRangeFactes(), 2324 m_textSearch.getValue()); 2325 } 2326 } 2327 2328 /** 2329 * Toggles the date series filter.<p> 2330 */ 2331 void toggleDateSeries() { 2332 2333 setsDateSeriesHiddenFlag(!m_hideSeriesInstances); 2334 refreshResult(); 2335 } 2336 2337 /** 2338 * Tries to unlocks the current resource if available.<p> 2339 */ 2340 void tryUnlockCurrent() { 2341 2342 if ((m_lockAction != null) && m_lockAction.getChange().equals(CmsLockActionRecord.LockChange.locked)) { 2343 try { 2344 A_CmsUI.getCmsObject().unlockResource(m_currentResource); 2345 } catch (CmsException e) { 2346 e.printStackTrace(); 2347 } 2348 } 2349 } 2350 2351 /** 2352 * Unlocks the current resource in case it has been locked by previous actions.<p> 2353 */ 2354 void unlockCurrent() { 2355 2356 if (m_currentResource != null) { 2357 if ((m_lockAction != null) && m_lockAction.getChange().equals(LockChange.locked)) { 2358 CmsLockUtil.tryUnlock(A_CmsUI.getCmsObject(), m_currentResource); 2359 } 2360 } 2361 m_lockAction = null; 2362 } 2363 2364 /** 2365 * Updates the given items in the result table.<p> 2366 * 2367 * @param updatedItems the items to update 2368 */ 2369 void updateItems(List<String> updatedItems) { 2370 2371 Set<CmsUUID> ids = new HashSet<CmsUUID>(); 2372 for (String id : updatedItems) { 2373 ids.add(new CmsUUID(id)); 2374 } 2375 m_resultTable.update(ids, false); 2376 } 2377 2378 /** 2379 * Displays the list config resources.<p> 2380 */ 2381 private void displayListConfigs() { 2382 2383 CmsObject cms = A_CmsUI.getCmsObject(); 2384 resetTableFilter(); 2385 try { 2386 // display the search configuration overview 2387 List<CmsResource> resources = cms.readResources( 2388 "/", 2389 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType( 2390 OpenCms.getResourceManager().getResourceType(RES_TYPE_LIST_CONFIG))); 2391 m_overviewTable.fillTable(cms, resources); 2392 } catch (Exception e) { 2393 CmsErrorDialog.showErrorDialog(e); 2394 LOG.error(e.getLocalizedMessage(), e); 2395 } 2396 } 2397 2398 /** 2399 * Executes a search.<p> 2400 * 2401 * @param controller the search controller 2402 * @param query the SOLR query 2403 */ 2404 private void executeSearch(CmsSearchController controller, CmsSolrQuery query) { 2405 2406 CmsObject cms = A_CmsUI.getCmsObject(); 2407 I_CmsSearchConfigurationCommon commonConfig = controller.getCommon().getConfig(); 2408 CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(commonConfig.getSolrIndex()); 2409 try { 2410 CmsSolrResultList solrResultList = index.search( 2411 cms, 2412 query, 2413 true, 2414 null, 2415 false, 2416 CmsResourceFilter.IGNORE_EXPIRATION, 2417 commonConfig.getMaxReturnedResults()); 2418 displayResult(solrResultList); 2419 m_resultFacets.displayFacetResult( 2420 solrResultList, 2421 new CmsSearchResultWrapper(controller, solrResultList, query, cms, null)); 2422 } catch (CmsSearchException e) { 2423 CmsErrorDialog.showErrorDialog(e); 2424 2425 LOG.error("Error executing search.", e); 2426 } 2427 } 2428 2429 /** 2430 * Returns the content locale configured for the first search root folder of the search configuration.<p> 2431 * 2432 * @param bean the search configuration data 2433 * 2434 * @return the locale 2435 */ 2436 private Locale getContentLocale(ListConfigurationBean bean) { 2437 2438 CmsObject cms = A_CmsUI.getCmsObject(); 2439 if (bean.getFolders().isEmpty()) { 2440 return OpenCms.getLocaleManager().getDefaultLocale(cms, "/"); 2441 } else { 2442 return OpenCms.getLocaleManager().getDefaultLocale( 2443 cms, 2444 cms.getRequestContext().removeSiteRoot(m_currentConfig.getFolders().get(0))); 2445 } 2446 } 2447 2448 /** 2449 * Resets the locale select according to the current configuration data.<p> 2450 * 2451 * @param defaultLocale the default content locale 2452 */ 2453 private void resetContentLocale(Locale defaultLocale) { 2454 2455 m_resetting = true; 2456 m_localeSelect.removeAllItems(); 2457 if (m_currentConfig.getFolders().isEmpty()) { 2458 m_localeSelect.addItem(defaultLocale); 2459 m_localeSelect.setItemCaption(defaultLocale, defaultLocale.getDisplayLanguage(UI.getCurrent().getLocale())); 2460 } else { 2461 for (String folder : m_currentConfig.getFolders()) { 2462 for (Locale locale : OpenCms.getLocaleManager().getAvailableLocales(A_CmsUI.getCmsObject(), folder)) { 2463 if (!m_localeSelect.containsId(locale)) { 2464 m_localeSelect.addItem(locale); 2465 m_localeSelect.setItemCaption(locale, locale.getDisplayLanguage(UI.getCurrent().getLocale())); 2466 } 2467 } 2468 } 2469 } 2470 m_localeSelect.setValue(defaultLocale); 2471 m_localeSelect.setEnabled(m_localeSelect.getItemIds().size() > 1); 2472 m_resetting = false; 2473 } 2474 2475 /** 2476 * Resets the table filter.<p> 2477 */ 2478 private void resetTableFilter() { 2479 2480 m_resetting = true; 2481 m_tableFilter.clear(); 2482 m_resetting = false; 2483 } 2484 2485 /** 2486 * Resets the text search input.<p> 2487 */ 2488 private void resetTextSearch() { 2489 2490 m_resetting = true; 2491 m_textSearch.clear(); 2492 m_resetting = false; 2493 } 2494 2495 /** 2496 * Sets options which are specific to the backend list manager on the cnofiguration parser.<p> 2497 * 2498 * @param configParser the configuration parser 2499 * @param locale the search locale 2500 */ 2501 private void setBackendSpecificOptions(CmsSimpleSearchConfigurationParser configParser, Locale locale) { 2502 2503 configParser.setSearchLocale(locale); 2504 configParser.setIgnoreBlacklist(true); 2505 configParser.setPagination(PAGINATION); 2506 } 2507}