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.module.workflow.inbox;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.ItemType;
38 import info.magnolia.cms.gui.control.ContextMenu;
39 import info.magnolia.cms.gui.control.ContextMenuItem;
40 import info.magnolia.cms.gui.control.FunctionBar;
41 import info.magnolia.cms.gui.control.FunctionBarItem;
42 import info.magnolia.cms.gui.controlx.list.ListColumn;
43 import info.magnolia.cms.gui.controlx.list.ListControl;
44 import info.magnolia.cms.gui.controlx.list.ListModel;
45 import info.magnolia.cms.i18n.Messages;
46 import info.magnolia.cms.i18n.MessagesManager;
47 import info.magnolia.cms.util.AlertUtil;
48 import info.magnolia.cms.util.DateUtil;
49 import info.magnolia.context.MgnlContext;
50 import info.magnolia.freemarker.FreemarkerUtil;
51 import info.magnolia.module.ModuleRegistry;
52 import info.magnolia.module.admininterface.lists.AbstractList;
53 import info.magnolia.module.admininterface.lists.AdminListControlRenderer;
54 import info.magnolia.module.workflow.WorkflowConstants;
55 import info.magnolia.module.workflow.WorkflowModule;
56 import info.magnolia.module.workflow.WorkflowUtil;
57 import info.magnolia.objectfactory.Classes;
58 import info.magnolia.objectfactory.Components;
59
60 import java.text.ParseException;
61 import java.text.SimpleDateFormat;
62 import java.util.Date;
63 import java.util.HashMap;
64 import java.util.Map;
65 import java.util.Map.Entry;
66
67 import javax.jcr.ItemNotFoundException;
68 import javax.jcr.RepositoryException;
69 import javax.servlet.http.HttpServletRequest;
70 import javax.servlet.http.HttpServletResponse;
71
72 import org.apache.commons.lang.ObjectUtils;
73 import org.apache.commons.lang.StringEscapeUtils;
74 import org.apache.commons.lang.StringUtils;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78
79
80
81
82
83
84 public class Inbox extends AbstractList {
85
86 private static final Logger log = LoggerFactory.getLogger(Inbox.class);
87
88
89
90
91 private String flowItemId;
92
93
94
95
96 private String comment;
97
98
99
100
101 private boolean debug = false;
102
103 protected Messages msgs = MessagesManager.getMessages("info.magnolia.module.workflow.messages");
104
105 private Map<String, Object> showFunctions = new HashMap<String, Object>();
106
107 public Inbox(String name, HttpServletRequest request, HttpServletResponse response) {
108 super(name, request, response);
109 }
110
111 @Override
112 public void init() {
113 super.init();
114 final WorkflowModule module = Components.getComponent(ModuleRegistry.class).getModuleInstance(WorkflowModule.class);
115 resolveShowFunctions(module.getShowFunctions());
116 }
117
118 private void resolveShowFunctions(Map<String, String> showFunctions) {
119 for (Entry<String, String> entry : showFunctions.entrySet()) {
120 String repository = entry.getKey();
121 String value = entry.getValue();
122 Object clazz = null;
123 try {
124 clazz = Classes.newInstance(value, null);
125 } catch (ClassNotFoundException e) {
126
127 }
128 if (clazz != null && clazz instanceof InboxShowFunction) {
129 this.showFunctions.put(repository, clazz);
130 } else {
131 this.showFunctions.put(repository, value);
132 }
133 }
134 }
135
136 @Override
137 public ListModel getModel() {
138 return new InboxListModel(MgnlContext.getUser().getName());
139 }
140
141 @Override
142 public String getSortBy() {
143 if (StringUtils.isEmpty(super.getSortBy())) {
144 setSortBy("lastModified");
145 }
146 return super.getSortBy();
147 }
148
149
150
151
152 @Override
153 public void configureList(ListControl list) {
154
155
156 list.setRenderer(new AdminListControlRenderer() {
157
158 @Override
159 public String onSelect(ListControl list, Integer index) {
160
161 String customEditDialog = ObjectUtils.toString(list
162 .getIteratorValue(WorkflowConstants.ATTRIBUTE_EDIT_DIALOG));
163
164 String editDialog = StringUtils.defaultIfEmpty(customEditDialog, WorkflowConstants.DEFAULT_EDIT_DIALOG);
165 String repository = ObjectUtils.toString(list.getIteratorValue("repository"));
166 String path = ObjectUtils.toString(list.getIteratorValue("path"));
167
168 StringBuffer js = new StringBuffer();
169 js.append("mgnl.workflow.Inbox.current = ");
170 js.append("{");
171 js.append("id : '").append(list.getIteratorValue("id")).append("',");
172 js.append("path : '").append(path).append("',");
173 js.append("version : '").append(list.getIteratorValue("version")).append("',");
174 js.append("repository : '").append(repository).append("',");
175 js.append("workItemPath : '").append(list.getIteratorValue("workItemPath")).append("',");
176 js.append("editDialog : '").append(editDialog).append("'");
177 js.append("};");
178 js.append("mgnl.workflow.Inbox.show = ").append(getShowJSFunction(repository, path)).append(";");
179 js.append(super.onSelect(list, index));
180 return js.toString();
181 }
182
183 @Override
184 public String onDblClick(ListControl list, Integer index) {
185 return "mgnl.workflow.Inbox.edit();";
186 }
187 });
188
189 list.addSortableField("lastModified");
190 list.addGroupableField("repository");
191 list.addGroupableField("workflow");
192
193 list.addColumn(new ListColumn() {
194
195 {
196 setName("icon");
197 setLabel("");
198 setWidth("30px");
199 setSeparator(false);
200 }
201
202 @Override
203 public Object getValue() {
204 String path = "" + this.getListControl().getIteratorValue("path");
205 String repository = "" + this.getListControl().getIteratorValue("repository");
206 String uuid = "" + this.getListControl().getIteratorValue("uuid");
207 String version = "" + this.getListControl().getIteratorValue("version");
208 try {
209 final Content content;
210
211 if (StringUtils.isEmpty(version)) {
212 content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid);
213 } else {
214 content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid).getVersionedContent(version);
215 }
216 if (content.hasMixin(ItemType.DELETED_NODE_MIXIN)) {
217 path = ItemType.DELETED_NODE_MIXIN;
218 }
219 } catch (ItemNotFoundException e) {
220 log.debug("Item {}:{} does no longer exist in the workspace. Uuid: {}", new String[] { repository, path, uuid });
221
222 } catch (RepositoryException e) {
223 log.error("Failed to retrieve versioned node [path=" + path + ", uuid=" + uuid + ", version=" + version, e);
224 }
225 return "<img src=\""
226 + MgnlContext.getContextPath()
227 + "/"
228 + getIcon(path, repository)
229 + "\" alt=\"\" border=\"0\" />";
230 }
231 });
232 list.addColumn(new ListColumn("name", msgs.get("inbox.item"), "100", true));
233 list.addColumn(new ListColumn("repository", msgs.get("inbox.repository"), "100px", true));
234 list.addColumn(new ListColumn("workflow", msgs.get("inbox.workflow"), "100px", true));
235 list.addColumn(new ListColumn() {
236 {
237 setName("comment");
238 setLabel(msgs.get("inbox.comment"));
239 setWidth("200px");
240 setSeparator(true);
241 }
242
243 @Override
244 public Object getValue() {
245 if (super.getValue() instanceof String) {
246 String comment = (String) super.getValue();
247 return StringEscapeUtils.escapeHtml(comment);
248 } else {
249 openwfe.org.engine.workitem.StringAttribute comment = (openwfe.org.engine.workitem.StringAttribute) super.getValue();
250 comment.setValue(StringEscapeUtils.escapeHtml(comment.getValue().toString()));
251 return comment;
252 }
253 }
254 });
255 list.addColumn(new ListColumn() {
256
257 {
258 setName("lastModified");
259 setLabel(msgs.get("inbox.date"));
260 setWidth("150px");
261 }
262
263 @Override
264 public Object getValue() {
265 String str = (String) super.getValue();
266 Date date = null;
267 try {
268 date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse(str);
269 return DateUtil.formatDateTime(date);
270
271 }
272 catch (ParseException e) {
273 return StringUtils.EMPTY;
274 }
275 }
276 });
277
278 }
279
280 protected String getIcon(String path, String repository) {
281 return InboxHelper.getIcon(repository, path);
282 }
283
284 protected String getShowJSFunction(String repository, String path) {
285 if (this.showFunctions.containsKey(repository)) {
286 Object showFunction = showFunctions.get(repository);
287 if (showFunction instanceof InboxShowFunction) {
288 return ((InboxShowFunction) showFunctions.get(repository)).getShowJsFunction(path);
289 }
290 if (((String) showFunction).length() > 0) {
291 return (String) showFunctions.get(repository);
292 }
293 }
294 return InboxHelper.getShowJSFunction(repository, path);
295 }
296
297 @Override
298 public void configureContextMenu(ContextMenu menu) {
299 ContextMenuItem edit = new ContextMenuItem("edit");
300 edit.setLabel(msgs.get("inbox.edit"));
301 edit.setOnclick("mgnl.workflow.Inbox.edit();");
302 edit.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/mail_write.gif");
303 edit.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
304
305 ContextMenuItem show = new ContextMenuItem("show");
306 show.setLabel(msgs.get("inbox.show"));
307 show.setOnclick("mgnl.workflow.Inbox.show();");
308 show.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/note_view.gif");
309 show.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
310
311 ContextMenuItem proceed = new ContextMenuItem("proceed");
312 proceed.setLabel(msgs.get("inbox.proceed"));
313 proceed.setOnclick("mgnl.workflow.Inbox.proceed();");
314 proceed.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_right2_green.gif");
315 proceed.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
316
317 ContextMenuItem reject = new ContextMenuItem("reject");
318 reject.setLabel(msgs.get("inbox.reject"));
319 reject.setOnclick("mgnl.workflow.Inbox.reject();");
320 reject.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_left2_red.gif");
321 reject.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
322
323 ContextMenuItem cancel = new ContextMenuItem("cancel");
324 cancel.setLabel(msgs.get("inbox.cancel"));
325 cancel.setOnclick("mgnl.workflow.Inbox.cancel();");
326 cancel.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/delete2.gif");
327 cancel.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
328
329 menu.addMenuItem(edit);
330 menu.addMenuItem(null);
331 menu.addMenuItem(show);
332 menu.addMenuItem(null);
333 menu.addMenuItem(proceed);
334 menu.addMenuItem(reject);
335 menu.addMenuItem(null);
336 menu.addMenuItem(cancel);
337 }
338
339
340
341
342 @Override
343 public void configureFunctionBar(FunctionBar bar) {
344 ContextMenu menu = this.getContextMenu();
345 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("edit")));
346 bar.addMenuItem(null);
347 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("show")));
348 bar.addMenuItem(null);
349 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("reject")));
350 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("proceed")));
351 bar.addMenuItem(null);
352 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("cancel")));
353 }
354
355
356
357
358 @Override
359 public String onRender() {
360 return FreemarkerUtil.process(this);
361 }
362
363
364
365
366 public String proceed() {
367 try {
368 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_PROCEED);
369 } catch (Exception e) {
370 AlertUtil.setMessage("can't proceed:", e);
371 }
372 return this.show();
373 }
374
375
376
377
378 public String reject() {
379 try {
380 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_REJECT, this.getComment());
381 } catch (Exception e) {
382 AlertUtil.setMessage("can't reject:", e);
383 }
384 return this.show();
385 }
386
387
388
389
390 public String cancel() {
391 try {
392 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_CANCEL);
393 } catch (Exception e) {
394 AlertUtil.setMessage("can't cancel:", e);
395 }
396 return this.show();
397 }
398
399 public String getFlowItemId() {
400 return this.flowItemId;
401 }
402
403 public void setFlowItemId(String flowItemId) {
404 this.flowItemId = flowItemId;
405 }
406
407 public String getComment() {
408 return this.comment;
409 }
410
411 public void setComment(String comment) {
412 this.comment = comment;
413 }
414
415 public boolean isDebug() {
416 return this.debug;
417 }
418
419 public void setDebug(boolean debug) {
420 this.debug = debug;
421 }
422
423 }