Commit 683f739f authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '340795-don-t-set-default-timezone-to-utc-for-users' into 'master'

Remove default value for time zone user preference

See merge request gitlab-org/gitlab!70834
parents 0b183f7a a1ba00ef
......@@ -27,19 +27,22 @@ export const findTimezoneByIdentifier = (tzList = [], identifier = null) => {
};
export default class TimezoneDropdown {
constructor({ $dropdownEl, $inputEl, onSelectTimezone, displayFormat } = defaults) {
constructor({
$dropdownEl,
$inputEl,
onSelectTimezone,
displayFormat,
allowEmpty = false,
} = defaults) {
this.$dropdown = $dropdownEl;
this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
this.$input = $inputEl;
this.timezoneData = this.$dropdown.data('data');
this.timezoneData = this.$dropdown.data('data') || [];
this.onSelectTimezone = onSelectTimezone;
this.displayFormat = displayFormat || defaults.displayFormat;
this.allowEmpty = allowEmpty;
this.initialTimezone =
findTimezoneByIdentifier(this.timezoneData, this.$input.val()) || defaultTimezone;
this.initDefaultTimezone();
this.initDropdown();
}
......@@ -52,24 +55,25 @@ export default class TimezoneDropdown {
search: {
fields: ['name'],
},
clicked: (cfg) => this.updateInputValue(cfg),
clicked: (cfg) => this.handleDropdownChange(cfg),
text: (item) => formatTimezone(item),
});
this.setDropdownToggle(this.displayFormat(this.initialTimezone));
}
const initialTimezone = findTimezoneByIdentifier(this.timezoneData, this.$input.val());
initDefaultTimezone() {
if (!this.$input.val()) {
this.$input.val(defaultTimezone.name);
if (initialTimezone !== null) {
this.setDropdownValue(initialTimezone);
} else if (!this.allowEmpty) {
this.setDropdownValue(defaultTimezone);
}
}
setDropdownToggle(dropdownText) {
this.$dropdownToggle.text(dropdownText);
setDropdownValue(timezone) {
this.$dropdownToggle.text(this.displayFormat(timezone));
this.$input.val(timezone.name);
}
updateInputValue({ selectedObj, e }) {
handleDropdownChange({ selectedObj, e }) {
e.preventDefault();
this.$input.val(selectedObj.identifier);
if (this.onSelectTimezone) {
......
......@@ -21,6 +21,7 @@ export default class Profile {
$inputEl: this.$inputEl,
$dropdownEl: $('.js-timezone-dropdown'),
displayFormat: (selectedItem) => formatTimezone(selectedItem),
allowEmpty: true,
});
}
......
......@@ -33,6 +33,8 @@ module TimeZoneHelper
end
def local_time(timezone)
return if timezone.blank?
time_zone_instance = ActiveSupport::TimeZone.new(timezone) || Time.zone
time_zone_instance.now.strftime("%-l:%M %p")
end
......
......@@ -23,7 +23,6 @@ class UserPreference < ApplicationRecord
ignore_columns :experience_level, remove_with: '14.10', remove_after: '2021-03-22'
default_value_for :tab_width, value: Gitlab::TabWidth::DEFAULT, allows_nil: false
default_value_for :timezone, value: Time.zone.tzinfo.name, allows_nil: false
default_value_for :time_display_relative, value: true, allows_nil: false
default_value_for :time_format_in_24h, value: false, allows_nil: false
default_value_for :render_whitespace_in_code, value: false, allows_nil: false
......
......@@ -80,7 +80,7 @@
%p= s_("Profiles|Set your local time zone")
.col-lg-8
%h5= _("Time zone")
= dropdown_tag(_("Select a time zone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg', title: _("Select a time zone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
= dropdown_tag(_("Select a time zone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg gl-w-full!', title: _("Select a time zone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
%input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
.col-lg-12
%hr
......
......@@ -84,10 +84,12 @@
= sprite_icon('location', css_class: 'fgray')
%span{ itemprop: 'addressLocality' }
= @user.location
= render 'middle_dot_divider', stacking: true do
- user_local_time = local_time(@user.timezone)
- unless user_local_time.nil?
= render 'middle_dot_divider', stacking: true, data: { testid: 'user-local-time' } do
= sprite_icon('clock', css_class: 'fgray')
%span
= local_time(@user.timezone)
= user_local_time
- unless work_information(@user).blank?
= render 'middle_dot_divider', stacking: true do
= sprite_icon('work', css_class: 'fgray')
......
......@@ -48,8 +48,12 @@ gitlab-ctl restart
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/29669) in GitLab 13.9.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/29669) in GitLab 14.1.
A user can set their time zone in their profile. If a user has not set their time zone, it defaults
to the time zone [configured at the instance level](#changing-your-time-zone). On GitLab.com, the
default time zone is UTC.
Users can set their time zone in their profile. On GitLab.com, the default time zone is UTC.
New users do not have a default time zone in [GitLab 14.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/340795). New users must
explicitly set their time zone before it displays on their profile.
In GitLab 14.3 and earlier, users with no configured time zone default to the time zone
[configured at the instance level](#changing-your-time-zone).
For more information, see [Set your time zone](../user/profile/index.md#set-your-time-zone).
......@@ -561,14 +561,11 @@ RSpec.describe 'User edit profile' do
page.find("a", text: "Nuku'alofa").click
tz = page.find('.user-time-preferences #user_timezone', visible: false)
expect(tz.value).to eq('Pacific/Tongatapu')
expect(page).to have_field(:user_timezone, with: 'Pacific/Tongatapu', type: :hidden)
end
it 'timezone defaults to servers default' do
timezone_name = Time.zone.tzinfo.name
expect(page.find('.user-time-preferences #user_timezone', visible: false).value).to eq(timezone_name)
it 'timezone defaults to empty' do
expect(page).to have_field(:user_timezone, with: '', type: :hidden)
end
end
end
......
......@@ -81,6 +81,7 @@ RSpec.describe 'User page' do
context 'timezone' do
let_it_be(:timezone) { 'America/Los_Angeles' }
let_it_be(:local_time_selector) { '[data-testid="user-local-time"]' }
before do
travel_to Time.find_zone(timezone).local(2021, 7, 20, 15, 30, 45)
......@@ -92,9 +93,21 @@ RSpec.describe 'User page' do
it 'shows local time' do
subject
within local_time_selector do
expect(page).to have_content('3:30 PM')
end
end
end
context 'when timezone is not set' do
let_it_be(:user) { create(:user, timezone: nil) }
it 'does not show local time' do
subject
expect(page).not_to have_selector(local_time_selector)
end
end
context 'when timezone is invalid' do
let_it_be(:user) { create(:user, timezone: 'Foo/Bar') }
......@@ -102,10 +115,12 @@ RSpec.describe 'User page' do
it 'shows local time using the configured default timezone (UTC in this case)' do
subject
within local_time_selector do
expect(page).to have_content('10:30 PM')
end
end
end
end
context 'follow/unfollow and followers/following' do
let_it_be(:followee) { create(:user) }
......
......@@ -10,7 +10,17 @@ describe('Timezone Dropdown', () => {
let $dropdownEl = null;
let $wrapper = null;
const tzListSel = '.dropdown-content ul li a.is-active';
const tzDropdownToggleText = '.dropdown-toggle-text';
const initTimezoneDropdown = (options = {}) => {
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
...options,
});
};
const findDropdownToggleText = () => $wrapper.find('.dropdown-toggle-text');
describe('Initialize', () => {
describe('with dropdown already loaded', () => {
......@@ -18,16 +28,13 @@ describe('Timezone Dropdown', () => {
loadFixtures('pipeline_schedules/edit.html');
$wrapper = $('.dropdown');
$inputEl = $('#schedule_cron_timezone');
$inputEl.val('');
$dropdownEl = $('.js-timezone-dropdown');
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
});
});
it('can take an $inputEl in the constructor', () => {
initTimezoneDropdown();
const tzStr = '[UTC + 5.5] Sri Jayawardenepura';
const tzValue = 'Asia/Colombo';
......@@ -42,6 +49,8 @@ describe('Timezone Dropdown', () => {
});
it('will format data array of timezones into a list of offsets', () => {
initTimezoneDropdown();
const data = $dropdownEl.data('data');
const formatted = $wrapper.find(tzListSel).text();
......@@ -50,6 +59,11 @@ describe('Timezone Dropdown', () => {
});
});
describe('when `allowEmpty` property is `false`', () => {
beforeEach(() => {
initTimezoneDropdown();
});
it('will default the timezone to UTC', () => {
const tz = $inputEl.val();
......@@ -57,6 +71,19 @@ describe('Timezone Dropdown', () => {
});
});
describe('when `allowEmpty` property is `true`', () => {
beforeEach(() => {
initTimezoneDropdown({
allowEmpty: true,
});
});
it('will default the value of the input to an empty string', () => {
expect($inputEl.val()).toBe('');
});
});
});
describe('without dropdown loaded', () => {
beforeEach(() => {
loadFixtures('pipeline_schedules/edit.html');
......@@ -68,23 +95,15 @@ describe('Timezone Dropdown', () => {
it('will populate the list of UTC offsets after the dropdown is loaded', () => {
expect($wrapper.find(tzListSel).length).toEqual(0);
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
});
initTimezoneDropdown();
expect($wrapper.find(tzListSel).length).toEqual($($dropdownEl).data('data').length);
});
it('will call a provided handler when a new timezone is selected', () => {
const onSelectTimezone = jest.fn();
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
onSelectTimezone,
});
initTimezoneDropdown({ onSelectTimezone });
$wrapper.find(tzListSel).first().trigger('click');
......@@ -94,24 +113,15 @@ describe('Timezone Dropdown', () => {
it('will correctly set the dropdown label if a timezone identifier is set on the inputEl', () => {
$inputEl.val('America/St_Johns');
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
displayFormat: (selectedItem) => formatTimezone(selectedItem),
});
initTimezoneDropdown({ displayFormat: (selectedItem) => formatTimezone(selectedItem) });
expect($wrapper.find(tzDropdownToggleText).html()).toEqual('[UTC - 2.5] Newfoundland');
expect(findDropdownToggleText().html()).toEqual('[UTC - 2.5] Newfoundland');
});
it('will call a provided `displayFormat` handler to format the dropdown value', () => {
const displayFormat = jest.fn();
// eslint-disable-next-line no-new
new TimezoneDropdown({
$inputEl,
$dropdownEl,
displayFormat,
});
initTimezoneDropdown({ displayFormat });
$wrapper.find(tzListSel).first().trigger('click');
......
......@@ -76,6 +76,18 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
travel_to Time.find_zone(timezone).local(2021, 7, 20, 15, 30, 45)
end
context 'when timezone is `nil`' do
it 'returns `nil`' do
expect(helper.local_time(nil)).to eq(nil)
end
end
context 'when timezone is blank' do
it 'returns `nil`' do
expect(helper.local_time('')).to eq(nil)
end
end
context 'when a valid timezone is passed' do
it 'returns local time' do
expect(helper.local_time(timezone)).to eq('3:30 PM')
......
......@@ -80,12 +80,6 @@ RSpec.describe UserPreference do
end
end
describe '#timezone' do
it 'returns server time as default' do
expect(user_preference.timezone).to eq(Time.zone.tzinfo.name)
end
end
describe '#tab_width' do
it 'is set to 8 by default' do
# Intentionally not using factory here to test the constructor.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment