1 /**
  2  * Copyright (C) 2005-2010 Alfresco Software Limited.
  3  *
  4  * This file is part of Alfresco
  5  *
  6  * Alfresco is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU Lesser General Public License as published by
  8  * the Free Software Foundation, either version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * Alfresco is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public License
 17  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 18  */
 19 
 20 /**
 21  * Rules "Workflow" Action module.
 22  *
 23  * @namespace Alfresco.module
 24  * @class Alfresco.module.RulesWorkflowAction
 25  */
 26 (function()
 27 {
 28    /**
 29    * YUI Library aliases
 30    */
 31    var Dom = YAHOO.util.Dom,
 32       KeyListener = YAHOO.util.KeyListener,
 33       Selector = YAHOO.util.Selector;
 34 
 35    /**
 36     * Alfresco Slingshot aliases
 37     */
 38     var $html = Alfresco.util.encodeHTML,
 39        $combine = Alfresco.util.combinePaths,
 40        $hasEventInterest = Alfresco.util.hasEventInterest;
 41 
 42    Alfresco.module.RulesWorkflowAction = function(htmlId)
 43    {
 44       Alfresco.module.RulesWorkflowAction.superclass.constructor.call(this, "Alfresco.module.RulesWorkflowAction", htmlId, ["button", "container", "connection"]);
 45 
 46       // Decoupled event listeners
 47       if (htmlId != "null")
 48       {
 49          YAHOO.Bubbling.on("folderSelected", this.onDestinationSelected, this);
 50       }
 51 
 52       return this;
 53    };
 54 
 55    /**
 56    * Alias to self
 57    */
 58    var RWA = Alfresco.module.RulesWorkflowAction;
 59 
 60    /**
 61    * View Mode Constants
 62    */
 63    YAHOO.lang.augmentObject(RWA,
 64    {
 65       /**
 66        * "Approval step" view mode constant.
 67        *
 68        * @property VIEW_MODE_APPROVAL_STEP
 69        * @type string
 70        * @final
 71        */
 72       VIEW_MODE_APPROVAL_STEP: "approval-step",
 73 
 74       /**
 75        * "Rejection steo" view mode constant.
 76        *
 77        * @property VIEW_MODE_REJECTION_STEP
 78        * @type string
 79        * @final
 80        */
 81       VIEW_MODE_REJECTION_STEP: "rejection-step"
 82    });
 83 
 84    YAHOO.extend(Alfresco.module.RulesWorkflowAction, Alfresco.component.Base,
 85    {
 86       /**
 87        * Object container for initialization options
 88        */
 89       options:
 90       {
 91          /**
 92           * Current siteId for site view mode.
 93           *
 94           * @property siteId
 95           * @type string
 96           */
 97          siteId: "",
 98 
 99          /**
100           * Repository's rootNode
101           *
102           * @property rootNode
103           * @type Alfresco.util.NodeRef
104           */
105          rootNode: null,
106 
107          /**
108           * Whether the Repo Browser is in use or not
109           *
110           * @property repositoryBrowsing
111           * @type boolean
112           */
113          repositoryBrowsing: true,
114 
115          /**
116           * ContainerId representing root container in site view mode
117           *
118           * @property containerId
119           * @type string
120           * @default "documentLibrary"
121           */
122          containerId: "documentLibrary",
123 
124          /**
125           * Template URL
126           *
127           * @property templateUrl
128           * @type string
129           * @default Alfresco.constants.URL_SERVICECONTEXT + "modules/rules/actions/workflow"
130           */
131          templateUrl: Alfresco.constants.URL_SERVICECONTEXT + "modules/rules/actions/workflow",
132 
133          /**
134           * Dialog view mode: approval step or rejection steo
135           *
136           * @property viewMode
137           * @type string
138           * @default Alfresco.modules.RulesWorkflowAction.VIEW_MODE_APPROVAL_STEP
139           */
140          viewMode: RWA.VIEW_MODE_APPROVAL_STEP,
141 
142          /**
143           * Allowed dialog view modes
144           *
145           * @property allowedViewModes
146           * @type array
147           * @default [VIEW_MODE_APPROVAL_STEP, VIEW_MODE_REJECTION_STEP]
148           */
149          allowedViewModes:
150          [
151             RWA.VIEW_MODE_APPROVAL_STEP,
152             RWA.VIEW_MODE_REJECTION_STEP
153          ]
154       },
155 
156 
157       /**
158        * Container element for template in DOM.
159        *
160        * @property containerDiv
161        * @type HTMLElement
162        */
163       containerDiv: null,
164 
165       /**
166        * Main entry point
167        * @method showDialog
168        * @param workflowConfig {object} Data to fill the form with
169        */
170       showDialog: function RWA_showDialog(workflowConfig)
171       {
172          if (!this.containerDiv)
173          {
174             // Load the UI template from the server
175             Alfresco.util.Ajax.request(
176             {
177                url: this.options.templateUrl,
178                dataObj:
179                {
180                   htmlid: this.id
181                },
182                successCallback:
183                {
184                   fn: this.onTemplateLoaded,
185                   obj: workflowConfig,
186                   scope: this
187                },
188                failureMessage: "Could not load template:" + this.options.templateUrl,
189                execScripts: true
190             });
191          }
192          else
193          {
194             // Show the dialog
195             this._showDialog(workflowConfig);
196          }
197       },
198 
199       /**
200        * Event callback when dialog template has been loaded
201        *
202        * @method onTemplateLoaded
203        * @param response {object} Server response from load template XHR request
204        * @param workflowConfig {object} Data to fill the form with
205        */
206       onTemplateLoaded: function RWA_onTemplateLoaded(response, workflowConfig)
207       {
208          // Inject the template from the XHR request into a new DIV element
209          this.containerDiv = document.createElement("div");
210          this.containerDiv.setAttribute("style", "display:none");
211          this.containerDiv.innerHTML = response.serverResponse.responseText;
212 
213          // The panel is created from the HTML returned in the XHR request, not the container
214          var dialogDiv = Dom.getFirstChild(this.containerDiv);
215 
216          // Create and render the YUI dialog
217          this.widgets.dialog = Alfresco.util.createYUIPanel(dialogDiv);
218 
219          this.widgets.destinationLocation = new Alfresco.Location(this.id + "-destinationLabel");
220          this.widgets.destinationLocation.setOptions(
221          {
222             siteId: this.options.siteId,
223             rootNode: this.options.rootNode
224          });
225 
226          // Buttons (note: ok button's click will be handled in forms onBeforeAjaxSubmit)
227          this.widgets.selectDestinationButton = Alfresco.util.createYUIButton(this, "selectDestination-button", this.onSelectDestinationClick);
228          this.widgets.okButton = Alfresco.util.createYUIButton(this, "ok-button", null,
229          {
230             type: "submit"
231          });
232          this.widgets.cancelButton = Alfresco.util.createYUIButton(this, "cancel-button", this.onCancelClick);
233 
234          // Configure the forms runtime
235          var form = new Alfresco.forms.Form(this.id + "-form");
236          this.widgets.form = form;
237 
238          // Comment is mandatory
239          form.addValidation(this.id + "-action", Alfresco.forms.validation.mandatory, null, "keyup");
240          form.addValidation(this.id + "-nodeRef", Alfresco.forms.validation.mandatory, null, "keyup");
241 
242          // The ok button is the submit button, and it should be enabled when the form is ready
243          form.setShowSubmitStateDynamically(true, false);
244          form.setSubmitElements(this.widgets.okButton);
245 
246          // Stop the form from being submitted and fire and event from the collected information        
247          form.doBeforeAjaxRequest =
248          {
249             fn: function(p_config, p_obj)
250             {
251                // Fire event so other component know
252                YAHOO.Bubbling.fire("workflowOptionsSelected",
253                {
254                   options:
255                   {
256                      label: p_config.dataObj.label,
257                      action: p_config.dataObj.action,
258                      nodeRef: p_config.dataObj.nodeRef,
259                      path: p_config.dataObj.path,
260                      viewMode: this.options.viewMode
261                   },
262                   eventGroup: this
263                });
264 
265                this.widgets.dialog.hide();
266 
267                // Return fals so the form isn't submitted
268                return false;
269             },
270             obj: null,
271             scope: this
272          };
273 
274          // We're in a popup, so need the tabbing fix
275          form.applyTabFix();
276          form.init();
277 
278          // Register the ESC key to close the dialog
279          var escapeListener = new KeyListener(document,
280          {
281             keys: KeyListener.KEY.ESCAPE
282          },
283          {
284             fn: function(id, keyEvent)
285             {
286                this.onCancelClick();
287             },
288             scope: this,
289             correctScope: true
290          });
291          escapeListener.enable();                  
292 
293          // Show the dialog
294          this._showDialog(workflowConfig);
295       },
296 
297       /**
298        * Internal show dialog function
299        * @method _showDialog
300        * @param workflowConfig {object} Data to fill the form with
301        */
302       _showDialog: function RWA__showDialog(workflowConfig)
303       {
304          // Dialog title
305          Dom.get(this.id + "-title").innerHTML = this.msg(this.options.viewMode + ".header");
306 
307          // Display form data
308          workflowConfig = workflowConfig ? workflowConfig : {};
309 
310          // Label textfield
311          Dom.get(this.id + "-label").value = workflowConfig.label ? $html(workflowConfig.label) : this.msg(this.options.viewMode + ".label.default");
312 
313          // Action drop down
314          Alfresco.util.setSelectedIndex(Dom.get(this.id + "-action"), workflowConfig.action);
315 
316          // Destination picker
317          Dom.get(this.id + "-nodeRef").value = workflowConfig.nodeRef ? workflowConfig.nodeRef.toString() : "";
318          this.widgets.destinationLocation.displayByNodeRef(workflowConfig.nodeRef);
319 
320          // Update submit elements & show the dialog
321          this.widgets.form.updateSubmitElements();
322          this.widgets.dialog.show();
323       },
324 
325 
326       /**
327        * YUI WIDGET EVENT HANDLERS
328        * Handlers for standard events fired from YUI widgets, e.g. "click"
329        */
330 
331       /**
332        * Dialog select destination button event handler
333        *
334        * @method onSelectDestinationClick
335        * @param e {object} DomEvent
336        * @param p_obj {object} Object passed back from addListener method
337        */
338       onSelectDestinationClick: function RCIA_onSelectDestinationClick(e, p_obj)
339       {
340          // Set up select destination dialog
341          if (!this.widgets.destinationDialog)
342          {
343             this.widgets.destinationDialog = new Alfresco.module.DoclibGlobalFolder(this.id + "-selectDestination");
344 
345             var allowedViewModes =
346             [
347                Alfresco.module.DoclibGlobalFolder.VIEW_MODE_SITE
348             ];
349             if (this.options.repositoryBrowsing === true)
350             {
351                allowedViewModes.push(Alfresco.module.DoclibGlobalFolder.VIEW_MODE_REPOSITORY, Alfresco.module.DoclibGlobalFolder.VIEW_MODE_USERHOME);
352             }
353 
354             this.widgets.destinationDialog.setOptions(
355             {
356                allowedViewModes: allowedViewModes,
357                siteId: this.options.siteId,
358                containerId: this.options.containerId,
359                title: this.msg("title.destinationDialog"),
360                nodeRef: this.options.rootNode
361             });
362          }
363 
364          // Make sure correct path is expanded
365          var pathNodeRef = Dom.get(this.id + "-nodeRef").value;
366          this.widgets.destinationDialog.setOptions(
367          {
368             pathNodeRef: pathNodeRef ? new Alfresco.util.NodeRef(pathNodeRef) : null              
369          });
370 
371          // Show dialog
372          this.widgets.destinationDialog.showDialog();
373       },
374 
375 
376       /**
377        * Folder selected in destination dialog
378        *
379        * @method onDestinationSelected
380        * @param layer {object} Event fired
381        * @param args {array} Event parameters (depends on event type)
382        */
383       onDestinationSelected: function RWA_onDestinationSelected(layer, args)
384       {
385          // Check the event is directed towards this instance
386          if ($hasEventInterest(this.widgets.destinationDialog, args))
387          {
388             // Save values from dialog and update submit elements
389             var obj = args[1];
390             if (obj !== null)
391             {
392                Dom.get(this.id + "-nodeRef").value = obj.selectedFolder.nodeRef;
393                this.widgets.destinationLocation.displayByNodeRef(obj.selectedFolder.nodeRef);
394             }
395             this.widgets.form.updateSubmitElements();
396          }
397       },
398 
399       /**
400        * Dialog Cancel button event handler
401        *
402        * @method onCancelClick
403        * @param e {object} DomEvent
404        * @param p_obj {object} Object passed back from addListener method
405        */
406       onCancelClick: function RWA_onCancelClick(e, p_obj)
407       {
408          this.widgets.dialog.hide();
409       }
410    });
411 
412    /* Dummy instance to load optional YUI components early */
413    var dummyInstance = new Alfresco.module.RulesWorkflowAction("null");
414 })();
415