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.ade.sitemap.client.attributes; 029 030import org.opencms.ade.sitemap.client.CmsSitemapView; 031import org.opencms.ade.sitemap.client.Messages; 032import org.opencms.ade.sitemap.shared.CmsSitemapAttributeData; 033import org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapServiceAsync; 034import org.opencms.gwt.client.rpc.CmsRpcAction; 035import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 036import org.opencms.gwt.client.ui.input.I_CmsFormField; 037import org.opencms.gwt.client.ui.input.I_CmsFormWidget; 038import org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel; 039import org.opencms.gwt.client.ui.input.form.CmsBasicFormField; 040import org.opencms.gwt.client.ui.input.form.CmsDialogFormHandler; 041import org.opencms.gwt.client.ui.input.form.CmsForm; 042import org.opencms.gwt.client.ui.input.form.CmsFormDialog; 043import org.opencms.gwt.client.ui.input.form.CmsFormRow; 044import org.opencms.gwt.client.ui.input.form.CmsInfoBoxFormFieldPanel; 045import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry; 046import org.opencms.gwt.client.ui.input.form.I_CmsFormSubmitHandler; 047import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory; 048import org.opencms.gwt.shared.CmsListInfoBean; 049import org.opencms.util.CmsUUID; 050import org.opencms.xml.content.CmsXmlContentProperty; 051 052import java.util.Collections; 053import java.util.Map; 054import java.util.Set; 055 056import com.google.common.base.Optional; 057import com.google.gwt.event.logical.shared.AttachEvent; 058import com.google.gwt.event.shared.HandlerRegistration; 059import com.google.gwt.user.client.Window; 060import com.google.gwt.user.client.ui.Widget; 061 062import jsinterop.annotations.JsMethod; 063 064/** 065 * Sitemap attribute editor dialog. 066 */ 067public class CmsAttributesDialog extends CmsFormDialog { 068 069 /** 070 * Field panel for the form fields. 071 */ 072 public static class FieldPanel extends CmsInfoBoxFormFieldPanel { 073 074 /** 075 * Creates a new instance. 076 * 077 * @param info the list info bean for the sitemap configuration file 078 */ 079 public FieldPanel(CmsListInfoBean info) { 080 081 super(info); 082 } 083 084 /** 085 * @see org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel#createRow(org.opencms.gwt.client.ui.input.I_CmsFormField) 086 */ 087 @Override 088 protected CmsFormRow createRow(I_CmsFormField field) { 089 090 // show description on help icons instead of the title 091 CmsFormRow row = createRow( 092 field.getLabel(), 093 A_CmsFormFieldPanel.NO_DESCRIPTION, 094 (Widget)field.getWidget(), 095 field.getDescription(), 096 true); 097 return row; 098 } 099 100 } 101 102 /** The sitemap attribute data. */ 103 private CmsSitemapAttributeData m_data; 104 105 /** The registration for the WindowClose handler registered by this dialog. */ 106 private HandlerRegistration m_windowCloseRegistration; 107 108 /** 109 * Creates a new instance. 110 * 111 * @param data the sitemap attribute data 112 */ 113 public CmsAttributesDialog(CmsSitemapAttributeData data) { 114 115 super(Messages.get().key(Messages.GUI_EDIT_ATTRIBUTES_0), new CmsForm(false), null); 116 setAnimationEnabled(false); 117 setUseAnimation(false); 118 addStyleName(I_CmsLayoutBundle.INSTANCE.attributeEditorCss().attributeEditor()); 119 m_data = data; 120 121 I_CmsFormSubmitHandler submitHandler = new I_CmsFormSubmitHandler() { 122 123 /** 124 * @see org.opencms.gwt.client.ui.input.form.I_CmsFormSubmitHandler#onSubmitForm(org.opencms.gwt.client.ui.input.form.CmsForm, java.util.Map, java.util.Set) 125 */ 126 public void onSubmitForm( 127 CmsForm formParam, 128 final Map<String, String> fieldValues, 129 Set<String> editedFields) { 130 131 final I_CmsSitemapServiceAsync service = CmsSitemapView.getInstance().getController().getService(); 132 CmsRpcAction<Void> action = new CmsRpcAction<Void>() { 133 134 @Override 135 public void execute() { 136 137 start(0, true); 138 CmsUUID rootId = CmsSitemapView.getInstance().getController().getData().getRoot().getId(); 139 // We need to send all values to the server, not just the edited ones, because when an inherited 140 // value from a parent sitemap has changed to match the value explicitly set in a child sitemap, we want 141 // to clear the value from the child sitemap even if the user hasn't edited it just now. 142 service.saveSitemapAttributes(rootId, fieldValues, this); 143 } 144 145 @SuppressWarnings("synthetic-access") 146 @Override 147 protected void onResponse(Void result) { 148 149 stop(false); 150 sendUnlockRequest(); 151 } 152 }; 153 action.execute(); 154 } 155 }; 156 CmsDialogFormHandler formHandler = new CmsDialogFormHandler(); 157 formHandler.setSubmitHandler(submitHandler); 158 getForm().setWidget(new FieldPanel(data.getInfo())); 159 getForm().setFormHandler(formHandler); 160 formHandler.setDialog(this); 161 for (Map.Entry<String, CmsXmlContentProperty> attrEntry : m_data.getAttributeDefinitions().entrySet()) { 162 String attrName = attrEntry.getKey(); 163 CmsXmlContentProperty definition = attrEntry.getValue(); 164 CmsBasicFormField field = CmsBasicFormField.createField( 165 definition, 166 definition.getName(), 167 new I_CmsFormWidgetMultiFactory() { 168 169 public I_CmsFormWidget createFormWidget( 170 String widgetName, 171 Map<String, String> widgetParams, 172 Optional<String> defaultValue) { 173 174 return CmsWidgetFactoryRegistry.instance().createFormWidget( 175 widgetName, 176 widgetParams, 177 defaultValue); 178 } 179 }, 180 Collections.<String, String> emptyMap(), 181 false); 182 getForm().addField(field, m_data.getAttributeValues().get(attrName)); 183 } 184 addAttachHandler(event -> handleAttach(event)); 185 getForm().render(); 186 } 187 188 /** 189 * Native method - navigator.sendBeacon(). 190 * 191 * @param target the target URL 192 * @param data the data to send to the target URL 193 */ 194 @JsMethod(namespace = "navigator") 195 private static native void sendBeacon(String target, String data); 196 197 /** 198 * @see com.google.gwt.user.client.ui.PopupPanel#setPopupPosition(int, int) 199 */ 200 @Override 201 public void setPopupPosition(int left, int top) { 202 203 // handled by CSS 204 } 205 206 /** 207 * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#show() 208 */ 209 @Override 210 public void show() { 211 212 super.show(); 213 // positioning handled by CSS 214 getElement().getStyle().clearPosition(); 215 getElement().getStyle().clearLeft(); 216 getElement().getStyle().clearTop(); 217 218 } 219 220 /** 221 * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#onClickCancel() 222 */ 223 @Override 224 protected void onClickCancel() { 225 226 super.onClickCancel(); 227 sendUnlockRequest(); 228 } 229 230 /** 231 * Handles attach/detach events for the dialog. 232 * 233 * @param event the attach/detach event 234 */ 235 private void handleAttach(AttachEvent event) { 236 237 if (event.isAttached()) { 238 m_windowCloseRegistration = Window.addWindowClosingHandler(closingEvent -> sendUnlockRequest()); 239 } else { 240 m_windowCloseRegistration.removeHandler(); 241 } 242 } 243 244 /** 245 * Tells the server to unlock the sitemap configuration. 246 */ 247 private void sendUnlockRequest() { 248 249 sendBeacon(m_data.getUnlockUrl(), ""); 250 251 } 252}