Datetime and date picker fixes.
This commit is contained in:
parent
04bd45fc2d
commit
b25fbd92ba
|
@ -129,11 +129,13 @@ export default {
|
|||
return this.$gettext('Delete');
|
||||
},
|
||||
apiUrl() {
|
||||
let params = {};
|
||||
params.start = DateTime.fromJSDate(this.dateRange.startDate).toISODate();
|
||||
params.end = DateTime.fromJSDate(this.dateRange.endDate).toISODate();
|
||||
let apiUrl = new URL(this.baseApiUrl, document.location);
|
||||
|
||||
return this.baseApiUrl + '?start=' + params.start + '&end=' + params.end;
|
||||
let apiUrlParams = apiUrl.searchParams;
|
||||
apiUrlParams.set('start', DateTime.fromJSDate(this.dateRange.startDate).toISO());
|
||||
apiUrlParams.set('end', DateTime.fromJSDate(this.dateRange.endDate).toISO());
|
||||
|
||||
return apiUrl.toString();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<date-range-picker
|
||||
ref="picker" controlContainerClass="" opens="left" show-dropdowns
|
||||
v-bind="$props" :ranges="ranges" @update="onUpdate">
|
||||
v-bind="$props"
|
||||
:time-picker-increment="1" :ranges="ranges" @update="onUpdate">
|
||||
<template #input="datePicker">
|
||||
<a class="btn btn-bg dropdown-toggle" id="reportrange" href="#" @click.prevent="">
|
||||
<icon icon="date_range"></icon>
|
||||
|
@ -63,48 +64,48 @@ export default {
|
|||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
let ranges = {};
|
||||
computed: {
|
||||
ranges() {
|
||||
let ranges = {};
|
||||
|
||||
if (null !== this.customRanges) {
|
||||
return this.customRanges;
|
||||
}
|
||||
|
||||
if (null !== this.customRanges) {
|
||||
ranges = this.customRanges;
|
||||
} else {
|
||||
let nowTz = DateTime.now().setZone(this.tz);
|
||||
let nowTzDate = nowTz.toJSDate();
|
||||
|
||||
ranges[this.$gettext('Today')] = [
|
||||
nowTzDate,
|
||||
nowTz.minus({days: 1}).toJSDate(),
|
||||
nowTzDate
|
||||
];
|
||||
ranges[this.$gettext('Yesterday')] = [
|
||||
nowTz.minus({days: 1}).toJSDate(),
|
||||
nowTz.minus({days: 2}).toJSDate(),
|
||||
nowTz.minus({days: 1}).toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('Last 7 Days')] = [
|
||||
nowTz.minus({days: 6}).toJSDate(),
|
||||
nowTz.minus({days: 7}).toJSDate(),
|
||||
nowTzDate
|
||||
];
|
||||
ranges[this.$gettext('Last 14 Days')] = [
|
||||
nowTz.minus({days: 13}).toJSDate(),
|
||||
nowTz.minus({days: 14}).toJSDate(),
|
||||
nowTzDate
|
||||
];
|
||||
ranges[this.$gettext('Last 30 Days')] = [
|
||||
nowTz.minus({days: 29}).toJSDate(),
|
||||
nowTz.minus({days: 30}).toJSDate(),
|
||||
nowTzDate
|
||||
];
|
||||
ranges[this.$gettext('This Month')] = [
|
||||
nowTz.startOf('month').toJSDate(),
|
||||
nowTz.endOf('month').toJSDate()
|
||||
nowTz.startOf('month').startOf('day').toJSDate(),
|
||||
nowTz.endOf('month').endOf('day').toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('Last Month')] = [
|
||||
nowTz.minus({months: 1}).startOf('month').toJSDate(),
|
||||
nowTz.minus({months: 1}).endOf('month').toJSDate()
|
||||
nowTz.minus({months: 1}).startOf('month').startOf('day').toJSDate(),
|
||||
nowTz.minus({months: 1}).endOf('month').endOf('day').toJSDate()
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
ranges: ranges
|
||||
};
|
||||
return ranges;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onUpdate(newValue) {
|
||||
|
|
|
@ -4,33 +4,28 @@
|
|||
<div class="card">
|
||||
<div class="card-header bg-primary-dark">
|
||||
<div class="d-flex align-items-center">
|
||||
<h2 class="card-title flex-fill my-0">
|
||||
<translate key="lang_header">Listeners</translate>
|
||||
</h2>
|
||||
<div class="flex-fill my-0">
|
||||
<h2 class="card-title">
|
||||
<translate key="lang_header">Listeners</translate>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex-shrink">
|
||||
<a class="btn btn-bg" id="btn-export" :href="exportUrl" target="_blank">
|
||||
<icon icon="file_download"></icon>
|
||||
<translate key="lang_download_csv_button">Download CSV</translate>
|
||||
</a>
|
||||
|
||||
<date-range-dropdown time-picker :min-date="minDate" :max-date="maxDate"
|
||||
<date-range-dropdown v-if="!isLive" time-picker :min-date="minDate" :max-date="maxDate"
|
||||
:tz="stationTimeZone" :custom-ranges="dateRanges"
|
||||
v-model="dateRange" @update="updateListeners">
|
||||
<template #input="datePicker">
|
||||
<a class="btn btn-bg dropdown-toggle" id="reportrange" href="#" @click.prevent="">
|
||||
<icon icon="date_range"></icon>
|
||||
<template v-if="isLive">
|
||||
<translate key="lang_live_listeners">Live Listeners</translate>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ datePicker.rangeText }}
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
</date-range-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<b-tabs pills card lazy>
|
||||
<b-tab key="live" active @click="setIsLive(true)" :title="langLiveListeners" no-body></b-tab>
|
||||
<b-tab key="not-live" @click="setIsLive(false)" :title="langListenerHistory" no-body></b-tab>
|
||||
</b-tabs>
|
||||
<div id="map">
|
||||
<StationReportsListenersMap :listeners="listeners"></StationReportsListenersMap>
|
||||
</div>
|
||||
|
@ -137,26 +132,32 @@ export default {
|
|||
stationTimeZone: String,
|
||||
},
|
||||
data() {
|
||||
let liveTime = DateTime.now().setZone(this.stationTimeZone).plus({days: 1}).toJSDate();
|
||||
const nowTz = DateTime.now().setZone(this.stationTimeZone);
|
||||
|
||||
return {
|
||||
isLive: true,
|
||||
listeners: [],
|
||||
liveTime: liveTime,
|
||||
dateRange: {
|
||||
startDate: liveTime,
|
||||
endDate: liveTime
|
||||
startDate: nowTz.minus({days: 1}).toJSDate(),
|
||||
endDate: nowTz
|
||||
},
|
||||
fields: [
|
||||
{ key: 'ip', label: this.$gettext('IP'), sortable: false },
|
||||
{ key: 'time', label: this.$gettext('Time'), sortable: false },
|
||||
{ key: 'time_sec', label: this.$gettext('Time (sec)'), sortable: false },
|
||||
{ key: 'user_agent', isRowHeader: true, label: this.$gettext('User Agent'), sortable: false },
|
||||
{ key: 'stream', label: this.$gettext('Stream'), sortable: false },
|
||||
{ key: 'location', label: this.$gettext('Location'), sortable: false }
|
||||
{key: 'ip', label: this.$gettext('IP'), sortable: false},
|
||||
{key: 'time', label: this.$gettext('Time'), sortable: false},
|
||||
{key: 'time_sec', label: this.$gettext('Time (sec)'), sortable: false},
|
||||
{key: 'user_agent', isRowHeader: true, label: this.$gettext('User Agent'), sortable: false},
|
||||
{key: 'stream', label: this.$gettext('Stream'), sortable: false},
|
||||
{key: 'location', label: this.$gettext('Location'), sortable: false}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
langLiveListeners() {
|
||||
return this.$gettext('Live Listeners');
|
||||
},
|
||||
langListenerHistory() {
|
||||
return this.$gettext('Listener History');
|
||||
},
|
||||
nowTz() {
|
||||
return DateTime.now().setZone(this.stationTimeZone);
|
||||
},
|
||||
|
@ -168,25 +169,21 @@ export default {
|
|||
},
|
||||
dateRanges() {
|
||||
let ranges = {};
|
||||
ranges[this.$gettext('Live Listeners')] = [
|
||||
this.liveTime,
|
||||
this.liveTime
|
||||
];
|
||||
ranges[this.$gettext('Today')] = [
|
||||
this.nowTz.startOf('day').toJSDate(),
|
||||
this.nowTz.endOf('day').toJSDate()
|
||||
this.nowTz.minus({days: 1}).toJSDate(),
|
||||
this.nowTz.toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('Yesterday')] = [
|
||||
this.nowTz.minus({days: 1}).startOf('day').toJSDate(),
|
||||
this.nowTz.minus({days: 1}).endOf('day').toJSDate()
|
||||
this.nowTz.minus({days: 2}).toJSDate(),
|
||||
this.nowTz.minus({days: 1}).toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('Last 7 Days')] = [
|
||||
this.nowTz.minus({days: 6}).startOf('day').toJSDate(),
|
||||
this.nowTz.endOf('day').toJSDate()
|
||||
this.nowTz.minus({days: 6}).toJSDate(),
|
||||
this.nowTz.toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('Last 30 Days')] = [
|
||||
this.nowTz.minus({days: 29}).startOf('day').toJSDate(),
|
||||
this.nowTz.endOf('day').toJSDate()
|
||||
this.nowTz.minus({days: 29}).toJSDate(),
|
||||
this.nowTz.toJSDate()
|
||||
];
|
||||
ranges[this.$gettext('This Month')] = [
|
||||
this.nowTz.startOf('month').startOf('day').toJSDate(),
|
||||
|
@ -196,11 +193,9 @@ export default {
|
|||
this.nowTz.minus({months: 1}).startOf('month').startOf('day').toJSDate(),
|
||||
this.nowTz.minus({months: 1}).endOf('month').endOf('day').toJSDate()
|
||||
];
|
||||
|
||||
return ranges;
|
||||
},
|
||||
isLive() {
|
||||
return DateTime.fromJSDate(this.liveTime).equals(DateTime.fromJSDate(this.dateRange.startDate));
|
||||
},
|
||||
exportUrl() {
|
||||
let exportUrl = new URL(this.apiUrl, document.location);
|
||||
let exportUrlParams = exportUrl.searchParams;
|
||||
|
@ -227,6 +222,10 @@ export default {
|
|||
this.updateListeners();
|
||||
},
|
||||
methods: {
|
||||
setIsLive(newValue) {
|
||||
this.isLive = newValue;
|
||||
this.updateListeners();
|
||||
},
|
||||
formatTime(time) {
|
||||
return formatTime(time);
|
||||
},
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<data-table ref="datatable" responsive paginated
|
||||
<data-table ref="datatable" responsive paginated select-fields
|
||||
:fields="fields" :apiUrl="apiUrl">
|
||||
<template #cell(datetime)="row">
|
||||
{{ formatTimestamp(row.item.played_at) }}
|
||||
</template>
|
||||
<template #cell(datetime_station)="row">
|
||||
{{ formatTimestampStation(row.item.played_at) }}
|
||||
</template>
|
||||
<template #cell(listeners_start)="row">
|
||||
{{ row.item.listeners_start }}
|
||||
</template>
|
||||
|
@ -92,11 +95,44 @@ export default {
|
|||
endDate: nowTz.toJSDate(),
|
||||
},
|
||||
fields: [
|
||||
{key: 'datetime', label: this.$gettext('Date/Time'), sortable: false},
|
||||
{key: 'listeners_start', label: this.$gettext('Listeners'), sortable: false},
|
||||
{key: 'delta', label: this.$gettext('Change'), sortable: false},
|
||||
{key: 'song', isRowHeader: true, label: this.$gettext('Song Title'), sortable: false},
|
||||
{key: 'source', label: this.$gettext('Source'), sortable: false}
|
||||
{
|
||||
key: 'datetime',
|
||||
label: this.$gettext('Date/Time (Browser)'),
|
||||
selectable: true,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
key: 'datetime_station',
|
||||
label: this.$gettext('Date/Time (Station)'),
|
||||
sortable: false,
|
||||
selectable: true,
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
key: 'listeners_start',
|
||||
label: this.$gettext('Listeners'),
|
||||
selectable: true,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
key: 'delta',
|
||||
label: this.$gettext('Change'),
|
||||
selectable: true,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
key: 'song',
|
||||
isRowHeader: true,
|
||||
label: this.$gettext('Song Title'),
|
||||
selectable: true,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
key: 'source',
|
||||
label: this.$gettext('Source'),
|
||||
selectable: true,
|
||||
sortable: false
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -127,6 +163,9 @@ export default {
|
|||
return Math.abs(val);
|
||||
},
|
||||
formatTimestamp(unix_timestamp) {
|
||||
return DateTime.fromSeconds(unix_timestamp).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
},
|
||||
formatTimestampStation(unix_timestamp) {
|
||||
return DateTime.fromSeconds(unix_timestamp).setZone(this.stationTimeZone).toLocaleString(DateTime.DATETIME_SHORT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ class AuditLogAction
|
|||
$tz = new DateTimeZone('UTC');
|
||||
|
||||
$params = $request->getParams();
|
||||
if (!empty($params['start'])) {
|
||||
$start = CarbonImmutable::parse($params['start'] . ' 00:00:00', $tz);
|
||||
$end = CarbonImmutable::parse(($params['end'] ?? $params['start']) . ' 23:59:59', $tz);
|
||||
if (!empty($params['start']) && !empty($params['end'])) {
|
||||
$start = CarbonImmutable::parse($params['start'], $tz)->setSecond(0);
|
||||
$end = CarbonImmutable::parse($params['end'], $tz)->setSecond(59);
|
||||
} else {
|
||||
$start = CarbonImmutable::parse('-2 weeks', $tz);
|
||||
$end = CarbonImmutable::now($tz);
|
||||
|
|
|
@ -80,8 +80,8 @@ class HistoryController
|
|||
|
||||
$params = $request->getQueryParams();
|
||||
if (!empty($params['start']) && !empty($params['end'])) {
|
||||
$start = CarbonImmutable::parse($params['start'], $station_tz);
|
||||
$end = CarbonImmutable::parse($params['end'], $station_tz);
|
||||
$start = CarbonImmutable::parse($params['start'], $station_tz)->setSecond(0);
|
||||
$end = CarbonImmutable::parse($params['end'], $station_tz)->setSecond(59);
|
||||
} else {
|
||||
$start = CarbonImmutable::parse('-2 weeks', $station_tz);
|
||||
$end = CarbonImmutable::now($station_tz);
|
||||
|
|
|
@ -81,20 +81,12 @@ class ListenersAction
|
|||
|
||||
$qb = $qb->andWhere('l.timestamp_end = 0');
|
||||
} else {
|
||||
$startString = $params['start'];
|
||||
if (10 === strlen($startString)) {
|
||||
$startString .= ' 00:00:00';
|
||||
}
|
||||
|
||||
$start = CarbonImmutable::parse($startString, $stationTz);
|
||||
$start = CarbonImmutable::parse($params['start'], $stationTz)
|
||||
->setSecond(0);
|
||||
$startTimestamp = $start->getTimestamp();
|
||||
|
||||
$endString = $params['end'] ?? $params['start'];
|
||||
if (10 === strlen($endString)) {
|
||||
$endString .= ' 23:59:59';
|
||||
}
|
||||
|
||||
$end = CarbonImmutable::parse($endString, $stationTz);
|
||||
$end = CarbonImmutable::parse($params['end'] ?? $params['start'], $stationTz)
|
||||
->setSecond(59);
|
||||
$endTimestamp = $end->getTimestamp();
|
||||
|
||||
$range = $start->format('Y-m-d_H-i-s') . '_to_' . $end->format('Y-m-d_H-i-s');
|
||||
|
|
Loading…
Reference in New Issue