Overview

This area is to serve as a reference for developing, extending or learnign about the inner workings of my take on the project.

Table of Contents

Project Structure

All of the files for this project reside within the src folder, and once running a local instance the only file you will have to open is index.html.

src/
├── Components/
│   ├── LeftPaneControl.js
│   ├── NavigationButtonControl.js
│   ├── PropertiesPaneControl.js
│   ├── RightPaneControl.js
│   └── Table.js
├── Styles/
│   ├── Layout.css
│   ├── Navigation.css
│   ├── Panes.css
│   └── Tables.css
├── Services/
│   ├── http.js
│   └── ws.js
│
├── index.html
└── index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Application Entries

The base src directory houses two particulary important files.

file Contents
index.html hold the application shell
index.js renders and connects all of our components to the shell

Directories

Components

Files that render, create and handle all of our logic

file Contents
LeftPaneControl.js Serves as the menu to handle different queries
NavigationButtonControl.js Serves as buttons and titles within the navigation bar
PropertiesPaneControl.js Slideout menu that allows users to enter custom domain identifiers
RightPaneControl.js Serves as the dashboard content area
Table.js Holds the logic behind the dashboard data table

Services

Javascript class files used to handle our service connections

file Contents
http.js Class constructor to handle our historic queries
ws.js Class constructor to handle our real time subscription

Styles

Files that define the look and feel of the application

file Contents
Layout.css These are the styles for the primary layout.
Navigation.css Defines the style of our dashboard navigation bar
Panes.css Defines the style of our three major layour areas
Tables.css Controls the styles of our data tables

How to use

Real Time Subscriptions

Directions

Open index.html file in your web browser.

By Default Real time queries is the first page you will see, on the left hand side you will see several options. To subscribe to a topic, press any of the buttons that appear under REAL-TIME QUERIES. After the dashboard data table will begin updating with data.

To close the websocket connection, press the Reset button.

To querie a custom point, press the Custom button, and enter the details within the slideout form. After, press the Connect button on the slideout. If you had sent a succesfull subscription point, your datatable will begin updating.

Historic Queries

Directions

Open index.html file in your web browser. By Default Real time queries is the first page you will see.

On the navigation bar click the Toggle Historic button to change to the historic query menu.

Getting data

Click any of the buttons on the side menu to preform a new query

Sorting Data

By Default the returned data will be sorted by timestamp ascending. To change that, activate the prefered sort method by clicking either of the options bellow Sorting within the left control panel.

How its made

In this section I will break down how the application was made, and the important elements within each file.

Components Breakdown

For this exercise, components are arguably the most important pieces of the puzzle. They tell our application, how to look, feel, and move. Primarily throughout the application I choose to stick to singleton class patterns, and generator functions. This allows me to move usefull data, and help maintain state in a framework barren app.

Repeated functions to avoid redundant explination

Some patters and functions are repeated within the app, as a roadmap I would refactor the project to be more dry, and write more test cases. Regaurdless bellow are some of the patterns that are standard.

Rendering Views, and attaching listeners

In most of the files you will see a pattern like bellow, it is used to asyncronously render dom elements, and then attaching listeners to said dom elements. This pattern allows us to ensure that before we try to attach a event listener, the dom is ready. I've replaced the important parts with placeholder text.


let /*Unique Name*/ = {
  
   render: async () => {
      let view = `
        /*String representing dom object, and any logic within*/
        `
      return view
   },
   attach_listeners: async () => {
      
   const /*Some Element Constant Name */ = document.getElementById(/*Some Element ID Referenced from the above render methods view */ );
   

      /**
      * Attach an event listener to the selected element
      */

      /*Some Element Constant */.addEventListener(/* Listener */, () => {
         /* Functions completed on listener */
      })

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Table.js

Table.js is used to render all of our data

Includes

Includes Use
wsInstance Used to render data if there exists any within the websocket instance

Important Dom Elements

Selector TagName Use
#data-table table Renderable table to hold all of our data
#tableBody tbody Targeted so that we can render, and manipulate our table rows easier

Renderable HTML

Table.js has two two areas where it can render new html from, so it is unique in that it doesnt only hold a view, as seen in other files.

Initial Table Element

   const newTable = `
        <table class="fixed_header" id="data-table">
        <thead>
            <tr class="trHeader">
           ${tblObj.columns.map((column) => `\t\t\t<th class="trHeader" onclick="sortBy('${column.text}')">${column.text}</th>`).join('\n ')}
            
            </tr>
        </thead>
        <tbody id="tableBody">
        ${tblObj.data.map((row, index) =>
            `\t\t\t<tr class="trself" data-id="${index}" id="${index}">
            <td>${row.id}</td> <td>${row.id}</td> <td>${index}</td>`)}
                   
        </tbody>
        </table>`;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

New Table Rows


const baseRowContent = `<tr class="trself"><td>${rowItem.id}</td><td>${rowItem.timestamp}</td><td>${rowItem.value}</td></tr>`

1
2
3

Javascript Overview

The javascript located in Table.js is what controls the inner workings of data table.

Scattered Variables,Paramaters, and Arguments

Variable Use
currentTableObject Holds the data responsible for rendering elements within the table
pageTitle Title of the page table you are on

Main Frontend Functions and Methods

Function Arguments Use
init none sets up the data for the new table object and calls the render function
render none initializes the base table object
setPageTitle title sets the title of the current page
getPagetitle none gets the title of the current page
generateTableExtended table, tblObj creates the new table object
addRow rowItem accepts and object representing a table row and adds it to the table
switchDataSource none removes all elements from the table

RightPanelControl.js

Serves as the dashboard content area

Includes

Includes Use
tableDataInstance Class used to retrieve the data table, and attach it to the dom

Important Dom Elements

Selector TagName Use
#data-table table Renderable table to hold all of our data
#tableBody tbody Targeted so that we can render, and manipulate our table rows easier

Renderable HTML

   let view = `
        <div id="rightPanelWrapper">
           <h2>current table</h2>
             <table id="dataTable">
                     <!-- Data Appears Here -->
            </table>
         </div>
        `
1
2
3
4
5
6
7
8

Javascript Overview

The javascript located in RightPaneControl is primarily used to initialize the table singleton when the dom is ready.

PropertiesPaneControl.js

Slide out menu used for custom websocket queries

Includes

Includes Use
toggleSlideMenu Used to toggle the slide out menu
tableDataInstance Used to access the table data singleton instance
wsInstance Used to create the custom ws connections

Important Dom Elements

Selector TagName Use
.customTextInput input User enabled text input area to send custom subscription pointId's
#propertyFormSubmit button calls the websocket class to create a new subcription
#propertiesCloseMenu button used to close the propetry menu

Renderable HTML

   let view = `
        <div id="propertiesMenu" class="propertiesMenu">
  <div class="propertiesMenuTitle">
    Custom-Queries
  </div>
  <!--MARK : Property Data-->
  <div class="proprtyFormContainer">
    <form class="propertyForm" action="#" method="post">
      <div class="propertiesPaneDescriptor">
        <h4>Enter PointId </h4>
        <p>single : pwr.c</p>
        <p>multi : pwr.v,pwr.c </p>
        
        <input id="customTextInput" placeholder="Enter your domain object here" required></input>
      </div>
      </form>
  </div>
   <button class="propertyFormButton connect" id="propertyFormSubmit">Connect</button>
    
  <div>
   <button id="propertiesCloseMenu" class="propertyFormButton connect">Close Panel</button>
  
  </div>
</div>
        `
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Holds the html renderer and offers the ability to switch query menues

Includes

Includes Use
getMenu gets current menu selected
changeMenu changes the current menu selected

Important Dom Elements

Selector TagName Use
.toggleButton li class that helps us select our different route options for changing the menu

Renderable HTML

   let view = `
   <ul id="nav_wrapper">
         <li class="navLink">OpenMCT Exam - </li>
          <li class="navLink toggleButton is-active"  data-menu="realTime">Toggle Real-Time </li>
          <li class="navLink toggleButton"  data-menu="historic">Toggle Historic </li>      
      </ul>`
1
2
3
4
5
6

Main Frontend Functions and Methods

Function Arguments Use
handleClick event switches our query menu by sending the event target data-menu

LeftPaneControl.js

Handles many of the dom updating, querying and state management operations

Includes

Includes Use
httpInstance Class used to call historic data
handleSlideShow handle toggling the slide out menu
tableDataInstance Used to access the table data singleton instance
wsInstance Class used to call real time data

Important Dom Elements

Selector TagName Use
#wcMenu div wrapper for our real time menu
#httpMenu div wrapper for our historic menu
.httpQuery div wrapper for our buttons to call 'x' service
.wsQuery div wrapper for our buttons used to create new ws subscriptions
#toggleCustomPanel div wrapper for button used to toggle the slideout menu
#httpSetSortAscending div wrapper for our buttons used to sort historic data ascending
#httpSetDescending div wrapper for our buttons used to sort historic data descending

Renderable HTML

   let view = `
   <div id="wcMenu" class="is-active">
                  <div class="leftPaneTitle" id="querylatest">
                            Real-Time Queries
                  </div>
                  <hr />
                  <div class="leftPaneControl is-active wsQuery" data-point="pwr.v,pwr.c">
                            Query Both
                  </div>
                  <div class="leftPaneControl wsQuery"  data-point="pwr.v" >
                            Query Voltage
                  </div>
                  <div class="leftPaneControl wsQuery" data-point="pwr.c">
                            Query Current
                  </div>
                  <div class="leftPaneControl wsQuery">
                            Reset
                  </div>
                  <div class="leftPaneTitle">
                            Toggle Custom Panel
                  </div>
                  <hr />
                  <div class="leftPaneControl" id="toggleCustomPanel">
                            Custom
                  </div>
            </div>
            <div id="httpMenu">
                  <div class="leftPaneTitle"  >
                            Historic Queries
                  </div>
                  <hr />
                  <div class="leftPaneControl is-active httpQuery" data-point="pwr.v,pwr.c">
                            Query Latest
                  </div>
                  <div class="leftPaneControl httpQuery" data-point="pwr.v">
                            Query One : A
                  </div>
                  <div class="leftPaneControl httpQuery" data-point="pwr.c">
                            Query One : B
                  </div>
                  <div class="leftPaneTitle">
                            Sorting
                  </div>
                  <hr />
                  <div class="leftPaneControlSort is-active-sort" id="httpSetSortAscending">
                            Sort Ascending
                  </div>
                  <div class="leftPaneControlSort is-active-sort" id="httpSetDescending">
                            Sort Descending
                  </div>
            </div>`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Main Frontend Functions and Methods

Function Arguments Use
changeMenu menuName cancels certain connections, clears table data and handles visual appearence of elements
toggleSortDescending none sorts the historic data descending by timestamp
toggleSortAscending none sorts the historic data Ascending by timestamp
handleWSClick event sends new ws subscription messages, an ex. of a single subscription would be 'pointid' a ex of multiple new subscriptions would be 'pointidA,pointidB'
handleHTTPClick event sends new historic request, like wsclick it also uses the elements data atribute and can call multiple new at a time
toggleCustomMenu none toggles the slide out menu
changeMenu menuName handles the switching of our views, and helps maintain table data state

Services Breakdown

For this exercise, components are arguably the most important pieces of the puzzle. They tell our application, how to look, feel, and move. Primarily throughout the application I choose to stick to singleton class patterns, and generator functions. This allows me to move usefull data, and help maintain state in a framework barren app.

ws.js

Handles all of the queries for websocket real time events

:: tip Unlike http requests to create a websocket connection the url will begin with ws or wss rather than http or https ::

Includes

Includes Use
tableDataInstance Class used to retrieve the data table, and attach it to the dom

Main Frontend Functions and Methods

Function Arguments Use
createSocketConnection endpoint handles our new websocket connection lifecycle
handleSubscriptions points accepts strings of points to create new subscription messages
closeSocket none closes the current websocket connection

http.js

Handles all of the queries for historical data

Includes

Includes Use
tableDataInstance Class used to retrieve the data table, and attach it to the dom

Main Frontend Functions and Methods

Function Arguments Use
subtract_minutes dt, minutes returns a date - x minutes, 15 in our case
setSortValue requestedSort handles sorting value for results, in the case of no new http call
handleRequest points handles querying new historic data

Styles Breakdown

For this exercise, the style files are broken up so that they coorespond to their prospective elements, and sections. There is not much to explain about them though overall the intention was to sort of have fun with building a colorful flexbox based responsive dashboard.

Last Updated: 8/11/2019, 2:06:00 AM