settings.js 7.02 KB
/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 ONOS GUI -- Component Settings View Module
 */

(function () {
    'use strict';

    // injected refs
    var $log, $scope, wss, fs, ks, ps, is;

    // internal state
    var detailsPanel,
        panelData,
        top,
        pStartY,
        pHeight,
        wSize = false;

    // constants
    var pName = 'settings-details-panel',
        panelWidth = 540,
        topPdg = 60,
        propOrder = ['fqComponent', 'id', 'type', 'value', 'defValue', 'desc'],
        friendlyProps = [
            'Component', 'Property', 'Type', 'Value', 'Default Value',
            'Description'
        ];

    function createDetailsPanel() {
        detailsPanel = ps.createPanel(pName, {
            width: wSize.width,
            margin: 0,
            hideMargin: 0
        });

        detailsPanel.el().style({
            position: 'absolute',
            top: pStartY + 'px'
        });

        detailsPanel.hide();
    }

    function closePanel() {
        if (detailsPanel.isVisible()) {
            $scope.selId = null;
            panelData = null;
            detailsPanel.hide();
            return true;
        }
        return false;
    }

    function addCloseBtn(div) {
        is.loadEmbeddedIcon(div, 'close', 26);
        div.on('click', closePanel);
    }

    function setUpPanel() {
        var container, closeBtn, div;

        detailsPanel.empty();
        detailsPanel.width(panelWidth);

        container = detailsPanel.append('div').classed('container', true);

        top = container.append('div').classed('top', true);
        closeBtn = top.append('div').classed('close-btn', true);
        addCloseBtn(closeBtn);

        div = top.append('div').classed('top-content', true);

        function ndiv(cls, addTable) {
            var  d = div.append('div').classed(cls, true);
            if (addTable) {
                d.append('table');
            }
        }

        ndiv('settings-title');
        ndiv('settings-props', true);
    }

    function addProp(tbody, index, value) {
        var tr = tbody.append('tr');

        function addCell(cls, txt) {
            tr.append('td').attr('class', cls).html(txt);
        }

        addCell('label', friendlyProps[index] + ':');
        addCell('value', value);
    }

    function populateTop(details) {
        var propsBody = top.select('.settings-props').append('tbody');

        top.select('.settings-title').text(details.id);

        propOrder.forEach(function (prop, i) {
            addProp(propsBody, i, details[prop]);
        });
    }

    function populateDetails() {
        setUpPanel();
        populateTop(panelData);
        detailsPanel.height(pHeight);
    }

    angular.module('ovSettings', [])
        .controller('OvSettingsCtrl',
            ['$log', '$scope',
            'WebSocketService', 'FnService', 'KeyService', 'PanelService',
            'IconService', 'TableBuilderService',

        function (_$log_, _$scope_, _wss_, _fs_, _ks_, _ps_, _is_, tbs) {
            $log = _$log_;
            $scope = _$scope_;
            wss = _wss_;
            fs = _fs_;
            ks = _ks_;
            ps = _ps_;
            is = _is_;
            $scope.panelData = {};

            function selCb($event, row) {
                if ($scope.selId) {
                    panelData = row;
                    populateDetails();
                    detailsPanel.show();
                } else {
                    panelData = null;
                    detailsPanel.hide();
                }
            }

            tbs.buildTable({
                scope: $scope,
                tag: 'setting',
                selCb: selCb
            });

            ks.keyBindings({
                esc: [$scope.selectCallback, 'Deselect property'],
                _helpFormat: ['esc']
            });
            ks.gestureNotes([
                ['click row', 'Select / deselect settings property'],
                ['scroll down', 'See more settings']
            ]);

            $scope.$on('$destroy', function () {
                ks.unbindKeys();
            });

            $log.log('OvSettingsCtrl has been created');
        }])

        .directive('settingsDetailsPanel',
            ['$rootScope', '$window', '$timeout', 'KeyService',
            function ($rootScope, $window, $timeout, ks) {
                return function (scope) {
                    var unbindWatch;

                    function heightCalc() {
                        pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
                            + topPdg;
                        wSize = fs.windowSize(pStartY);
                        pHeight = wSize.height;
                    }

                    function initPanel() {
                        heightCalc();
                        createDetailsPanel();
                        $log.debug('start to initialize panel!');
                    }

                    // Safari has a bug where it renders the fixed-layout table wrong
                    // if you ask for the window's size too early
                    if (scope.onos.browser === 'safari') {
                        $timeout(initPanel);
                    } else {
                        initPanel();
                    }
                    // create key bindings to handle panel
                    ks.keyBindings({
                        esc: [closePanel, 'Close the details panel'],
                        _helpFormat: ['esc']
                    });
                    ks.gestureNotes([
                        ['click', 'Select a row to show property details'],
                        ['scroll down', 'See more properties']
                    ]);

                    // if the window size changes
                    unbindWatch = $rootScope.$watchCollection(
                        function () {
                            return {
                                h: $window.innerHeight,
                                w: $window.innerWidth
                            };
                        }, function () {
                            if (panelData) {
                                heightCalc();
                                populateDetails();
                            }
                        }
                    );

                    scope.$on('$destroy', function () {
                        panelData = null;
                        unbindWatch();
                        ks.unbindKeys();
                        ps.destroyPanel(pName);
                    });
                };
            }]);
}());