Home | History | Annotate | Download | only in webapp
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview
      7  * Class to track of connections to and from this computer and display them.
      8  */
      9 
     10 'use strict';
     11 
     12 /** @suppress {duplicate} */
     13 var remoting = remoting || {};
     14 
     15 /** @constructor */
     16 remoting.ConnectionHistory = function() {
     17   /** @type {HTMLElement} @private */
     18   this.viewAll_ = document.getElementById('history-view-all');
     19   /** @type {HTMLElement} @private */
     20   this.viewOutgoing_ = document.getElementById('history-view-outgoing');
     21   /** @type {HTMLElement} @private */
     22   this.viewIncoming_ = document.getElementById('history-view-incoming');
     23   /** @type {HTMLElement} @private */
     24   this.clear_ = document.getElementById('clear-connection-history');
     25   /** @type {HTMLElement} @private */
     26   this.historyEntries_ = document.getElementById('connection-history-entries');
     27   /** @type {remoting.ConnectionHistory.Filter} @private */
     28   this.filter_ = remoting.ConnectionHistory.Filter.VIEW_ALL;
     29 
     30   /** @type {remoting.ConnectionHistory} */
     31   var that = this;
     32   var closeButton = document.getElementById('close-connection-history');
     33   closeButton.addEventListener('click', this.hide.bind(this), false);
     34   /** @param {Event} event Event identifying which button was clicked. */
     35   var setFilter = function(event) { that.setFilter_(event.target); };
     36   this.viewAll_.addEventListener('click', setFilter, false);
     37   this.viewOutgoing_.addEventListener('click', setFilter, false);
     38   this.viewIncoming_.addEventListener('click', setFilter, false);
     39   this.clear_.addEventListener('click', this.clearHistory_.bind(this), false);
     40 };
     41 
     42 /** @enum {string} */
     43 remoting.ConnectionHistory.Filter = {
     44   VIEW_ALL: 'history-view-all',
     45   VIEW_OUTGOING: 'history-view-outgoing',
     46   VIEW_INCOMING: 'history-view-incoming'
     47 };
     48 
     49 /** Show the dialog and refresh its contents */
     50 remoting.ConnectionHistory.prototype.show = function() {
     51   this.load();
     52   remoting.setMode(remoting.AppMode.HISTORY);
     53 };
     54 
     55 /** Hide the dialog */
     56 remoting.ConnectionHistory.prototype.hide = function() {
     57   remoting.setMode(remoting.AppMode.HOME);
     58 };
     59 
     60 /**
     61  * A saved entry in the connection history.
     62  * @param {Object} object A Javascript object, which may or may not be of the
     63  *     correct type.
     64  * @constructor
     65  */
     66 remoting.ConnectionHistory.Entry = function(object) {
     67   this.valid =
     68       'date' in object && typeof(object['date']) == 'number' &&
     69       'from' in object && typeof(object['from']) == 'string' &&
     70       'to' in object && typeof(object['to']) == 'string' &&
     71       'duration' in object && typeof(object['duration']) == 'number';
     72   if (this.valid) {
     73     /** @type {Date} */
     74     this.date = new Date(object['date']);
     75     /** @type {string} */
     76     this.from = object['from'];
     77     /** @type {string} */
     78     this.to = object['to'];
     79     /** @type {number} */
     80     this.duration = object['duration'];
     81   }
     82 };
     83 
     84 /**
     85  * @return {string} The connection duration, formatted as a string, or 'Not
     86  *     available' if there is no duration stored.
     87  * @private
     88  */
     89 remoting.ConnectionHistory.Entry.prototype.durationString_ = function() {
     90   var secs = this.duration % 60;
     91   var mins = ((this.duration - secs) / 60) % 60;
     92   var hours = (this.duration - secs - 60 * mins) / 3600;
     93   if (secs < 10) {
     94     secs = '0' + secs;
     95   }
     96   var result = mins + ':' + secs;
     97   if (hours > 0) {
     98     if (mins < 10) {
     99       result = '0' + result;
    100     }
    101     result = hours + ':' + result;
    102   }
    103   return result;
    104 };
    105 
    106 /**
    107  * @return {{summary: Element, detail: Element}} Two table rows containing the
    108  *     summary and detail information, respectively, for the connection.
    109  */
    110 remoting.ConnectionHistory.Entry.prototype.createTableRows = function() {
    111   var summary = /** @type {HTMLElement} */ document.createElement('tr');
    112   summary.classList.add('connection-history-summary');
    113   var zippy = /** @type {HTMLElement} */ document.createElement('td');
    114   zippy.classList.add('zippy');
    115   summary.appendChild(zippy);
    116   // TODO(jamiewalch): Find a way of combining date and time such both align
    117   // vertically without being considered separate columns, which puts too much
    118   // space between them.
    119   var date = document.createElement('td');
    120   // TODO(jamiewalch): Use a shorter localized version of the date.
    121   date.innerText = this.date.toLocaleDateString();
    122   summary.appendChild(date);
    123   var time = document.createElement('td');
    124   time.innerText = this.date.toLocaleTimeString();
    125   summary.appendChild(time);
    126   var from = document.createElement('td');
    127   from.innerText = this.from;
    128   summary.appendChild(from);
    129   var to = document.createElement('td');
    130   to.innerText = this.to;
    131   summary.appendChild(to);
    132   var duration = document.createElement('td');
    133   duration.innerText = this.durationString_();
    134   summary.appendChild(duration);
    135   // TODO(jamiewalch): Fill out the detail row correctly.
    136   var detail = /** @type {HTMLElement} */ document.createElement('tr');
    137   detail.classList.add('connection-history-detail');
    138   for (var i = 0; i < summary.childElementCount; ++i) {
    139     var td = document.createElement('td');
    140     if (i != 0) {
    141       // The inner div allows the details rows to be hidden without changing
    142       // the column widths.
    143       var div = document.createElement('div');
    144       div.innerText = 'Nothing to see here';
    145       td.appendChild(div);
    146     }
    147     detail.appendChild(td);
    148   }
    149   /** @param {HTMLElement} node The summary row. */
    150   var toggleDetail = function(node) {
    151     node.classList.toggle('expanded');
    152   };
    153   summary.addEventListener('click',
    154                            function() { toggleDetail(summary); },
    155                            false);
    156   detail.addEventListener('click',
    157                           function() { toggleDetail(summary); },
    158                           false);
    159   return { 'summary': summary, 'detail': detail };
    160 };
    161 
    162 /** Refresh the contents of the connection history table */
    163 remoting.ConnectionHistory.prototype.load = function() {
    164   // TODO(jamiewalch): Load connection history data when it's available.
    165   var history = [];
    166   // Remove existing entries from the DOM and repopulate.
    167   // TODO(jamiewalch): Enforce the filter.
    168   this.historyEntries_.innerText = '';
    169   for (var i in history) {
    170     var connection = new remoting.ConnectionHistory.Entry(history[i]);
    171     if (connection.valid) {
    172       var rows = connection.createTableRows();
    173       this.historyEntries_.appendChild(rows.summary);
    174       this.historyEntries_.appendChild(rows.detail);
    175     }
    176   }
    177 };
    178 
    179 /**
    180  * @param {EventTarget} element The element that was clicked.
    181  * @private
    182  */
    183 remoting.ConnectionHistory.prototype.setFilter_ = function(element) {
    184   for (var i in remoting.ConnectionHistory.Filter) {
    185     var link = document.getElementById(remoting.ConnectionHistory.Filter[i]);
    186     if (element == link) {
    187       link.classList.add('no-link');
    188       this.filter_ = /** @type {remoting.ConnectionHistory.Filter} */ (i);
    189     } else {
    190       link.classList.remove('no-link');
    191     }
    192   }
    193 };
    194 
    195 /**
    196  * @private
    197  */
    198 remoting.ConnectionHistory.prototype.clearHistory_ = function() {
    199   // TODO(jamiewalch): Implement once we store users' connection histories.
    200 };
    201 
    202 /** @type {remoting.ConnectionHistory} */
    203 remoting.ConnectionHistory.connectionHistory = null;
    204