Add support for per-user 24-hour clock display setting.
This commit is contained in:
parent
d5fb9edf61
commit
f6c363163f
|
@ -10,6 +10,9 @@ release channel, you can take advantage of these new features and fixes.
|
|||
media. Because cover art files are often named a variety of things, we currently will use _any_ image file that exists
|
||||
alongside media. You can also now view cover art via the Media Manager UI.
|
||||
|
||||
- **24-Hour Time Display Support**: You can now choose whether to view time in 12 or 24 hour format from your user
|
||||
profile, or use the default settings for your locale.
|
||||
|
||||
## Code Quality/Technical Changes
|
||||
|
||||
- Because both our Docker and Ansible installations are managed by Supervisor now, we can view the realtime status of
|
||||
|
|
|
@ -80,14 +80,26 @@ return [
|
|||
$localeShort = substr($locale, 0, 2);
|
||||
$localeWithDashes = str_replace('_', '-', $locale);
|
||||
|
||||
// User profile-specific 24-hour display setting.
|
||||
$userObj = $request->getAttribute(ServerRequest::ATTR_USER);
|
||||
$show24Hours = ($userObj instanceof App\Entity\User)
|
||||
? $userObj->getShow24HourTime()
|
||||
: null;
|
||||
|
||||
$timeConfig = new \stdClass();
|
||||
if (null !== $show24Hours) {
|
||||
$timeConfig->hour12 = !$show24Hours;
|
||||
}
|
||||
|
||||
$app = [
|
||||
'lang' => [
|
||||
'confirm' => __('Are you sure?'),
|
||||
'lang' => [
|
||||
'confirm' => __('Are you sure?'),
|
||||
'advanced' => __('Advanced'),
|
||||
],
|
||||
'locale' => $locale,
|
||||
'locale_short' => $localeShort,
|
||||
'locale_with_dashes' => $localeWithDashes,
|
||||
'time_config' => $timeConfig,
|
||||
'api_csrf' => null,
|
||||
];
|
||||
|
||||
|
|
|
@ -22,30 +22,44 @@
|
|||
</template>
|
||||
|
||||
<b-form-row>
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_locale"
|
||||
:field="form.locale">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Language</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-radio-group stacked :id="props.id" :options="localeOptions"
|
||||
v-model="props.field.$model">
|
||||
</b-form-radio-group>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_theme"
|
||||
:field="form.theme">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Site Theme</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-radio-group stacked :id="props.id" :options="themeOptions"
|
||||
v-model="props.field.$model">
|
||||
</b-form-radio-group>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
<b-col md="6">
|
||||
<b-wrapped-form-group class="col-md-6" id="edit_form_locale"
|
||||
:field="form.locale">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Language</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-radio-group stacked :id="props.id" :options="localeOptions"
|
||||
v-model="props.field.$model">
|
||||
</b-form-radio-group>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<b-wrapped-form-group id="edit_form_theme"
|
||||
:field="form.theme">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Site Theme</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-radio-group stacked :id="props.id" :options="themeOptions"
|
||||
v-model="props.field.$model">
|
||||
</b-form-radio-group>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
|
||||
<b-wrapped-form-group id="edit_form_show_24_hour_time"
|
||||
:field="form.show_24_hour_time">
|
||||
<template #label="{lang}">
|
||||
<translate :key="lang">Time Display</translate>
|
||||
</template>
|
||||
<template #default="props">
|
||||
<b-form-radio-group stacked :id="props.id" :options="show24hourOptions"
|
||||
v-model="props.field.$model">
|
||||
</b-form-radio-group>
|
||||
</template>
|
||||
</b-wrapped-form-group>
|
||||
</b-col>
|
||||
</b-form-row>
|
||||
</b-form-fieldset>
|
||||
</div>
|
||||
|
@ -87,6 +101,22 @@ export default {
|
|||
value: 'dark'
|
||||
}
|
||||
];
|
||||
},
|
||||
show24hourOptions() {
|
||||
return [
|
||||
{
|
||||
text: this.$gettext('Prefer System Default'),
|
||||
value: null
|
||||
},
|
||||
{
|
||||
text: this.$gettext('12 Hour'),
|
||||
value: false
|
||||
},
|
||||
{
|
||||
text: this.$gettext('24 Hour'),
|
||||
value: true
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ export default {
|
|||
name: {},
|
||||
email: {required, email},
|
||||
locale: {required},
|
||||
theme: {required}
|
||||
theme: {required},
|
||||
show_24_hour_time: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -52,7 +53,8 @@ export default {
|
|||
name: '',
|
||||
email: '',
|
||||
locale: 'default',
|
||||
theme: 'browser'
|
||||
theme: 'browser',
|
||||
show_24_hour_time: null,
|
||||
};
|
||||
},
|
||||
open() {
|
||||
|
|
|
@ -143,7 +143,9 @@ export default {
|
|||
this.$refs.datatable.relist();
|
||||
},
|
||||
formatTimestamp(unix_timestamp) {
|
||||
return DateTime.fromSeconds(unix_timestamp).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
return DateTime.fromSeconds(unix_timestamp).toLocaleString(
|
||||
{...DateTime.DATETIME_SHORT, ...App.time_config}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,7 +183,9 @@ export default {
|
|||
return DateTime.fromSeconds(timestamp).toRelative();
|
||||
},
|
||||
toLocaleTime(timestamp) {
|
||||
return DateTime.fromSeconds(timestamp).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
return DateTime.fromSeconds(timestamp).toLocaleString(
|
||||
{...DateTime.DATETIME_SHORT, ...App.time_config}
|
||||
);
|
||||
},
|
||||
formatFileSize(size) {
|
||||
return formatFileSize(size);
|
||||
|
|
|
@ -267,7 +267,9 @@ export default {
|
|||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
return DateTime.fromSeconds(value).setZone(this.stationTimeZone).toLocaleString(DateTime.DATETIME_MED);
|
||||
return DateTime.fromSeconds(value).setZone(this.stationTimeZone).toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
},
|
||||
selectable: true,
|
||||
visible: true
|
||||
|
|
|
@ -192,7 +192,9 @@ export default {
|
|||
: this.$gettext('Enable');
|
||||
},
|
||||
formatTime (time) {
|
||||
return DateTime.fromSeconds(time).setZone(this.stationTimeZone).toLocaleString(DateTime.DATETIME_MED);
|
||||
return DateTime.fromSeconds(time).setZone(this.stationTimeZone).toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
},
|
||||
formatLength (length) {
|
||||
return humanizeDuration(length * 1000, {
|
||||
|
|
|
@ -60,15 +60,23 @@ export default {
|
|||
row.time_until = start_moment.toRelative();
|
||||
|
||||
if (start_moment.hasSame(now, 'day')) {
|
||||
row.start_formatted = start_moment.toLocaleString(DateTime.TIME_SIMPLE);
|
||||
row.start_formatted = start_moment.toLocaleString(
|
||||
{...DateTime.TIME_SIMPLE, ...App.time_config}
|
||||
);
|
||||
} else {
|
||||
row.start_formatted = start_moment.toLocaleString(DateTime.DATETIME_MED);
|
||||
row.start_formatted = start_moment.toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
}
|
||||
|
||||
if (end_moment.hasSame(start_moment, 'day')) {
|
||||
row.end_formatted = end_moment.toLocaleString(DateTime.TIME_SIMPLE);
|
||||
row.end_formatted = end_moment.toLocaleString(
|
||||
{...DateTime.TIME_SIMPLE, ...App.time_config}
|
||||
);
|
||||
} else {
|
||||
row.end_formatted = end_moment.toLocaleString(DateTime.DATETIME_MED);
|
||||
row.end_formatted = end_moment.toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
}
|
||||
|
||||
return row;
|
||||
|
|
|
@ -81,7 +81,9 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
formatTime(time) {
|
||||
return this.getDateTime(time).toLocaleString(DateTime.TIME_WITH_SECONDS);
|
||||
return this.getDateTime(time).toLocaleString(
|
||||
{...DateTime.TIME_WITH_SECONDS, ...App.time_config}
|
||||
);
|
||||
},
|
||||
formatRelativeTime(time) {
|
||||
return this.getDateTime(time).toRelative();
|
||||
|
|
|
@ -104,7 +104,9 @@ export default {
|
|||
this.$refs.datatable.refresh();
|
||||
},
|
||||
formatTime(time) {
|
||||
return DateTime.fromSeconds(time).setZone(this.stationTimeZone).toLocaleString(DateTime.DATETIME_MED);
|
||||
return DateTime.fromSeconds(time).setZone(this.stationTimeZone).toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
},
|
||||
doDelete(url) {
|
||||
this.$confirmDelete({
|
||||
|
|
|
@ -165,10 +165,14 @@ export default {
|
|||
return Math.abs(val);
|
||||
},
|
||||
formatTimestamp(unix_timestamp) {
|
||||
return DateTime.fromSeconds(unix_timestamp).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
return DateTime.fromSeconds(unix_timestamp).toLocaleString(
|
||||
{...DateTime.DATETIME_SHORT, ...App.time_config}
|
||||
);
|
||||
},
|
||||
formatTimestampStation(unix_timestamp) {
|
||||
return DateTime.fromSeconds(unix_timestamp).setZone(this.stationTimeZone).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
return DateTime.fromSeconds(unix_timestamp).setZone(this.stationTimeZone).toLocaleString(
|
||||
{...DateTime.DATETIME_SHORT, ...App.time_config}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -61,7 +61,9 @@ export default {
|
|||
label: this.$gettext('Start Time'),
|
||||
sortable: false,
|
||||
formatter: (value, key, item) => {
|
||||
return DateTime.fromSeconds(value).toLocaleString(DateTime.DATETIME_MED);
|
||||
return DateTime.fromSeconds(value).toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -72,7 +74,9 @@ export default {
|
|||
if (value === 0) {
|
||||
return this.$gettext('Live');
|
||||
}
|
||||
return DateTime.fromSeconds(value).toLocaleString(DateTime.DATETIME_MED);
|
||||
return DateTime.fromSeconds(value).toLocaleString(
|
||||
{...DateTime.DATETIME_MED, ...App.time_config}
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity\Migration;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20221102125558 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add user-level 24-hour time setting.';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE users ADD show_24_hour_time TINYINT(1) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE users DROP show_24_hour_time');
|
||||
}
|
||||
}
|
|
@ -81,6 +81,14 @@ class User implements Stringable, IdentifiableEntityInterface
|
|||
]
|
||||
protected ?string $theme = null;
|
||||
|
||||
#[
|
||||
OA\Property(example: true),
|
||||
ORM\Column(nullable: true),
|
||||
Attributes\AuditIgnore,
|
||||
Groups([EntityGroupsInterface::GROUP_GENERAL, EntityGroupsInterface::GROUP_ALL])
|
||||
]
|
||||
protected ?bool $show_24_hour_time = null;
|
||||
|
||||
#[
|
||||
OA\Property(example: "A1B2C3D4"),
|
||||
ORM\Column(length: 255, nullable: true),
|
||||
|
@ -234,6 +242,16 @@ class User implements Stringable, IdentifiableEntityInterface
|
|||
$this->theme = $theme;
|
||||
}
|
||||
|
||||
public function getShow24HourTime(): ?bool
|
||||
{
|
||||
return $this->show_24_hour_time;
|
||||
}
|
||||
|
||||
public function setShow24HourTime(?bool $show_24_hour_time): void
|
||||
{
|
||||
$this->show_24_hour_time = $show_24_hour_time;
|
||||
}
|
||||
|
||||
public function getTwoFactorSecret(): ?string
|
||||
{
|
||||
return $this->two_factor_secret;
|
||||
|
|
|
@ -49,10 +49,12 @@ $(document).on('click', '.api-call', function (e) {
|
|||
$(function () {
|
||||
function updateClock() {
|
||||
let d = new Date();
|
||||
let time = d.toLocaleString(App.locale_with_dashes, {
|
||||
timeZone: <?=$this->escapeJs($station->getTimezone()) ?>,
|
||||
timeStyle: 'long'
|
||||
})
|
||||
|
||||
let timeConfig = App.time_config;
|
||||
timeConfig.timeZone = <?=$this->escapeJs($station->getTimezone()) ?>;
|
||||
timeConfig.timeStyle = 'long';
|
||||
|
||||
let time = d.toLocaleString(App.locale_with_dashes, timeConfig);
|
||||
|
||||
$('#station-time').text(time);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue