Redux Store Structure

The taranta front end has single redux store. This redux store is used to store data for devices & dashboard tab. This store can also be used to store data for future additions in taranta. Hence when user lands initially on devices or dashboard tab, entire store object is loaded which is mostly empty. This store object is populated as user navigates.

For example if user is on testdb/devices route all devices from testdb database along with database info is fetched and stored on store.

IMG6

deviceList: {
  nameList: [
    'dserver/databaseds/2',
    'dserver/starter/45ba3714711d',
    'dserver/tangoaccesscontrol/1',
    'dserver/tangotest/test',
    'dserver/tarantatestdevice/test',
    'dserver/tarantatestdevice/test2',
    'sys/access_control/1',
    'sys/database/2',
    'sys/tg_test/1',
    'tango/admin/45ba3714711d',
    'test/tarantatestdevice/1',
    'test/tarantatestdevice/2'
  ]
},
database: {
  info: 'TANGO Database sys/database/2\n \nRunning since 2023-05-04 07:59:44\n \nDevices defined  = 12\nDevices exported  = 10\nDevice servers defined  = 6\nDevice servers exported  = 5\n \nDevice properties defined  = 217 [History lgth = 217]\nClass properties defined  = 84 [History lgth = 180]\nDevice attribute properties defined  = 0 [History lgth = 0]\nClass attribute properties defined  = 0 [History lgth = 0]\nObject properties defined  = 0 [History lgth = 0]\n',
  tangoDBName: 'testdb'
},

When user clicks on specific device then device details are loaded on the store and the same is used to render the page.

IMG7

When user navigates from devices to dashboard tab then dashboard relevant details are loaded in the store. Populating redux store with data as user navigates on the UI helps to keep store object light. The light store object approach helps to reduce un-necessary page rendering upto some extent because with every change in store subscribed components are rendered again Also note while navigating between devices & dashboard tab store data is not lost.

Adding data in store

Now that we have common store for dashboard & devices tab hence any store related code will go under src/shared/state folder. Redux entities will be stored as below:

  1. Redux ActionsTypes & Actions will go under src/shared/state/actions folder

  2. Redux reducers will go under src/shared/state/reducers folder

  3. Redux selectors will go under src/shared/state/selectors folder

  4. Saga will go under src/shared/state/sagas folder

Once above code is in place, then we just need to trigger the respective redux action, this will load the store with data & same store data is used to render the page. For some redux action we may need to fetch data from dashboard-repo or auth repo, in such case saga is used to fetch data asynchronously and then this data is added in store with help of reducers.

IMG8

For example when taranta Devices tab is open a couple of actions are triggered:

1. FETCH_DEVICES_NAME action that results in FETCH_DEVICE_NAMES_SUCCESS or FETCH_DEVICE_NAMES_FAILED in case of success the following structure is added to the redux state:

deviceList: {
  nameList: [
      "dserver/databaseds/2",
      "dserver/starter/17a39f945d53",
      "dserver/tangoaccesscontrol/1",
      "dserver/tangotest/test",
      "dserver/tarantatestdevice/test",
      "sys/access_control/1",
      "sys/database/2",
      "sys/tg_test/1",
      "tango/admin/17a39f945d53",
      "test/tarantatestdevice/1"
  ]
}

This information is then used to populate DeviceList component:

IMG1

2. FETCH_DATABASE_INFO action that results in FETCH_DATABASE_INFO_SUCCESS or FETCH_DATABASE_INFO_FAILED in case of success the following structure is added to the redux state:

database: {
  info: 'TANGO Database sys/database/2
  Running since 2023-01-16 14:28:23
  Devices defined  = 10
  Devices exported  = 10
  Device servers defined  = 5
  Device servers exported  = 5
  Device properties defined  = 215 [History lgth = 215]
  Class properties defined  = 84 [History lgth = 36]
  Device attribute properties defined  = 0 [History lgth = 0]
  Class attribute properties defined  = 0 [History lgth = 0]
  Object properties defined  = 0 [History lgth = 0]'
}

This information is then used to populate InfoPage component:

IMG2

  1. When a user clicks in a device, example:

IMG3

FETCH_DEVICE action is trigger, that results in FETCH_DEVICE_SUCCESS or FETCH_DEVICE_FAILED in case of success the following structure is added to the redux state:

devices: {
  "sys/access_control/1": {
      "connected": true,
      "state": "ON",
      "server": {
          "id": "TangoAccessControl/1",
          "host": "17a39f945d53"
      },
      "errors": [],
      "name": "sys/access_control/1"
  }
},
attributes: {
"sys/access_control/1": {
    "state": {
        "name": "state",
        "label": "State",
        "dataformat": "SCALAR",
        "datatype": "DevState",
        "writable": "READ",
        "description": "No description",
        "displevel": "OPERATOR",
        "minvalue": null,
        "maxvalue": null
    },
    "status": {
        "name": "status",
        "label": "Status",
        "dataformat": "SCALAR",
        "datatype": "DevString",
        "writable": "READ",
        "description": "No description",
        "displevel": "OPERATOR",
        "minvalue": null,
        "maxvalue": null
    }
  }
},
commands: {
  "sys/access_control/1": {
      "AddAddressForUser": {
          "name": "AddAddressForUser",
          "tag": 0,
          "displevel": "OPERATOR",
          "intype": "DevVarStringArray",
          "intypedesc": "user name, address",
          "outtype": "DevVoid",
          "outtypedesc": "Uninitialised"
      },
      ...
      "State": {
          "name": "State",
          "tag": 0,
          "displevel": "OPERATOR",
          "intype": "DevVoid",
          "intypedesc": "Uninitialised",
          "outtype": "DevState",
          "outtypedesc": "Device state"
      },
      "Status": {
          "name": "Status",
          "tag": 0,
          "displevel": "OPERATOR",
          "intype": "DevVoid",
          "intypedesc": "Uninitialised",
          "outtype": "DevString",
          "outtypedesc": "Device status"
      },
  }
},
properties: {
  "sys/access_control/1": {}
}

This information is then used to populate all the following devices tabs:

IMG5