Tutorial

Page actions

TL;DR Complete API description

How to define a page action

cplaceJS page actions are defined in a type's cplaceJS settings which can be found next to its "attribute" tab since 4.55. Page actions can be used to add new functionality or automate certain process that would otherwise require navigating to multiple pages or may require multiple clicks. Page actions are a powerful feature and they must be written carefully and tested thoroughly.

Defining a simple page action

For our example we will implement a simple page action that archives a page. The action should only be visible to administrators and page can only be archived if its older than 3 months.

We've got an attribute:

  • cf.cplace.archived a boolean attribute that indicates if the page has been archived,

A page will be considered archived if cf.cplace.archived attribute is set to true.

Navigate to the type definition and open the cplaceJS panel, then in the Page actions section click on the "New page action" button. In the modal enter the name for your action, this will be displayed to the user. We will name it "Archive". Optionally we can choose an icon and declare if this action should be displayed as button or in dropdown menu (default). You will also have to enter a message that will be displayed to the user when the action completes successfully. Other than the "As button" option, all other values can be overridden in the script.

The actual script: We want this action to be visible to administrators and only be available on pages that are older than 3 months. The logic to decide if an action should be displayed or not is written in the checkAccess method.

function checkAccess() {
    var currentUser = cplace.utils().getCurrentUser();
    var isAdmin = currentUser.isMemberOf('Administrators');
    var createdAt = page.getBuiltinFeatureValue('createdAt');
    var threshold = DateTime.now().minusMonths(3);
    
    return isAdmin && createdAt.isBefore(threshold);
    
}

The page from which this actions is executed is available to the script as a binding.

Now on to the script that actually archive the page, this is defined in call method.

function call() {
    cplace.actions().updatePage(page, {
        customAttributes: {
            'cf.cplace.archived': true
        }       
    });
}

If we do not return any thing from the call method then the action execution will be considered successful and declared success message will be displayed to the user. We can also override the success message:

function call() {
    cplace.actions().updatePage(page, {
        customAttributes: {
            'cf.cplace.archived': true
        }       
    });
    
    return {
        message: {
            de: page.getName() + ' wurde archiviert',
            en: page.getName() + ' has been archived'
        }       
    }
}

If a message is returned from the call method then it will be used instead of the declared success message.

The complete script looks like below:

return  {
    checkAccess: function() {
        var currentUser = cplace.utils().getCurrentUser();
        var isAdmin = currentUser.isMemberOf('Administrators');
        var createdAt = page.getBuiltinFeatureValue('createdAt');
        var threshold = DateTime.now().minusMonths(3);
        
        return !!(isAdmin && createdAt.isBefore(threshold));
    },
    
    call: function() {
        cplace.actions().updatePage(page, {
            customAttributes: {
                'cf.cplace.archived': true
            }       
        });
        
        return {
            message: {
                de: page.getName() + ' wurde archiviert',
                en: page.getName() + ' has been archived'
            }       
        }
    }   
}

User familiar with cplace pro-code development, will recognize this API as similar to the Handler API.

Complete API description

return {
    // Decide if this action is applicable to a page or not
    // This method is optional. If not implemented then this action will be available to all pages of the type
    checkAccess: function() {
        // return true or false. eg.
        return false;      
    },
    
    // Return an icon for this action
    // This method is optional. If not implemented then the configured icon will be used.
    icon: function() {
        // return an icon name as string 
        return 'fa-archive' 
    },
    
    // Return a label that will be displayed to the user
    // This method is optional. If not implemented then the configured label will be used 
    label: function() {
      return {
          en: 'My action',      
          de: 'Meine Aktion'      
      }   
    },

    // This method is compulsory and must be implemented
    call: function() {
        // actual logic of the action
        // returned object decides what the user will see as response
        return {
            success: false, // default is true
            job: jobId, //if your action starts a job and you want to show job modal
            message: {
                en: 'Some text to be displayed to the user',
                de: 'Ein Text, der dem Benutzer angezeigt werden soll.'
            }  // Override the success message to be displayed to the user or provide error message.
        }
    } 
}

Return from call method is completely optional.

  • If nothing is returned then the action is considered to have succeeded and the configured success message is displayed to the user.
  • If the success property is set to false then action is considered to have failed and error message is displayed to the user.
  • If a jobId is returned then a job progress modal is displayed to the user.