Weka editor view for mobile and extensions

Weka view architecture

The Weka content view architecture is based on the visitor design pattern. For Weka content in mobile, we use the concept of preorder tree traversal and transforming the JSON input into Weka Nodes, which are linked in a tree data structure. The Tree uses an accept method, which triggers visit methods to accept Visitor Nodes. Those methods are joined to form a class of operations which transforms that Node. Therefore, adding new operations will create new extensions. The goal is to have flexibility, with the ability to add and remove operations without having to modify the Node structure. It is one way to follow the open/closed principle.

The objects participating in this pattern are:

  • Object Structure: Nodes list
    • Maintains a collection of Elements which can be iterated over
  • Elements: WekaNode/Node objects
    • Defines an accept method that accepts visitor objects
    • In the accept method, the visitor's visit method is invoked with 'this' as a parameter
  • Visitors: Text/Paragraph/Emoji/List(Bullet list, Numerical list)
    • Implements a visit method. The argument is the Element being visited. This is where the Element's changes are made
    • Visits each part (Text/Paragraph/Emoji/List(Bullet list, Numerical list))



In the UML class diagram above, the WekaBulletList class doesn't implement a new operation directly. Instead, WekaBulletList  implements a dispatching operation accept(visitor) that 'dispatches' (delegates) a request to the accepted visitor object (visitor.visitWekaBulletList(this)). The ToFullSumary  class implements the operation (visitWekaBulletList(e:WekaBulletList)).

Extending Weka editor view for mobile

This section demonstrates how you can extend Weka view in mobile with an example. Let's suppose we need to add an underline text format view in the profile page in the Totara Mobile app.

One way to achieve this would be to create a new tree operation, which could be added to src/totara/components/weka/treeOperations.tsx :

Let's call the operation 'ToUnderlineText':

class ToUnderlineText extends ToFullSummary {
  visitWekaText(element: WekaText): Object {
    return (<Text style={{textDecorationLine: 'underline'}}>
      {element.text}
    </Text>);
  }
}

Note that in this example an existing operation (ToFullSummary) was extended, which already formats most of the content. Other example of operations can be found in src/totara/components/weka/treeOperations.tsx.

The next step is to use that operation. For instance, let's suppose you have a profile page for which the inputs are the user info and Weka content. User data can be rendered in a UserView, for instance. The Weka content will be rendered, however, using the function wrappedWekaNodes, jsonObjectToWekaNodes and JSON.parse . Those functions are in src/totara/components/weka/WekaUtils.ts


import { jsonObjectToWekaNodes, wrappedWekaNodes } from "./wekaUtils";

const Profile = ({user, wekaContent}) =>
 { const root = wrappedWekaNodes(jsonObjectToWekaNodes(JSON.parse(wekaContent)));

 return ( 
	 <View>
		<UserView user={user}></UserView>
		{root.accept(new ToUnderlineText())}
	 </View>
 );
}


Finally you will see the Weka content from the API being rendered in the mobile interface.

In the code you can find other examples in:
 - src/totara/components/weka/WekaContent.tsx 
 - src/totara/components/SummaryContent.tsx 
 - src/totara/components/weka/__tests__/wekaUtils-test.js 

References

https://en.wikipedia.org/wiki/Visitor_pattern

https://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern