Replaced existing usage on GrRestApiInterface with `RestApiService & Element` Change-Id: Id16f489ea382522c9f1c765fe44550248878f149
272 lines
6.8 KiB
TypeScript
272 lines
6.8 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright (C) 2015 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.
|
|
*/
|
|
import '../gr-rest-api-interface/gr-rest-api-interface';
|
|
import '../../../styles/shared-styles';
|
|
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
|
|
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
|
|
import {PolymerElement} from '@polymer/polymer/polymer-element';
|
|
import {htmlTemplate} from './gr-date-formatter_html';
|
|
import {TooltipMixin} from '../../../mixins/gr-tooltip-mixin/gr-tooltip-mixin';
|
|
import {property, customElement} from '@polymer/decorators';
|
|
import {
|
|
parseDate,
|
|
fromNow,
|
|
isValidDate,
|
|
isWithinDay,
|
|
isWithinHalfYear,
|
|
formatDate,
|
|
utcOffsetString,
|
|
} from '../../../utils/date-util';
|
|
import {TimeFormat, DateFormat} from '../../../constants/constants';
|
|
import {assertNever} from '../../../utils/common-util';
|
|
import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api';
|
|
|
|
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
|
|
};
|
|
|
|
const DateFormats = {
|
|
STD: {
|
|
short: 'MMM DD', // Aug 29
|
|
full: 'MMM DD, YYYY', // Aug 29, 1997
|
|
},
|
|
US: {
|
|
short: 'MM/DD', // 08/29
|
|
full: 'MM/DD/YY', // 08/29/97
|
|
},
|
|
ISO: {
|
|
short: 'MM-DD', // 08-29
|
|
full: 'YYYY-MM-DD', // 1997-08-29
|
|
},
|
|
EURO: {
|
|
short: 'DD. MMM', // 29. Aug
|
|
full: 'DD.MM.YYYY', // 29.08.1997
|
|
},
|
|
UK: {
|
|
short: 'DD/MM', // 29/08
|
|
full: 'DD/MM/YYYY', // 29/08/1997
|
|
},
|
|
};
|
|
|
|
interface DateFormatPair {
|
|
short: string;
|
|
full: string;
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'gr-date-formatter': GrDateFormatter;
|
|
}
|
|
}
|
|
|
|
export interface GrDateFormatter {
|
|
$: {
|
|
restAPI: RestApiService & Element;
|
|
};
|
|
}
|
|
|
|
@customElement('gr-date-formatter')
|
|
export class GrDateFormatter extends TooltipMixin(
|
|
GestureEventListeners(LegacyElementMixin(PolymerElement))
|
|
) {
|
|
static get template() {
|
|
return htmlTemplate;
|
|
}
|
|
|
|
@property({type: String, notify: true})
|
|
dateStr: string | null = null;
|
|
|
|
@property({type: Boolean})
|
|
showDateAndTime = false;
|
|
|
|
/**
|
|
* When true, the detailed date appears in a GR-TOOLTIP rather than in the
|
|
* native browser tooltip.
|
|
*/
|
|
@property({type: Boolean})
|
|
hasTooltip = false;
|
|
|
|
/**
|
|
* The title to be used as the native tooltip or by the tooltip behavior.
|
|
*/
|
|
@property({
|
|
type: String,
|
|
reflectToAttribute: true,
|
|
computed: '_computeFullDateStr(dateStr, _timeFormat, _dateFormat)',
|
|
})
|
|
title = '';
|
|
|
|
/** @type {?{short: string, full: string}} */
|
|
@property({type: Object})
|
|
_dateFormat?: DateFormatPair;
|
|
|
|
@property({type: String})
|
|
_timeFormat?: string;
|
|
|
|
@property({type: Boolean})
|
|
_relative?: boolean;
|
|
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
/** @override */
|
|
attached() {
|
|
super.attached();
|
|
this._loadPreferences();
|
|
}
|
|
|
|
_getUtcOffsetString() {
|
|
return utcOffsetString();
|
|
}
|
|
|
|
_loadPreferences() {
|
|
return this._getLoggedIn().then(loggedIn => {
|
|
if (!loggedIn) {
|
|
this._timeFormat = TimeFormats.TIME_24;
|
|
this._dateFormat = DateFormats.STD;
|
|
this._relative = false;
|
|
return;
|
|
}
|
|
return Promise.all([this._loadTimeFormat(), this._loadRelative()]);
|
|
});
|
|
}
|
|
|
|
_loadTimeFormat() {
|
|
return this._getPreferences().then(preferences => {
|
|
if (!preferences) {
|
|
throw Error('Preferences is not set');
|
|
}
|
|
this._decideTimeFormat(preferences.time_format);
|
|
this._decideDateFormat(preferences.date_format);
|
|
});
|
|
}
|
|
|
|
_decideTimeFormat(timeFormat: TimeFormat) {
|
|
switch (timeFormat) {
|
|
case TimeFormat.HHMM_12:
|
|
this._timeFormat = TimeFormats.TIME_12;
|
|
break;
|
|
case TimeFormat.HHMM_24:
|
|
this._timeFormat = TimeFormats.TIME_24;
|
|
break;
|
|
default:
|
|
assertNever(timeFormat, `Invalid time format: ${timeFormat}`);
|
|
}
|
|
}
|
|
|
|
_decideDateFormat(dateFormat: DateFormat) {
|
|
switch (dateFormat) {
|
|
case DateFormat.STD:
|
|
this._dateFormat = DateFormats.STD;
|
|
break;
|
|
case DateFormat.US:
|
|
this._dateFormat = DateFormats.US;
|
|
break;
|
|
case DateFormat.ISO:
|
|
this._dateFormat = DateFormats.ISO;
|
|
break;
|
|
case DateFormat.EURO:
|
|
this._dateFormat = DateFormats.EURO;
|
|
break;
|
|
case DateFormat.UK:
|
|
this._dateFormat = DateFormats.UK;
|
|
break;
|
|
default:
|
|
assertNever(dateFormat, `Invalid date format: ${dateFormat}`);
|
|
}
|
|
}
|
|
|
|
_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();
|
|
}
|
|
|
|
_computeDateStr(
|
|
dateStr?: string,
|
|
timeFormat?: string,
|
|
dateFormat?: DateFormatPair,
|
|
relative?: boolean,
|
|
showDateAndTime?: boolean
|
|
) {
|
|
if (!dateStr || !timeFormat || !dateFormat) {
|
|
return '';
|
|
}
|
|
const date = parseDate(dateStr);
|
|
if (!isValidDate(date)) {
|
|
return '';
|
|
}
|
|
if (relative) {
|
|
return fromNow(date);
|
|
}
|
|
const now = new Date();
|
|
let format = dateFormat.full;
|
|
if (isWithinDay(now, date)) {
|
|
format = timeFormat;
|
|
} else {
|
|
if (isWithinHalfYear(now, date)) {
|
|
format = dateFormat.short;
|
|
}
|
|
if (this.showDateAndTime || showDateAndTime) {
|
|
format = `${format} ${timeFormat}`;
|
|
}
|
|
}
|
|
return formatDate(date, format);
|
|
}
|
|
|
|
_timeToSecondsFormat(timeFormat: string | undefined) {
|
|
return timeFormat === TimeFormats.TIME_12
|
|
? TimeFormats.TIME_12_WITH_SEC
|
|
: TimeFormats.TIME_24_WITH_SEC;
|
|
}
|
|
|
|
_computeFullDateStr(
|
|
dateStr?: string,
|
|
timeFormat?: string,
|
|
dateFormat?: DateFormatPair
|
|
) {
|
|
// Polymer 2: check for undefined
|
|
if ([dateStr, timeFormat].includes(undefined) || !dateFormat) {
|
|
return undefined;
|
|
}
|
|
|
|
if (!dateStr) {
|
|
return '';
|
|
}
|
|
const date = parseDate(dateStr);
|
|
if (!isValidDate(date)) {
|
|
return '';
|
|
}
|
|
let format = dateFormat.full + ', ';
|
|
format += this._timeToSecondsFormat(timeFormat);
|
|
return formatDate(date, format) + this._getUtcOffsetString();
|
|
}
|
|
}
|