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 final 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 Object value = super.getValue();
246 if (value instanceof String) {
247 String comment = (String) super.getValue();
248 return StringEscapeUtils.escapeHtml(comment);
249 } else if (value instanceof openwfe.org.engine.workitem.StringAttribute) {
250 openwfe.org.engine.workitem.StringAttribute comment = (openwfe.org.engine.workitem.StringAttribute) super.getValue();
251 comment.setValue(StringEscapeUtils.escapeHtml(comment.getValue().toString()));
252 return comment;
253 } else {
254 log.warn("Inbox: cannot set value for column '{}'.", this.getName());
255 return StringUtils.EMPTY;
256 }
257 }
258 });
259 list.addColumn(new ListColumn() {
260
261 {
262 setName("lastModified");
263 setLabel(msgs.get("inbox.date"));
264 setWidth("150px");
265 }
266
267 @Override
268 public Object getValue() {
269 String str = (String) super.getValue();
270 Date date = null;
271 try {
272 date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse(str);
273 return DateUtil.formatDateTime(date);
274
275 }
276 catch (ParseException e) {
277 return StringUtils.EMPTY;
278 }
279 }
280 });
281
282 }
283
284 protected String getIcon(String path, String repository) {
285 return InboxHelper.getIcon(repository, path);
286 }
287
288 protected String getShowJSFunction(String repository, String path) {
289 if (this.showFunctions.containsKey(repository)) {
290 Object showFunction = showFunctions.get(repository);
291 if (showFunction instanceof InboxShowFunction) {
292 return ((InboxShowFunction) showFunctions.get(repository)).getShowJsFunction(path);
293 }
294 if (((String) showFunction).length() > 0) {
295 return (String) showFunctions.get(repository);
296 }
297 }
298 return InboxHelper.getShowJSFunction(repository, path);
299 }
300
301 @Override
302 public void configureContextMenu(ContextMenu menu) {
303 ContextMenuItem edit = new ContextMenuItem("edit");
304 edit.setLabel(msgs.get("inbox.edit"));
305 edit.setOnclick("mgnl.workflow.Inbox.edit();");
306 edit.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/mail_write.gif");
307 edit.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
308
309 ContextMenuItem show = new ContextMenuItem("show");
310 show.setLabel(msgs.get("inbox.show"));
311 show.setOnclick("mgnl.workflow.Inbox.show();");
312 show.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/note_view.gif");
313 show.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
314
315 ContextMenuItem proceed = new ContextMenuItem("proceed");
316 proceed.setLabel(msgs.get("inbox.proceed"));
317 proceed.setOnclick("mgnl.workflow.Inbox.proceed();");
318 proceed.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_right2_green.gif");
319 proceed.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
320
321 ContextMenuItem reject = new ContextMenuItem("reject");
322 reject.setLabel(msgs.get("inbox.reject"));
323 reject.setOnclick("mgnl.workflow.Inbox.reject();");
324 reject.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_left2_red.gif");
325 reject.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
326
327 ContextMenuItem cancel = new ContextMenuItem("cancel");
328 cancel.setLabel(msgs.get("inbox.cancel"));
329 cancel.setOnclick("mgnl.workflow.Inbox.cancel();");
330 cancel.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/delete2.gif");
331 cancel.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
332
333 menu.addMenuItem(edit);
334 menu.addMenuItem(null);
335 menu.addMenuItem(show);
336 menu.addMenuItem(null);
337 menu.addMenuItem(proceed);
338 menu.addMenuItem(reject);
339 menu.addMenuItem(null);
340 menu.addMenuItem(cancel);
341 }
342
343
344
345
346 @Override
347 public void configureFunctionBar(FunctionBar bar) {
348 ContextMenu menu = this.getContextMenu();
349 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("edit")));
350 bar.addMenuItem(null);
351 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("show")));
352 bar.addMenuItem(null);
353 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("reject")));
354 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("proceed")));
355 bar.addMenuItem(null);
356 bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("cancel")));
357 }
358
359
360
361
362 @Override
363 public String onRender() {
364 return FreemarkerUtil.process(this);
365 }
366
367
368
369
370 public String proceed() {
371 try {
372 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_PROCEED);
373 } catch (Exception e) {
374 AlertUtil.setMessage("can't proceed:", e);
375 }
376 return this.show();
377 }
378
379
380
381
382 public String reject() {
383 try {
384 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_REJECT, this.getComment());
385 } catch (Exception e) {
386 AlertUtil.setMessage("can't reject:", e);
387 }
388 return this.show();
389 }
390
391
392
393
394 public String cancel() {
395 try {
396 WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_CANCEL);
397 } catch (Exception e) {
398 AlertUtil.setMessage("can't cancel:", e);
399 }
400 return this.show();
401 }
402
403 public String getFlowItemId() {
404 return this.flowItemId;
405 }
406
407 public void setFlowItemId(String flowItemId) {
408 this.flowItemId = flowItemId;
409 }
410
411 public String getComment() {
412 return this.comment;
413 }
414
415 public void setComment(String comment) {
416 this.comment = comment;
417 }
418
419 public boolean isDebug() {
420 return this.debug;
421 }
422
423 public void setDebug(boolean debug) {
424 this.debug = debug;
425 }
426
427 }