Skip to content

Commit 36cb243

Browse files
committed
Timezones: Updated date displays to use consistent formats
1 parent 579c1bf commit 36cb243

20 files changed

+100
-84
lines changed

app/Entities/Tools/PageEditActivity.php

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,15 @@
44

55
use BookStack\Entities\Models\Page;
66
use BookStack\Entities\Models\PageRevision;
7+
use BookStack\Util\DateFormatter;
78
use Carbon\Carbon;
89
use Illuminate\Database\Eloquent\Builder;
910

1011
class PageEditActivity
1112
{
12-
protected Page $page;
13-
14-
/**
15-
* PageEditActivity constructor.
16-
*/
17-
public function __construct(Page $page)
18-
{
19-
$this->page = $page;
13+
public function __construct(
14+
protected Page $page
15+
) {
2016
}
2117

2218
/**
@@ -50,11 +46,9 @@ public function activeEditingMessage(): string
5046
/**
5147
* Get any editor clash warning messages to show for the given draft revision.
5248
*
53-
* @param PageRevision|Page $draft
54-
*
5549
* @return string[]
5650
*/
57-
public function getWarningMessagesForDraft($draft): array
51+
public function getWarningMessagesForDraft(Page|PageRevision $draft): array
5852
{
5953
$warnings = [];
6054

@@ -82,7 +76,8 @@ protected function hasPageBeenUpdatedSinceDraftCreated(PageRevision $draft): boo
8276
*/
8377
public function getEditingActiveDraftMessage(PageRevision $draft): string
8478
{
85-
$message = trans('entities.pages_editing_draft_notification', ['timeDiff' => $draft->updated_at->diffForHumans()]);
79+
$formatter = resolve(DateFormatter::class);
80+
$message = trans('entities.pages_editing_draft_notification', ['timeDiff' => $formatter->relative($draft->updated_at)]);
8681
if ($draft->page->updated_at->timestamp <= $draft->updated_at->timestamp) {
8782
return $message;
8883
}

app/Util/DateFormatter.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace BookStack\Util;
44

55
use Carbon\Carbon;
6+
use Carbon\CarbonInterface;
67

78
class DateFormatter
89
{
@@ -11,15 +12,15 @@ public function __construct(
1112
) {
1213
}
1314

14-
public function isoWithTimezone(Carbon $date): string
15+
public function absolute(Carbon $date): string
1516
{
1617
$withDisplayTimezone = $date->clone()->setTimezone($this->displayTimezone);
1718

1819
return $withDisplayTimezone->format('Y-m-d H:i:s T');
1920
}
2021

21-
public function relative(Carbon $date): string
22+
public function relative(Carbon $date, bool $includeSuffix = true): string
2223
{
23-
return $date->diffForHumans();
24+
return $date->diffForHumans(null, $includeSuffix ? null : CarbonInterface::DIFF_ABSOLUTE);
2425
}
2526
}

phpunit.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<server name="APP_THEME" value="none"/>
1717
<server name="APP_AUTO_LANG_PUBLIC" value="true"/>
1818
<server name="APP_URL" value="http://bookstack.dev"/>
19+
<server name="APP_TIMEZONE" value="UTC"/>
20+
<server name="APP_DISPLAY_TIMEZONE" value="UTC"/>
1921
<server name="ALLOWED_IFRAME_HOSTS" value=""/>
2022
<server name="ALLOWED_IFRAME_SOURCES" value="https://*.draw.io https://*.youtube.com https://*.youtube-nocookie.com https://*.vimeo.com"/>
2123
<server name="ALLOWED_SSR_HOSTS" value="*"/>

resources/views/comments/comment.blade.php

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class="comment-box">
1414
<div class="flex-container-row wrap items-center gap-x-xs">
1515
@if ($comment->createdBy)
1616
<div>
17-
<img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar block mr-xs" alt="{{ $comment->createdBy->name }}">
17+
<img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar block mr-xs"
18+
alt="{{ $comment->createdBy->name }}">
1819
</div>
1920
@endif
2021
<div class="meta text-muted flex-container-row wrap items-center flex text-small">
@@ -23,50 +24,55 @@ class="comment-box">
2324
@else
2425
{{ trans('common.deleted_user') }}
2526
@endif
26-
<span title="{{ $comment->created_at }}">&nbsp;{{ trans('entities.comment_created', ['createDiff' => $comment->created_at->diffForHumans() ]) }}</span>
27+
<span title="{{ $dates->absolute($comment->created_at) }}">&nbsp;{{ trans('entities.comment_created', ['createDiff' => $dates->relative($comment->created_at) ]) }}</span>
2728
@if($comment->isUpdated())
2829
<span class="mx-xs">&bull;</span>
29-
<span title="{{ trans('entities.comment_updated', ['updateDiff' => $comment->updated_at, 'username' => $comment->updatedBy->name ?? trans('common.deleted_user')]) }}">
30+
<span title="{{ trans('entities.comment_updated', ['updateDiff' => $dates->absolute($comment->updated_at), 'username' => $comment->updatedBy->name ?? trans('common.deleted_user')]) }}">
3031
{{ trans('entities.comment_updated_indicator') }}
3132
</span>
3233
@endif
3334
</div>
3435
<div class="right-meta flex-container-row justify-flex-end items-center px-s">
3536
@if(!$readOnly && (userCan('comment-create-all') || userCan('comment-update', $comment) || userCan('comment-delete', $comment)))
36-
<div class="actions mr-s">
37-
@if(userCan('comment-create-all'))
38-
<button refs="page-comment@reply-button" type="button" class="text-button text-muted hover-underline text-small p-xs">@icon('reply') {{ trans('common.reply') }}</button>
39-
@endif
40-
@if(!$comment->parent_id && (userCan('comment-update', $comment) || userCan('comment-delete', $comment)))
41-
<button refs="page-comment@archive-button"
42-
type="button"
43-
data-is-archived="{{ $comment->archived ? 'true' : 'false' }}"
44-
class="text-button text-muted hover-underline text-small p-xs">@icon('archive') {{ trans('common.' . ($comment->archived ? 'unarchive' : 'archive')) }}</button>
45-
@endif
46-
@if(userCan('comment-update', $comment))
47-
<button refs="page-comment@edit-button" type="button" class="text-button text-muted hover-underline text-small p-xs">@icon('edit') {{ trans('common.edit') }}</button>
48-
@endif
49-
@if(userCan('comment-delete', $comment))
50-
<div component="dropdown" class="dropdown-container">
51-
<button type="button" refs="dropdown@toggle" aria-haspopup="true" aria-expanded="false" class="text-button text-muted hover-underline text-small p-xs">@icon('delete') {{ trans('common.delete') }}</button>
52-
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
53-
<li class="px-m text-small text-muted pb-s">{{trans('entities.comment_delete_confirm')}}</li>
54-
<li>
55-
<button refs="page-comment@delete-button" type="button" class="text-button text-neg icon-item">
56-
@icon('delete')
57-
<div>{{ trans('common.delete') }}</div>
58-
</button>
59-
</li>
60-
</ul>
61-
</div>
62-
@endif
63-
<span class="text-muted">
37+
<div class="actions mr-s">
38+
@if(userCan('comment-create-all'))
39+
<button refs="page-comment@reply-button" type="button"
40+
class="text-button text-muted hover-underline text-small p-xs">@icon('reply') {{ trans('common.reply') }}</button>
41+
@endif
42+
@if(!$comment->parent_id && (userCan('comment-update', $comment) || userCan('comment-delete', $comment)))
43+
<button refs="page-comment@archive-button"
44+
type="button"
45+
data-is-archived="{{ $comment->archived ? 'true' : 'false' }}"
46+
class="text-button text-muted hover-underline text-small p-xs">@icon('archive') {{ trans('common.' . ($comment->archived ? 'unarchive' : 'archive')) }}</button>
47+
@endif
48+
@if(userCan('comment-update', $comment))
49+
<button refs="page-comment@edit-button" type="button"
50+
class="text-button text-muted hover-underline text-small p-xs">@icon('edit') {{ trans('common.edit') }}</button>
51+
@endif
52+
@if(userCan('comment-delete', $comment))
53+
<div component="dropdown" class="dropdown-container">
54+
<button type="button" refs="dropdown@toggle" aria-haspopup="true" aria-expanded="false"
55+
class="text-button text-muted hover-underline text-small p-xs">@icon('delete') {{ trans('common.delete') }}</button>
56+
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
57+
<li class="px-m text-small text-muted pb-s">{{trans('entities.comment_delete_confirm')}}</li>
58+
<li>
59+
<button refs="page-comment@delete-button" type="button"
60+
class="text-button text-neg icon-item">
61+
@icon('delete')
62+
<div>{{ trans('common.delete') }}</div>
63+
</button>
64+
</li>
65+
</ul>
66+
</div>
67+
@endif
68+
<span class="text-muted">
6469
&nbsp;&bull;&nbsp;
6570
</span>
66-
</div>
71+
</div>
6772
@endif
6873
<div>
69-
<a class="bold text-muted text-small" href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
74+
<a class="bold text-muted text-small"
75+
href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
7076
</div>
7177
</div>
7278
</div>
@@ -76,7 +82,8 @@ class="text-button text-muted hover-underline text-small p-xs">@icon('archive')
7682
<div refs="page-comment@content-container" class="content">
7783
@if ($comment->parent_id)
7884
<p class="comment-reply">
79-
<a class="text-muted text-small" href="#comment{{ $comment->parent_id }}">@icon('reply'){{ trans('entities.comment_in_reply_to', ['commentId' => '#' . $comment->parent_id]) }}</a>
85+
<a class="text-muted text-small"
86+
href="#comment{{ $comment->parent_id }}">@icon('reply'){{ trans('entities.comment_in_reply_to', ['commentId' => '#' . $comment->parent_id]) }}</a>
8087
</p>
8188
@endif
8289
@if($comment->content_ref)
@@ -86,7 +93,8 @@ class="text-button text-muted hover-underline text-small p-xs">@icon('archive')
8693
option:page-comment-reference:view-comment-text="{{ trans('entities.comment_view') }}"
8794
option:page-comment-reference:jump-to-thread-text="{{ trans('entities.comment_jump_to_thread') }}"
8895
option:page-comment-reference:close-text="{{ trans('common.close') }}"
89-
href="#">@icon('bookmark'){{ trans('entities.comment_reference') }} <span>{{ trans('entities.comment_reference_outdated') }}</span></a>
96+
href="#">@icon('bookmark'){{ trans('entities.comment_reference') }}
97+
<span>{{ trans('entities.comment_reference_outdated') }}</span></a>
9098
</div>
9199
@endif
92100
{!! $commentHtml !!}
@@ -95,10 +103,12 @@ class="text-button text-muted hover-underline text-small p-xs">@icon('archive')
95103
@if(!$readOnly && userCan('comment-update', $comment))
96104
<form novalidate refs="page-comment@form" hidden class="content pt-s px-s block">
97105
<div class="form-group description-input">
98-
<textarea refs="page-comment@input" name="html" rows="3" placeholder="{{ trans('entities.comment_placeholder') }}">{{ $commentHtml }}</textarea>
106+
<textarea refs="page-comment@input" name="html" rows="3"
107+
placeholder="{{ trans('entities.comment_placeholder') }}">{{ $commentHtml }}</textarea>
99108
</div>
100109
<div class="form-group text-right">
101-
<button type="button" class="button outline" refs="page-comment@form-cancel">{{ trans('common.cancel') }}</button>
110+
<button type="button" class="button outline"
111+
refs="page-comment@form-cancel">{{ trans('common.cancel') }}</button>
102112
<button type="submit" class="button">{{ trans('entities.comment_save') }}</button>
103113
</div>
104114
</form>

resources/views/common/activity-item.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@
2626

2727
<br>
2828

29-
<span class="text-muted"><small>@icon('time'){{ $activity->created_at->diffForHumans() }}</small></span>
29+
<span class="text-muted" title="{{ $dates->absolute($activity->created_at) }}"><small>@icon('time'){{ $dates->relative($activity->created_at) }}</small></span>
3030
</div>

resources/views/entities/grid-item.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<p class="text-muted">{{ $entity->getExcerpt(130) }}</p>
1111
</div>
1212
<div class="grid-card-footer text-muted ">
13-
<p>@icon('star')<span title="{{ $entity->created_at->toDayDateTimeString() }}">{{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}</span></p>
14-
<p>@icon('edit')<span title="{{ $entity->updated_at->toDayDateTimeString() }}">{{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}</span></p>
13+
<p>@icon('star')<span title="{{ $dates->absolute($entity->created_at) }}">{{ trans('entities.meta_created', ['timeLength' => $dates->relative($entity->created_at)]) }}</span></p>
14+
<p>@icon('edit')<span title="{{ $dates->absolute($entity->updated_at) }}">{{ trans('entities.meta_updated', ['timeLength' => $dates->relative($entity->updated_at)]) }}</span></p>
1515
</div>
1616
</a>

resources/views/entities/list-item.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
@endif
2828

2929
@if(($showUpdatedBy ?? false) && $entity->relationLoaded('updatedBy') && $entity->updatedBy)
30-
<small title="{{ $entity->updated_at->toDayDateTimeString() }}">
30+
<small title="{{ $dates->absolute($entity->updated_at) }}">
3131
{!! trans('entities.meta_updated_name', [
32-
'timeLength' => $entity->updated_at->diffForHumans(),
32+
'timeLength' => $dates->relative($entity->updated_at),
3333
'user' => e($entity->updatedBy->name)
3434
]) !!}
3535
</small>

resources/views/entities/meta.blade.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
@icon('star')
3232
<div>
3333
{!! trans('entities.meta_created_name', [
34-
'timeLength' => '<span title="'. $dates->isoWithTimezone($entity->created_at) .'">'. $dates->relative($entity->created_at) . '</span>',
34+
'timeLength' => '<span title="'. $dates->absolute($entity->created_at) .'">'. $dates->relative($entity->created_at) . '</span>',
3535
'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".e($entity->createdBy->name). "</a>"
3636
]) !!}
3737
</div>
3838
</div>
3939
@else
4040
<div class="entity-meta-item">
4141
@icon('star')
42-
<span title="{{ $dates->isoWithTimezone($entity->created_at) }}">{{ trans('entities.meta_created', ['timeLength' => $dates->relative($entity->created_at)]) }}</span>
42+
<span title="{{ $dates->absolute($entity->created_at) }}">{{ trans('entities.meta_created', ['timeLength' => $dates->relative($entity->created_at)]) }}</span>
4343
</div>
4444
@endif
4545

@@ -48,15 +48,15 @@
4848
@icon('edit')
4949
<div>
5050
{!! trans('entities.meta_updated_name', [
51-
'timeLength' => '<span title="' . $dates->isoWithTimezone($entity->updated_at) .'">' . $dates->relative($entity->updated_at) .'</span>',
51+
'timeLength' => '<span title="' . $dates->absolute($entity->updated_at) .'">' . $dates->relative($entity->updated_at) .'</span>',
5252
'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".e($entity->updatedBy->name). "</a>"
5353
]) !!}
5454
</div>
5555
</div>
5656
@elseif (!$entity->isA('revision'))
5757
<div class="entity-meta-item">
5858
@icon('edit')
59-
<span title="{{ $dates->isoWithTimezone($entity->updated_at) }}">{{ trans('entities.meta_updated', ['timeLength' => $dates->relative($entity->updated_at)]) }}</span>
59+
<span title="{{ $dates->absolute($entity->updated_at) }}">{{ trans('entities.meta_updated', ['timeLength' => $dates->relative($entity->updated_at)]) }}</span>
6060
</div>
6161
@endif
6262

resources/views/exports/import-show.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</div>
2727
<div class="text-right text-muted">
2828
<div>{{ trans('entities.import_size', ['size' => $import->getSizeString()]) }}</div>
29-
<div><span title="{{ $import->created_at->toISOString() }}">{{ trans('entities.import_uploaded_at', ['relativeTime' => $import->created_at->diffForHumans()]) }}</span></div>
29+
<div><span title="{{ $dates->absolute($import->created_at) }}">{{ trans('entities.import_uploaded_at', ['relativeTime' => $dates->relative($import->created_at)]) }}</span></div>
3030
@if($import->createdBy)
3131
<div>
3232
{{ trans('entities.import_uploaded_by') }}

resources/views/exports/parts/import.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ class="text-{{ $import->type }}">@icon($import->type) {{ $import->name }}</a>
55
</div>
66
<div class="px-m py-s flex-container-row gap-m items-center">
77
<div class="bold opacity-80 text-muted">{{ $import->getSizeString() }}</div>
8-
<div class="bold opacity-80 text-muted min-width-xs text-right" title="{{ $import->created_at->toISOString() }}">@icon('time'){{ $import->created_at->diffForHumans() }}</div>
8+
<div class="bold opacity-80 text-muted min-width-xs text-right" title="{{ $dates->absolute($import->created_at) }}">@icon('time'){{ $dates->relative($import->created_at) }}</div>
99
</div>
1010
</div>

0 commit comments

Comments
 (0)