Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Note

To be able to use the archetype overlay mechanism such that we can add the custom, table, and topology-overlay samples incrementally, we actually create three separate UiExtension instances and register them with the UiExtensionService individually. If your ONOS application was indeed creating multiple views, it should define a single UiExtension instance and declare each of the views and message handlers in one place. See UiExtensionManager.createCoreExtension() for an example of how to do this. Also see the sample application onos-app-uiref.

 

AppUiTableComponent

This is the base class for UI functionality. Things to note:

...

Code Block
languagejava
private static final String SAMPLE_TABLE_DATA_REQ = "sampleTableDataRequest";
private static final String SAMPLE_TABLE_DATA_RESP = "sampleTableDataResponse";
private static final String SAMPLE_TABLES = "sampleTables";

... 
 
private final class SampleTableDataRequestHandler extends TableRequestHandler {
    private SampleTableDataRequestHandler() {
        super(SAMPLE_TABLE_DATA_REQ, SAMPLE_TABLE_DATA_RESP, SAMPLE_TABLES);
    }
    ...
}

...

Code Block
languagejava
collapsetrue
private static final String MAC = "mac";
 
...
 
@Override
protected String defaultColumnId() {
    return MAC;
}

...

Code Block
languagejava
private static final String SAMPLE_TABLE_DETAIL_REQ = "sampleTableDetailsRequest";

...
 
private final class SampleTableDetailRequestHandler extends RequestHandler {
    private SampleTableDetailRequestHandler() {
        super(SAMPLE_TABLE_DETAIL_REQ);
    }
    ...
}

...

Code Block
languagejava
private static final String SAMPLE_TABLE_DETAIL_RESP = "sampleTableDetailsResponse";
private static final String DETAILS = "details";
...
private static final String COMMENT = "comment";
private static final String RESULT = "result";

...
 
@Override
public void process(long sid, ObjectNode payload) {
    String id = string(payload, ID, "(none)");

    // SomeService ss = get(SomeService.class);
    // Item item = ss.getItemDetails(id)

    // fake data for demonstration purposes...
    Item item = getItem(id);

    ObjectNode rootNode = objectNode();
    ObjectNode data = objectNode();
    rootNode.set(DETAILS, data);

    if (item == null) {
        rootNode.put(RESULT, "Item with id '" + id + "' not found");
        log.warn("attempted to get item detail for id '{}'", id);

    } else {
        rootNode.put(RESULT, "Found item with id '" + id + "'");

        data.put(ID, item.id());
        data.put(LABEL, item.label());
        data.put(CODE, item.code());
        data.put(COMMENT, "Some arbitrary comment");
    }

    sendMessage(SAMPLE_TABLE_DETAIL_RESP, 0, rootNode);
}

...

Code Block
languagexml
 <div class="ctrl-btns">
        <div class="refresh" ng-class="{active: autoRefresh}"
             icon icon-id="refresh" icon-size="36"
             tooltip tt-msg="autoRefreshTip"
             ng-click="toggleRefresh()"></div>
 </div>
Info

See the tablular view directives page for more details about the directives used to define the refresh button.

...

The <div> with class "summary-list" defines the actual table.

Code Block
languagexml
<div class="summary-list" onos-table-resize>
    ...
</div>

...

Code Block
languagexml
<div class="table-header" onos-sortable-header>
    <table>
        <tr>
            <td colId="id" sortable>Item ID </td>
            <td colId="label" sortable>Label </td>
            <td colId="code" sortable>Code </td>
        </tr>
    </table>
</div>
Info

See the tabular view directives page for more information on the onos-sortable-header and sortable directives.

...

The second is used as a template to stamp out rows; one per data item:

Code Block
languagexml
<tr ng-repeat="item in tableData track by $index"
    ng-click="selectCallback($event, item)"
    ng-class="{selected: item.id === selId}">
    <td>{{item.id}}</td>
    <td>{{item.label}}</td>
    <td>{{item.code}}</td>
</tr>

...

Next we define the callback function to be invoked when a "sampleTableDetailsResponse" event arrives with details about a selected item:

Code Block
languagejs
function respDetailsCb(data) {
    $scope.panelDetails = data.details;
    $scope.$apply();
}

...

Code Block
languagejs
angular.module('ovSampleovSampleTable', [])
    .controller('OvSampleCtrlOvSampleTableCtrl'
    ['$log', '$scope', 'TableBuilderService',
        'FnService', 'WebSocketService',
 
        function (_$log_, _$scope_, tbs, _fs_, _wss_) {
            ...
        }])

...

The last file in our client-side trio is the stylesheet for the sample view.

Code Block
languagecsslinenumberstrue
collapsetrue
/* css for sample app view */

#ov-sample-table h2 {
    display: inline-block;
}

/* Panel Styling */
#ov-sample-table-item-details-panel.floatpanel {
    position: absolute;
    top: 115px;
}

.light #ov-sample-table-item-details-panel.floatpanel {
    background-color: rgb(229, 234, 237);
}
.dark #ov-sample-table-item-details-panel.floatpanel {
    background-color: #3A4042;
}

#ov-sample-table-item-details-panel h3 {
    margin: 0;
    font-size: large;
}

#ov-sample-table-item-details-panel h4 {
    margin: 0;
}

#ov-sample-table-item-details-panel td {
    padding: 5px;
}
#ov-sample-table-item-details-panel td.label {
    font-style: italic;
    opacity: 0.8;
} 

...

Recall in AppUiTableComponent we defined the resource path when building the UiExtension instance...

Code Block
languagejava
private static final String VIEW_ID = "sampleTable";
...
protected UiExtension extension = 
        new UiExtension.Builder(getClass().getClassLoader(), uiViews)
                .resourcePath(VIEW_ID)
                ...

...