View Javadoc
1   /**
2    * This file Copyright (c) 2012-2017 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.pages.app.editor;
35  
36  import info.magnolia.event.EventBus;
37  import info.magnolia.i18nsystem.SimpleTranslator;
38  import info.magnolia.pages.app.editor.event.ComponentMoveEvent;
39  import info.magnolia.pages.app.editor.event.NodeSelectedEvent;
40  import info.magnolia.pages.app.editor.parameters.PageEditorStatus;
41  import info.magnolia.ui.api.action.ActionExecutionException;
42  import info.magnolia.ui.api.action.ActionExecutor;
43  import info.magnolia.ui.api.app.SubAppContext;
44  import info.magnolia.ui.api.app.SubAppEventBus;
45  import info.magnolia.ui.api.message.Message;
46  import info.magnolia.ui.api.message.MessageType;
47  import info.magnolia.ui.api.overlay.AlertCallback;
48  import info.magnolia.ui.contentapp.detail.DetailLocation;
49  import info.magnolia.ui.vaadin.editor.PageEditorListener;
50  import info.magnolia.ui.vaadin.editor.PageEditorView;
51  import info.magnolia.ui.vaadin.editor.events.PageEditorNavigationEvent;
52  import info.magnolia.ui.vaadin.gwt.client.shared.AbstractElement;
53  import info.magnolia.ui.vaadin.gwt.client.shared.ErrorType;
54  import info.magnolia.ui.vaadin.gwt.client.shared.PageEditorParameters;
55  import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
56  
57  import javax.inject.Inject;
58  import javax.inject.Named;
59  import javax.inject.Singleton;
60  
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  import com.google.common.base.CaseFormat;
65  
66  /**
67   * Presenter for the server side {@link PageEditorView}.
68   * Serves multiple methods for actions triggered from the page editor.
69   */
70  @Singleton
71  public class PageEditorPresenter implements PageEditorListener {
72  
73      private static final Logger log = LoggerFactory.getLogger(PageEditorPresenter.class);
74      private static final String EXTERNAL_PAGE_CAPTION = "pages.edit.external.page.caption";
75  
76      private final ActionExecutor actionExecutor;
77      private final PageEditorView view;
78      private final EventBus subAppEventBus;
79      private final SubAppContext subAppContext;
80      private final SimpleTranslator i18n;
81      private final PageEditorStatus pageEditorStatus;
82  
83      private boolean moving = false;
84      private Listener listener;
85  
86      @Inject
87      public PageEditorPresenter(final ActionExecutor actionExecutor, PageEditorView view, final @Named(SubAppEventBus.NAME) EventBus subAppEventBus,
88              SubAppContext subAppContext, SimpleTranslator i18n, PageEditorStatus pageEditorStatus) {
89          this.actionExecutor = actionExecutor;
90          this.view = view;
91          this.subAppEventBus = subAppEventBus;
92          this.subAppContext = subAppContext;
93          this.i18n = i18n;
94          this.pageEditorStatus = pageEditorStatus;
95          registerHandlers();
96      }
97  
98      public PageEditorView start(DetailLocation location) {
99          view.setListener(this);
100         pageEditorStatus.updateStatusFromLocation(location);
101         loadPageEditor();
102         return view;
103     }
104 
105     public void reload(DetailLocation location) {
106         pageEditorStatus.updateStatusFromLocation(location);
107         loadPageEditor();
108     }
109 
110     private void registerHandlers() {
111         subAppEventBus.addHandler(ComponentMoveEvent.class, new ComponentMoveEvent.Handler() {
112             @Override
113             public void onMove(ComponentMoveEvent event) {
114                 moving = event.isStart();
115                 if (moving) {
116                     view.startMoveComponent();
117                 } else if (event.isServerSide()) {
118                     view.cancelMoveComponent();
119                 }
120                 listener.onMove();
121             }
122         });
123 
124     }
125 
126     @Override
127     public void onElementSelect(AbstractElement selectedElement) {
128         getStatus().setSelectedElement(selectedElement);
129         updateParameters();
130         subAppEventBus.fireEvent(new NodeSelectedEvent(selectedElement));
131     }
132 
133     @Override
134     public void onExternalPageSelect() {
135         listener.updateCaptionForExternalPage(i18n.translate(EXTERNAL_PAGE_CAPTION));
136         listener.deactivateComponents();
137     }
138 
139     /**
140      * Used for executing actions from 'client-side'. These might have a {@link AbstractElement} as part of the arguments, but don't have to.
141      * See {@link info.magnolia.ui.vaadin.gwt.client.rpc.PageEditorServerRpc} which receives the calls from 'client-side'.
142      *
143      * @see PagesEditorSubApp#prepareAndExecutePagesEditorAction(String) for 'server-side' action execution as comparison.
144      */
145     @Override
146     public void onError(ErrorType errorType, String... parameters) {
147         if (errorType == null) {
148             throw new IllegalArgumentException("ErrorType must be one of ErrorType.values().");
149         }
150 
151         String key = String.format("pages.templateErrorAlert.%s.message", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, errorType.name()));
152         String message = i18n.translate(key, parameters);
153         subAppContext.openAlert(MessageStyleTypeEnum.WARNING, i18n.translate("pages.templateErrorAlert.title"), message, i18n.translate("button.ok"), new AlertCallback() {
154             @Override
155             public void onOk() {
156                 // Do nothing.
157             }
158         });
159     }
160 
161     @Override
162     public void onNavigation(String url) {
163         subAppEventBus.fireEvent(new PageEditorNavigationEvent(url));
164     }
165 
166     /**
167      * Used for executing actions from 'client-side'. These might have a {@link AbstractElement} as part of the arguments, but don't have to.
168      * See {@link info.magnolia.ui.vaadin.gwt.client.rpc.PageEditorServerRpc} which receives the calls from 'client-side'.
169      *
170      * @see PagesEditorSubApp#prepareAndExecutePagesEditorAction(String) for 'server-side' action execution as comparison.
171      */
172     @Override
173     public void onAction(String actionName, Object... args) {
174         try {
175             actionExecutor.execute(actionName, args);
176         } catch (ActionExecutionException e) {
177             Message error = new Message(MessageType.ERROR, i18n.translate("pages.pageEditorPresenter.actionExecutionError.message"), e.getMessage());
178             log.error("An error occurred while executing action [{}]", actionName, e);
179             subAppContext.getAppContext().sendLocalMessage(error);
180         }
181     }
182 
183     public AbstractElement getSelectedElement() {
184         return pageEditorStatus.getSelectedElement();
185     }
186 
187     public void loadPageEditor() {
188         PageEditorParameters pageEditorParameters = pageEditorStatus.getParameters();
189         view.load(pageEditorParameters);
190     }
191 
192     public void updateParameters() {
193         PageEditorParameters pageEditorParameters = pageEditorStatus.getParameters();
194         view.update(pageEditorParameters);
195     }
196 
197     public void refresh() {
198         view.refresh();
199     }
200 
201     public boolean isMoving() {
202         return moving;
203     }
204 
205     public void setListener(Listener listener) {
206         this.listener = listener;
207     }
208 
209     public PageEditorStatus getStatus() {
210         return pageEditorStatus;
211     }
212 
213     /**
214      * Listener interface to call {@link PageEditorPresenter}.
215      */
216     interface Listener {
217         void onMove();
218 
219         void updateCaptionForExternalPage(String title);
220 
221         void deactivateComponents();
222     }
223 }