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.form.field.factory;
35
36 import info.magnolia.i18nsystem.SimpleTranslator;
37 import info.magnolia.ui.api.app.AppController;
38 import info.magnolia.ui.api.app.ChooseDialogCallback;
39 import info.magnolia.ui.api.context.UiContext;
40 import info.magnolia.ui.form.field.definition.RichTextFieldDefinition;
41 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
42 import info.magnolia.ui.vaadin.richtext.MagnoliaRichTextField;
43 import info.magnolia.ui.vaadin.richtext.MagnoliaRichTextFieldConfig;
44 import info.magnolia.ui.vaadin.richtext.MagnoliaRichTextFieldConfig.ToolbarGroup;
45
46 import java.util.ArrayList;
47 import java.util.List;
48
49 import javax.jcr.Node;
50
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import com.google.gson.Gson;
55 import com.google.inject.Inject;
56 import com.vaadin.data.Item;
57 import com.vaadin.server.VaadinService;
58 import com.vaadin.server.WebBrowser;
59 import com.vaadin.ui.Field;
60
61
62
63
64 public class RichTextFieldFactory extends AbstractFieldFactory<RichTextFieldDefinition, String> {
65
66 private static final String PLUGIN_NAME_MAGNOLIALINK = "magnolialink";
67
68 private static final String PLUGIN_PATH_MAGNOLIALINK = "/VAADIN/js/magnolialink/";
69
70
71
72
73 public static final String EVENT_SEND_MAGNOLIA_LINK = "mgnlLinkSelected";
74
75
76
77
78
79
80 public static final String EVENT_CANCEL_LINK = "mgnlLinkCancel";
81
82
83
84
85
86 public static final String EVENT_GET_MAGNOLIA_LINK = "mgnlGetLink";
87
88 private final AppController appController;
89 private MagnoliaRichTextField richTextEditor;
90 private static final Logger log = LoggerFactory.getLogger(LinkFieldFactory.class);
91
92 private final UiContext uiContext;
93 private final SimpleTranslator i18n;
94
95 @Inject
96 public RichTextFieldFactory(RichTextFieldDefinition definition, Item relatedFieldItem, AppController appController, UiContext uiContext, SimpleTranslator i18n) {
97 super(definition, relatedFieldItem);
98 this.appController = appController;
99 this.uiContext = uiContext;
100 this.i18n = i18n;
101 }
102
103 @Override
104 protected Field<String> createFieldComponent() {
105
106 final MagnoliaRichTextFieldConfig config = new MagnoliaRichTextFieldConfig();
107
108 List<ToolbarGroup> toolbars = new ArrayList<ToolbarGroup>();
109 toolbars.add(new ToolbarGroup("basictyles", new String[] { "Bold", "Italic", "Underline", "SpecialChar" }));
110 toolbars.add(new ToolbarGroup("paragraph", new String[] { "NumberedList", "BulletedList" }));
111 toolbars.add(new ToolbarGroup("insert", new String[] { "Link", "InternalLink", "DamLink", "Unlink" }));
112 toolbars.add(new ToolbarGroup("clipboard", new String[] { "Cut", "Copy", "Paste", "PasteText", "PasteFromWord" }));
113 toolbars.add(new ToolbarGroup("objects", new String[] { "Table" }));
114 toolbars.add(new ToolbarGroup("special", new String[] { "Undo", "Redo" }));
115 config.addToolbarLine(toolbars);
116 config.addListenedEvent(EVENT_GET_MAGNOLIA_LINK);
117 config.setResizeEnabled(false);
118
119 richTextEditor = new MagnoliaRichTextField(config) {
120 @Override
121 public void attach() {
122 super.attach();
123 String path = VaadinService.getCurrentRequest().getContextPath();
124 config.addPlugin(PLUGIN_NAME_MAGNOLIALINK, path + PLUGIN_PATH_MAGNOLIALINK);
125
126 WebBrowser browser = getSession().getBrowser();
127 if (browser.isTouchDevice()) {
128
129 richTextEditor.setEnabled(false);
130 richTextEditor.setReadOnly(true);
131 richTextEditor.addStyleName("richtextfield-disabled");
132 }
133
134 }
135 };
136
137 richTextEditor.addListener(new MagnoliaRichTextField.PluginListener() {
138
139 @Override
140 public void onPluginEvent(String eventName, String value) {
141
142 if (eventName.equals(EVENT_GET_MAGNOLIA_LINK)) {
143 try {
144 Gson gson = new Gson();
145 PluginData pluginData = gson.fromJson(value, PluginData.class);
146 openLinkDialog(pluginData.path, pluginData.workspace);
147 } catch (Exception e) {
148 log.error("openLinkDialog failed", e);
149 richTextEditor.firePluginEvent(EVENT_CANCEL_LINK, i18n.translate("ui-form.richtexteditorexception.opentargetappfailure"));
150 }
151 }
152 }
153 });
154
155 return richTextEditor;
156 }
157
158 private static class PluginData {
159 public String workspace;
160 public String path;
161 }
162
163 private String mapWorkSpaceToApp(String workspace) {
164 if (workspace.equalsIgnoreCase("dam")) {
165 return "assets";
166 } else if (workspace.equalsIgnoreCase("website")) {
167 return "pages";
168 }
169
170 return "";
171 }
172
173 private void openLinkDialog(String path, String workspace) {
174
175 appController.openChooseDialog(mapWorkSpaceToApp(workspace), uiContext, null, new ChooseDialogCallback() {
176
177 @Override
178 public void onItemChosen(String actionName, Item chosenValue) {
179 if (!(chosenValue instanceof JcrItemAdapter)) {
180 richTextEditor
181 .firePluginEvent(EVENT_CANCEL_LINK);
182 return;
183 }
184
185 try {
186
187 javax.jcr.Item jcrItem = ((JcrItemAdapter) chosenValue).getJcrItem();
188
189 if (!jcrItem.isNode()) {
190 return;
191 }
192
193 final Node selected = (Node) jcrItem;
194 Gson gson = new Gson();
195 MagnoliaLink mlink = new MagnoliaLink();
196 mlink.identifier = selected.getIdentifier();
197 mlink.repository = selected.getSession().getWorkspace().getName();
198 mlink.path = selected.getPath();
199 if (selected.hasProperty("title")) {
200 mlink.caption = selected.getProperty("title").getString();
201 } else {
202 mlink.caption = selected.getName();
203 }
204
205 richTextEditor.firePluginEvent(EVENT_SEND_MAGNOLIA_LINK, gson.toJson(mlink));
206 } catch (Exception e) {
207 String error = i18n.translate("ui-form.richtexteditorexception.cannotaccessselecteditem");
208 log.error(error, e);
209 richTextEditor.firePluginEvent(EVENT_CANCEL_LINK, error);
210 }
211 }
212
213 @Override
214 public void onCancel() {
215 richTextEditor.firePluginEvent(EVENT_CANCEL_LINK);
216 }
217 });
218 }
219
220 private static class MagnoliaLink {
221 @SuppressWarnings("unused")
222 public String identifier;
223 @SuppressWarnings("unused")
224 public String repository;
225 @SuppressWarnings("unused")
226 public String path;
227 @SuppressWarnings("unused")
228 public String caption;
229 }
230 }