From fa56786e530f2bb15de7e431d4aedfedd7939dad Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 8 Jun 2012 16:56:26 +0000 Subject: [PATCH] =?UTF-8?q?Neuer=20Tab=20im=20ItemSearchWidget:=20Zeigt=20?= =?UTF-8?q?eine=20flache=20Liste=20aller=20Items=20(eines=20bestimmten=20T?= =?UTF-8?q?yps)=20an.=20Erlaubt=20das=20Filtern=20der=20Liste=20nach=20Nam?= =?UTF-8?q?e/Titel.=20Au=C3=9Ferdem=20Ver=C3=A4nderung=20Erscheinungsbild:?= =?UTF-8?q?=20Das=20Feld=20f=C3=BCr=20die=20ID=20des=20ausgew=C3=A4hlten?= =?UTF-8?q?=20Items=20ist=20jetzt=20nicht=20mehr=20sichtbar,=20statt=20des?= =?UTF-8?q?sen=20wird=20ein=20Text-Feld=20anzeigt=20in=20dem=20der=20Titel?= =?UTF-8?q?=20des=20ausgew=C3=A4hlten=20Items=20angezeigt=20wird.=20Was=20?= =?UTF-8?q?noch=20fehlt=20ist=20=C3=9Cbernahme=20eines=20in=20diesem=20Fel?= =?UTF-8?q?d=20eingegebenen=20Strings=20in=20das=20ItemSearch-Widget.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://svn.libreccm.org/ccm/trunk@1700 8810af33-2d31-482b-a856-94f89814c4df --- .../com/arsdigita/cms/CMSResources.properties | 6 + .../arsdigita/cms/CMSResources_de.properties | 6 + .../cms/CMSResources_en_GB.properties | 6 + .../arsdigita/cms/CMSResources_fr.properties | 6 + .../cms/ui/ItemSearchFlatBrowsePane.java | 239 ++++++++++++++++++ .../com/arsdigita/cms/ui/ItemSearchPage.java | 12 + .../arsdigita/cms/ui/ItemSearchParameter.java | 49 ++-- .../arsdigita/cms/ui/ItemSearchWidget.java | 29 ++- 8 files changed, 320 insertions(+), 33 deletions(-) create mode 100644 ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources.properties index 6bd1af98b..e8098e31d 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources.properties @@ -1092,3 +1092,9 @@ cms.ui.item.lifecycle.publish_locked.update=Update cms.ui.lifecycle.publish.error=An error occured while publishing this item.The system administrator has been notified about this problem. This item will stay locked until the lock is removed by the system administrator manually. cms.ui.delete_confirmation=Permanently delete this item? cms.ui.lifecycle.details.last_published=Item last (re-)published +cms.ui.item_search.flat.filter=Filter list +cms.ui.item_search.flat.no_items=No items matching the filter found +cms.ui.item_search.flat.title=Title +cms.ui.item_search.flat.place=Place +cms.ui.item_search.flat.type=Type +cms.ui.item_search.flatBrowse=Select item diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties index cf71eeee7..b650da59c 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_de.properties @@ -1083,3 +1083,9 @@ cms.ui.item.lifecycle.publish_locked.update=Aktualisieren cms.ui.lifecycle.publish.error=W\u00e4hrend des Publizierens ist ein Fehler aufgetreten. Der System-Administrator wurde per \u00fcber das Problem informiert. Dieses Item bleibt besperrt, bis der Administrator die Sperre manuell entfernt. cms.ui.delete_confirmation=Wollen Sie dieses Content-Item l\u00f6schen? cms.ui.lifecycle.details.last_published=Das Item wurde zuletzt republiziert am +cms.ui.item_search.flat.filter=Liste filtern +cms.ui.item_search.flat.no_items=Kein Item entspricht dem Filter +cms.ui.item_search.flat.title=Titel +cms.ui.item_search.flat.place=Ort +cms.ui.item_search.flat.type=Typ +cms.ui.item_search.flatBrowse=Item ausw\u00e4hlen diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties index 85f3e5ec0..c1fa76778 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_en_GB.properties @@ -31,3 +31,9 @@ cms.ui.item.lifecycle.publish_locked.update= cms.ui.lifecycle.publish.error= cms.ui.delete_confirmation= cms.ui.lifecycle.details.last_published= +cms.ui.item_search.flat.filter= +cms.ui.item_search.flat.no_items= +cms.ui.item_search.flat.title=Title +cms.ui.item_search.flat.place=Place +cms.ui.item_search.flat.type=Type +cms.ui.item_search.flatBrowse=Select item diff --git a/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties b/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties index 8b513b9ce..dcf4f435c 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties +++ b/ccm-cms/src/com/arsdigita/cms/CMSResources_fr.properties @@ -562,3 +562,9 @@ cms.ui.item.lifecycle.publish_locked.update= cms.ui.lifecycle.publish.error= cms.ui.delete_confirmation= cms.ui.lifecycle.details.last_published= +cms.ui.item_search.flat.filter= +cms.ui.item_search.flat.no_items= +cms.ui.item_search.flat.title=Title +cms.ui.item_search.flat.place=Place +cms.ui.item_search.flat.type=Type +cms.ui.item_search.flatBrowse=Select item diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java new file mode 100644 index 000000000..29f45f8f2 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFlatBrowsePane.java @@ -0,0 +1,239 @@ +package com.arsdigita.cms.ui; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.cms.ContentBundle; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentPage; +import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.Folder; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.Session; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.util.LockableImpl; +import java.math.BigDecimal; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class ItemSearchFlatBrowsePane extends Form implements FormInitListener, FormProcessListener { + + private static final String QUERY_PARAM = "query"; + public static final String WIDGET_PARAM = "widget"; + public static final String SEARCHWIDGET_PARAM = "searchWidget"; + private final Table resultsTable; + private final StringParameter queryParam; + + + public ItemSearchFlatBrowsePane(final String name) { + super(name); + + queryParam = new StringParameter(QUERY_PARAM); + + final BoxPanel boxPanel = new BoxPanel(BoxPanel.HORIZONTAL); + boxPanel.add(new Label(GlobalizationUtil.globalize("cms.ui.item_search.flat.filter"))); + final TextField filter = new TextField(new StringParameter(QUERY_PARAM)); + boxPanel.add(filter); + add(boxPanel); + + resultsTable = new ResultsTable(); + add(resultsTable); + + addInitListener(this); + addProcessListener(this); + } + + @Override + public void register(final Page page) { + super.register(page); + page.addComponentStateParam(this, queryParam); + } + + public void init(final FormSectionEvent fse) throws FormProcessException { + + } + + public void process(final FormSectionEvent fse) throws FormProcessException { + final FormData data = fse.getFormData(); + final PageState state = fse.getPageState(); + + state.setValue(queryParam, data.get(QUERY_PARAM)); + } + + private class ResultsTable extends Table { + + private static final String TABLE_COL_TITLE = "title"; + private static final String TABLE_COL_PLACE = "place"; + private static final String TABLE_COL_TYPE = "type"; + + public ResultsTable() { + super(); + setEmptyView(new Label(GlobalizationUtil.globalize("cms.ui.item_search.flat.no_items"))); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn(0, + GlobalizationUtil.globalize("cms.ui.item_search.flat.title").localize(), + TABLE_COL_TITLE)); + columnModel.add(new TableColumn(1, + GlobalizationUtil.globalize("cms.ui.item_search.flat.place").localize(), + TABLE_COL_PLACE)); + columnModel.add(new TableColumn(2, + GlobalizationUtil.globalize("cms.ui.item_search.flat.type").localize(), + TABLE_COL_TYPE)); + + setModelBuilder(new ResultsTableModelBuilder()); + + columnModel.get(0).setCellRenderer(new TitleCellRenderer()); + } + + } + + private class ResultsTableModelBuilder extends LockableImpl implements TableModelBuilder { + + public TableModel makeModel(final Table table, final PageState state) { + return new ResultsTableModel(table, state); + } + + } + + private class ResultsTableModel implements TableModel { + + private final Table table; + private final DataCollection collection; + private ContentItem currentItem; + + public ResultsTableModel(final Table table, final PageState state) { + this.table = table; + final Session session = SessionManager.getSession(); + final BigDecimal typeId = (BigDecimal) state.getValue(new BigDecimalParameter(ItemSearch.SINGLE_TYPE_PARAM)); + if (typeId == null) { + collection = session.retrieve(ContentPage.BASE_DATA_OBJECT_TYPE); + } else { + final ContentType type = new ContentType(typeId); + collection = session.retrieve(type.getClassName()); + } + + final String query = (String) state.getValue(queryParam); + if ((query != null) && !query.isEmpty()) { + collection.addFilter(String.format("(lower(%s) like lower('%%%s%%')) or (lower(%s) like lower('%%%s%%'))", + ContentItem.NAME, query, + ContentPage.TITLE, query)); + } + } + + public int getColumnCount() { + return table.getColumnModel().size(); + } + + public boolean nextRow() { + boolean ret; + + if ((collection != null) && collection.next()) { + currentItem = (ContentItem) DomainObjectFactory.newInstance(collection.getDataObject()); + ret = true; + } else { + ret = false; + } + + return ret; + } + + public Object getElementAt(final int columnIndex) { + switch (columnIndex) { + case 0: + if (currentItem instanceof ContentPage) { + return ((ContentPage) currentItem).getTitle(); + } else { + return currentItem.getName(); + } + case 1: + return getItemPath(currentItem); + case 2: + return currentItem.getContentType().getLabel(); + default: + return null; + } + } + + private String getItemPath(final ContentItem item) { + final StringBuilder path = new StringBuilder(item.getName()); + + ContentItem current = item; + + while (current.getParent() != null) { + if (current.getParent() instanceof ContentBundle) { + current = (ContentBundle) current.getParent(); + } else if (current.getParent() instanceof Folder) { + current = (Folder) current.getParent(); + if (!current.getName().equals("/")) { + path.insert(0, '/'); + path.insert(0, current.getName()); + } + } + } + + path.insert(0, ":/"); + path.insert(0, item.getContentSection().getName()); + + return path.toString(); + } + + public Object getKeyAt(final int columnIndex) { + return currentItem.getID(); + } + } + + private class TitleCellRenderer extends LockableImpl implements TableCellRenderer { + + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final Link link = new Link(value.toString(), ""); + + final String widget = (String) state.getValue(new StringParameter(WIDGET_PARAM)); + final String searchWidget = (String) state.getValue(new StringParameter(SEARCHWIDGET_PARAM)); + + final ContentPage page = new ContentPage((BigDecimal) key); + + link.setOnClick(String.format( + "window.opener.document.%s.value=\"%s\";window.opener.document.%s.value=\"%s\";self.close();return false;", + widget, + key.toString(), + searchWidget, + page.getTitle())); + + return link; + } + + + + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPage.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPage.java index 1006c7bc1..9794f2270 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPage.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchPage.java @@ -54,6 +54,7 @@ public class ItemSearchPage extends CMSPage { private final static String XSL_CLASS = "CMS Admin"; private TabbedPane m_tabbedPane; + private ItemSearchFlatBrowsePane m_flatBrowse; private ItemSearchBrowsePane m_browse; private ItemSearchPopup m_search; //private ItemSearchCreateItemPane m_create; @@ -72,11 +73,13 @@ public class ItemSearchPage extends CMSPage { addGlobalStateParam(new BigDecimalParameter(ItemSearch.SINGLE_TYPE_PARAM)); addGlobalStateParam(new StringParameter(ItemSearchPopup.WIDGET_PARAM)); + addGlobalStateParam(new StringParameter("searchWidget")); m_sectionId = new BigDecimalParameter(CONTENT_SECTION); addGlobalStateParam(m_sectionId); m_browse = getBrowsePane(); + m_flatBrowse = getFlatBrowsePane(); m_search = getSearchPane(); // m_create = getCreatePane(); @@ -98,6 +101,14 @@ public class ItemSearchPage extends CMSPage { return m_browse; } + protected ItemSearchFlatBrowsePane getFlatBrowsePane() { + if (m_flatBrowse == null) { + m_flatBrowse = new ItemSearchFlatBrowsePane("flatBrowse"); + } + + return m_flatBrowse; + } + /** * Creates, and then caches, the Creation pane. Overriding this * method to return null will prevent this tab from appearing. @@ -135,6 +146,7 @@ public class ItemSearchPage extends CMSPage { TabbedPane pane = new TabbedPane(); pane.setClassAttr(XSL_CLASS); + addToPane(pane, "flatBrowse", getFlatBrowsePane()); addToPane(pane, "browse", getBrowsePane()); addToPane(pane, "search", getSearchPane()); // addToPane(pane, "create", getCreatePane()); diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java index f2775b455..3b7e5e867 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java @@ -38,7 +38,6 @@ import java.math.BigDecimal; * * @author Scott Seago */ - public class ItemSearchParameter extends StringParameter { private ContentType m_contentType; @@ -50,10 +49,9 @@ public class ItemSearchParameter extends StringParameter { * @param name the name of the request parameter from which item */ public ItemSearchParameter(String name) { - this(name,null); + this(name, null); } - /** * Create a new item search parameter corresponding to a request parameter * with the given name. @@ -62,10 +60,10 @@ public class ItemSearchParameter extends StringParameter { * @param contentType If not null, search will be limited to the * specified content type */ - public ItemSearchParameter(String name, - ContentType contentType) { + public ItemSearchParameter(String name, + ContentType contentType) { super(name); - m_contentType = contentType; + m_contentType = contentType; } /** @@ -80,22 +78,27 @@ public class ItemSearchParameter extends StringParameter { */ @Override public Object transformValue(HttpServletRequest request) - throws IllegalArgumentException { + throws IllegalArgumentException { String itemStr = Globalization.decodeParameter(request, getName()); - + return unmarshal(itemStr); } @Override public Object unmarshal(String encoded) - throws IllegalArgumentException { + throws IllegalArgumentException { // As stated above, if we get an invalid address just return null. if (encoded == null || encoded.length() < 1) { return null; - } - String idStr = encoded.substring(0,encoded.indexOf(' ')); + } + String idStr; + if (encoded.indexOf(' ') < 0) { + idStr = encoded; + } else { + idStr = encoded.substring(0, encoded.indexOf(' ')); + } if (idStr == null || idStr.length() < 1) { return null; } @@ -105,19 +108,15 @@ public class ItemSearchParameter extends StringParameter { } ContentItem contentItem; try { - contentItem = (ContentItem) DomainObjectFactory.newInstance - (new OID(ContentItem.BASE_DATA_OBJECT_TYPE, itemID)); + contentItem = (ContentItem) DomainObjectFactory.newInstance(new OID(ContentItem.BASE_DATA_OBJECT_TYPE, + itemID)); } catch (DataObjectNotFoundException e) { - throw new IllegalArgumentException - (encoded + - " is not a valid contentItem." + - e.getMessage()); + throw new IllegalArgumentException(encoded + " is not a valid contentItem." + e.getMessage()); + } + + if (m_contentType != null && !contentItem.isContentType(m_contentType)) { + return null; } - - if (m_contentType != null && - !contentItem.isContentType(m_contentType)) { - return null; - } return contentItem; } @@ -126,11 +125,11 @@ public class ItemSearchParameter extends StringParameter { if (value == null) { return null; } else { - ContentPage theItem = (ContentPage) value; - return (theItem.getID().toString() + " (" + theItem.getTitle() + ")"); + ContentPage theItem = (ContentPage) value; + return (theItem.getID().toString() + " (" + theItem.getTitle() + ")"); } } - + @Override public Class getValueClass() { return ContentPage.class; diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java index 3a197cbcc..52c9357c0 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java @@ -30,10 +30,12 @@ import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSubmissionListener; import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.form.Hidden; import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.form.TextField; import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.util.BebopConstants; import com.arsdigita.cms.CMS; import com.arsdigita.cms.ContentItem; @@ -55,6 +57,7 @@ public class ItemSearchWidget extends FormSection implements BebopConstants, FormSubmissionListener, FormInitListener { private static final Logger s_log = Logger.getLogger(ItemSearchWidget.class); + private Hidden m_selected; private TextField m_item; private Submit m_search; private Submit m_clear; @@ -67,7 +70,9 @@ public class ItemSearchWidget extends FormSection private String m_searchName; private String m_clearName; private ParameterModel m_model; + private ParameterModel m_searchModel; public static final String BEBOP_ITEM_SEARCH = "bebop:itemSearch"; + public static final String SEARCH = "search"; public static final boolean LIMIT_TO_CONTENT_SECTION = false; private class ItemFragment extends TextField { @@ -77,7 +82,7 @@ public class ItemSearchWidget extends FormSection public ItemFragment(ParameterModel parameter, ItemSearchWidget parent) { super(parameter); this.parent = parent; - this.setReadOnly(); + //this.setReadOnly(); this.setSize(35); } } @@ -89,7 +94,7 @@ public class ItemSearchWidget extends FormSection public SearchFragment(String name, ItemSearchWidget parent) { super(name, "Search"); this.parent = parent; - this.setAttribute("onClick", "return " + parent.m_item.getName(). + this.setAttribute("onClick", "return " + parent.m_selected.getName(). //+ parent.m_item.getName(). replace('.', '_') + "Popup(this.form)"); this.setAttribute("value", "Search"); } @@ -109,7 +114,7 @@ public class ItemSearchWidget extends FormSection public ClearFragment(String name, ItemSearchWidget parent) { super(name, "Clear"); this.parent = parent; - this.setAttribute("onClick", "this.form." + parent.m_item.getName() + this.setAttribute("onClick", "this.form." + parent.m_selected.getName() //parent.m_item.getName() + ".value = \"\"; return false;"); this.setAttribute("value", "Clear"); } @@ -199,9 +204,13 @@ public class ItemSearchWidget extends FormSection } else { typeURLFrag = null; } + + m_searchModel = new StringParameter(SEARCH); m_contentType = contentType; - m_item = new ItemFragment(model, this); + m_selected = new Hidden(model); + //m_item = new ItemFragment(model, this); + m_item = new TextField(m_searchModel); m_search = new SearchFragment(m_searchName, this); m_clear = new ClearFragment(m_clearName, this); m_jsLabel = new LabelFragment("", false, this); @@ -215,8 +224,9 @@ public class ItemSearchWidget extends FormSection ParameterMap params = new ParameterMap(); params.setParameter("section_id", CMS.getContext().getContentSection().getID()); - params.setParameter("widget", formName + ".elements['" + m_item. + params.setParameter("widget", formName + ".elements['" + m_selected. //m_item. getName() + "']"); + params.setParameter("searchWidget", formName + ".elements['" + m_item.getName() + "']"); if (typeURLFrag != null) { params.setParameter("single_type", typeURLFrag); } @@ -235,10 +245,12 @@ public class ItemSearchWidget extends FormSection t.setLabel(" "); @@ -249,6 +261,7 @@ public class ItemSearchWidget extends FormSection FormSection searchSection = new FormSection(new BoxPanel( BoxPanel.HORIZONTAL)); searchSection.add(m_item); + searchSection.add(m_selected); searchSection.add(m_search); searchSection.add(m_clear); searchSection.add(m_jsLabel);