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.dam.app.ui.field.factory;
35
36 import info.magnolia.dam.api.Asset;
37 import info.magnolia.dam.api.AssetProviderRegistry;
38 import info.magnolia.dam.api.DamException;
39 import info.magnolia.dam.api.ItemKey;
40 import info.magnolia.dam.jcr.DamConstants;
41 import info.magnolia.i18nsystem.SimpleTranslator;
42 import info.magnolia.link.LinkException;
43 import info.magnolia.link.LinkUtil;
44 import info.magnolia.objectfactory.Components;
45 import info.magnolia.ui.api.app.AppController;
46 import info.magnolia.ui.api.app.ChooseDialogCallback;
47 import info.magnolia.ui.api.context.UiContext;
48 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
49 import info.magnolia.ui.form.field.definition.RichTextFieldDefinition;
50 import info.magnolia.ui.form.field.factory.RichTextFieldFactory;
51 import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
52 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeItemId;
53 import info.magnolia.ui.vaadin.richtext.MagnoliaRichTextField;
54 import info.magnolia.ui.vaadin.richtext.MagnoliaRichTextFieldConfig;
55
56 import java.util.Locale;
57 import java.util.regex.Matcher;
58
59 import javax.inject.Inject;
60
61 import org.apache.commons.lang3.StringUtils;
62
63 import com.google.gson.Gson;
64 import com.vaadin.server.VaadinService;
65 import com.vaadin.ui.UI;
66 import com.vaadin.v7.data.Item;
67 import com.vaadin.v7.data.util.converter.Converter;
68 import com.vaadin.v7.ui.Field;
69
70
71
72
73
74
75 public class AssetsEnabledRichTextFieldFactory extends RichTextFieldFactory {
76
77 private static final String FILE_BROWSER_PLUGIN = "magnoliaFileBrowser";
78
79 private static final String FILE_BROWSER_PLUGIN_CHOOSE_ASSET_EVENT = "chooseAsset";
80
81 public static final String ASSET_CHOSEN_EVENT_ID = "assetChosen";
82
83 private AssetProviderRegistry assetProviderRegistry;
84
85 @Inject
86 public AssetsEnabledRichTextFieldFactory(RichTextFieldDefinition definition, Item relatedFieldItem, UiContext uiContext, I18NAuthoringSupport i18nAuthoringSupport, AppController appController, SimpleTranslator i18n, AssetProviderRegistry assetProviderRegistry) {
87 super(definition, relatedFieldItem, uiContext, i18nAuthoringSupport, appController, i18n);
88 this.assetProviderRegistry = assetProviderRegistry;
89 }
90
91
92
93
94 @Deprecated
95 public AssetsEnabledRichTextFieldFactory(RichTextFieldDefinition definition, Item relatedFieldItem, AppController appController, UiContext uiContext, SimpleTranslator i18n, AssetProviderRegistry assetProviderRegistry) {
96 this(definition, relatedFieldItem, uiContext, Components.getComponent(I18NAuthoringSupport.class), appController, i18n, assetProviderRegistry);
97 }
98
99
100
101
102 @Deprecated
103 public AssetsEnabledRichTextFieldFactory(RichTextFieldDefinition definition, Item relatedFieldItem, AppController appController, UiContext uiContext, SimpleTranslator i18n, AssetProviderRegistry assetProviderRegistry, ContentConnector contentConnector) {
104 this(definition, relatedFieldItem, uiContext, Components.getComponent(I18NAuthoringSupport.class), appController, i18n, assetProviderRegistry);
105 }
106
107 @Override
108 protected Field<String> createFieldComponent() {
109 MagnoliaRichTextField field = (MagnoliaRichTextField) super.createFieldComponent();
110 if (definition.isImages() || StringUtils.isNotBlank(definition.getConfigJsFile())) {
111
112 field.addListener((eventName, value) -> {
113 if (eventName.equals(FILE_BROWSER_PLUGIN_CHOOSE_ASSET_EVENT)) {
114 UI.getCurrent().addStyleName("ui-overlapping-ck-editor");
115 chooseAsset();
116 }
117 });
118
119 field.setConverter(new Converter<String, String>() {
120 @Override
121 public String convertToModel(String value, Class<? extends String> targetType, Locale locale) throws ConversionException {
122 return LinkUtil.convertAbsoluteLinksToUUIDs(value);
123 }
124
125 @Override
126 public String convertToPresentation(String value, Class<? extends String> targetType, Locale locale) throws ConversionException {
127 if (value != null) {
128
129
130 try {
131 Matcher matcher = LinkUtil.IMAGE_PATTERN.matcher(value);
132 while (matcher.find()) {
133 value = value.replace(matcher.group(), LinkUtil.convertLinksFromUUIDPattern(matcher.group()));
134 }
135 return value;
136 } catch (LinkException e) {
137 return StringUtils.EMPTY;
138 }
139 }
140 return StringUtils.EMPTY;
141 }
142
143 @Override
144 public Class<String> getModelType() {
145 return String.class;
146 }
147
148 @Override
149 public Class<String> getPresentationType() {
150 return String.class;
151 }
152 });
153 }
154 return field;
155 }
156
157 private void chooseAsset() {
158 appController.openChooseDialog("assets", uiContext, null, new ChooseDialogCallback() {
159 @Override
160 public void onItemChosen(String actionName, Object chosenValue) {
161 UI.getCurrent().removeStyleName("ui-overlapping-ck-editor");
162
163 Gson gson = new Gson();
164 String eventJson = "{}";
165 Asset asset;
166
167 try {
168 if (!(chosenValue instanceof JcrNodeItemId)) {
169 return;
170 }
171 asset = assetProviderRegistry.getProviderById(DamConstants.DEFAULT_JCR_PROVIDER_ID).getAsset(new ItemKey(DamConstants.DEFAULT_JCR_PROVIDER_ID, ((JcrNodeItemId) chosenValue).getUuid()));
172 if (asset != null && asset.getMimeType().matches("image.*")) {
173 eventJson = gson.toJson(new FileBrowserUrlDTO(asset.getLink()));
174 } else {
175 eventJson = gson.toJson(new FileBrowserUrlDTO("", "Selected asset is not an image"));
176 }
177 } catch (DamException e) {
178 eventJson = gson.toJson(new FileBrowserUrlDTO("", e.getMessage()));
179 } finally {
180 richTextEditor.firePluginEvent(ASSET_CHOSEN_EVENT_ID, eventJson);
181 }
182 }
183
184
185 @Override
186 public void onCancel() {
187 UI.getCurrent().removeStyleName("ui-overlapping-ck-editor");
188 }
189 });
190 }
191
192 @Override
193 protected MagnoliaRichTextFieldConfig initializeCKEditorConfig() {
194 MagnoliaRichTextFieldConfig config = super.initializeCKEditorConfig();
195
196
197 boolean isCustomConfig = StringUtils.isNotBlank(definition.getConfigJsFile());
198 if (definition.isImages() || isCustomConfig) {
199
200
201 String path = VaadinService.getCurrentRequest().getContextPath();
202 config.addExternalPlugin(FILE_BROWSER_PLUGIN, path + "/VAADIN/js/filebrowser/");
203 config.addListenedEvent(FILE_BROWSER_PLUGIN_CHOOSE_ASSET_EVENT);
204 if (!isCustomConfig) {
205 config.addToExtraPlugins(FILE_BROWSER_PLUGIN);
206 }
207
208
209 config.setFilebrowserImageBrowseLinkUrl("dummy");
210 config.setFilebrowserImageBrowseUrl("dummy");
211 }
212 return config;
213 }
214
215
216
217
218 public static class FileBrowserUrlDTO {
219 public String url;
220 public String errorMessage;
221
222 public FileBrowserUrlDTO(String url, String errorMessage) {
223 this.url = url;
224 this.errorMessage = errorMessage;
225 }
226
227 public FileBrowserUrlDTO(String url) {
228 this(url, null);
229 }
230 }
231 }