Commit 27f7771a authored by Fabian Schneider's avatar Fabian Schneider

Add setting for first day of the week

parent 20c83bbd
...@@ -64,6 +64,7 @@ class DueDateSelect { ...@@ -64,6 +64,7 @@ class DueDateSelect {
this.saveDueDate(true); this.saveDueDate(true);
} }
}, },
firstDay: gon.first_day_of_week,
}); });
calendar.setDate(parsePikadayDate($dueDateInput.val())); calendar.setDate(parsePikadayDate($dueDateInput.val()));
...@@ -183,6 +184,7 @@ export default class DueDateSelectors { ...@@ -183,6 +184,7 @@ export default class DueDateSelectors {
onSelect(dateText) { onSelect(dateText) {
$datePicker.val(calendar.toString(dateText)); $datePicker.val(calendar.toString(dateText));
}, },
firstDay: gon.first_day_of_week,
}); });
calendar.setDate(parsePikadayDate(datePickerVal)); calendar.setDate(parsePikadayDate(datePickerVal));
......
...@@ -44,6 +44,7 @@ export default class IssuableForm { ...@@ -44,6 +44,7 @@ export default class IssuableForm {
parse: dateString => parsePikadayDate(dateString), parse: dateString => parsePikadayDate(dateString),
toString: date => pikadayToString(date), toString: date => pikadayToString(date),
onSelect: dateText => $issuableDueDate.val(calendar.toString(dateText)), onSelect: dateText => $issuableDueDate.val(calendar.toString(dateText)),
firstDay: gon.first_day_of_week,
}); });
calendar.setDate(parsePikadayDate($issuableDueDate.val())); calendar.setDate(parsePikadayDate($issuableDueDate.val()));
} }
......
...@@ -33,6 +33,7 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d ...@@ -33,6 +33,7 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
toggleClearInput.call($input); toggleClearInput.call($input);
}, },
firstDay: gon.first_day_of_week,
}); });
calendar.setDate(parsePikadayDate($input.val())); calendar.setDate(parsePikadayDate($input.val()));
......
...@@ -43,10 +43,26 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -43,10 +43,26 @@ document.addEventListener('DOMContentLoaded', () => {
], ],
}); });
const reorderWeekDays = (weekDays, firstDayOfWeek = 0) => {
if (firstDayOfWeek === 0) {
return weekDays;
}
return Object.keys(weekDays).reduce((acc, dayName, idx, arr) => {
const reorderedDayName = arr[(idx + firstDayOfWeek) % arr.length];
return {
...acc,
[reorderedDayName]: weekDays[reorderedDayName],
};
}, {});
};
const hourData = chartData(projectChartData.hour); const hourData = chartData(projectChartData.hour);
responsiveChart($('#hour-chart'), hourData); responsiveChart($('#hour-chart'), hourData);
const dayData = chartData(projectChartData.weekDays); const weekDays = reorderWeekDays(projectChartData.weekDays, gon.first_day_of_week);
const dayData = chartData(weekDays);
responsiveChart($('#weekday-chart'), dayData); responsiveChart($('#weekday-chart'), dayData);
const monthData = chartData(projectChartData.month); const monthData = chartData(projectChartData.month);
......
...@@ -159,7 +159,7 @@ export default class ActivityCalendar { ...@@ -159,7 +159,7 @@ export default class ActivityCalendar {
.append('g') .append('g')
.attr('transform', (group, i) => { .attr('transform', (group, i) => {
_.each(group, (stamp, a) => { _.each(group, (stamp, a) => {
if (a === 0 && stamp.day === 0) { if (a === 0 && stamp.day === this.firstDayOfWeek) {
const month = stamp.date.getMonth(); const month = stamp.date.getMonth();
const x = this.daySizeWithSpace * i + 1 + this.daySizeWithSpace; const x = this.daySizeWithSpace * i + 1 + this.daySizeWithSpace;
const lastMonth = _.last(this.months); const lastMonth = _.last(this.months);
...@@ -205,6 +205,14 @@ export default class ActivityCalendar { ...@@ -205,6 +205,14 @@ export default class ActivityCalendar {
y: 29 + this.dayYPos(5), y: 29 + this.dayYPos(5),
}, },
]; ];
if (this.firstDayOfWeek === 1) {
days.push({
text: 'S',
y: 29 + this.dayYPos(7),
});
}
this.svg this.svg
.append('g') .append('g')
.selectAll('text') .selectAll('text')
......
...@@ -234,7 +234,7 @@ export default class UserTabs { ...@@ -234,7 +234,7 @@ export default class UserTabs {
data, data,
calendarActivitiesPath, calendarActivitiesPath,
utcOffset, utcOffset,
0, gon.first_day_of_week,
monthsAgo, monthsAgo,
); );
} }
......
...@@ -40,6 +40,7 @@ export default { ...@@ -40,6 +40,7 @@ export default {
toString: date => pikadayToString(date), toString: date => pikadayToString(date),
onSelect: this.selected.bind(this), onSelect: this.selected.bind(this),
onClose: this.toggled.bind(this), onClose: this.toggled.bind(this),
firstDay: gon.first_day_of_week,
}); });
this.$el.append(this.calendar.el); this.$el.append(this.calendar.el);
......
...@@ -37,6 +37,6 @@ class Profiles::PreferencesController < Profiles::ApplicationController ...@@ -37,6 +37,6 @@ class Profiles::PreferencesController < Profiles::ApplicationController
end end
def preferences_param_names def preferences_param_names
[:color_scheme_id, :layout, :dashboard, :project_view, :theme_id] [:color_scheme_id, :layout, :dashboard, :project_view, :theme_id, :first_day_of_week]
end end
end end
...@@ -136,6 +136,7 @@ module ApplicationSettingsHelper ...@@ -136,6 +136,7 @@ module ApplicationSettingsHelper
:container_registry_token_expire_delay, :container_registry_token_expire_delay,
:default_artifacts_expire_in, :default_artifacts_expire_in,
:default_branch_protection, :default_branch_protection,
:default_first_day_of_week,
:default_group_visibility, :default_group_visibility,
:default_project_visibility, :default_project_visibility,
:default_projects_limit, :default_projects_limit,
......
...@@ -43,6 +43,13 @@ module PreferencesHelper ...@@ -43,6 +43,13 @@ module PreferencesHelper
] ]
end end
def first_day_of_week_choices
[
['Sunday', 0],
['Monday', 1]
]
end
def user_application_theme def user_application_theme
@user_application_theme ||= Gitlab::Themes.for_user(current_user).css_class @user_application_theme ||= Gitlab::Themes.for_user(current_user).css_class
end end
......
...@@ -237,6 +237,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -237,6 +237,7 @@ class ApplicationSetting < ActiveRecord::Base
container_registry_token_expire_delay: 5, container_registry_token_expire_delay: 5,
default_artifacts_expire_in: '30 days', default_artifacts_expire_in: '30 days',
default_branch_protection: Settings.gitlab['default_branch_protection'], default_branch_protection: Settings.gitlab['default_branch_protection'],
default_first_day_of_week: 0,
default_group_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_group_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_projects_limit: Settings.gitlab['default_projects_limit'], default_projects_limit: Settings.gitlab['default_projects_limit'],
......
...@@ -228,6 +228,9 @@ class User < ApplicationRecord ...@@ -228,6 +228,9 @@ class User < ApplicationRecord
delegate :path, to: :namespace, allow_nil: true, prefix: true delegate :path, to: :namespace, allow_nil: true, prefix: true
delegate :notes_filter_for, to: :user_preference delegate :notes_filter_for, to: :user_preference
delegate :set_notes_filter, to: :user_preference delegate :set_notes_filter, to: :user_preference
delegate :first_day_of_week, :first_day_of_week=, to: :user_preference
accepts_nested_attributes_for :user_preference, update_only: true
state_machine :state, initial: :active do state_machine :state, initial: :active do
event :block do event :block do
......
= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-localization-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
.form-group
= f.label :default_first_day_of_week, _('Default first day of the week'), class: 'label-bold'
= f.select :default_first_day_of_week, options_for_select({_('Sunday') => 0, _('Monday') => 1}, @application_setting.default_first_day_of_week), {}, class: 'form-control'
.form-text.text-muted
Default first day of the week in calendars and date pickers.
= f.submit 'Save changes', class: "btn btn-success"
...@@ -56,3 +56,14 @@ ...@@ -56,3 +56,14 @@
= _('Configure Gitaly timeouts.') = _('Configure Gitaly timeouts.')
.settings-content .settings-content
= render 'gitaly' = render 'gitaly'
%section.settings.as-localization.no-animate#js-localization-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Localization')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Various localization settings.')
.settings-content
= render 'localization'
...@@ -60,5 +60,23 @@ ...@@ -60,5 +60,23 @@
= f.select :project_view, project_view_choices, {}, class: 'form-control' = f.select :project_view, project_view_choices, {}, class: 'form-control'
.form-text.text-muted .form-text.text-muted
Choose what content you want to see on a project’s overview page. Choose what content you want to see on a project’s overview page.
.col-sm-12
%hr
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
Localization
%p
Customize language and region related settings.
= succeed '.' do
= link_to 'Learn more', help_page_path('user/profile/preferences', anchor: 'localization'), target: '_blank'
.col-lg-8
.form-group
= f.label :first_day_of_week, class: 'label-bold' do
First day of the week
= f.select :first_day_of_week, options_for_select(first_day_of_week_choices, @user.first_day_of_week || Gitlab::CurrentSettings.default_first_day_of_week), {}, class: 'form-control'
.form-text.text-muted
Choose on what day the week should start.
.form-group .form-group
= f.submit 'Save changes', class: 'btn btn-success' = f.submit 'Save changes', class: 'btn btn-success'
---
title: Add setting for first day of the week
merge_request: 22755
author: Fabian Schneider @fabsrc
type: added
# frozen_string_literal: true
class AddFirstDayOfWeekToUserPreferences < ActiveRecord::Migration
DOWNTIME = false
def change
add_column :user_preferences, :first_day_of_week, :integer
end
end
# frozen_string_literal: true
class AddDefaultFirstDayOfWeekToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
DOWNTIME = false
def up
add_column_with_default(:application_settings, :default_first_day_of_week, :integer, default: 0)
end
def down
remove_column(:application_settings, :default_first_day_of_week)
end
end
...@@ -168,6 +168,7 @@ ActiveRecord::Schema.define(version: 20190131122559) do ...@@ -168,6 +168,7 @@ ActiveRecord::Schema.define(version: 20190131122559) do
t.string "commit_email_hostname" t.string "commit_email_hostname"
t.boolean "protected_ci_variables", default: false, null: false t.boolean "protected_ci_variables", default: false, null: false
t.string "runners_registration_token_encrypted" t.string "runners_registration_token_encrypted"
t.integer "default_first_day_of_week", default: 0, null: false
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end end
...@@ -2153,6 +2154,7 @@ ActiveRecord::Schema.define(version: 20190131122559) do ...@@ -2153,6 +2154,7 @@ ActiveRecord::Schema.define(version: 20190131122559) do
t.integer "merge_request_notes_filter", limit: 2, default: 0, null: false t.integer "merge_request_notes_filter", limit: 2, default: 0, null: false
t.datetime_with_timezone "created_at", null: false t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false t.datetime_with_timezone "updated_at", null: false
t.integer "first_day_of_week"
t.string "issues_sort" t.string "issues_sort"
t.string "merge_requests_sort" t.string "merge_requests_sort"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree
......
...@@ -87,3 +87,11 @@ You can choose between 3 options: ...@@ -87,3 +87,11 @@ You can choose between 3 options:
- Files and Readme (default) - Files and Readme (default)
- Readme - Readme
- Activity - Activity
## Localization
This following setting allows you to customize calendar layouts.
### First day of the week
You can choose between **Sunday** and **Monday** for the first day of the week. This will be used for all calendar views and datepickers.
...@@ -24,12 +24,14 @@ module Gitlab ...@@ -24,12 +24,14 @@ module Gitlab
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites') gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
gon.test_env = Rails.env.test? gon.test_env = Rails.env.test?
gon.suggested_label_colors = LabelsHelper.suggested_colors gon.suggested_label_colors = LabelsHelper.suggested_colors
gon.first_day_of_week = Gitlab::CurrentSettings.default_first_day_of_week
if current_user if current_user
gon.current_user_id = current_user.id gon.current_user_id = current_user.id
gon.current_username = current_user.username gon.current_username = current_user.username
gon.current_user_fullname = current_user.name gon.current_user_fullname = current_user.name
gon.current_user_avatar_url = current_user.avatar_url gon.current_user_avatar_url = current_user.avatar_url
gon.first_day_of_week = current_user.first_day_of_week if current_user.first_day_of_week
end end
end end
......
...@@ -2507,6 +2507,9 @@ msgstr "" ...@@ -2507,6 +2507,9 @@ msgstr ""
msgid "Default Branch" msgid "Default Branch"
msgstr "" msgstr ""
msgid "Default first day of the week"
msgstr ""
msgid "Default: Directly import the Google Code email address or username" msgid "Default: Directly import the Google Code email address or username"
msgstr "" msgstr ""
...@@ -4297,6 +4300,9 @@ msgstr "" ...@@ -4297,6 +4300,9 @@ msgstr ""
msgid "Loading…" msgid "Loading…"
msgstr "" msgstr ""
msgid "Localization"
msgstr ""
msgid "Lock" msgid "Lock"
msgstr "" msgstr ""
...@@ -4615,6 +4621,9 @@ msgstr "" ...@@ -4615,6 +4621,9 @@ msgstr ""
msgid "Modal|Close" msgid "Modal|Close"
msgstr "" msgstr ""
msgid "Monday"
msgstr ""
msgid "Monitor your errors by integrating with Sentry" msgid "Monitor your errors by integrating with Sentry"
msgstr "" msgstr ""
...@@ -6926,6 +6935,9 @@ msgstr "" ...@@ -6926,6 +6935,9 @@ msgstr ""
msgid "Suggested change" msgid "Suggested change"
msgstr "" msgstr ""
msgid "Sunday"
msgstr ""
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it." msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr "" msgstr ""
...@@ -7977,6 +7989,9 @@ msgstr "" ...@@ -7977,6 +7989,9 @@ msgstr ""
msgid "Various email settings." msgid "Various email settings."
msgstr "" msgstr ""
msgid "Various localization settings."
msgstr ""
msgid "Various settings that affect GitLab performance." msgid "Various settings that affect GitLab performance."
msgstr "" msgstr ""
......
...@@ -42,7 +42,8 @@ describe Profiles::PreferencesController do ...@@ -42,7 +42,8 @@ describe Profiles::PreferencesController do
prefs = { prefs = {
color_scheme_id: '1', color_scheme_id: '1',
dashboard: 'stars', dashboard: 'stars',
theme_id: '2' theme_id: '2',
first_day_of_week: '1'
}.with_indifferent_access }.with_indifferent_access
expect(user).to receive(:assign_attributes).with(ActionController::Parameters.new(prefs).permit!) expect(user).to receive(:assign_attributes).with(ActionController::Parameters.new(prefs).permit!)
......
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