View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
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.freemarker.FreemarkerUtil;
50  import info.magnolia.context.MgnlContext;
51  import info.magnolia.module.admininterface.lists.AbstractList;
52  import info.magnolia.module.admininterface.lists.AdminListControlRenderer;
53  import info.magnolia.module.workflow.WorkflowConstants;
54  import info.magnolia.module.workflow.WorkflowUtil;
55  
56  import java.text.ParseException;
57  import java.text.SimpleDateFormat;
58  import java.util.Date;
59  
60  import javax.jcr.ItemNotFoundException;
61  import javax.jcr.RepositoryException;
62  import javax.servlet.http.HttpServletRequest;
63  import javax.servlet.http.HttpServletResponse;
64  
65  import org.apache.commons.lang.ObjectUtils;
66  import org.apache.commons.lang.StringEscapeUtils;
67  import org.apache.commons.lang.StringUtils;
68  import org.slf4j.Logger;
69  import org.slf4j.LoggerFactory;
70  
71  
72  /**
73   * The {@link info.magnolia.module.admininterface.lists.AbstractList} responsible for displaying a user's inbox, i.e current work items.
74   * @author Philipp Bracher
75   * @version $Revision:3416 $ ($Author:philipp $)
76   */
77  public class Inbox extends AbstractList {
78  
79      private static final Logger log = LoggerFactory.getLogger(Inbox.class);
80  
81      /**
82       * The id of the workitem on which we called the command.
83       */
84      private String flowItemId;
85  
86      /**
87       * The comment the user entered by proceeding or rejecting.
88       */
89      private String comment;
90  
91      /**
92       * Show all the values of the workitem if true.
93       */
94      private boolean debug = false;
95  
96      protected Messages msgs = MessagesManager.getMessages("info.magnolia.module.workflow.messages");
97  
98      public Inbox(String name, HttpServletRequest request, HttpServletResponse response) {
99          super(name, request, response);
100     }
101 
102     @Override
103     public ListModel getModel() {
104         return new InboxListModel(MgnlContext.getUser().getName());
105     }
106 
107     @Override
108     public String getSortBy() {
109         if(StringUtils.isEmpty(super.getSortBy())){
110             setSortBy("lastModified");
111         }
112         return super.getSortBy();
113     }
114 
115     /**
116      * Sets the select js code and defines the columns.
117      */
118     @Override
119     public void configureList(ListControl list) {
120 
121         // define the select action
122         list.setRenderer(new AdminListControlRenderer() {
123 
124             @Override
125             public String onSelect(ListControl list, Integer index) {
126 
127                 String customEditDialog = ObjectUtils.toString(list
128                         .getIteratorValue(WorkflowConstants.ATTRIBUTE_EDIT_DIALOG));
129 
130                 String editDialog = StringUtils.defaultIfEmpty(customEditDialog, WorkflowConstants.DEFAULT_EDIT_DIALOG);
131                 String repository = ObjectUtils.toString(list.getIteratorValue("repository"));
132                 String path = ObjectUtils.toString(list.getIteratorValue("path"));
133 
134                 StringBuffer js = new StringBuffer();
135                 js.append("mgnl.workflow.Inbox.current = ");
136                 js.append("{");
137                 js.append("id : '").append(list.getIteratorValue("id")).append("',");
138                 js.append("path : '").append(path).append("',");
139                 js.append("version : '").append(list.getIteratorValue("version")).append("',");
140                 js.append("repository : '").append(repository).append("',");
141                 js.append("workItemPath : '").append(list.getIteratorValue("workItemPath")).append("',");
142                 js.append("editDialog : '").append(editDialog).append("'");
143                 js.append("};");
144                 js.append("mgnl.workflow.Inbox.show = ").append(getShowJSFunction(repository, path)).append(";");
145                 js.append(super.onSelect(list, index));
146                 return js.toString();
147             }
148 
149             @Override
150             public String onDblClick(ListControl list, Integer index) {
151                 return "mgnl.workflow.Inbox.edit();";
152             }
153         });
154 
155         list.addSortableField("lastModified");
156         list.addGroupableField("repository");
157         list.addGroupableField("workflow");
158 
159         list.addColumn(new ListColumn() {
160 
161             {
162                 setName("icon");
163                 setLabel("");
164                 setWidth("30px");
165                 setSeparator(false);
166             }
167 
168             @Override
169             public Object getValue() {
170                 String path = "" + this.getListControl().getIteratorValue("path");
171                 String repository = "" + this.getListControl().getIteratorValue("repository");
172                 String uuid = "" + this.getListControl().getIteratorValue("uuid");
173                 String version = "" + this.getListControl().getIteratorValue("version");
174                 try {
175                     final Content content;
176                     // versioning disabled
177                     if (StringUtils.isEmpty(version)) {
178                         content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid);
179                     } else {
180                         content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid).getVersionedContent(version);
181                     }
182                     if (content.hasMixin(ItemType.DELETED_NODE_MIXIN)) {
183                         path = ItemType.DELETED_NODE_MIXIN;
184                     }
185                 } catch (ItemNotFoundException e) {
186                     log.debug("Item {}:{} does no longer exist in the workspace. Uuid: {}", new String[] {repository, path, uuid});
187 
188                 } catch (RepositoryException e) {
189                     log.error("Failed to retrieve versioned node [path=" + path + ", uuid=" + uuid + ", version=" + version, e);
190                 }
191                 return "<img src=\""
192                 + MgnlContext.getContextPath()
193                 + "/"
194                 + getIcon(path, repository)
195                 + "\" alt=\"\" border=\"0\" />";
196             }
197         });
198         list.addColumn(new ListColumn("name", msgs.get("inbox.item"), "100", true));
199         list.addColumn(new ListColumn("repository", msgs.get("inbox.repository"), "100px", true));
200         list.addColumn(new ListColumn("workflow", msgs.get("inbox.workflow"), "100px", true));
201         list.addColumn(new ListColumn() {
202             {
203                 setName("comment");
204                 setLabel(msgs.get("inbox.comment"));
205                 setWidth("200px");
206                 setSeparator(true);
207             }
208 
209             @Override
210             public Object getValue() {
211                 if (super.getValue() instanceof String) { 
212                     String comment = (String) super.getValue(); 
213                     return StringEscapeUtils.escapeHtml(comment);
214                 }else{
215                     openwfe.org.engine.workitem.StringAttribute comment = (openwfe.org.engine.workitem.StringAttribute) super.getValue();
216                     comment.setValue(StringEscapeUtils.escapeHtml(comment.getValue().toString()));
217                     return comment;
218                 }
219             }
220         });
221         list.addColumn(new ListColumn() {
222 
223             {
224                 setName("lastModified");
225                 setLabel(msgs.get("inbox.date"));
226                 setWidth("150px");
227             }
228 
229             @Override
230             public Object getValue() {
231                 String str = (String) super.getValue();
232                 Date date = null;
233                 try {
234                     date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse(str);
235                     return DateUtil.formatDateTime(date);
236 
237                 }
238                 catch (ParseException e) {
239                     return StringUtils.EMPTY;
240                 }
241             }
242         });
243 
244     }
245 
246     protected String getIcon(String path, String repository) {
247         return InboxHelper.getIcon(repository, path);
248     }
249 
250     protected String getShowJSFunction(String repository, String path) {
251         return InboxHelper.getShowJSFunction(repository, path);
252     }
253 
254     @Override
255     public void configureContextMenu(ContextMenu menu) {
256         ContextMenuItem edit = new ContextMenuItem("edit");
257         edit.setLabel(msgs.get("inbox.edit"));
258         edit.setOnclick("mgnl.workflow.Inbox.edit();");
259         edit.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/mail_write.gif");
260         edit.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
261 
262         ContextMenuItem show = new ContextMenuItem("show");
263         show.setLabel(msgs.get("inbox.show"));
264         show.setOnclick("mgnl.workflow.Inbox.show();");
265         show.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/note_view.gif");
266         show.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
267 
268         ContextMenuItem proceed = new ContextMenuItem("proceed");
269         proceed.setLabel(msgs.get("inbox.proceed"));
270         proceed.setOnclick("mgnl.workflow.Inbox.proceed();");
271         proceed.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_right2_green.gif");
272         proceed.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
273 
274         ContextMenuItem reject = new ContextMenuItem("reject");
275         reject.setLabel(msgs.get("inbox.reject"));
276         reject.setOnclick("mgnl.workflow.Inbox.reject();");
277         reject.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_left2_red.gif");
278         reject.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
279 
280         ContextMenuItem cancel = new ContextMenuItem("cancel");
281         cancel.setLabel(msgs.get("inbox.cancel"));
282         cancel.setOnclick("mgnl.workflow.Inbox.cancel();");
283         cancel.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/delete2.gif");
284         cancel.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
285 
286         menu.addMenuItem(edit);
287         menu.addMenuItem(null);
288         menu.addMenuItem(show);
289         menu.addMenuItem(null);
290         menu.addMenuItem(proceed);
291         menu.addMenuItem(reject);
292         menu.addMenuItem(null);
293         menu.addMenuItem(cancel);
294     }
295 
296     /**
297      * Same as the context menu.
298      */
299     @Override
300     public void configureFunctionBar(FunctionBar bar) {
301         ContextMenu menu = this.getContextMenu();
302         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("edit")));
303         bar.addMenuItem(null);
304         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("show")));
305         bar.addMenuItem(null);
306         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("reject")));
307         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("proceed")));
308         bar.addMenuItem(null);
309         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("cancel")));
310     }
311 
312     /**
313      * Add some inbox specific stuff: mainly hidden fields.
314      */
315     @Override
316     public String onRender() {
317         return FreemarkerUtil.process(this);
318     }
319 
320     /**
321      * Proceed the item.
322      */
323     public String proceed() {
324         try {
325             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_PROCEED);
326         }
327         catch (Exception e) {
328             AlertUtil.setMessage("can't proceed:", e);
329         }
330         return this.show();
331     }
332 
333     /**
334      * Reject the item (adds a comment).
335      */
336     public String reject() {
337         try {
338             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_REJECT, this.getComment());
339         }
340         catch (Exception e) {
341             AlertUtil.setMessage("can't reject:", e);
342         }
343         return this.show();
344     }
345 
346     /**
347      * Stop the workflow.
348      */
349     public String cancel() {
350         try {
351             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_CANCEL);
352         }
353         catch (Exception e) {
354             AlertUtil.setMessage("can't cancel:", e);
355         }
356         return this.show();
357     }
358 
359     public String getFlowItemId() {
360         return this.flowItemId;
361     }
362 
363     public void setFlowItemId(String flowItemId) {
364         this.flowItemId = flowItemId;
365     }
366 
367     public String getComment() {
368         return this.comment;
369     }
370 
371     public void setComment(String comment) {
372         this.comment = comment;
373     }
374 
375     public boolean isDebug() {
376         return this.debug;
377     }
378 
379     public void setDebug(boolean debug) {
380         this.debug = debug;
381     }
382 
383 }