Commit 4e283ee7 authored by Jon Kolb's avatar Jon Kolb Committed by Heinrich Lee Yu

Limit time tracking values to hours

Adds an instance setting to limit display of time tracking
values to hours only
parent db9783f7
...@@ -16,10 +16,15 @@ export default { ...@@ -16,10 +16,15 @@ export default {
}, },
computed: { computed: {
title() { title() {
return stringifyTime(parseSeconds(this.estimate), true); return stringifyTime(
parseSeconds(this.estimate, { limitToHours: gon.time_tracking_display_hours_only }),
true
);
}, },
timeEstimate() { timeEstimate() {
return stringifyTime(parseSeconds(this.estimate)); return stringifyTime(
parseSeconds(this.estimate, { limitToHours: gon.time_tracking_display_hours_only })
);
}, },
}, },
}; };
......
...@@ -479,7 +479,10 @@ export const pikadayToString = date => { ...@@ -479,7 +479,10 @@ export const pikadayToString = date => {
* Seconds can be negative or positive, zero or non-zero. Can be configured for any day * Seconds can be negative or positive, zero or non-zero. Can be configured for any day
* or week length. * or week length.
*/ */
export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) => { export const parseSeconds = (
seconds,
{ daysPerWeek = 5, hoursPerDay = 8, limitToHours = false } = {},
) => {
const DAYS_PER_WEEK = daysPerWeek; const DAYS_PER_WEEK = daysPerWeek;
const HOURS_PER_DAY = hoursPerDay; const HOURS_PER_DAY = hoursPerDay;
const MINUTES_PER_HOUR = 60; const MINUTES_PER_HOUR = 60;
...@@ -496,6 +499,10 @@ export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) ...@@ -496,6 +499,10 @@ export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {})
let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR); let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
return _.mapObject(timePeriodConstraints, minutesPerPeriod => { return _.mapObject(timePeriodConstraints, minutesPerPeriod => {
if (limitToHours && minutesPerPeriod > MINUTES_PER_HOUR) {
return 0;
}
const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod); const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
unorderedMinutes -= periodCount * minutesPerPeriod; unorderedMinutes -= periodCount * minutesPerPeriod;
......
...@@ -32,7 +32,7 @@ export default { ...@@ -32,7 +32,7 @@ export default {
computed: { computed: {
parsedTimeRemaining() { parsedTimeRemaining() {
const diffSeconds = this.timeEstimate - this.timeSpent; const diffSeconds = this.timeEstimate - this.timeSpent;
return parseSeconds(diffSeconds); return parseSeconds(diffSeconds, { limitToHours: gon.time_tracking_display_hours_only });
}, },
timeRemainingHumanReadable() { timeRemainingHumanReadable() {
return stringifyTime(this.parsedTimeRemaining); return stringifyTime(this.parsedTimeRemaining);
......
...@@ -253,6 +253,7 @@ module ApplicationSettingsHelper ...@@ -253,6 +253,7 @@ module ApplicationSettingsHelper
:throttle_unauthenticated_enabled, :throttle_unauthenticated_enabled,
:throttle_unauthenticated_period_in_seconds, :throttle_unauthenticated_period_in_seconds,
:throttle_unauthenticated_requests_per_period, :throttle_unauthenticated_requests_per_period,
:time_tracking_display_hours_only,
:two_factor_grace_period, :two_factor_grace_period,
:unique_ips_limit_enabled, :unique_ips_limit_enabled,
:unique_ips_limit_per_user, :unique_ips_limit_per_user,
......
...@@ -82,6 +82,7 @@ module ApplicationSettingImplementation ...@@ -82,6 +82,7 @@ module ApplicationSettingImplementation
throttle_unauthenticated_enabled: false, throttle_unauthenticated_enabled: false,
throttle_unauthenticated_period_in_seconds: 3600, throttle_unauthenticated_period_in_seconds: 3600,
throttle_unauthenticated_requests_per_period: 3600, throttle_unauthenticated_requests_per_period: 3600,
time_tracking_display_hours_only: false,
two_factor_grace_period: 48, two_factor_grace_period: 48,
unique_ips_limit_enabled: false, unique_ips_limit_enabled: false,
unique_ips_limit_per_user: 10, unique_ips_limit_per_user: 10,
......
...@@ -8,4 +8,10 @@ ...@@ -8,4 +8,10 @@
.form-text.text-muted .form-text.text-muted
= _('Default first day of the week in calendars and date pickers.') = _('Default first day of the week in calendars and date pickers.')
.form-group
.form-check
= f.check_box :time_tracking_display_hours_only, class: 'form-check-input'
= f.label :time_tracking_display_hours_only, class: 'form-check-label' do
_('Limit time tracking display to hours.')
= f.submit _('Save changes'), class: "btn btn-success" = f.submit _('Save changes'), class: "btn btn-success"
---
title: Add option to show time tracking values in hours only
merge_request: 29469
author: Jon Kolb
type: added
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddTimeTrackingDisplayHoursOnlyToApplicationSettings < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :application_settings, :time_tracking_display_hours_only, :boolean, default: false, allow_null: false
end
def down
remove_column :application_settings, :time_tracking_display_hours_only
end
end
...@@ -229,6 +229,7 @@ ActiveRecord::Schema.define(version: 20190620112608) do ...@@ -229,6 +229,7 @@ ActiveRecord::Schema.define(version: 20190620112608) do
t.integer "custom_project_templates_group_id" t.integer "custom_project_templates_group_id"
t.boolean "elasticsearch_limit_indexing", default: false, null: false t.boolean "elasticsearch_limit_indexing", default: false, null: false
t.string "geo_node_allowed_ips", default: "0.0.0.0/0, ::/0" t.string "geo_node_allowed_ips", default: "0.0.0.0/0, ::/0"
t.boolean "time_tracking_display_hours_only", default: false, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id", using: :btree t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id", using: :btree
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id", using: :btree t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id", using: :btree
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
......
...@@ -231,6 +231,7 @@ are listed in the descriptions of the relevant settings. ...@@ -231,6 +231,7 @@ are listed in the descriptions of the relevant settings.
| `throttle_unauthenticated_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated request rate limit. Helps reduce request volume (e.g. from crawlers or abusive bots). | | `throttle_unauthenticated_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated request rate limit. Helps reduce request volume (e.g. from crawlers or abusive bots). |
| `throttle_unauthenticated_period_in_seconds` | integer | required by: `throttle_unauthenticated_enabled` | Rate limit period in seconds. | | `throttle_unauthenticated_period_in_seconds` | integer | required by: `throttle_unauthenticated_enabled` | Rate limit period in seconds. |
| `throttle_unauthenticated_requests_per_period` | integer | required by: `throttle_unauthenticated_enabled` | Max requests per period per IP. | | `throttle_unauthenticated_requests_per_period` | integer | required by: `throttle_unauthenticated_enabled` | Max requests per period per IP. |
| `time_tracking_display_hours_only` | boolean | no | Limit time tracking values to hours only. Default is `false`. |
| `two_factor_grace_period` | integer | required by: `require_two_factor_authentication` | Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication. | | `two_factor_grace_period` | integer | required by: `require_two_factor_authentication` | Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication. |
| `unique_ips_limit_enabled` | boolean | no | (**If enabled, requires:** `unique_ips_limit_per_user` and `unique_ips_limit_time_window`) Limit sign in from multiple ips. | | `unique_ips_limit_enabled` | boolean | no | (**If enabled, requires:** `unique_ips_limit_per_user` and `unique_ips_limit_time_window`) Limit sign in from multiple ips. |
| `unique_ips_limit_per_user` | integer | required by: `unique_ips_limit_enabled` | Maximum number of ips per user. | | `unique_ips_limit_per_user` | integer | required by: `unique_ips_limit_enabled` | Maximum number of ips per user. |
......
...@@ -32,6 +32,8 @@ module Gitlab ...@@ -32,6 +32,8 @@ module Gitlab
gon.first_day_of_week = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week gon.first_day_of_week = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week
gon.ee = Gitlab.ee? gon.ee = Gitlab.ee?
gon.time_tracking_display_hours_only = Gitlab::CurrentSettings.time_tracking_display_hours_only
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
......
...@@ -16,7 +16,8 @@ module Gitlab ...@@ -16,7 +16,8 @@ module Gitlab
def output(seconds) def output(seconds)
with_custom_config do with_custom_config do
ChronicDuration.output(seconds, format: :short, limit_to_hours: false, weeks: true) rescue nil limit_to_hours = Gitlab::CurrentSettings.time_tracking_display_hours_only
ChronicDuration.output(seconds, format: :short, limit_to_hours: limit_to_hours, weeks: true) rescue nil
end end
end end
......
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