Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

Actual Implementation

Project setup

Create a module and empty webapp using the maven archetype selector, then change the parent pom and module pom to thisCheck out the project from git here.

Slightly modified Content app

Import the following configuration as you can see, we slightly modified certain fields of a "standard" content app.

Image Added

Adding categorization

Categorization was added in the same way as for 4.5:

Image Added

Basically you add a tab and extend /modules/categorization/dialogs/generic/tabCategorization.

Linking the image to use stuff from the assets

Instead of using the image uploader we will link the image field of the restaurant to a Node in the assets. Uploading assets will be done using the asset app. It is foreseen to be able to upload as well assets directly through the content app (probably 5.1).

This is done by adding the following:

Image Added

Or link to the asset will be stored under the image node, to retrieve it in our page, we can use the DAMTemplating API, we can use it as follows:

Code Block
languagejava
//restoNode is the node in our restaurant workspace that holds the restaurant we want to submit. 
ContentMap cm = new ContentMap(restoNode);
Asset asset = damTemplatingFunctions.getAssetForId((String)cm.get("image"));

Adding an activation action

We duplicate the activation action we can find in ... the Pages app and add it under the actions, add an acticate the corresponding activate action in the actionbar.

Image Added

As you can see we only allowed superuser to activate content, this is because we would like to add a sort of activation authorization command or a basic approval workflow.

Adding the public instance

We add a public server as described in the documentation, for easyness easiness of use we will have author and public on teh same instance.

...

We now create a new template and blog page by extending stkHome, we will as well add a new FTL and new component to the project.

Image Added

The modelClass will list all activated restaurants.

The new FTL will just display the activated items.

Code Block
languagejava
public class FetchRestos extends AbstractSTKTemplateModel<TemplateDefinition> {

    private static Logger log = Logger.getLogger(FetchRestos.class);
    private static final String ACTIVE_RESTOS = "select * from [mgnl:content] where [mgnl:activationStatus] = CAST('true' AS BOOLEAN)";
    private List<Resto> restos = null;
    private DamTemplatingFunctions damTemplatingFunctions;


    @Inject
    public FetchRestos(Node content, TemplateDefinition definition, RenderingModel<?> parent, STKTemplatingFunctions stkFunctions, TemplatingFunctions templatingFunctions,DamTemplatingFunctions damFunctions) {
        super(content, definition, parent, stkFunctions, templatingFunctions);
        damTemplatingFunctions=damFunctions;
        restos = new ArrayList<Resto>();

    }


    public String execute(){
        try {
            Session session = MgnlContext.getJCRSession("restaurants");
            Query query = session.getWorkspace().getQueryManager().createQuery(ACTIVE_RESTOS,Query.JCR_SQL2);
            NodeIterator ni = query.execute().getNodes();

            while(ni.hasNext()){
               ContentMap cm = new ContentMap(ni.nextNode());
               Asset asset = damTemplatingFunctions.getAssetForId((String)cm.get("image"));
               Map assetMap = damTemplatingFunctions.getAssetMap(asset);
               String type = (String)assetMap.get("type");
               restos.add(new Resto((String)cm.getJCRNode().getName(),damTemplatingFunctions.getAssetRendition(asset, "thumbnail").getLink(), (String) cm.get("description"),type));

            }


        } catch (RepositoryException e) {
            log.error(e.getMessage());
        } catch (DamException e) {
            log.error(e.getMessage());
        }



        return "ok";
    }


    public List<Resto> getRestos() {
        return restos;
    }

    public void setRestos(List<Resto> restos) {
        this.restos = restos;
    }

}

 

Creating normal users and the correct roles

We create a new role for teh the mobile authors who submit the restosrestaurants, add a new user and give him the correct roles and basic groups for only accessing the addrsto appaddresto app.

First create the role:

Image AddedImage Added

Then create add the access rights:

Image Added

Create a group and add the following roles to it:

Image Added

Finally create a user and assign the preceding group to it.

Giving correct access rights to the app

We give the correct rights to the app. We want our user to be able to open the app but only the app, so we add the role we created to the app's security.

Image Added

Adding a messageView

We need to register a messageView so that the pulse can find it and open it. So we add a messageview to the addresto app as follows.

Image Added

Adding a "Request for activation action"

...

We want to show a notification so we need the Shell.

Giving the correct rights to the activation action and request for activation action

We want to disable the "direct" publishing for the mobile author and enable only the "request for activation" button so this is how we restrict it.

Adding a messageView

...

.

The API is quite well designed actually, creating those notifications requires us to write a minimum of code.

First we create the definition of the action, this definition will be used as parameter object for the implemented action, when fired it looks for the implemented action class instantiates it and executes the action. (RequestForActivation.class) .

Info

Action definitions are configured in the jcr on the sub app, read by node2bean, node2bean looks at the class property in jcr and creates the instance using the component provider (guice), if no class property is set it uses the type-mapping.

Code Block
languagejava
/**
 * Created with IntelliJ IDEA.
 * User: kdewitte
 * Date: 7/1/13
 * Time: 2:39 PM
 * 
 * This class contains the definition of the action we would like to create.
 * 
 */
public class RequestForActivationActionDefinition extends ConfiguredActionDefinition {
    public RequestForActivationActionDefinition() {
        setImplementationClass(RequestForActivationAction.class);
    }
}

We define it in the module descriptor.

Code Block
languagehtml/xml
 <type-mapping>
      <type>info.magnolia.ui.api.action.ConfiguredActionDefinition</type>
      <implementation>info.magnolia.m5.apps.actions.RequestForActivationActionDefinition</implementation>
  </type-mapping>

Now we can implement the action:

Code Block
languagejava
public class RequestForActivationAction extends AbstractAction<RequestForActivationActionDefinition> {


    private final Shell shell;
    private final SubAppContext subAppContext;

    @Inject
    public RequestForActivationAction(RequestForActivationActionDefinition definition,SubAppContext subAppContext,  Shell shell) {
        super(definition);
        this.shell = shell;
        this.subAppContext = subAppContext;
    }

    @Override
    public void execute() throws ActionExecutionException {
        MessageStyleTypeEnum messageStyleType;
        messageStyleType = MessageStyleTypeEnum.INFO;
        Message message = new Message();
        message.setMessage("User "+MgnlContext.getUser().getName()+ " would like to activate the following ");
        message.setSubject("request for activation");
        message.setType(MessageType.WORKITEM);
        //give it the messageView we want to display on opening the message
        message.put(Message.MESSAGE_VIEW, "addresto:restoView");
        //we need the location to travel back to the contentview and approve or reject
        message.put("location",subAppContext.getLocation().toString());
        subAppContext.getAppContext().sendUserMessage("superuser", message);
        shell.openNotification(messageStyleType, true, "Your request for activation has been sent !");
    }
}

Adding a review action to the messageView.

...