Skip to content
Alexandr Kalinin edited this page Aug 16, 2016 · 7 revisions

SOCRAT is designed to be highly scalable. According to large-scale architecture principles, each module implements standard structure. You can add a new module to SOCRAT in a few easy steps:

Module template

Each module is represented by a collection of files, one file per AngularJs component, such as module, controller, directive, or service. These components are implemented as CoffeeScript classes in CommonJs module format. SOCRAT provides base classes for different types of components, which can be used to create custom implementations. Let's create new analysis module, that will appear in main menu under Tools drop-down.

Empty template

We can start by creating a new directory MyModule under scripts/analysis/tools and create MyModule.module.coffee file inside:

'use strict'
# import module class
Module = require 'scripts/BaseClasses/BaseModule.coffee'
# export instance of new module
module.exports = myModule = new Module
  # module id for registration
  id: 'socrat_analysis_mymodule'
  # module components
  components:
    services:
      'socrat_analysis_mymodule_initService': require 'scripts/analysis/tools/MyModule/MyModuleInit.service.coffee'
      'socrat_analysis_mymodule_msgService': require 'scripts/analysis/tools/MyModule/MyModuleMsgService.service.coffee'
      'socrat_analysis_mymodule_dataService': require 'scripts/analysis/tools/MyModule/MyModuleDataService.service.coffee'
      'socrat_analysis_mymodule_myService': require 'scripts/analysis/tools/MyModule/MyModuleMyService.service.coffee'
    controllers:
      'mymoduleMainCtrl': require 'scripts/analysis/tools/MyModule/MyModuleMainCtrl.ctrl.coffee'
      'mymoduleSidebarCtrl': require 'scripts/analysis/tools/MyModule/MyModuleSidebarCtrl.ctrl.coffee'
    directives:
      'socratMyModuleDir': require 'scripts/analysis/tools/MyModule/MyModuleDir.directive.coffee'
  # module state config
  state:
    # module name to show in UI
    name: 'My Awesome Module'
    url: '/tools/mymodule'
    mainTemplate: require 'partials/analysis/tools/MyModule/main.jade'
    sidebarTemplate: require 'partials/analysis/tools/MyModule/sidebar.jade'

Here we can see that module instance contains few key components. id is a string that makes it addressable by SOCRAT. components enlists all services, controllers, and directives of current module referring to their implementations via require statement. state is used to add a new state to routing system, identified by corresponding url and providing Jade templates with module UI.

First 2 services are required for any module to initialize. Let's take a closer look on their implementation.

Init Service

Create MyModuleInit.service.coffee:

'use strict'
# import base service class
BaseModuleInitService = require 'scripts/BaseClasses/BaseModuleInitService.coffee'
# export custom service class
module.exports = class MyModuleInitService extends BaseModuleInitService
  # requires message service as a dependency
  @inject 'socrat_analysis_mymodule_msgService'
  # entry point function:
  initialize: ->
    # this renaming is required for initialization!
    @msgService = @socrat_analysis_mymodule_msgService
    # required method call to initiate module messaging interface
    @setMsgList()

As you can see it's easy to create Init Service based on already existing class that hides all necessary functions. Only thing we need to do is to provide a link to messaging service, which is a required dependency. Note, that whatever you name your module messaging service, it has to be renamed in the initialize method to @msgService.

As a next step we can look how to implement messaging service which will allow our module to interact with SOCRAT.

Every module have it's own config block which is started at the stage of module initialization. Services, providers from ng module (such as $http, $resource) can be injected in config. Note, that services, providers in this module cannot be injected in the config block, because it's run before their initialization.

.config([
  () ->
    console.log "config block of myModule module"
])

Event Manager

This is another essential module component. Every module has to have a MODULE_NAMEEventMngr() service which provides messaging with core

.service('myModuleEventMngr', [
  () ->
    sb = null

    msgList =
      outcome: ['outcomeMsg']
      income: ['incomeMsg']
      scope: ['myModule']

    eventManager = (msg, data) ->
      # here goes implementation of inner listener

    setSb: (_sb) ->
      return false if _sb is undefined
      sb = _sb

    getMsgList: () ->
      msgList

    listenToIncomeEvents: () ->
      console.log 'subscribed for ' + msgList.income[0]
      sb.subscribe
        msg: msgList.income[0]
        listener: eventManager
        msgScope: msgList.scope

    sum: sum
])

Factory

Module initialization is handled by the Core module of the Framework by invoking the Angular factory of the same name. For example, app.myModule module has to have myModule factory. Factory takes Sandbox object sb as a parameter. Factory returns an object containing methods init() and destroy() and message list msgList. In the init() method module subscribes for messages from it's own components (communication within the module).

.factory('myModule', [
  # Factory has Event Manager as a dependency
  'myModuleEventMngr'
  (myModuleEventMngr) ->
    # Sandbox is used in Event Manager for communications
    (sb) ->

      # List of messages is retrieved from Event Manager
      msgList = myModuleEventMngr.getMsgList()
      myModuleEventMngr.setSb sb unless !sb?

      # This method invoked on module initialization
      init: (opt) ->
        console.log 'myModule init invoked'
        myModuleEventMngr.listenToIncomeEvents()

      # This method invoked on module destruction
      destroy: () ->

      # Return list of messages to Core
      msgList: msgList
])
Clone this wiki locally