| // Copyright (C) 2016 The Android Open Source Project | 
 | // | 
 | // 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. | 
 | (function() { | 
 |   'use strict'; | 
 |  | 
 |   const Duration = { | 
 |     HOUR: 1000 * 60 * 60, | 
 |     DAY: 1000 * 60 * 60 * 24, | 
 |   }; | 
 |  | 
 |   const TimeFormats = { | 
 |     TIME_12: 'h:mm A', // 2:14 PM | 
 |     TIME_12_WITH_SEC: 'h:mm:ss A', // 2:14:00 PM | 
 |     TIME_24: 'HH:mm', // 14:14 | 
 |     TIME_24_WITH_SEC: 'HH:mm:ss', // 14:14:00 | 
 |     MONTH_DAY: 'MMM DD', // Aug 29 | 
 |     MONTH_DAY_YEAR: 'MMM DD, YYYY', // Aug 29, 1997 | 
 |   }; | 
 |  | 
 |   Polymer({ | 
 |     is: 'gr-date-formatter', | 
 |  | 
 |     properties: { | 
 |       dateStr: { | 
 |         type: String, | 
 |         value: null, | 
 |         notify: true, | 
 |       }, | 
 |  | 
 |       /** | 
 |        * When true, the detailed date appears in a GR-TOOLTIP rather than in the | 
 |        * native browser tooltip. | 
 |        */ | 
 |       hasTooltip: Boolean, | 
 |  | 
 |       /** | 
 |        * The title to be used as the native tooltip or by the tooltip behavior. | 
 |        */ | 
 |       title: { | 
 |         type: String, | 
 |         reflectToAttribute: true, | 
 |         computed: '_computeFullDateStr(dateStr, _timeFormat)', | 
 |       }, | 
 |  | 
 |       _timeFormat: String, // No default value to prevent flickering. | 
 |       _relative: Boolean, // No default value to prevent flickering. | 
 |     }, | 
 |  | 
 |     behaviors: [ | 
 |       Gerrit.TooltipBehavior, | 
 |     ], | 
 |  | 
 |     attached() { | 
 |       this._loadPreferences(); | 
 |     }, | 
 |  | 
 |     _getUtcOffsetString() { | 
 |       return ' UTC' + moment().format('Z'); | 
 |     }, | 
 |  | 
 |     _loadPreferences() { | 
 |       return this._getLoggedIn().then(loggedIn => { | 
 |         if (!loggedIn) { | 
 |           this._timeFormat = TimeFormats.TIME_24; | 
 |           this._relative = false; | 
 |           return; | 
 |         } | 
 |         return Promise.all([ | 
 |           this._loadTimeFormat(), | 
 |           this._loadRelative(), | 
 |         ]); | 
 |       }); | 
 |     }, | 
 |  | 
 |     _loadTimeFormat() { | 
 |       return this._getPreferences().then(preferences => { | 
 |         const timeFormat = preferences && preferences.time_format; | 
 |         switch (timeFormat) { | 
 |           case 'HHMM_12': | 
 |             this._timeFormat = TimeFormats.TIME_12; | 
 |             break; | 
 |           case 'HHMM_24': | 
 |             this._timeFormat = TimeFormats.TIME_24; | 
 |             break; | 
 |           default: | 
 |             throw Error('Invalid time format: ' + timeFormat); | 
 |         } | 
 |       }); | 
 |     }, | 
 |  | 
 |     _loadRelative() { | 
 |       return this._getPreferences().then(prefs => { | 
 |         // prefs.relative_date_in_change_table is not set when false. | 
 |         this._relative = !!(prefs && prefs.relative_date_in_change_table); | 
 |       }); | 
 |     }, | 
 |  | 
 |     _getLoggedIn() { | 
 |       return this.$.restAPI.getLoggedIn(); | 
 |     }, | 
 |  | 
 |     _getPreferences() { | 
 |       return this.$.restAPI.getPreferences(); | 
 |     }, | 
 |  | 
 |     /** | 
 |      * Return true if date is within 24 hours and on the same day. | 
 |      */ | 
 |     _isWithinDay(now, date) { | 
 |       const diff = -date.diff(now); | 
 |       return diff < Duration.DAY && date.day() === now.getDay(); | 
 |     }, | 
 |  | 
 |     /** | 
 |      * Returns true if date is from one to six months. | 
 |      */ | 
 |     _isWithinHalfYear(now, date) { | 
 |       const diff = -date.diff(now); | 
 |       return (date.day() !== now.getDay() || diff >= Duration.DAY) && | 
 |           diff < 180 * Duration.DAY; | 
 |     }, | 
 |  | 
 |     _computeDateStr(dateStr, timeFormat, relative) { | 
 |       if (!dateStr) { return ''; } | 
 |       const date = moment(util.parseDate(dateStr)); | 
 |       if (!date.isValid()) { return ''; } | 
 |       if (relative) { | 
 |         const dateFromNow = date.fromNow(); | 
 |         if (dateFromNow === 'a few seconds ago') { | 
 |           return 'just now'; | 
 |         } else { | 
 |           return dateFromNow; | 
 |         } | 
 |       } | 
 |       const now = new Date(); | 
 |       let format = TimeFormats.MONTH_DAY_YEAR; | 
 |       if (this._isWithinDay(now, date)) { | 
 |         format = timeFormat; | 
 |       } else if (this._isWithinHalfYear(now, date)) { | 
 |         format = TimeFormats.MONTH_DAY; | 
 |       } | 
 |       return date.format(format); | 
 |     }, | 
 |  | 
 |     _timeToSecondsFormat(timeFormat) { | 
 |       return timeFormat === TimeFormats.TIME_12 ? | 
 |           TimeFormats.TIME_12_WITH_SEC : | 
 |           TimeFormats.TIME_24_WITH_SEC; | 
 |     }, | 
 |  | 
 |     _computeFullDateStr(dateStr, timeFormat) { | 
 |       if (!dateStr) { return ''; } | 
 |       const date = moment(util.parseDate(dateStr)); | 
 |       if (!date.isValid()) { return ''; } | 
 |       let format = TimeFormats.MONTH_DAY_YEAR + ', '; | 
 |       format += this._timeToSecondsFormat(timeFormat); | 
 |       return date.format(format) + this._getUtcOffsetString(); | 
 |     }, | 
 |   }); | 
 | })(); |