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.StringUtils;
67  import org.slf4j.Logger;
68  import org.slf4j.LoggerFactory;
69  
70  
71  /**
72   * The {@link info.magnolia.module.admininterface.lists.AbstractList} responsible for displaying a user's inbox, i.e current work items.
73   * @author Philipp Bracher
74   * @version $Revision:3416 $ ($Author:philipp $)
75   */
76  public class Inbox extends AbstractList {
77  
78      private static final Logger log = LoggerFactory.getLogger(Inbox.class);
79  
80      /**
81       * The id of the workitem on which we called the command.
82       */
83      private String flowItemId;
84  
85      /**
86       * The comment the user entered by proceeding or rejecting.
87       */
88      private String comment;
89  
90      /**
91       * Show all the values of the workitem if true.
92       */
93      private boolean debug = false;
94  
95      protected Messages msgs = MessagesManager.getMessages("info.magnolia.module.workflow.messages");
96  
97      public Inbox(String name, HttpServletRequest request, HttpServletResponse response) {
98          super(name, request, response);
99      }
100 
101     @Override
102     public ListModel getModel() {
103         return new InboxListModel(MgnlContext.getUser().getName());
104     }
105 
106     @Override
107     public String getSortBy() {
108         if(StringUtils.isEmpty(super.getSortBy())){
109             setSortBy("lastModified");
110         }
111         return super.getSortBy();
112     }
113 
114     /**
115      * Sets the select js code and defines the columns.
116      */
117     @Override
118     public void configureList(ListControl list) {
119 
120         // define the select action
121         list.setRenderer(new AdminListControlRenderer() {
122 
123             @Override
124             public String onSelect(ListControl list, Integer index) {
125 
126                 String customEditDialog = ObjectUtils.toString(list
127                         .getIteratorValue(WorkflowConstants.ATTRIBUTE_EDIT_DIALOG));
128 
129                 String editDialog = StringUtils.defaultIfEmpty(customEditDialog, WorkflowConstants.DEFAULT_EDIT_DIALOG);
130                 String repository = ObjectUtils.toString(list.getIteratorValue("repository"));
131                 String path = ObjectUtils.toString(list.getIteratorValue("path"));
132 
133                 StringBuffer js = new StringBuffer();
134                 js.append("mgnl.workflow.Inbox.current = ");
135                 js.append("{");
136                 js.append("id : '").append(list.getIteratorValue("id")).append("',");
137                 js.append("path : '").append(path).append("',");
138                 js.append("version : '").append(list.getIteratorValue("version")).append("',");
139                 js.append("repository : '").append(repository).append("',");
140                 js.append("workItemPath : '").append(list.getIteratorValue("workItemPath")).append("',");
141                 js.append("editDialog : '").append(editDialog).append("'");
142                 js.append("};");
143                 js.append("mgnl.workflow.Inbox.show = ").append(getShowJSFunction(repository, path)).append(";");
144                 js.append(super.onSelect(list, index));
145                 return js.toString();
146             }
147 
148             @Override
149             public String onDblClick(ListControl list, Integer index) {
150                 return "mgnl.workflow.Inbox.edit();";
151             }
152         });
153 
154         list.addSortableField("lastModified");
155         list.addGroupableField("repository");
156         list.addGroupableField("workflow");
157 
158         list.addColumn(new ListColumn() {
159 
160             {
161                 setName("icon");
162                 setLabel("");
163                 setWidth("30px");
164                 setSeparator(false);
165             }
166 
167             @Override
168             public Object getValue() {
169                 String path = "" + this.getListControl().getIteratorValue("path");
170                 String repository = "" + this.getListControl().getIteratorValue("repository");
171                 String uuid = "" + this.getListControl().getIteratorValue("uuid");
172                 String version = "" + this.getListControl().getIteratorValue("version");
173                 try {
174                     final Content content;
175                     // versioning disabled
176                     if (StringUtils.isEmpty(version)) {
177                         content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid);
178                     } else {
179                         content = MgnlContext.getSystemContext().getHierarchyManager(repository).getContentByUUID(uuid).getVersionedContent(version);
180                     }
181                     if (content.hasMixin(ItemType.DELETED_NODE_MIXIN)) {
182                         path = ItemType.DELETED_NODE_MIXIN;
183                     }
184                 } catch (ItemNotFoundException e) {
185                     log.debug("Item {}:{} does no longer exist in the workspace. Uuid: {}", new String[] {repository, path, uuid});
186 
187                 } catch (RepositoryException e) {
188                     log.error("Failed to retrieve versioned node [path=" + path + ", uuid=" + uuid + ", version=" + version, e);
189                 }
190                 return "<img src=\""
191                 + MgnlContext.getContextPath()
192                 + "/"
193                 + getIcon(path, repository)
194                 + "\" alt=\"\" border=\"0\" />";
195             }
196         });
197         list.addColumn(new ListColumn("name", msgs.get("inbox.item"), "100", true));
198         list.addColumn(new ListColumn("repository", msgs.get("inbox.repository"), "100px", true));
199         list.addColumn(new ListColumn("workflow", msgs.get("inbox.workflow"), "100px", true));
200         list.addColumn(new ListColumn("comment", msgs.get("inbox.comment"), "200", true));
201         list.addColumn(new ListColumn() {
202 
203             {
204                 setName("lastModified");
205                 setLabel(msgs.get("inbox.date"));
206                 setWidth("150px");
207             }
208 
209             @Override
210             public Object getValue() {
211                 String str = (String) super.getValue();
212                 Date date = null;
213                 try {
214                     date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse(str);
215                     return DateUtil.formatDateTime(date);
216 
217                 }
218                 catch (ParseException e) {
219                     return StringUtils.EMPTY;
220                 }
221             }
222         });
223 
224     }
225 
226     protected String getIcon(String path, String repository) {
227         return InboxHelper.getIcon(repository, path);
228     }
229 
230     protected String getShowJSFunction(String repository, String path) {
231         return InboxHelper.getShowJSFunction(repository, path);
232     }
233 
234     @Override
235     public void configureContextMenu(ContextMenu menu) {
236         ContextMenuItem edit = new ContextMenuItem("edit");
237         edit.setLabel(msgs.get("inbox.edit"));
238         edit.setOnclick("mgnl.workflow.Inbox.edit();");
239         edit.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/mail_write.gif");
240         edit.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
241 
242         ContextMenuItem show = new ContextMenuItem("show");
243         show.setLabel(msgs.get("inbox.show"));
244         show.setOnclick("mgnl.workflow.Inbox.show();");
245         show.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/note_view.gif");
246         show.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
247 
248         ContextMenuItem proceed = new ContextMenuItem("proceed");
249         proceed.setLabel(msgs.get("inbox.proceed"));
250         proceed.setOnclick("mgnl.workflow.Inbox.proceed();");
251         proceed.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_right2_green.gif");
252         proceed.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
253 
254         ContextMenuItem reject = new ContextMenuItem("reject");
255         reject.setLabel(msgs.get("inbox.reject"));
256         reject.setOnclick("mgnl.workflow.Inbox.reject();");
257         reject.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/navigate_left2_red.gif");
258         reject.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
259 
260         ContextMenuItem cancel = new ContextMenuItem("cancel");
261         cancel.setLabel(msgs.get("inbox.cancel"));
262         cancel.setOnclick("mgnl.workflow.Inbox.cancel();");
263         cancel.setIcon(MgnlContext.getContextPath() + "/.resources/icons/16/delete2.gif");
264         cancel.addJavascriptCondition("{test: function(){return mgnl.workflow.Inbox.current.id!=null}}");
265 
266         menu.addMenuItem(edit);
267         menu.addMenuItem(null);
268         menu.addMenuItem(show);
269         menu.addMenuItem(null);
270         menu.addMenuItem(proceed);
271         menu.addMenuItem(reject);
272         menu.addMenuItem(null);
273         menu.addMenuItem(cancel);
274     }
275 
276     /**
277      * Same as the context menu.
278      */
279     @Override
280     public void configureFunctionBar(FunctionBar bar) {
281         ContextMenu menu = this.getContextMenu();
282         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("edit")));
283         bar.addMenuItem(null);
284         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("show")));
285         bar.addMenuItem(null);
286         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("reject")));
287         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("proceed")));
288         bar.addMenuItem(null);
289         bar.addMenuItem(new FunctionBarItem(menu.getMenuItemByName("cancel")));
290     }
291 
292     /**
293      * Add some inbox specific stuff: mainly hidden fields.
294      */
295     @Override
296     public String onRender() {
297         return FreemarkerUtil.process(this);
298     }
299 
300     /**
301      * Proceed the item.
302      */
303     public String proceed() {
304         try {
305             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_PROCEED);
306         }
307         catch (Exception e) {
308             AlertUtil.setMessage("can't proceed:", e);
309         }
310         return this.show();
311     }
312 
313     /**
314      * Reject the item (adds a comment).
315      */
316     public String reject() {
317         try {
318             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_REJECT, this.getComment());
319         }
320         catch (Exception e) {
321             AlertUtil.setMessage("can't reject:", e);
322         }
323         return this.show();
324     }
325 
326     /**
327      * Stop the workflow.
328      */
329     public String cancel() {
330         try {
331             WorkflowUtil.proceed(this.getFlowItemId(), WorkflowConstants.ACTION_CANCEL);
332         }
333         catch (Exception e) {
334             AlertUtil.setMessage("can't cancel:", e);
335         }
336         return this.show();
337     }
338 
339     public String getFlowItemId() {
340         return this.flowItemId;
341     }
342 
343     public void setFlowItemId(String flowItemId) {
344         this.flowItemId = flowItemId;
345     }
346 
347     public String getComment() {
348         return this.comment;
349     }
350 
351     public void setComment(String comment) {
352         this.comment = comment;
353     }
354 
355     public boolean isDebug() {
356         return this.debug;
357     }
358 
359     public void setDebug(boolean debug) {
360         this.debug = debug;
361     }
362 
363 }