Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
6141fc14
Commit
6141fc14
authored
3 years ago
by
Lukas 'Eipi' Eipert
Committed by
Ezekiel Kigbo
3 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Enable user setting for absolute dates
parent
cd7057b8
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
180 additions
and
79 deletions
+180
-79
app/assets/javascripts/lib/utils/datetime/timeago_utility.js
app/assets/javascripts/lib/utils/datetime/timeago_utility.js
+24
-5
app/views/profiles/preferences/show.html.haml
app/views/profiles/preferences/show.html.haml
+22
-24
doc/user/profile/preferences.md
doc/user/profile/preferences.md
+24
-0
lib/gitlab/gon_helper.rb
lib/gitlab/gon_helper.rb
+2
-0
locale/gitlab.pot
locale/gitlab.pot
+4
-10
spec/frontend/lib/utils/datetime/timeago_utility_spec.js
spec/frontend/lib/utils/datetime/timeago_utility_spec.js
+104
-0
spec/frontend/lib/utils/datetime_utility_spec.js
spec/frontend/lib/utils/datetime_utility_spec.js
+0
-40
No files found.
app/assets/javascripts/lib/utils/datetime/timeago_utility.js
View file @
6141fc14
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
*
as
timeago
from
'
timeago.js
'
;
import
*
as
timeago
from
'
timeago.js
'
;
import
{
languageCode
,
s__
}
from
'
../../../locale
'
;
import
{
languageCode
,
s__
,
createDateTimeFormat
}
from
'
../../../locale
'
;
import
{
formatDate
}
from
'
./date_format_utility
'
;
import
{
formatDate
}
from
'
./date_format_utility
'
;
window
.
timeago
=
timeago
;
/**
/**
* Timeago uses underscores instead of dashes to separate language from country code.
* Timeago uses underscores instead of dashes to separate language from country code.
*
*
...
@@ -76,7 +74,26 @@ const memoizedLocale = () => {
...
@@ -76,7 +74,26 @@ const memoizedLocale = () => {
timeago
.
register
(
timeagoLanguageCode
,
memoizedLocale
());
timeago
.
register
(
timeagoLanguageCode
,
memoizedLocale
());
timeago
.
register
(
`
${
timeagoLanguageCode
}
-remaining`
,
memoizedLocaleRemaining
());
timeago
.
register
(
`
${
timeagoLanguageCode
}
-remaining`
,
memoizedLocaleRemaining
());
export
const
getTimeago
=
()
=>
timeago
;
let
memoizedFormatter
=
null
;
function
setupAbsoluteFormatter
()
{
if
(
memoizedFormatter
===
null
)
{
const
formatter
=
createDateTimeFormat
({
dateStyle
:
'
medium
'
,
timeStyle
:
'
short
'
,
});
memoizedFormatter
=
{
format
(
date
)
{
return
formatter
.
format
(
date
instanceof
Date
?
date
:
new
Date
(
date
));
},
};
}
return
memoizedFormatter
;
}
export
const
getTimeago
=
()
=>
window
.
gon
?.
time_display_relative
===
false
?
setupAbsoluteFormatter
()
:
timeago
;
/**
/**
* For the given elements, sets a tooltip with a formatted date.
* For the given elements, sets a tooltip with a formatted date.
...
@@ -84,8 +101,9 @@ export const getTimeago = () => timeago;
...
@@ -84,8 +101,9 @@ export const getTimeago = () => timeago;
* @param {Boolean} setTimeago
* @param {Boolean} setTimeago
*/
*/
export
const
localTimeAgo
=
(
$timeagoEls
,
setTimeago
=
true
)
=>
{
export
const
localTimeAgo
=
(
$timeagoEls
,
setTimeago
=
true
)
=>
{
const
{
format
}
=
getTimeago
();
$timeagoEls
.
each
((
i
,
el
)
=>
{
$timeagoEls
.
each
((
i
,
el
)
=>
{
$
(
el
).
text
(
timeago
.
format
(
$
(
el
).
attr
(
'
datetime
'
),
timeagoLanguageCode
));
$
(
el
).
text
(
format
(
$
(
el
).
attr
(
'
datetime
'
),
timeagoLanguageCode
));
});
});
if
(
!
setTimeago
)
{
if
(
!
setTimeago
)
{
...
@@ -117,6 +135,7 @@ export const timeFor = (time, expiredLabel) => {
...
@@ -117,6 +135,7 @@ export const timeFor = (time, expiredLabel) => {
return
timeago
.
format
(
time
,
`
${
timeagoLanguageCode
}
-remaining`
).
trim
();
return
timeago
.
format
(
time
,
`
${
timeagoLanguageCode
}
-remaining`
).
trim
();
};
};
window
.
timeago
=
getTimeago
();
window
.
gl
=
window
.
gl
||
{};
window
.
gl
=
window
.
gl
||
{};
window
.
gl
.
utils
=
{
window
.
gl
.
utils
=
{
...(
window
.
gl
.
utils
||
{}),
...(
window
.
gl
.
utils
||
{}),
...
...
This diff is collapsed.
Click to expand it.
app/views/profiles/preferences/show.html.haml
View file @
6141fc14
...
@@ -128,29 +128,27 @@
...
@@ -128,29 +128,27 @@
=
f
.
label
:first_day_of_week
,
class:
'label-bold'
do
=
f
.
label
:first_day_of_week
,
class:
'label-bold'
do
=
_
(
'First day of the week'
)
=
_
(
'First day of the week'
)
=
f
.
select
:first_day_of_week
,
first_day_of_week_choices_with_default
,
{},
class:
'select2'
=
f
.
select
:first_day_of_week
,
first_day_of_week_choices_with_default
,
{},
class:
'select2'
-
if
Feature
.
enabled?
(
:user_time_settings
)
.col-sm-12
.col-sm-12
%hr
%hr
.col-lg-4.profile-settings-sidebar
.row.js-preferences-form.js-search-settings-section
%h4
.gl-mt-0
=
s_
(
'Preferences|Time preferences'
)
.col-lg-4.profile-settings-sidebar
#time-preferences
%p
=
s_
(
'Preferences|These settings will update how dates and times are displayed for you.'
)
%h4
.gl-mt-0
=
s_
(
'Preferences|Time preferences'
)
%p
=
s_
(
'Preferences|Configure how dates and times display for you.'
)
=
succeed
'.'
do
=
link_to
_
(
'Learn more'
),
help_page_path
(
'user/profile/preferences'
,
anchor:
'time-preferences'
),
target:
'_blank'
.col-lg-8
.col-lg-8
.form-group
.form-group.form-check
%h5
=
s_
(
'Preferences|Time format'
)
=
f
.
check_box
:time_display_relative
,
class:
'form-check-input'
.checkbox-icon-inline-wrapper
=
f
.
label
:time_display_relative
,
class:
'form-check-label'
do
-
time_format_label
=
capture
do
=
s_
(
'Preferences|Display time in 24-hour format'
)
=
f
.
check_box
:time_format_in_24h
=
f
.
label
:time_format_in_24h
do
=
time_format_label
%h5
=
s_
(
'Preferences|Time display'
)
.checkbox-icon-inline-wrapper
-
time_display_label
=
capture
do
=
s_
(
'Preferences|Use relative times'
)
=
s_
(
'Preferences|Use relative times'
)
=
f
.
check_box
:time_display_relative
=
f
.
label
:time_display_relative
do
=
time_display_label
.form-text.text-muted
.form-text.text-muted
=
s_
(
'Preferences|For example: 30 mins ago.'
)
=
s_
(
'Preferences|For example: 30 minutes ago.'
)
-
if
Feature
.
enabled?
(
:user_time_settings
)
.form-group.form-check
=
f
.
check_box
:time_format_in_24h
,
class:
'form-check-input'
=
f
.
label
:time_format_in_24h
,
class:
'form-check-label'
do
=
s_
(
'Preferences|Display time in 24-hour format'
)
#js-profile-preferences-app
{
data:
data_attributes
}
#js-profile-preferences-app
{
data:
data_attributes
}
This diff is collapsed.
Click to expand it.
doc/user/profile/preferences.md
View file @
6141fc14
...
@@ -165,6 +165,30 @@ You can choose one of the following options as the first day of the week:
...
@@ -165,6 +165,30 @@ You can choose one of the following options as the first day of the week:
If you select
**System Default**
, the
[
instance default
](
../admin_area/settings/index.md#default-first-day-of-the-week
)
setting is used.
If you select
**System Default**
, the
[
instance default
](
../admin_area/settings/index.md#default-first-day-of-the-week
)
setting is used.
## Time preferences
### Use relative times
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65570) in GitLab 14.1.
You can select your preferred time format for the GitLab user interface:
-
Relative times, for example,
`30 minutes ago`
.
-
Absolute times, for example,
`May 18, 2021, 3:57 PM`
.
The times are formatted depending on your chosen language.
To set your time preference:
1.
On the
**Preferences**
page, go to
**Time preferences**
.
1.
Select the
**Use relative times**
checkbox to use relative times,
or clear the checkbox to use absolute times.
1.
Select
**Save changes**
.
NOTE:
This feature is experimental, and choosing absolute times might break certain layouts.
Please open an issue if you notice that using absolute times breaks a layout.
## Integrations
## Integrations
Configure your preferences with third-party services which provide enhancements to your GitLab experience.
Configure your preferences with third-party services which provide enhancements to your GitLab experience.
...
...
This diff is collapsed.
Click to expand it.
lib/gitlab/gon_helper.rb
View file @
6141fc14
...
@@ -33,6 +33,7 @@ module Gitlab
...
@@ -33,6 +33,7 @@ module Gitlab
gon
.
disable_animations
=
Gitlab
.
config
.
gitlab
[
'disable_animations'
]
gon
.
disable_animations
=
Gitlab
.
config
.
gitlab
[
'disable_animations'
]
gon
.
suggested_label_colors
=
LabelsHelper
.
suggested_colors
gon
.
suggested_label_colors
=
LabelsHelper
.
suggested_colors
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
.
time_display_relative
=
true
gon
.
ee
=
Gitlab
.
ee?
gon
.
ee
=
Gitlab
.
ee?
gon
.
dot_com
=
Gitlab
.
com?
gon
.
dot_com
=
Gitlab
.
com?
...
@@ -41,6 +42,7 @@ module Gitlab
...
@@ -41,6 +42,7 @@ module Gitlab
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
.
time_display_relative
=
current_user
.
time_display_relative
end
end
# Initialize gon.features with any flags that should be
# Initialize gon.features with any flags that should be
...
...
This diff is collapsed.
Click to expand it.
locale/gitlab.pot
View file @
6141fc14
...
@@ -24655,6 +24655,9 @@ msgstr ""
...
@@ -24655,6 +24655,9 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on your homepage."
msgid "Preferences|Choose what content you want to see on your homepage."
msgstr ""
msgstr ""
msgid "Preferences|Configure how dates and times display for you."
msgstr ""
msgid "Preferences|Customize integrations with third party services."
msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgstr ""
...
@@ -24673,7 +24676,7 @@ msgstr ""
...
@@ -24673,7 +24676,7 @@ msgstr ""
msgid "Preferences|Failed to save preferences."
msgid "Preferences|Failed to save preferences."
msgstr ""
msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgid "Preferences|For example: 30 min
ute
s ago."
msgstr ""
msgstr ""
msgid "Preferences|Gitpod"
msgid "Preferences|Gitpod"
...
@@ -24721,9 +24724,6 @@ msgstr ""
...
@@ -24721,9 +24724,6 @@ msgstr ""
msgid "Preferences|Tab width"
msgid "Preferences|Tab width"
msgstr ""
msgstr ""
msgid "Preferences|These settings will update how dates and times are displayed for you."
msgstr ""
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
msgstr ""
...
@@ -24733,12 +24733,6 @@ msgstr ""
...
@@ -24733,12 +24733,6 @@ msgstr ""
msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
msgstr ""
msgstr ""
msgid "Preferences|Time display"
msgstr ""
msgid "Preferences|Time format"
msgstr ""
msgid "Preferences|Time preferences"
msgid "Preferences|Time preferences"
msgstr ""
msgstr ""
...
...
This diff is collapsed.
Click to expand it.
spec/frontend/lib/utils/datetime/timeago_utility_spec.js
0 → 100644
View file @
6141fc14
import
$
from
'
jquery
'
;
import
{
getTimeago
,
localTimeAgo
,
timeFor
}
from
'
~/lib/utils/datetime/timeago_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
import
'
~/commons/bootstrap
'
;
describe
(
'
TimeAgo utils
'
,
()
=>
{
let
oldGon
;
afterEach
(()
=>
{
window
.
gon
=
oldGon
;
});
beforeEach
(()
=>
{
oldGon
=
window
.
gon
;
});
describe
(
'
getTimeago
'
,
()
=>
{
describe
(
'
with User Setting timeDisplayRelative: true
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
{
time_display_relative
:
true
};
});
it
.
each
([
[
new
Date
().
toISOString
(),
'
just now
'
],
[
new
Date
().
getTime
(),
'
just now
'
],
[
new
Date
(),
'
just now
'
],
[
null
,
'
just now
'
],
])(
'
formats date `%p` as `%p`
'
,
(
date
,
result
)
=>
{
expect
(
getTimeago
().
format
(
date
)).
toEqual
(
result
);
});
});
describe
(
'
with User Setting timeDisplayRelative: false
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
{
time_display_relative
:
false
};
});
it
.
each
([
[
new
Date
().
toISOString
(),
'
Jul 6, 2020, 12:00 AM
'
],
[
new
Date
(),
'
Jul 6, 2020, 12:00 AM
'
],
[
new
Date
().
getTime
(),
'
Jul 6, 2020, 12:00 AM
'
],
// Slightly different behaviour when `null` is passed :see_no_evil`
[
null
,
'
Jan 1, 1970, 12:00 AM
'
],
])(
'
formats date `%p` as `%p`
'
,
(
date
,
result
)
=>
{
expect
(
getTimeago
().
format
(
date
)).
toEqual
(
result
);
});
});
});
describe
(
'
timeFor
'
,
()
=>
{
it
(
'
returns localize `past due` when in past
'
,
()
=>
{
const
date
=
new
Date
();
date
.
setFullYear
(
date
.
getFullYear
()
-
1
);
expect
(
timeFor
(
date
)).
toBe
(
s__
(
'
Timeago|Past due
'
));
});
it
(
'
returns localized remaining time when in the future
'
,
()
=>
{
const
date
=
new
Date
();
date
.
setFullYear
(
date
.
getFullYear
()
+
1
);
// Add a day to prevent a transient error. If date is even 1 second
// short of a full year, timeFor will return '11 months remaining'
date
.
setDate
(
date
.
getDate
()
+
1
);
expect
(
timeFor
(
date
)).
toBe
(
s__
(
'
Timeago|1 year remaining
'
));
});
});
describe
(
'
localTimeAgo
'
,
()
=>
{
beforeEach
(()
=>
{
document
.
body
.
innerHTML
=
'
<time title="some time" datetime="2020-02-18T22:22:32Z">1 hour ago</time>
'
;
});
describe
.
each
`
timeDisplayRelative | text
${
true
}
|
${
'
4 months ago
'
}
${
false
}
|
${
'
Feb 18, 2020, 10:22 PM
'
}
`
(
`With User Setting timeDisplayRelative: $timeDisplayRelative`
,
({
timeDisplayRelative
,
text
})
=>
{
it
.
each
`
timeagoArg | title
${
false
}
|
${
'
some time
'
}
${
true
}
|
${
'
Feb 18, 2020 10:22pm UTC
'
}
`
(
`has content: '
${
text
}
' and tooltip: '$title' with timeagoArg = $timeagoArg`
,
({
timeagoArg
,
title
})
=>
{
window
.
gon
=
{
time_display_relative
:
timeDisplayRelative
};
const
element
=
document
.
querySelector
(
'
time
'
);
localTimeAgo
(
$
(
element
),
timeagoArg
);
jest
.
runAllTimers
();
expect
(
element
.
getAttribute
(
'
title
'
)).
toBe
(
title
);
expect
(
element
.
innerText
).
toBe
(
text
);
},
);
},
);
});
});
This diff is collapsed.
Click to expand it.
spec/frontend/lib/utils/datetime_utility_spec.js
View file @
6141fc14
import
$
from
'
jquery
'
;
import
timezoneMock
from
'
timezone-mock
'
;
import
timezoneMock
from
'
timezone-mock
'
;
import
*
as
datetimeUtility
from
'
~/lib/utils/datetime_utility
'
;
import
*
as
datetimeUtility
from
'
~/lib/utils/datetime_utility
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
import
'
~/commons/bootstrap
'
;
import
'
~/commons/bootstrap
'
;
describe
(
'
Date time utils
'
,
()
=>
{
describe
(
'
Date time utils
'
,
()
=>
{
describe
(
'
timeFor
'
,
()
=>
{
it
(
'
returns localize `past due` when in past
'
,
()
=>
{
const
date
=
new
Date
();
date
.
setFullYear
(
date
.
getFullYear
()
-
1
);
expect
(
datetimeUtility
.
timeFor
(
date
)).
toBe
(
s__
(
'
Timeago|Past due
'
));
});
it
(
'
returns localized remaining time when in the future
'
,
()
=>
{
const
date
=
new
Date
();
date
.
setFullYear
(
date
.
getFullYear
()
+
1
);
// Add a day to prevent a transient error. If date is even 1 second
// short of a full year, timeFor will return '11 months remaining'
date
.
setDate
(
date
.
getDate
()
+
1
);
expect
(
datetimeUtility
.
timeFor
(
date
)).
toBe
(
s__
(
'
Timeago|1 year remaining
'
));
});
});
describe
(
'
get localized day name
'
,
()
=>
{
describe
(
'
get localized day name
'
,
()
=>
{
it
(
'
should return Sunday
'
,
()
=>
{
it
(
'
should return Sunday
'
,
()
=>
{
const
day
=
datetimeUtility
.
getDayName
(
new
Date
(
'
07/17/2016
'
));
const
day
=
datetimeUtility
.
getDayName
(
new
Date
(
'
07/17/2016
'
));
...
@@ -870,25 +849,6 @@ describe('approximateDuration', () => {
...
@@ -870,25 +849,6 @@ describe('approximateDuration', () => {
});
});
});
});
describe
(
'
localTimeAgo
'
,
()
=>
{
beforeEach
(()
=>
{
document
.
body
.
innerHTML
=
`<time title="some time" datetime="2020-02-18T22:22:32Z">1 hour ago</time>`
;
});
it
.
each
`
timeagoArg | title
${
false
}
|
${
'
some time
'
}
${
true
}
|
${
'
Feb 18, 2020 10:22pm UTC
'
}
`
(
'
converts $seconds seconds to $approximation
'
,
({
timeagoArg
,
title
})
=>
{
const
element
=
document
.
querySelector
(
'
time
'
);
datetimeUtility
.
localTimeAgo
(
$
(
element
),
timeagoArg
);
jest
.
runAllTimers
();
expect
(
element
.
getAttribute
(
'
title
'
)).
toBe
(
title
);
});
});
describe
(
'
differenceInSeconds
'
,
()
=>
{
describe
(
'
differenceInSeconds
'
,
()
=>
{
const
startDateTime
=
new
Date
(
'
2019-07-17T00:00:00.000Z
'
);
const
startDateTime
=
new
Date
(
'
2019-07-17T00:00:00.000Z
'
);
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment