Merge "AgularJS pages display dates using Horizon's Settings Timezone"

This commit is contained in:
Zuul 2019-12-09 13:24:48 +00:00 committed by Gerrit Code Review
commit bd5642dc73
6 changed files with 191 additions and 11 deletions

View File

@ -17,7 +17,7 @@
'use strict';
angular
.module('horizon.framework.util.filters')
.module('horizon.framework.util.filters', ['ngCookies'])
.filter('yesno', yesNoFilter)
.filter('simpleDate', simpleDateFilter)
.filter('mediumDate', mediumDateFilter)
@ -53,10 +53,18 @@
* @description
* Evaluates given for display as a short date, returning '-' if empty.
*/
simpleDateFilter.$inject = ['$filter'];
function simpleDateFilter($filter) {
simpleDateFilter.$inject = [
'$cookies',
'$filter',
'horizon.framework.util.timezones.service'
];
function simpleDateFilter($cookies, $filter, timeZoneService) {
return function (input) {
return $filter('noValue')($filter('date')(input, 'short'));
var currentTimeZone = $cookies.get('django_timezone') || 'UTC';
currentTimeZone = currentTimeZone.replace(/^"(.*)"$/, '$1');
return timeZoneService.getTimeZoneOffset(currentTimeZone).then(function (timeZoneOffset) {
return $filter('noValue')($filter('date')(input, 'short', timeZoneOffset));
});
};
}
@ -66,10 +74,23 @@
* @description
* Evaluates given for display as a medium date, returning '-' if empty.
*/
mediumDateFilter.$inject = ['$filter'];
function mediumDateFilter($filter) {
mediumDateFilter.$inject = [
'$cookies',
'$filter',
'horizon.framework.util.timezones.service'
];
function mediumDateFilter($cookies, $filter, timeZoneService) {
return function (input) {
return $filter('noValue')($filter('date')(input, 'medium'));
/*
* For the input time, we need to add "Z" to fit iso8601 time format
* so the filter can confirm that the input time is in UTC timezone.
*/
input = input + 'Z';
var currentTimeZone = $cookies.get('django_timezone') || 'UTC';
currentTimeZone = currentTimeZone.replace(/^"(.*)"$/, '$1');
return timeZoneService.getTimeZoneOffset(currentTimeZone).then(function (timeZoneOffset) {
return $filter('noValue')($filter('date')(input, 'medium', timeZoneOffset));
});
};
}

View File

@ -59,11 +59,19 @@
}));
it('returns blank if nothing', function () {
expect(simpleDateFilter()).toBe('-');
simpleDateFilter().then(getResult);
function getResult(result) {
expect(result).toBe('-');
}
});
it('returns the expected time', function() {
expect(simpleDateFilter('2016-06-24T04:19:07')).toBe('6/24/16 4:19 AM');
simpleDateFilter().then(getResult);
function getResult(result) {
expect(result).toBe('9/3/19 9:19 AM');
}
});
});
@ -74,11 +82,19 @@
}));
it('returns blank if nothing', function () {
expect(mediumDateFilter()).toBe('-');
mediumDateFilter().then(getResult);
function getResult(result) {
expect(result).toBe('-');
}
});
it('returns the expected time', function() {
expect(mediumDateFilter('2001-02-03T16:05:06')).toBe('Feb 3, 2001 4:05:06 PM');
mediumDateFilter().then(getResult);
function getResult(result) {
expect(result).toBe('Sep 3, 2019 9:19:07 AM');
}
});
});

View File

@ -0,0 +1,74 @@
/*
* Copyright 2019 99Cloud Inc.
*
* 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';
angular
.module('horizon.framework.util.timezones', [])
.factory('horizon.framework.util.timezones.service', timeZoneService);
timeZoneService.$inject = [
'$q',
'horizon.framework.util.http.service'
];
/**
* @ngdoc service
* @name timeZoneService
* @param {Object} $q
* @param {Object} ApiService
* @description
* Horizon's AngularJS pages(for example Images and Keypairs) display dates
* using browser's timezone now. This service get timezone offset from
* Horizon's Settings and if Timezone is not set under Settings, AngularJS
* pages will display dates in 'UTC' timezone.
* @returns {Object} The service
*/
function timeZoneService($q, ApiService) {
var service = {
getTimeZones: getTimeZones,
getTimeZoneOffset: getTimeZoneOffset
};
return service;
/////////
function getTimeZones() {
return ApiService.get('/api/timezones/', {cache: true});
}
function getTimeZoneOffset(timezone) {
var deferred = $q.defer();
function onTimezonesLoaded(response) {
var offsetDict = response.data.timezone_dict;
timezone = timezone || 'UTC';
deferred.resolve(offsetDict[timezone]);
}
function onTimezonesFailure(message) {
deferred.reject(message);
}
service.getTimeZones()
.then(onTimezonesLoaded, onTimezonesFailure);
return deferred.promise;
}
}
}());

View File

@ -0,0 +1,52 @@
/*
* Copyright 2019 99Cloud Inc.
*
* 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';
describe('horizon.framework.util.timezones.service', function () {
var service;
beforeEach(module('horizon.framework'));
beforeEach(inject(function($injector) {
service = $injector.get('horizon.framework.util.timezones.service');
}));
it('defines the service', function() {
expect(service).toBeDefined();
});
describe('get timezone offset', function () {
it('returns +0000(UTC offset) if nothing', function () {
function getResult(result) {
expect(result).toBe('+0000');
}
service.getTimeZoneOffset().then(getResult);
});
it('returns the timezone offset', function() {
function getResult(result) {
expect(result).toBe('+0800');
}
service.getTimeZoneOffset('Asia/Shanghai').then(getResult);
});
});
}); // end of horizon.framework.util.timezones
})();

View File

@ -27,6 +27,7 @@
'horizon.framework.util.promise-toggle',
'horizon.framework.util.q',
'horizon.framework.util.tech-debt',
'horizon.framework.util.timezones',
'horizon.framework.util.uuid',
'horizon.framework.util.workflow',
'horizon.framework.util.validators',

View File

@ -13,8 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import datetime
from django.conf import settings
from django.http import JsonResponse
from django.views import generic
import pytz
from openstack_dashboard import api
from openstack_dashboard.api.rest import urls
@ -55,3 +59,15 @@ class Settings(generic.View):
in settings_allowed if k not in self.SPECIALS}
plain_settings.update(self.SPECIALS)
return plain_settings
@urls.register
class Timezones(generic.View):
"""API for timezone service."""
url_regex = r'timezones/$'
@rest_utils.ajax()
def get(self, request):
zones = {tz: datetime.now(pytz.timezone(tz)).strftime('%z')
for tz in pytz.common_timezones}
return JsonResponse({'timezone_dict': zones})