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.pages.app.detail;
35
36 import info.magnolia.i18nsystem.SimpleTranslator;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.pages.app.detail.context.MoveComponentContext;
40 import info.magnolia.pages.app.detail.context.NavigationContext;
41 import info.magnolia.ui.ValueContext;
42 import info.magnolia.ui.api.action.ActionExecutionException;
43 import info.magnolia.ui.api.action.ActionExecutor;
44 import info.magnolia.ui.api.app.SubAppContext;
45 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
46 import info.magnolia.ui.api.message.Message;
47 import info.magnolia.ui.api.message.MessageType;
48 import info.magnolia.ui.contentapp.detail.ContentDetailSubApp;
49 import info.magnolia.ui.datasource.jcr.JcrDatasource;
50 import info.magnolia.ui.editor.LocaleContext;
51 import info.magnolia.ui.framework.ioc.Destructible;
52 import info.magnolia.ui.observation.DatasourceObservation;
53 import info.magnolia.ui.vaadin.editor.PageEditorListener;
54 import info.magnolia.ui.vaadin.editor.PageEditorView;
55 import info.magnolia.ui.vaadin.gwt.client.shared.AbstractElement;
56 import info.magnolia.ui.vaadin.gwt.client.shared.ErrorType;
57
58 import java.util.stream.Stream;
59
60 import javax.inject.Inject;
61 import javax.jcr.Node;
62
63 import com.machinezoo.noexception.Exceptions;
64 import com.vaadin.shared.Registration;
65 import com.vaadin.ui.Notification;
66
67 import lombok.extern.slf4j.Slf4j;
68
69
70
71
72
73 @Slf4j
74 public class PageEditorPresenter implements PageEditorListener, Destructible {
75
76 private final ActionExecutor actionExecutor;
77 private final PageEditorView view;
78 private final SubAppContext subAppContext;
79 private final SimpleTranslator i18n;
80 private final PageEditorStatus pageEditorStatus;
81 private final ValueContext<Node> valueContext;
82 private final ContentDetailSubApp.LocationContext locationContext;
83 private final NavigationContext<String> navigationContext;
84 private final Registration observation;
85
86 @Inject
87 public PageEditorPresenter(final ActionExecutor actionExecutor,
88 I18NAuthoringSupport<Node> i18NAuthoringSupport,
89 PageEditorView view,
90 SubAppContext subAppContext,
91 SimpleTranslator i18n,
92 PageEditorStatus pageEditorStatus,
93 LocaleContext localeContext,
94 ContentDetailSubApp.LocationContext locationContext,
95 NavigationContext<String> navigationContext,
96 MoveComponentContext moveComponentContext,
97 ValueContext<Node> valueContext,
98 JcrDatasource jcrDatasource,
99 DatasourceObservation.Manual datasourceObservation) {
100 this.actionExecutor = actionExecutor;
101 this.subAppContext = subAppContext;
102 this.i18n = i18n;
103 this.pageEditorStatus = pageEditorStatus;
104 this.view = view;
105 this.valueContext = valueContext;
106 this.navigationContext = navigationContext;
107 this.locationContext = locationContext;
108
109 view.setListener(this);
110 view.asVaadinComponent().addAttachListener(event -> loadPageEditor());
111
112 locationContext.location().observe(detailLocation ->
113 detailLocation.ifPresent(location -> {
114 Exceptions.wrap().run(() -> {
115 Node relatedNode = jcrDatasource.getJCRSession().getNode(location.getNodePath());
116 pageEditorStatus.updateStatusFromLocation(location);
117 localeContext.populateFromI18NAuthoringSupport(relatedNode, i18NAuthoringSupport);
118 loadPageEditor();
119 });
120 }));
121
122 moveComponentContext.moving().observe(isMovingOptional -> isMovingOptional.ifPresent(isMoving -> {
123 if (isMoving) {
124 view.startMoveComponent();
125 } else if (moveComponentContext.serverSide().nullableValue()) {
126 view.cancelMoveComponent();
127 }
128 }));
129
130 valueContext.observe(nodes -> nodes.stream().findFirst()
131 .filter(Exceptions.wrap().predicate(n -> NodeUtil.isNodeType(n, NodeTypes.Page.NAME)))
132 .ifPresent(node -> localeContext.populateFromI18NAuthoringSupport(node, i18NAuthoringSupport)));
133
134 observation = datasourceObservation.register(() -> {
135 updateParameters();
136 view.refresh();
137 });
138 }
139
140 @Override
141 public void onElementSelect(AbstractElement selectedElement) {
142 pageEditorStatus.setSelectedElement(selectedElement);
143 updateParameters();
144 }
145
146 @Override
147 public void onExternalPageSelect() {
148 valueContext.clear();
149 }
150
151
152
153
154
155 @Override
156 public void onError(ErrorType errorType, String... parameters) {
157 String key = String.format("pages-app.templateErrorAlert.%s.message", errorType.name());
158 Notification.show(i18n.translate("pages-app.templateErrorAlert.title"), i18n.translate(key, (Object[]) parameters), Notification.Type.WARNING_MESSAGE);
159 }
160
161 @Override
162 public void onNavigation(String url) {
163 navigationContext.url().set(url);
164 locationContext.location().update(detailLocation -> {
165 valueContext.getSingle()
166 .filter(Exceptions.wrap().predicate(node -> NodeUtil.isNodeType(node, NodeTypes.Page.NAME)))
167 .ifPresent(Exceptions.wrap().consumer(node -> detailLocation.updateNodePath(node.getPath())));
168 }
169 );
170 }
171
172
173
174
175
176 @Override
177 public void onAction(String actionName, Object... args) {
178 Stream.of(args)
179 .filter(AbstractElement.class::isInstance)
180 .map(AbstractElement.class::cast)
181 .findFirst()
182 .ifPresent(pageEditorStatus::setSelectedElement);
183 try {
184 actionExecutor.execute(actionName, args);
185 } catch (ActionExecutionException e) {
186 Message error = new Message(MessageType.ERROR, i18n.translate("pages.pageEditorPresenter.actionExecutionError.message"), e.getMessage());
187 subAppContext.getAppContext().sendLocalMessage(error);
188 log.error("An error occurred while executing action [{}]", actionName, e);
189 }
190 }
191
192 private void loadPageEditor() {
193 view.load(pageEditorStatus.getParameters());
194 }
195
196 private void updateParameters() {
197 view.update(pageEditorStatus.getParameters());
198 }
199
200 @Override
201 public void destroy() {
202 observation.remove();
203 }
204 }