APIs

Show:
/**
 This module manages active list of remote stations (screens) retrieved from the server
 Poll for stations status every n seconds, as well as remote manage each station individually.
 @class StationsListView
 @constructor
 @param {String} i_container element that CompCampaignNavigator inserts itself into
 @return {Object} instantiated StationsListView
 **/
define(['jquery', 'backbone', 'StationsCollection', 'LiveInput'], function ($, Backbone, StationsCollection, LiveInput) {

    BB.SERVICES.STATIONS_LIST_VIEW = 'StationsListView';

    var StationsListView = Backbone.View.extend({

        /**
         Constructor
         @method initialize
         **/
        initialize: function () {
            var self = this;

            BB.comBroker.setService(BB.SERVICES['STATIONS_LIST_VIEW'], self);
            self.m_snapshotInProgress = undefined;
            self.m_imageReloadCount = 0;
            self.m_imagePath = '';
            self.m_selected_station_id = undefined;
            self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']);
            self.m_property.initPanel(Elements.STATION_PROPERTIES);
            self.m_stationCollection = new StationsCollection();

            self.listenTo(self.m_stationCollection, 'add', function (i_model) {
                $(Elements.STATION_ALERT).hide();
                self._onAddStation(i_model);
                self._listenStationSelected();
            });

            self.listenTo(self.m_stationCollection, 'change', function (i_model) {
                self._onUpdateStation(i_model);
            });

            BB.comBroker.listen(BB.EVENTS.STATION_NAME_CHANGED, function (e) {
                var stationID = e.edata.stationID;
                var stationName = e.edata.stationName;
                var a = $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + stationID + '"]');
                $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + stationID + '"]').find(Elements.CLASS_LIVE_RENAME).text(stationName);
            });

            self._wireUI();
            self._initStationRename();
            self._wireSnapshot();
            self._populateStationCampaignDropDown(-1);
            self._listenEnableServerMode();
            self._listenIpChange();
            self._listenPortChange();
        },

        /**
         Listen to changes in IP selection to assign to station local server
         @method _listenIpChange
         **/
        _listenIpChange: function () {
            var self = this;
            var input = self.m_liveSationIpInput = new LiveInput({
                el: Elements.STATION_SERVER_IP,
                dataLocalize: 'stationServerIp',
                placeHolder: 'Station IP',
                value: ''
            }).on('LIVE_INPUT_CHANGED', function (e) {
                    var stationRecord = BB.Pepper.getStationRecord(self.m_selected_station_id);
                    stationRecord.lan_server_ip = e.value;
                    BB.Pepper.setStationRecord(self.m_selected_station_id, stationRecord);
                }
            ).on('LIVE_INPUT_VALID_ERROR', function (e) {
                }
            );
            input.rules({
                1: [input.getValidator().noEmpty, $(Elements.MSG_LIVEINPUT_NOT_BLANK).text()],
                2: [input.getValidator().isIP, $(Elements.MSG_LIVEINPUT_NO_IP).text()]
            });
        },

        /**
         Listen to changes in port selection to assign to station local server
         @method _listenPortChange
         **/
        _listenPortChange: function () {
            var self = this;
            var input = self.m_liveSationPortInput = new LiveInput({
                el: Elements.STATION_SERVER_PORT,
                dataLocalize: 'stationServerPort',
                placeHolder: 'Station Port',
                value: '1024'
            }).on('LIVE_INPUT_CHANGED', function (e) {
                    var stationRecord = BB.Pepper.getStationRecord(self.m_selected_station_id);
                    stationRecord.lan_server_port = e.value;
                    BB.Pepper.setStationRecord(self.m_selected_station_id, stationRecord);
                }
            ).on('LIVE_INPUT_VALID_ERROR', function (e) {
                }
            );
            input.rules({
                1: [
                    input.getValidator().isNumberInRange, $(Elements.MSG_LIVEINPUT_NOT_PORT).text(), {
                    min: 1024,
                    max: 65535
                }]
            });
        },

        /**
         Listen to enable server mode
         @method _listenEnableServerMode
         @param {Number} i_playerData
         @return {Number} Unique clientId.
         **/
        _listenEnableServerMode: function () {
            var self = this;
            $(Elements.STATION_SERVER_MODE).on('change', function (e) {
                var stationRecord = BB.Pepper.getStationRecord(self.m_selected_station_id);
                var mode = $(Elements.STATION_SERVER_MODE).prop('checked');
                if (mode) {
                    $(Elements.STATION_SERVER_PROPS).show();
                    stationRecord.lan_server_enabled = 'True';
                } else {
                    stationRecord.lan_server_enabled = 'False';
                    $(Elements.STATION_SERVER_PROPS).hide();
                }
                BB.Pepper.setStationRecord(self.m_selected_station_id, stationRecord);
            });
        },

        /**
         Render is called when the StackView is in view which tightly coupled with StationView instance
         so we can update the station list status when this View is visible
         @method render
         **/
        render: function () {
            var self = this;
            self.m_stationCollection.resumeGetRemoteStations();
            self.getTotalActiveStation();
            //log('in view');
        },

        /**
         Unrender method used to notify this View that is it no longer visible so we can stop
         updating remote station status to increase app perfromance
         @method unrender
         **/
        unrender: function () {
            var self = this;
            self.m_stationCollection.pauseGetRemoteStations();
            log('out of view');
        },

        /**
         Init station rename component
         @method _initStationRename
         **/
        _initStationRename: function () {
            var self = this;
            self.m_liveRenameInput = new LiveInput({
                el: Elements.STATION_RENAME,
                dataLocalize: 'stationRename',
                placeHolder: 'Station rename',
                value: ''
            }).on('LIVE_INPUT_CHANGED', function (e) {
                    var stationLI = $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + self.m_selected_station_id + '"]');
                    $(stationLI).find(Elements.CLASS_LIVE_RENAME).text(e.value);
                    pepper.setStationName(self.m_selected_station_id, e.value);
                    self._getStationModel(self.m_selected_station_id).set('stationName', e.value);
                });
        },

        /**
         Listen to station selection, populate the properties panel
         @method _listenStationSelected
         **/
        _listenStationSelected: function () {
            var self = this;
            $(Elements.CLASS_STATION_LIST_ITEMS).off('click');
            $(Elements.CLASS_STATION_LIST_ITEMS).on('click', function (e) {
                var elem = $(e.target).closest('li');
                var stationID = $(elem).attr('data-station_id');
                if (stationID !== self.m_selected_station_id)
                    self._stopSnapshot();
                self.m_selected_station_id = stationID;
                var stationModel = self._getStationModel(self.m_selected_station_id);
                self.m_liveRenameInput.setValue(stationModel.get('stationName'), false, false);
                $(Elements.CLASS_STATION_LIST_ITEMS).removeClass('activated').find('a').removeClass('whiteFont');
                $(elem).addClass('activated').find('a').addClass('whiteFont');
                self.m_property.viewPanel(Elements.STATION_PROPERTIES);
                self._updatePropStats(stationModel);
                self._updatePropButtonState(stationModel);
                self._selectCampaignDropDownForStation(self.m_selected_station_id);
                return false;
            });
        },

        /**
         Update properties > button state on station selection
         @method _updatePropButtonState
         @param {Object} i_model
         **/
        _updatePropButtonState: function (i_model) {
            var self = this;
            if (!_.isUndefined(self.m_snapshotInProgress))
                return;
            var disabled = ''
            if (i_model.get('connection') == '0') {
                disabled = 'disabled';
            }
            $(Elements.STATION_CONTROL + ' button').prop('disabled', disabled);
        },

        /**
         Update the properties UI station stats from Backbone collection > model
         @method _updateProperties
         @param {Object} i_model
         **/
        _updatePropStats: function (i_model) {
            var self = this;
            //$(Elements.STATION_NAME).text(pepper.getStationNameSync(self.m_selected_station_id));
            $(Elements.STATION_WATCHDOG).text(i_model.get('watchDogConnection'));
            $(Elements.STATION_TOTAL_MEMORY).text(i_model.get('totalMemory'));
            $(Elements.STATION_PEAK_MEMORY).text(i_model.get('peakMemory'));
            $(Elements.STATION_LAST_UPDATE).text(i_model.get('lastUpdate'));
            $(Elements.STATION_RUNNING_TIME).text(i_model.get('runningTime'));
            $(Elements.STATION_AIR_VERSION).text(i_model.get('airVersion'));
            $(Elements.STATION_APP_VERSION).text(i_model.get('appVersion'));
            $(Elements.STATION_OS).text(i_model.get('stationOS'));
            $(Elements.STATION_ID).text(i_model.get('stationID'));

            var stationRecord = BB.Pepper.getStationRecord(i_model.get('stationID'));

            if (stationRecord.lan_server_enabled == 'True') {
                $(Elements.STATION_SERVER_MODE).prop('checked', true);
                $(Elements.STATION_SERVER_PROPS).show();
            } else {
                $(Elements.STATION_SERVER_MODE).prop('checked', false);
                $(Elements.STATION_SERVER_PROPS).hide();
            }
            self.m_liveSationIpInput.setValue(i_model.get('localAddress'));
            self.m_liveSationPortInput.setValue(stationRecord.lan_server_port);
        },

        /**
         Reconfigure the location (offset) of the screen snapshot UI depending on current property with
         @method _reconfigSnapLocation

         _reconfigSnapLocation: function () {
            var offset = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).getPropWidth();
            if (offset < 240)
                offset = 240;
            var box = (offset / 2) - 120;
            $(Elements.SNAP_SHOT_SVG).css({
                left: box + 'px'
            });
            $(Elements.SNAP_SHOT_IMAGE).css({
                left: box + 15 + 'px'
            });
            $(Elements.SNAP_SHOT_SPINNER).css({
                left: (offset / 2) - 20 + 'px'
            });
        },
         **/

        /**
         Update existing station in list with data from remote mediaSERVER
         If a station is selected in the list, make sure we also update its open property values
         @method _onUpdateStation
         @param {Object} i_stationModel
         **/
        _onUpdateStation: function (i_stationModel) {
            var self = this;
            if (i_stationModel.get('connectionStatusChanged')) {
                var stationLI = $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + i_stationModel.get('stationID') + '"]');
                $(stationLI).find('circle').attr('fill', i_stationModel.get('stationColor'));
            }
            if (i_stationModel.get('stationID') == self.m_selected_station_id) {
                if (!stationLI)
                    var stationLI = $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + i_stationModel.get('stationID') + '"]');
                stationLI.trigger('click');
                // log('update data on ' + self.m_selected_station_id);
            }
        },

        /**
         When data is available from the remote server, update the list with current data.
         @method _onAddStation
         @param {Event} e remote server data call back from Ajax call
         @return none
         **/
        _onAddStation: function (i_stationModel) {
            var self = this;
            var snippet = '<li class="' + BB.lib.unclass(Elements.CLASS_STATION_LIST_ITEMS) + ' list-group-item" data-station_id="' + i_stationModel.get('stationID') + '">' +
                '<a href="#">' +
                '<span id="stationIcon' + i_stationModel.get('id') + '">' +
                '<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg"><g><circle stroke="black" id="svg_1" fill="' + i_stationModel.get('stationColor') + '" stroke-width="2" r="16" cy="20" cx="20"/></g></svg>' +
                '</span>' +
                '<span class="' + BB.lib.unclass(Elements.CLASS_LIVE_RENAME) + '" style="font-size: 1.5em; position: relative; top: -23px">' + i_stationModel.get('stationName') + '</span>' +
                '</a>' +
                '</li>';
            $(Elements.STATION_LIST_VIEW).append(snippet)
        },

        /**
         Bind all event listeners on the UI for remote stations commands including commands
         @method _wireUI
         @return none
         **/
        _wireUI: function () {
            var self = this;

            $(Elements.STATION_PLAY_COMMAND + ' , ' + Elements.STATION_STOP_COMMAND).on('click', function (e) {
                var command = BB.lib.unhash(Elements.STATION_PLAY_COMMAND) == e.currentTarget.id ? 'start' : 'stop';
                pepper.sendCommand(command, self.m_selected_station_id, function () {
                    // log('cmd done'+command);
                });
                return false;
            });

            $(Elements.STATION_REFRESH).on('click', function (e) {
                $(Elements.STATION_LIST_VIEW).fadeOut('fast', function () {
                    self.m_stationCollection.getRemoteStations();
                    $(this).fadeIn('fast');
                });
            });

            $(Elements.STATION_RELOAD_COMMAND).on('click', function (e) {
                // pepper.sendCommand('rebootStation', self.m_selected_station_id, function () {});
                pepper.sendCommand('rebootPlayer', self.m_selected_station_id, function () {
                });
                return false;
            });

            $(Elements.STATION_SELECTION_CAMPAIGN).on('change', function (e) {
                self._onChangedCampaign(e);
                return false;
            });

            $(Elements.STATION_REMOVE).on('click', function () {
                self._removeStation(self);
            });

            $(Elements.STATION_EVENT_SEND_COMMAND).on('click', function () {
                var eventValue = $(Elements.STATION_SEND_EVENT_VALUE).val();
                pepper.sendEvent(eventValue, self.m_selected_station_id, function () {
                });
            });
        },

        /**
         Translate a station id to Backbone.Model
         @method _getStationModel
         @param {Number} i_station_id
         **/
        _getStationModel: function (i_station_id) {
            var self = this;
            return self.m_stationCollection.findWhere({'stationID': i_station_id});
        },

        /**
         Send a remote value (i.e.: remote event / remote touch) to a selected station.
         If events are enabled at the campaign level, the _sendStationEvent method enables users to fire events on a selected
         Station and thus change campaign attributes.
         @method _sendStationEvent
         @param {String} i_eventName
         @param {String} i_eventValue
         @return none
         _sendStationEvent: function (i_eventName, i_eventValue) {
            var self = this;
            model.sendStationEvent(model.getDataByID(self.m_selected_resource_id)['id'], i_eventName, i_eventValue);
            $(Elements.EVENT_SEND_BUTTON).button('disable');
        },
         **/
        _removeStation: function (i_context) {
            var self = i_context;
            if (_.isUndefined(self.m_selected_station_id)) {
                bootbox.dialog({
                    message: $(Elements.MSG_BOOTBOX_NO_STATION_SELECTED).text(),
                    buttons: {
                        danger: {
                            label: $(Elements.MSG_BOOTBOX_OK).text(),
                            className: "btn-danger",
                            callback: function () {
                            }
                        }
                    }
                });
                return false;
            }
            bootbox.confirm($(Elements.MSG_BOOTBOX_STEPS).text(), function (result) {
                if (result == true) {
                    var navigationView = BB.comBroker.getService(BB.SERVICES.NAVIGATION_VIEW);
                    // pepper.sendCommand('rebootStation', self.m_selected_station_id, function () {});
                    pepper.sendCommand('rebootPlayer', self.m_selected_station_id, function () {
                    });
                    pepper.removeStation(self.m_selected_station_id);
                    navigationView.save(function () {
                    });
                    pepper.sync(function () {
                        self._removeStationFromLI(self.m_selected_station_id);
                        navigationView.resetPropertiesView();
                    });

                }
            });
        },

        /**
         Remove a selected station from UI LI
         @method _removeStationFromLI
         @param {Number} i_stationID
         **/
        _removeStationFromLI: function (i_stationID) {
            var self = this;
            $(Elements.STATION_LIST_VIEW).find('[data-station_id="' + i_stationID + '"]').remove();
        },

        /**
         Wire the Snapshot UI button and handle related opeations before and after executing a station snapshot
         @method _wireSnapshot
         **/
        _wireSnapshot: function () {
            var self = this;
            $(Elements.STATION_SNAPSHOT_COMMAND).on('click', function (e) {
                self.m_imagePath = '';
                self.m_imageReloadCount = 0;
                self._listenSnapshotComplete();

                /* Can't use short path due to IE error, gotta go long route via _sendSnapshotCommand
                 self.m_imagePath = pepper.sendSnapshot(Date.now(), '0.2', self.m_selected_station_id, function (e) {});
                 log(self.m_imagePath);
                 */

                self._sendSnapshotCommand(self.m_selected_station_id);
                $(Elements.SNAP_SHOT_IMAGE).attr('src', self.m_imagePath);
                $(Elements.SNAP_SHOT_IMAGE).hide();
                $(Elements.SNAP_SHOT_SPINNER).fadeIn('slow');
                $(Elements.STATION_CONTROL + ' button').prop('disabled', 'disabled');

                self.m_snapshotInProgress = setInterval(function () {
                    self.m_imageReloadCount++;
                    // log('snapshot JS... ' + self.m_imagePath);
                    $(Elements.SNAP_SHOT_IMAGE).attr('src', self.m_imagePath);

                    // snapshot timed out so reset
                    if (self.m_imageReloadCount > 6) {
                        self._stopSnapshot();
                        $(Elements.SNAP_SHOT_IMAGE).attr('src', self.m_imagePath);
                        var stationModel = self._getStationModel(self.m_selected_station_id);
                        self._updatePropButtonState(stationModel);
                    }
                }, 1000);
                return false;
            });
        },

        /**
         Send a remote snapshot command for station id and wait for a call back.
         @method _sendSnapshotCommand
         @param {Number} i_station
         @return none
         **/
        _sendSnapshotCommand: function (i_station) {
            var self = this;
            var d = new Date().getTime();
            var path = pepper.sendSnapshot(d, 0.2, i_station, function (e) {
            });
            setTimeout(function () {
                self.m_imagePath = path;
            }, 3000);

            /*
             var data = {
             '@functionName': 'f_captureScreen',
             '@stationID': i_station,
             '@quality': 1,
             '@time': Date.now()
             };
             self.ajaxJsonGetter.getData(data, onSnapshotReply);
             function onSnapshotReply(e) {
             if (e.responce['status'] == 'pass') {
             log('getting image from ' + e.responce['path']);
             self.m_imagePath = e.responce['path'];
             }
             }
             // self.m_imagePath = 'https://pluto.signage.me/Snapshots/business355181/station12/1397689062944.jpg';
             // return;
             */

        },

        /**
         Stop any ongoing snapshots that are pending and reset all related snapshot UI and values
         @method _stopSnapshot
         **/
        _stopSnapshot: function () {
            var self = this;
            if (self.m_snapshotInProgress)
                clearTimeout(self.m_snapshotInProgress);
            self.m_snapshotInProgress = undefined;
            $(Elements.SNAP_SHOT_SPINNER).hide();
            $(Elements.SNAP_SHOT_IMAGE).attr('src', '');
            $(Elements.SNAP_SHOT_IMAGE).hide();
            $(Elements.SNAP_SHOT_IMAGE).unbind('load');
        },

        /**
         Listen when a new remote snapshot is available on the server for a selected station, so we can display it in the properties panel
         We use the Image.load event to be notified when the Image element has succesfully recived a working image path
         @method _listenSnapshotComplete
         @return none
         **/
        _listenSnapshotComplete: function () {
            var self = this;
            // snapshot success
            $(Elements.SNAP_SHOT_IMAGE).one('load', function (e) {
                $(Elements.SNAP_SHOT_SPINNER).hide();
                $(Elements.SNAP_SHOT_IMAGE).attr('src', self.m_imagePath);
                $(Elements.SNAP_SHOT_IMAGE).fadeIn('slow');
                clearTimeout(self.m_snapshotInProgress);
                self.m_snapshotInProgress = undefined;
                var stationModel = self._getStationModel(self.m_selected_station_id);
                self._updatePropButtonState(stationModel);
            });
        },

        /**
         Select the campaign that is bound to i_stationID and select it in the dropdown UI
         @method _selectCampaignDropDownForStation
         @param {Number} i_stationID
         **/
        _selectCampaignDropDownForStation: function (i_stationID) {
            var self = this;
            var campaignID = pepper.getStationCampaignID(i_stationID);
            self._populateStationCampaignDropDown(campaignID);
        },

        /**
         Populate the selection drop down UI with all available campaigns for station selection
         @method _populateStationCampaignDropDown
         @param  {Number} i_campaignID
         **/
        _populateStationCampaignDropDown: function (i_campaignID) {
            var self = this;
            $(Elements.STATION_SELECTION_CAMPAIGN).empty();
            if (i_campaignID == undefined || i_campaignID == -1)
                $(Elements.STATION_SELECTION_CAMPAIGN).append('<option selected data-campaign_id="-1">Select campaign</option>');
            var campaignIDs = pepper.getCampaignIDs();
            for (var i = 0; i < campaignIDs.length; i++) {
                var campaignID = campaignIDs[i];
                var recCampaign = pepper.getCampaignRecord(campaignID);
                var selected = campaignID == i_campaignID ? 'selected' : '';
                var snippet = '<option ' + selected + ' data-campaign_id="' + campaignID + '">' + recCampaign['campaign_name'] + '</option>';
                $(Elements.STATION_SELECTION_CAMPAIGN).append(snippet);
            }
        },

        /**
         On change campaign action apply changes to local msdb
         @method _onChangedCampaign
         **/
        _onChangedCampaign: function (e) {
            var self = this;
            var campaign_id = $(Elements.STATION_SELECTION_CAMPAIGN + ' option:selected').attr('data-campaign_id');
            if (campaign_id == -1)
                return;
            pepper.setStationCampaignID(self.m_selected_station_id, campaign_id);
        },

        /**
         Get current total active, non red stations
         @method getTotalActiveStation
         @param {Number} i_playerData
         @return {Number} total active / non red stations
         **/
        getTotalActiveStation: function () {
            var self = this;
            var connected = self.m_stationCollection.filter(function (stationsModel) {
                return stationsModel.get('connection') != '0'
            });
            return connected.length;
        }
    });

    return StationsListView;
});