Alfresco Share 5, using “authority.ftl” form control

Last week I was designing an Alfresco Content Model including a property to gather a set of Alfresco users to be sent to an external service.

I remembered about authority.ftl form control, which is a picker that could fit fine with my requirements.

I searched about the control at official documentation

… and also in the Community.

After some research inspecting Alfresco source code, I realised that this control is auto-configured depending on the definition of the property to be rendered.


   picker.setOptions(
   {
      itemType: "${field.endpointType}",
      multipleSelectMode: ${field.endpointMany?string},
      itemFamily: "authority"
   });

So to include a form control to select MANY USERS following content model should be declared in Repository part.

<aspect name="ks:defaultSigners">
	<associations>
		<association name="ks:alfrescoUser">
			<source>
				<mandatory>false</mandatory>
				<many>true</many>
			</source>
			<target>
				<class>cm:person</class>
				<mandatory>false</mandatory>
				<many>true</many>
			</target>
		</association>
	</associations>
</aspect>

And a simple form control association in Share part makes the work.

<field id="ks:alfrescoUser">
    <control template="/org/alfresco/components/form/controls/authority.ftl"/>
</field>

Also relevant for this use case the addon provided by Douglas C. R. Paes at Alfresco Colleagues Picker Form.

Sometimes a small investigation before developing your tasks will save you many time and will produce an easier solution.

Alfresco Share actions: adding a waiting dialog while performing action in repo

When developing new Alfresco actions in Share part, there are two out-of-the-box JavaScript YUI functions to interact with the user:

  • onActionSimpleRepoAction, which invokes a repo action and shows a success or failure message when this action has finished
  • onActionFormDialog, which shows a form to the user to recover data fields and shows a success or failure message when this actions has finished

These implementations does not include a waiting message between user click and repo response. In some scenarios, the use of this components will produce weird effects on user experience, as the screen is doing “nothing” during some seconds.

Below you can find an alternative implementation for these functions which includes that waiting message.

onActionSimpleRepoAction alternative

(function() {

    YAHOO.Bubbling.fire("registerAction", {
        actionName : "onActionWaitingSimpleRepoAction",
        fn: function onActionWaitingSimpleRepoAction(record, owner) {
            
            this.widgets.waitDialog = Alfresco.util.PopupManager.displayMessage({
                text : this.msg("action.waiting.message"),
                spanClass : "wait",
                displayTime : 0
            });
            
            // Get action params
             var params = this.getAction(record, owner).params,
                displayName = record.displayName,
                namedParams = ["function", "action", "success", "successMessage", "failure", "failureMessage"],
                repoActionParams = {};

             for (var name in params)
             {
                if (params.hasOwnProperty(name) && !Alfresco.util.arrayContains(namedParams, name))
                {
                   repoActionParams[name] = params[name];
                }
             }

             // Deactivate action
             var ownerTitle = owner.title;
             owner.title = owner.title + "_deactivated";

             // Prepare genericAction config
             var config =
             {
                success:
                {
                   event:
                   {
                      name: "metadataRefresh",
                      obj: record
                   }
                },
                failure:
                {
                   message: this.msg(params.failureMessage, displayName),
                   fn: function showAction()
                   {
                      owner.title = ownerTitle;
                   },
                   scope: this
                },
                webscript:
                {
                   method: Alfresco.util.Ajax.POST,
                   stem: Alfresco.constants.PROXY_URI + "api/",
                   name: "actionQueue"
                },
                config:
                {
                   requestContentType: Alfresco.util.Ajax.JSON,
                   dataObj:
                   {
                      actionedUponNode: record.nodeRef,
                      actionDefinitionName: params.action,
                      parameterValues: repoActionParams
                   }
                }
             };

             // Add configured success callbacks and messages if provided
             if (YAHOO.lang.isFunction(this[params.success]))
             {
                config.success.callback =
                {
                   fn: this[params.success],
                   obj: record,
                   scope: this
                };
             }
             if (params.successMessage)
             {
                config.success.message = this.msg(params.successMessage, displayName);
             }

             // Acd configured failure callback and message if provided
             if (YAHOO.lang.isFunction(this[params.failure]))
             {
                config.failure.callback =
                {
                   fn: this[params.failure],
                   obj: record,
                   scope: this
                };
             }
             if (params.failureMessage)
             {
                config.failure.message = this.msg(params.failureMessage, displayName);
             }

             // Execute the repo action
             this.modules.actions.genericAction(config);
            
          }     
    });         
    
})();

onActionFormDialog alternative

(function() {
	
    YAHOO.Bubbling.fire("registerAction",
    {
        actionName: "onActionWaitingFormDialog",
        fn: function dlA_onActionWaitingFormDialog(record, owner)
        {
        	   // Get action & params and start create the config for displayForm
        	   var action = this.getAction(record, owner),
        	      params = action.params,
        	      config =
        	      {
        	         title: this.msg(action.label)
        	      },
        	      displayName = record.displayName;

        	   // Make sure we don't pass the function as a form parameter
        	   delete params["function"];

        	   // Add configured success callback
        	   var success = params["success"];
        	   delete params["success"];
        	   var failureMessage = params["failureMessage"];
        	   delete params["failureMessage"];
        	   config.success =
        	   {
        	      fn: function(response, obj)
        	      {
        	         // Invoke callback if configured and available
        	         if (YAHOO.lang.isFunction(this[success]))
        	         {
        	      	   if (response != null && response.json != null 
        	      			   && response.json.status != null
        	      			   && response.json.status.code != null 
        	      			   && response.json.status.code == "500"){
        	      		   this[success].call(this, response, obj);
        	      		   // Add configure failure message
        	      		   if (failureMessage != null) {
        	      			   this.msg(failureMessage, displayName);
        	      		   }
        	      	   }
        	         }

        	         // Fire metadataRefresh so other components may update themselves
        	         YAHOO.Bubbling.fire("metadataRefresh", obj);
        	      },
        	      obj: record,
        	      scope: this
        	   };

        	   // Add configured failure
        	   var success = params["failure"];
        	   delete params["failure"];
        	   nodeRef = record.nodeRef;
        	   
        	   // Add configure success message
        	   if (params.successMessage) {
        	      config.successMessage = this.msg(params.successMessage, displayName);
        	      delete params["successMessage"];
        	   }

        	   // Use the remaining properties as form properties
        	   config.properties = params;
        	   
        	   // Finally display form as dialog
        	   Alfresco.util.PopupManager.displayForm(config);
        	   
     		   // Waiting dialog
        	   waitDialog = Alfresco.util.PopupManager.displayMessage({
    				text : this.msg("action.waiting.message"),
    				spanClass : "wait",
    				displayTime : 0
    		   });
     		   
               YAHOO.Bubbling.on("beforeFormRuntimeInit", function PopupManager_displayForm_onBeforeFormRuntimeInit(layer, args)
               {
            	   
            	   // Clear wait dialog on close button click
            	   var panel = document.getElementById(config.properties.htmlid + "-panel");
            	   var closeButton = panel.getElementsByClassName("container-close")[0];
            	   if (closeButton) {
            		   closeButton.addEventListener("click", function(){
                     	  waitDialog.destroy();
                       });
            	   }
            	   
            	   // Clear wait dialog on cancel button click
            	   var cancelButton = document.getElementById(config.properties.htmlid + "-form-cancel-button");
                   if (cancelButton) {
                      cancelButton.addEventListener("click", function(){
                    	  waitDialog.destroy();
                      });
                      
                   }
               },
               {
                  config: config
               });
        	   
        	}

    });
    
})();