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