WCP/ADF to OJET: WCP Navigation Model to OJET Router

In this post I will bring a brief solution on how to move Oracle WebCenter Portal Navigation to Oracle JET oj.Router

From WCP to OJET

In Oracle WebCenter Portal the navigation consists in two main types:

Standard WCP Navigation

  • Portal Navigation: Which is the navigation between Portals created within Oracle WebCenter Portal.

  • Current Portal Navigation: Which is the navigation between the Pages of the Current Portal. 
In both of the above cases, WebCenter Portal Security (ADF Security) is applied to display / hide the links and also protects the access to those Pages.

How to move from WebCenter Portal Navigation Model to Oracle JET Routing?

Remember that Oracle JET is a SPA (Single Page Application) which loads dynamically Modules depending on the actions of the user.

The code of the example can be found in my GitHub (ojet-wcp-router):
https://github.com/DanielMerchan/ojet-examples/

Oracle JET uses a class oj.Router for Routing the user to the different Modules / Views "used as Pages". We can briefly say that the oj.Router is the Navigation Model in Oracle JET.

WCP Navigation in Oracle JET


So the following steps needs to be followed to move from WCP Navigation to OJET Navigation:
  • Build the logic in the appController.js for creating the oj.Router navigation model.
    You can configure the oj.Router for containing the full navigation based on the User Privileges or calculate it on-demand when the user clicks a navigation item.

    Use the Root Router for creating the Portal Navigation / Domain Navigation and create Child Routers for the Specific Portal Navigation.

    // 1. Router Setup. Calculates and contains all the links the user has access to.
          // Improvement: It can only contain the Portals links and calculate the rest of the links "lazily" on demand when a top navigation item is clicked.
          // This is just Demo Purpose
          self.router = oj.Router.rootInstance;
          self.router.configure({
            'home': {
              label: 'Home',
              isDefault: true
            },
            'hr': {
              label: 'HR',
              value: self.router.createChildRouter('hrportal', 'hr').configure({
                'home': {
                  label: 'Home',
                  isDefault: true
                },
                'employees': {
                  label: 'Employees'
                }
    
              })
            },
            'sales': {
              label: 'Sales',
              value: self.router.createChildRouter('salesportal', 'sales').configure({
                'home': {ff
                  label: 'Home',
                  isDefault: true
                },
                'search-organisation': {
                  label: 'Search Organisation'
                }
    
              })
            }
          });
  • Now, you can decide how to render the navigation based in the Tree generated in the Router. You have multiple choices:

    • You can generate a oj.JsonTreeDataSource in combination with oj-navigation-list to render the full tree in a Vertical Navigation. This is used in the navDrawer of the example in my GitHub.

      // 4. Auxiliar function to construct a JSON Tree Structure of the hole navigation
            const buildJsonNavTreeData = (router, parentId) => {
              let data = [];
      
              router.states.forEach(state => {
                let childrenData = [];
      
                if (state.value instanceof oj.Router) {
                  childrenData = buildJsonNavTreeData(state.value, state.id);
                }
      
                let jsonData = {};
                jsonData.attr = {
                  id: parentId ? parentId + '/' + state.id : state.id,
                  label: state.label
                }
      
                if (childrenData.length > 0) {
                  jsonData.children = childrenData;
                }
      
                data.push(jsonData);
      
              });
              return data;
            }
      
      
            // 5 Navigation Model in:
            // JSON plain format that can be iterated by iterators
            // JsonTreeDataSource if intended to be fully rendered in a vertical menu (like the Drawer)
            self.navTreeData = buildJsonNavTreeData(self.router, self.router.parentId);
            self.navJsonDataSource = new oj.JsonTreeDataSource(self.navTreeData);


    • You can split the navigation. Render in the top part the Portal Navigation and in the left side of the content area the Current Portal Navigation.  
  • As a good practice, I modified the loadModule function of appController.js to load the View / ViewModels from different folders. Each folder represent a different Portal.
    For example: viewModels/hr/employees.js is the Employees "Page" of the HR Portal.

    Views and ViewModels Folder Strructure




// 3. Modified version of the "loadModule" called from main.js.
      // It takes into consideration the new folder structure for placing Portal items
      self.loadModule = function () {
        ko.computed(function () {
          var portalName = self.router.moduleConfig.name();
          var name = portalName;
          if (portalName && portalName !== 'home') {
            name = portalName + '/' + self.router.getCurrentChildRouter().moduleConfig.name();
          }
          var viewPath = 'views/' + name + '.html';
          var modelPath = 'viewModels/' + name;
          console.log(`name: ${name} viewPath: ${viewPath} modelPath: ${modelPath}`);
          var masterPromise = Promise.all([
            moduleUtils.createView({ 'viewPath': viewPath }),
            moduleUtils.createViewModel({ 'viewModelPath': modelPath })
          ]);
          masterPromise.then(
            function (values) {
              self.moduleConfig({ 'view': values[0], 'viewModel': values[1] });
            }
          );
        });
      };

Check the files appController.js and index.html to understand how navigations are built.

Comments

Popular posts from this blog

OJET: Inter-Module communication in TypeScript Template

OJET: Build and Deploy in an Application Server

OJET: Select All options using only Checkboxset