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.ui.contentapp.detail;
35
36 import info.magnolia.context.Context;
37 import info.magnolia.ui.CloseHandler;
38 import info.magnolia.ui.api.app.SubAppContext;
39 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
40 import info.magnolia.ui.api.location.DefaultLocation;
41 import info.magnolia.ui.api.location.Location;
42 import info.magnolia.ui.contentapp.browser.context.ValueContext;
43 import info.magnolia.ui.dialog.DialogHelper;
44 import info.magnolia.ui.dialog.layout.DefaultEditorActionLayoutDefinition;
45 import info.magnolia.ui.field.EditorPropertyDefinition;
46 import info.magnolia.ui.form.FormDefinition;
47 import info.magnolia.ui.form.LocaleContext;
48 import info.magnolia.ui.framework.ContextProperty;
49 import info.magnolia.ui.framework.UiFrameworkView;
50 import info.magnolia.ui.framework.ViewContext;
51 import info.magnolia.ui.framework.app.BaseSubApp;
52 import info.magnolia.ui.framework.databinding.ItemProviderStrategy;
53 import info.magnolia.ui.framework.databinding.view.EditorView;
54 import info.magnolia.ui.framework.databinding.view.FormView;
55
56 import java.util.Locale;
57 import java.util.stream.Collectors;
58
59 import javax.inject.Inject;
60
61 import org.apache.commons.lang3.StringUtils;
62
63 import com.vaadin.ui.Component;
64 import com.vaadin.ui.CssLayout;
65
66
67
68
69
70
71 public class ContentDetailSubApp<T> extends BaseSubApp<ContentDetailSubApp.DetailSubAppView> {
72
73 private LocationContext locationContext;
74 private ItemProviderStrategy<T> itemProviderStrategy;
75
76 private final DetailDescriptor<T, ?> subAppDescriptor;
77 private final I18NAuthoringSupport i18NAuthoringSupport;
78 private final ValueContext<T> valueContext;
79 private final Context mgnlContext;
80
81 @Inject
82 protected ContentDetailSubApp(
83 SubAppContext subAppContext,
84 I18NAuthoringSupport i18NAuthoringSupport,
85 DetailDescriptor<T, ?> descriptor,
86 ValueContext<T> valueContext,
87 Context mgnlContext) {
88 super(subAppContext, new DetailSubAppView());
89 this.valueContext = valueContext;
90 this.subAppDescriptor = descriptor;
91 this.i18NAuthoringSupport = i18NAuthoringSupport;
92 this.mgnlContext = mgnlContext;
93 }
94
95 @Override
96 public DetailSubAppView start(Location location) {
97 super.start(location);
98
99 final DetailSubAppView view = getView();
100 final LocaleContext localeContext = bindContext(LocaleContext.class);
101 final Locale currentLocale = getSubAppContext().getAuthoringLocale() != null ?
102 getSubAppContext().getAuthoringLocale() :
103 i18NAuthoringSupport.getDefaultLocale();
104 localeContext.current().set(currentLocale);
105
106 this.locationContext = bindContext(LocationContext.class);
107 this.locationContext.location().set(DetailLocation.wrap(location));
108 this.itemProviderStrategy = create(subAppDescriptor.getItemProvider());
109
110 bindInstance(UiFrameworkView.class, view);
111 bindInstance(ItemProviderStrategy.class, itemProviderStrategy);
112 bindInstance(CloseHandler.class, () -> getSubAppContext().close());
113
114 FormDefinition<T> formDefinition = subAppDescriptor.getForm();
115 FormView<T> form = (FormView<T>) create(formDefinition.getName(), formDefinition);
116 view.bindInstance(EditorView.class, form);
117 view.setForm(new DialogHelper()
118 .withActions(subAppDescriptor.getActions())
119 .withCaption(subAppDescriptor.getLabel())
120 .withContent(form)
121 .withLayoutDefinition(new DefaultEditorActionLayoutDefinition())
122 .withLocaleContext(localeContext)
123 .withItems(valueContext.get().collect(Collectors.toList()))
124 .withLocaleContext(subAppDescriptor.getForm().getProperties().stream()
125 .filter(EditorPropertyDefinition::isI18n)
126 .findFirst()
127 .map(any -> localeContext)
128 .orElse(null)
129 )
130 .withUserLanguage(mgnlContext::getLocale)
131 .createDialogComponent()
132 );
133
134 locationContext.location().observeNullable(l -> itemProviderStrategy.read().ifPresent(item -> {
135 form.populate(item);
136 valueContext.set(item);
137 }));
138
139 return view;
140 }
141
142 @Override
143 public void locationChanged(Location location) {
144 super.locationChanged(location);
145 this.locationContext.location().set(DetailLocation.wrap(location));
146 }
147
148
149
150
151 public interface LocationContext extends ViewContext {
152 ContextProperty<DetailLocation> location();
153 }
154
155
156
157
158 public static class DetailSubAppView implements UiFrameworkView {
159
160 private Component form;
161
162 @Override
163 public Component asVaadinComponent() {
164 return form;
165 }
166
167 public void setForm(Component form) {
168 this.form = form;
169 }
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183 public static class DetailLocation extends DefaultLocation {
184
185 private String viewType;
186 private String nodePath;
187 private String version;
188
189 private final static int NODE_PATH_PARAM_POSITION = 0;
190 private final static int VIEW_TYPE_PARAM_POSITION = 1;
191 private final static int VERSION_PARAM_POSITION = 2;
192
193 public DetailLocation(String appName, String subAppId, String parameter) {
194 super(LOCATION_TYPE_APP, appName, subAppId, parameter);
195
196 setNodePath(extractNodePath(parameter));
197 setViewType(extractViewType(parameter));
198 setVersion(extractVersion(parameter));
199 }
200
201 public DetailLocation(String appName, String subAppId, String viewType, String nodePath, String version) {
202 super(LOCATION_TYPE_APP, appName, subAppId);
203
204 setNodePath(nodePath);
205 setViewType(viewType);
206 setVersion(version);
207 updateParameter();
208 }
209
210 public String getNodePath() {
211 return unescapeSpecialCharacters(nodePath);
212 }
213
214
215
216
217 private void setNodePath(String nodePath) {
218 this.nodePath = (nodePath == null || nodePath.isEmpty()) ? "/" : escapeSpecialCharacters(nodePath);
219 }
220
221 public String getViewType() {
222 return viewType;
223 }
224
225 public void setViewType(String viewType) {
226 this.viewType = viewType;
227 }
228
229 public String getVersion() {
230 return unescapeSpecialCharacters(version);
231 }
232
233 public void setVersion(String version) {
234 this.version = escapeSpecialCharacters(version);
235 }
236
237 public boolean hasVersion() {
238 return StringUtils.isNotBlank(version);
239 }
240
241
242
243
244
245
246
247 private String extractNodePath(String parameter) {
248 return getParameter(parameter, NODE_PATH_PARAM_POSITION);
249 }
250
251
252
253
254
255
256
257 private String extractViewType(String parameter) {
258 String action = getParameter(parameter, VIEW_TYPE_PARAM_POSITION);
259 return action;
260 }
261
262
263
264
265
266
267
268 private String extractVersion(String parameter) {
269 return getParameter(parameter, VERSION_PARAM_POSITION);
270 }
271
272 protected String getParameter(String parameter, int position) {
273 String arguments[] = StringUtils.split(parameter, ':');
274 if (position <= arguments.length - 1) {
275 return arguments[position];
276 }
277 return "";
278 }
279
280 protected void updateParameter() {
281 StringBuilder sb = new StringBuilder();
282 sb.append(nodePath);
283 sb.append(":");
284 sb.append(viewType);
285 if (StringUtils.isNotBlank(version)) {
286 sb.append(":");
287 sb.append(version);
288 }
289 super.setParameter(sb.toString());
290 }
291
292 public static DetailLocation wrap(Location location) {
293 return new DetailLocation(location.getAppName(), location.getSubAppId(), location.getParameter());
294 }
295
296 public void updateNodePath(String newNodePath) {
297 setNodePath(newNodePath);
298 updateParameter();
299 }
300
301 public void updateViewtype(String newViewType) {
302 setViewType(newViewType);
303 updateParameter();
304 }
305
306 public void updateVersion(String newVersion) {
307 setVersion(newVersion);
308 updateParameter();
309 }
310 }
311 }