1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.templating.editor.client;
35
36
37 import info.magnolia.templating.editor.client.jsni.LegacyJavascript;
38
39 import com.google.gwt.core.client.EntryPoint;
40 import com.google.gwt.core.client.GWT;
41 import com.google.gwt.dom.client.Document;
42 import com.google.gwt.dom.client.Element;
43 import com.google.gwt.dom.client.MetaElement;
44 import com.google.gwt.dom.client.Node;
45 import com.google.gwt.dom.client.NodeList;
46 import com.google.gwt.http.client.Request;
47 import com.google.gwt.http.client.RequestBuilder;
48 import com.google.gwt.http.client.RequestCallback;
49 import com.google.gwt.http.client.RequestException;
50 import com.google.gwt.http.client.Response;
51 import com.google.gwt.http.client.URL;
52 import com.google.gwt.http.client.UrlBuilder;
53 import com.google.gwt.i18n.client.Dictionary;
54 import com.google.gwt.user.client.Event;
55 import com.google.gwt.user.client.EventListener;
56 import com.google.gwt.user.client.Window;
57 import com.google.gwt.user.client.ui.HTML;
58
59
60
61
62
63
64 public class PageEditor extends HTML implements EventListener, EntryPoint {
65
66 public static final String MARKER_EDIT = "cms:edit";
67 public static final String MARKER_AREA = "cms:area";
68
69 private boolean pageEditBarAlreadyProcessed = false;
70 private String locale;
71 private static Dictionary dictionary;
72
73 @Override
74 public void onModuleLoad() {
75 Element documentElement = Document.get().getDocumentElement();
76
77 final NodeList<Element> edits = documentElement.getOwnerDocument().getElementsByTagName(MARKER_EDIT);
78 GWT.log("found " + edits.getLength() + " cms:edit tags");
79
80 final NodeList<Element> areas = documentElement.getOwnerDocument().getElementsByTagName(MARKER_AREA);
81 GWT.log("found " + areas.getLength() + " cms:area tags");
82
83 locale = detectCurrentLocale(documentElement);
84
85 LegacyJavascript.exposeMgnlMessagesToGwtDictionary("info.magnolia.module.admininterface.messages");
86 dictionary = Dictionary.getDictionary("mgnlGwtMessages");
87
88 processCmsTags(documentElement, null, edits, areas);
89
90 }
91
92 @Override
93 public void onBrowserEvent(Event event) {
94 super.onBrowserEvent(event);
95 }
96
97
98
99
100 public void openDialog(String dialog, String workspace, String path, String collectionName, String nodeName) {
101 if (collectionName == null) {
102 collectionName = "";
103 }
104 if (nodeName == null) {
105 nodeName = "";
106 }
107
108 LegacyJavascript.mgnlOpenDialog(path, collectionName, nodeName, dialog, workspace, "", "", "", locale);
109 }
110
111 public void moveComponentStart(String id) {
112 LegacyJavascript.mgnlMoveNodeStart(id);
113 }
114
115 public void moveComponentEnd(AbstractBarWidget source, String path) {
116 LegacyJavascript.mgnlMoveNodeEnd(source.getElement(), path);
117 }
118
119 public void moveComponentOver(AbstractBarWidget source) {
120 LegacyJavascript.mgnlMoveNodeHigh(source.getElement());
121 }
122
123 public void moveComponentOut(AbstractBarWidget source) {
124 LegacyJavascript.mgnlMoveNodeReset(source.getElement());
125 }
126
127 public void deleteComponent(String path) {
128 LegacyJavascript.mgnlDeleteNode(path);
129 }
130
131 public void addComponent(String workspace, String path, String collectionName, String nodeName, String availableComponents) {
132 if (collectionName == null) {
133 collectionName = "";
134 }
135 if (nodeName == null) {
136 nodeName = "mgnlNew";
137 }
138 if (availableComponents == null) {
139 availableComponents = "";
140 }
141 LegacyJavascript.mgnlOpenDialog(path, collectionName, nodeName, availableComponents, workspace, ".magnolia/dialogs/selectParagraph.html", "", "", locale);
142 }
143
144 public void preview(boolean isPreview) {
145 LegacyJavascript.mgnlPreview(isPreview);
146 }
147
148 public void showTree(String workspace, String path) {
149 LegacyJavascript.showTree(workspace, path);
150
151 }
152
153 public void createComponent(String workspace, String parent, String relPath, String itemType) {
154 GWT.log("Creating [" + itemType + "] in workspace [" + workspace + "] at path [" + parent + "/" + relPath + "]");
155
156 final StringBuilder url = new StringBuilder();
157 url.append(LegacyJavascript.getContextPath() + ".magnolia/pageeditor/PageEditorServlet");
158 url.append("?action=create");
159 url.append("&workspace=" + workspace);
160 url.append("&parent=" + parent);
161 url.append("&relPath=" + relPath);
162 url.append("&itemType=" + itemType);
163
164 RequestBuilder req = new RequestBuilder(RequestBuilder.GET, URL.encode(url.toString()));
165 req.setCallback(new RequestCallback() {
166
167 @Override
168 public void onResponseReceived(Request request, Response response) {
169 int status = response.getStatusCode();
170 String responseText = "";
171 boolean reload = false;
172
173 switch (status) {
174 case Response.SC_OK:
175 reload = true;
176 break;
177 case Response.SC_UNAUTHORIZED:
178 responseText = "Is your session expired? Please, try to login again.";
179 break;
180 default:
181 responseText = "See logs for more details.";
182 }
183
184 if (reload) {
185 UrlBuilder urlBuilder = Window.Location.createUrlBuilder();
186
187 urlBuilder.removeParameter("mgnlIntercept");
188 urlBuilder.removeParameter("mgnlPath");
189
190 Window.Location.replace(urlBuilder.buildString());
191 } else {
192 Window.alert("An error occurred on the server: response status code is " + status + "\n" + responseText);
193 }
194 }
195
196 @Override
197 public void onError(Request request, Throwable exception) {
198 Window.alert(exception.getMessage());
199 }
200 });
201 try {
202 req.send();
203 } catch (RequestException e) {
204 Window.alert("An error occurred while trying to send a request to the server: " + e.getMessage());
205 }
206
207 }
208
209
210
211
212 public static Dictionary getDictionary() {
213 return dictionary;
214 }
215
216
217
218
219
220 private String detectCurrentLocale(Element element) {
221 final NodeList<Element> meta = element.getOwnerDocument().getElementsByTagName("meta");
222 for (int i = 0; i < meta.getLength(); i++) {
223 MetaElement metaTag = ((MetaElement) meta.getItem(i));
224 if ("gwt:property".equals(metaTag.getName()) && metaTag.getContent().contains("locale")) {
225 String[] split = metaTag.getContent().split("=");
226 locale = split.length == 2 ? split[1] : "en";
227 GWT.log("Detected Locale " + locale);
228 break;
229 }
230 }
231 return locale;
232 }
233
234 private void processCmsTags(Element element, AreaBarWidget parentBar, NodeList<Element> edits, NodeList<Element> areas) {
235 for (int i = 0; i < element.getChildCount(); i++) {
236 Node childNode = element.getChild(i);
237 if (childNode.getNodeType() == Element.ELEMENT_NODE) {
238 Element child = (Element) childNode;
239 if (child.getTagName().equalsIgnoreCase(MARKER_EDIT)) {
240 GWT.log("processing element " + child);
241
242 if (!pageEditBarAlreadyProcessed) {
243 GWT.log("element was detected as page edit bar. Injecting it...");
244 PageBarWidget pageBarWidget = new PageBarWidget(this, child);
245 pageBarWidget.attach(child);
246 pageEditBarAlreadyProcessed = true;
247
248 if (pageBarWidget.isPreviewMode()) {
249
250 GWT.log("We're in preview mode, stop processing DOM.");
251 break;
252 }
253
254 } else if (!isAreaEditBar(child, areas)) {
255 GWT.log("element is a plain edit bar. Injecting it...");
256 EditBarWidget editBarWidget = new EditBarWidget(parentBar, this, child);
257 editBarWidget.attach(child);
258 }
259 } else if (child.getTagName().equalsIgnoreCase(MARKER_AREA)) {
260 GWT.log("processing element " + child);
261 Element edit = findCmsEditMarkerForArea(child, edits);
262 if (edit != null) {
263 GWT.log("element was detected as area edit bar. Injecting it...");
264 AreaBarWidget areaBarWidget = new AreaBarWidget(parentBar, this, child);
265 areaBarWidget.attach(edit);
266 parentBar = areaBarWidget;
267 }
268 }
269 processCmsTags(child, parentBar, edits, areas);
270 }
271 }
272 }
273
274
275
276
277
278
279 private boolean isAreaEditBar(Element edit, NodeList<Element> areas) {
280
281 String content = edit.getAttribute("content");
282 String name = edit.getAttribute("name");
283 boolean optional = Boolean.valueOf(edit.getAttribute("optional"));
284 String bestMatch = optional ? name : content;
285
286 for (int j = 0; j < areas.getLength(); j++) {
287
288 Element area = areas.getItem(j);
289
290 String areaContent = area.getAttribute("content");
291 String areaName = area.getAttribute("name");
292 boolean areaOptional = Boolean.valueOf(area.getAttribute("optional"));
293 boolean created = Boolean.valueOf(area.getAttribute("created"));
294
295 String areaMatch = areaContent + (LegacyJavascript.isNotEmpty(areaName) ? "/" + areaName : "");
296
297 if (areaOptional && !created) {
298 areaMatch = areaName;
299 }
300
301 if (bestMatch.equals(areaMatch)) {
302 GWT.log("element is an area edit bar (matched with [" + areaMatch + "])");
303 return true;
304 }
305 }
306 return false;
307 }
308
309
310
311
312
313
314 private Element findCmsEditMarkerForArea(Element area, NodeList<Element> edits) {
315 String content = area.getAttribute("content");
316 String name = area.getAttribute("name");
317 boolean optional = Boolean.valueOf(area.getAttribute("optional"));
318 boolean created = Boolean.valueOf(area.getAttribute("created"));
319
320 String bestMatch = optional && !created ? name : content + (LegacyJavascript.isNotEmpty(name) ? "/" + name : "");
321
322 GWT.log("Best match for " + (optional ? "optional" : "required") + " area and edit bar is [" + bestMatch + "]");
323
324 for (int i = 0; i < edits.getLength(); i++) {
325 Element edit = edits.getItem(i);
326 String toMatch = edit.getAttribute("content");
327 String editName = edit.getAttribute("name");
328 toMatch += (LegacyJavascript.isNotEmpty(editName) ? "/" + editName : "");
329 boolean editOptional = Boolean.valueOf(edit.getAttribute("optional"));
330
331 if (toMatch.equals(bestMatch) || (optional && editOptional && bestMatch.equals(editName))) {
332 GWT.log("found match with element " + edit);
333 return edit;
334 }
335 }
336 GWT.log("No match found. Area won't have an edit bar associated.");
337 return null;
338 }
339 }